Implement DMA engine Block Linear->Linear copies

This commit is contained in:
Billy Laws 2022-04-09 20:21:56 +01:00 committed by PixelyIon
parent 3e4e8de1d2
commit dbbc5704d2
2 changed files with 65 additions and 3 deletions

View File

@ -39,6 +39,9 @@ namespace skyline::soc::gm20b::engine {
if (registers.launchDma->srcMemoryLayout == Registers::LaunchDma::MemoryLayout::Pitch && if (registers.launchDma->srcMemoryLayout == Registers::LaunchDma::MemoryLayout::Pitch &&
registers.launchDma->dstMemoryLayout == Registers::LaunchDma::MemoryLayout::BlockLinear) registers.launchDma->dstMemoryLayout == Registers::LaunchDma::MemoryLayout::BlockLinear)
CopyPitchToBlockLinear(); CopyPitchToBlockLinear();
else if (registers.launchDma->srcMemoryLayout == Registers::LaunchDma::MemoryLayout::BlockLinear &&
registers.launchDma->dstMemoryLayout == Registers::LaunchDma::MemoryLayout::Pitch)
CopyBlockLinearToPitch();
else else
Logger::Warn("Unimplemented multi-line copy type: {} -> {}!", Logger::Warn("Unimplemented multi-line copy type: {} -> {}!",
static_cast<u8>(registers.launchDma->srcMemoryLayout), static_cast<u8>(registers.launchDma->dstMemoryLayout)); static_cast<u8>(registers.launchDma->srcMemoryLayout), static_cast<u8>(registers.launchDma->dstMemoryLayout));
@ -72,6 +75,9 @@ namespace skyline::soc::gm20b::engine {
return; return;
} }
if (*registers.lineLengthIn != registers.dstSurface->width)
Logger::Warn("DMA copy width mismatch: src: {} dst: {}", *registers.lineLengthIn, registers.dstSurface->width);
gpu::GuestTexture srcTexture{span<u8>{}, gpu::GuestTexture srcTexture{span<u8>{},
gpu::texture::Dimensions{*registers.lineLengthIn, *registers.lineCount, 1}, gpu::texture::Dimensions{*registers.lineLengthIn, *registers.lineCount, 1},
gpu::format::GetFormatForBpp(bytesPerPixel), gpu::format::GetFormatForBpp(bytesPerPixel),
@ -85,9 +91,6 @@ namespace skyline::soc::gm20b::engine {
return; return;
} }
if (*registers.lineLengthIn != registers.dstSurface->width)
Logger::Warn("DMA copy width mismatch: src: {} dst: {}", *registers.lineLengthIn, registers.dstSurface->width);
// This represents a single layer view into a potentially multi-layer texture // This represents a single layer view into a potentially multi-layer texture
gpu::GuestTexture dstTexture{span<u8>{}, gpu::GuestTexture dstTexture{span<u8>{},
gpu::texture::Dimensions{*registers.lineLengthIn, registers.dstSurface->height, 1}, gpu::texture::Dimensions{*registers.lineLengthIn, registers.dstSurface->height, 1},
@ -108,6 +111,63 @@ namespace skyline::soc::gm20b::engine {
gpu::texture::CopyLinearToBlockLinear(dstTexture, srcTexture.mappings.front().data(), dstTexture.mappings.front().data()); gpu::texture::CopyLinearToBlockLinear(dstTexture, srcTexture.mappings.front().data(), dstTexture.mappings.front().data());
} }
void MaxwellDma::CopyBlockLinearToPitch() {
if (registers.srcSurface->blockSize.Depth() > 1 || registers.srcSurface->depth > 1) {
Logger::Warn("3D DMA engine copies are unimplemented!");
return;
}
if (registers.srcSurface->blockSize.Width() != 1) {
Logger::Warn("DMA engine copies with block widths other than 1 are unimplemented!");
return;
}
u32 bytesPerPixel{static_cast<u32>(registers.remapComponents->ComponentSize() * registers.remapComponents->NumSrcComponents())};
if (bytesPerPixel * *registers.lineLengthIn != *registers.pitchOut) {
Logger::Warn("Non-linear DMA destination textures are not implemented!");
return;
}
if (registers.srcSurface->origin.x || registers.srcSurface->origin.y) {
Logger::Warn("Non-zero origin DMA copies are not implemented!");
return;
}
if (*registers.lineLengthIn != registers.srcSurface->width)
Logger::Warn("DMA copy width mismatch: src: {} dst: {}", *registers.lineLengthIn, registers.dstSurface->width);
gpu::GuestTexture srcTexture{span<u8>{},
gpu::texture::Dimensions{registers.srcSurface->width, registers.srcSurface->height, 1},
gpu::format::GetFormatForBpp(bytesPerPixel),
gpu::texture::TileConfig{ .mode = gpu::texture::TileMode::Block, .blockHeight = registers.srcSurface->blockSize.Height(), .blockDepth = 1 },
gpu::texture::TextureType::e2D};
if (auto mappings{channelCtx.asCtx->gmmu.TranslateRange(*registers.offsetIn, srcTexture.GetLayerSize())}; mappings.size() == 1) {
srcTexture.mappings[0] = mappings[0];
} else {
Logger::Warn("DMA for split textures is unimplemented!");
return;
}
gpu::GuestTexture dstTexture{span<u8>{},
gpu::texture::Dimensions{*registers.lineLengthIn, *registers.lineCount, 1},
gpu::format::GetFormatForBpp(bytesPerPixel),
gpu::texture::TileConfig{ .mode = gpu::texture::TileMode::Linear },
gpu::texture::TextureType::e2D};
if (auto mappings{channelCtx.asCtx->gmmu.TranslateRange(*registers.offsetOut, dstTexture.GetLayerSize())}; mappings.size() == 1) {
dstTexture.mappings[0] = mappings[0];
} else {
Logger::Warn("DMA for split textures is unimplemented!");
return;
}
Logger::Debug("{}x{}@0x{:X} -> {}x{}@0x{:X}", srcTexture.dimensions.width, srcTexture.dimensions.height, *registers.offsetIn, dstTexture.dimensions.width, dstTexture.dimensions.height, *registers.offsetOut);
gpu::texture::CopyBlockLinearToLinear(srcTexture, srcTexture.mappings.front().data(), dstTexture.mappings.front().data());
}
void MaxwellDma::CallMethodBatchNonInc(u32 method, span<u32> arguments) { void MaxwellDma::CallMethodBatchNonInc(u32 method, span<u32> arguments) {
for (u32 argument : arguments) for (u32 argument : arguments)
HandleMethod(method, argument); HandleMethod(method, argument);

View File

@ -24,6 +24,8 @@ namespace skyline::soc::gm20b::engine {
void CopyPitchToBlockLinear(); void CopyPitchToBlockLinear();
void CopyBlockLinearToPitch();
public: public:
/** /**
* @url https://github.com/NVIDIA/open-gpu-doc/blob/master/classes/dma-copy/clb0b5.h * @url https://github.com/NVIDIA/open-gpu-doc/blob/master/classes/dma-copy/clb0b5.h