Implement rest of I2M engine copies

This commit is contained in:
TheASVigilante 2023-02-19 15:11:04 +01:00 committed by Billy Laws
parent 72c2d94cbe
commit fd205ff0a9
3 changed files with 48 additions and 8 deletions

View file

@ -44,12 +44,12 @@ namespace skyline::gpu::interconnect {
});
}
void Inline2Memory::Upload(IOVA dst, span<u32> src) {
auto dstMappings{channelCtx.asCtx->gmmu.TranslateRange(dst, src.size_bytes())};
void Inline2Memory::Upload(IOVA dst, span<u8> src) {
auto dstMappings{channelCtx.asCtx->gmmu.TranslateRange(dst, src.size())};
size_t offset{};
for (auto mapping : dstMappings) {
UploadSingleMapping(mapping, src.cast<u8>().subspan(offset, mapping.size()));
UploadSingleMapping(mapping, src.subspan(offset, mapping.size()));
offset += mapping.size();
}
}

View file

@ -33,6 +33,6 @@ namespace skyline::gpu::interconnect {
public:
Inline2Memory(GPU &gpu, soc::gm20b::ChannelContext &channelCtx);
void Upload(IOVA dst, span<u32> src);
void Upload(IOVA dst, span<u8> src);
};
}

View file

@ -1,6 +1,7 @@
// SPDX-License-Identifier: MPL-2.0
// Copyright © 2022 Skyline Team and Contributors (https://github.com/skyline-emu/)
#include <gpu/texture/layout.h>
#include <soc/gm20b/channel.h>
#include "inline2memory.h"
@ -19,13 +20,52 @@ namespace skyline::soc::gm20b::engine {
if (state.launchDma.completion == RegisterState::DmaCompletionType::ReleaseSemaphore)
throw exception("Semaphore release on I2M completion is not supported!");
if (state.launchDma.layout == RegisterState::DmaDstMemoryLayout::Pitch && state.lineCount == 1) {
Logger::Debug("range: 0x{:X} -> 0x{:X}", u64{state.offsetOut}, u64{state.offsetOut} + buffer.size() * 0x4);
Logger::Debug("range: 0x{:X} -> 0x{:X}", u64{state.offsetOut}, u64{state.offsetOut} + buffer.size() * 0x4);
if (state.launchDma.layout == RegisterState::DmaDstMemoryLayout::Pitch) {
channelCtx.channelSequenceNumber++;
interconnect.Upload(u64{state.offsetOut}, span{buffer});
auto srcBuffer{span{buffer}.cast<u8>()};
for (u32 line{}, pitchOffset{}; line < state.lineCount; ++line, pitchOffset += state.pitchOut)
interconnect.Upload(u64{state.offsetOut + pitchOffset}, srcBuffer.subspan(state.lineLengthIn * line, state.lineLengthIn));
} else {
channelCtx.executor.Submit();
Logger::Warn("Non-linear I2M uploads are not supported!");
gpu::texture::Dimensions srcDimensions{state.lineLengthIn, state.lineCount, state.dstDepth};
gpu::texture::Dimensions dstDimensions{state.dstWidth, state.dstHeight, state.dstDepth};
size_t dstSize{GetBlockLinearLayerSize(dstDimensions, 1, 1, 1, 1 << (u8)state.dstBlockSize.height, 1 << (u8)state.dstBlockSize.depth)};
auto dstMappings{channelCtx.asCtx->gmmu.TranslateRange(state.offsetOut, dstSize)};
auto inlineCopy{[&](u8 *dst){
// The I2M engine only supports a formatBpb of 1
if ((srcDimensions.width != dstDimensions.width) || (srcDimensions.height != dstDimensions.height))
gpu::texture::CopyLinearToBlockLinearSubrect(srcDimensions, dstDimensions,
1, 1, 1,
1 << static_cast<u8>(state.dstBlockSize.height), 1 << static_cast<u8>(state.dstBlockSize.depth),
span{buffer}.cast<u8>().data(), dst,
state.originBytesX, state.originSamplesY
);
else
gpu::texture::CopyLinearToBlockLinear(dstDimensions,
1, 1, 1,
1 << static_cast<u8>(state.dstBlockSize.height), 1 << static_cast<u8>(state.dstBlockSize.depth),
span{buffer}.cast<u8>().data(), dst
);
}};
if (dstMappings.size() != 1) {
// We create a temporary buffer to hold the blockLinear texture if mappings are split
// NOTE: We don't reserve memory here since such copies on this engine are rarely used
std::vector<u8> tempBuffer(dstSize);
inlineCopy(tempBuffer.data());
interconnect.Upload(u64{state.offsetOut}, span{tempBuffer});
} else {
inlineCopy(dstMappings.front().data());
}
}
}