From 624f4327f8ccd07ba4333400406d0476f62ccf20 Mon Sep 17 00:00:00 2001 From: DH Date: Mon, 30 Sep 2024 22:43:21 +0300 Subject: [PATCH] gpu2: implement IT_DMA_DATA --- rpcsx-gpu2/Pipe.cpp | 127 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 126 insertions(+), 1 deletion(-) diff --git a/rpcsx-gpu2/Pipe.cpp b/rpcsx-gpu2/Pipe.cpp index da8aef903..1f4069676 100644 --- a/rpcsx-gpu2/Pipe.cpp +++ b/rpcsx-gpu2/Pipe.cpp @@ -5,6 +5,7 @@ #include "gnm/mmio.hpp" #include "gnm/pm4.hpp" #include "vk.hpp" +#include #include #include #include @@ -874,7 +875,131 @@ bool GraphicsPipe::eventWriteEos(Queue &queue) { } bool GraphicsPipe::dmaData(Queue &queue) { - // FIXME + auto control = queue.rptr[1]; + auto srcAddressLo = queue.rptr[2]; + auto data = srcAddressLo; + auto srcAddressHi = queue.rptr[3]; + auto dstAddressLo = queue.rptr[4]; + auto dstAddressHi = queue.rptr[5]; + auto cmdSize = queue.rptr[6]; + auto size = rx::getBits(cmdSize, 20, 0); + + auto engine = rx::getBit(control, 0); + auto srcVolatile = rx::getBit(control, 15); + + // 0 - dstAddress using das + // 1 - gds + // 3 - dstAddress using L2 + auto dstSel = rx::getBits(control, 21, 20); + + // 0 - LRU + // 1 - Stream + // 2 - Bypass + auto dstCachePolicy = rx::getBits(control, 26, 25); + + auto dstVolatile = rx::getBit(control, 27); + + // 0 - srcAddress using sas + // 1 - gds + // 2 - data + // 3 - srcAddress using L2 + auto srcSel = rx::getBits(control, 30, 29); + + auto cpSync = rx::getBit(control, 31); + + auto dataDisWc = rx::getBit(cmdSize, 21); + + // 0 - none + // 1 - 8 in 16 + // 2 - 8 in 32 + // 3 - 8 in 64 + auto dstSwap = rx::getBits(cmdSize, 25, 24); + + // 0 - memory + // 1 - register + auto sas = rx::getBit(cmdSize, 26); + + // 0 - memory + // 1 - register + auto das = rx::getBit(cmdSize, 27); + + auto saic = rx::getBit(cmdSize, 28); + auto daic = rx::getBit(cmdSize, 29); + auto rawWait = rx::getBit(cmdSize, 30); + + void *dst = nullptr; + switch (dstSel) { + case 3: + case 0: + if (dstSel == 3 || das == 0) { + auto dstAddress = + dstAddressLo | (static_cast(dstAddressHi) << 32); + dst = amdgpu::RemoteMemory{queue.vmId}.getPointer(dstAddress); + device->caches[queue.vmId].invalidate(scheduler, dstAddress, size); + } else { + dst = getMmRegister(dstAddressLo / sizeof(std::uint32_t)); + } + break; + + case 1: + dst = device->caches[queue.vmId].getGdsBuffer().getData() + dstAddressLo; + break; + + default: + rx::die("IT_DMA_DATA: unexpected dstSel %u", dstSel); + } + + void *src = nullptr; + std::uint32_t srcSize = 0; + switch (srcSel) { + case 3: + case 0: + if (srcSel == 3 || sas == 0) { + auto srcAddress = + srcAddressLo | (static_cast(srcAddressHi) << 32); + src = amdgpu::RemoteMemory{queue.vmId}.getPointer(srcAddress); + device->caches[queue.vmId].flush(scheduler, srcAddress, size); + } else { + src = getMmRegister(srcAddressLo / sizeof(std::uint32_t)); + } + + srcSize = ~0; + break; + case 1: + src = device->caches[queue.vmId].getGdsBuffer().getData() + srcAddressLo; + srcSize = ~0; + break; + + case 2: + src = &data; + srcSize = sizeof(data); + break; + + default: + rx::die("IT_DMA_DATA: unexpected srcSel %u", srcSel); + } + + rx::dieIf(size > srcSize, + "IT_DMA_DATA: out of source size srcSel %u, dstSel %u, size %u", + srcSel, dstSel, size); + + if (saic != 0 && srcSel == 0 && sas == 0) { + if (daic != 0 && dstSel == 0 && das == 0) { + std::memcpy(dst, src, sizeof(std::uint32_t)); + } else { + for (std::uint32_t i = 0; i < size / sizeof(std::uint32_t); ++i) { + std::memcpy(std::bit_cast(dst) + i, src, + sizeof(std::uint32_t)); + } + } + } else if (daic != 0 && dstSel == 0 && das == 0) { + for (std::uint32_t i = 0; i < size / sizeof(std::uint32_t); ++i) { + std::memcpy(dst, std::bit_cast(src) + i, + sizeof(std::uint32_t)); + } + } else { + std::memcpy(dst, src, size); + } return true; }