GPU/DMA: Partially implemented the 'enable_2d' bit in the DMA engine.

When not set, this tells the GPU to only use the X size when performing a DMA copy.
This is only implemented for linear->linear and tiled->tiled copies. Conversion copies still retain the assert.

This bit is unset by some games for various purposes, and by nouveau when copying the vertex buffers.
This commit is contained in:
Subv 2018-09-08 16:02:16 -05:00
parent 9cd79c25ed
commit fdb199290b
1 changed files with 10 additions and 2 deletions

View File

@ -41,7 +41,6 @@ void MaxwellDMA::HandleCopy() {
// TODO(Subv): Perform more research and implement all features of this engine. // TODO(Subv): Perform more research and implement all features of this engine.
ASSERT(regs.exec.enable_swizzle == 0); ASSERT(regs.exec.enable_swizzle == 0);
ASSERT(regs.exec.enable_2d == 1);
ASSERT(regs.exec.query_mode == Regs::QueryMode::None); ASSERT(regs.exec.query_mode == Regs::QueryMode::None);
ASSERT(regs.exec.query_intr == Regs::QueryIntr::None); ASSERT(regs.exec.query_intr == Regs::QueryIntr::None);
ASSERT(regs.exec.copy_mode == Regs::CopyMode::Unk2); ASSERT(regs.exec.copy_mode == Regs::CopyMode::Unk2);
@ -51,10 +50,19 @@ void MaxwellDMA::HandleCopy() {
ASSERT(regs.dst_params.pos_y == 0); ASSERT(regs.dst_params.pos_y == 0);
if (regs.exec.is_dst_linear == regs.exec.is_src_linear) { if (regs.exec.is_dst_linear == regs.exec.is_src_linear) {
Memory::CopyBlock(dest_cpu, source_cpu, regs.x_count * regs.y_count); size_t copy_size = regs.x_count;
// When the enable_2d bit is disabled, the copy is performed as if we were copying a 1D
// buffer of length `x_count`, otherwise we copy a 2D buffer of size (x_count, y_count).
if (regs.exec.enable_2d) {
copy_size = copy_size * regs.y_count;
}
Memory::CopyBlock(dest_cpu, source_cpu, copy_size);
return; return;
} }
ASSERT(regs.exec.enable_2d == 1);
u8* src_buffer = Memory::GetPointer(source_cpu); u8* src_buffer = Memory::GetPointer(source_cpu);
u8* dst_buffer = Memory::GetPointer(dest_cpu); u8* dst_buffer = Memory::GetPointer(dest_cpu);