From 86ea40a9e5946d0159bb1bff723c10e8b7ca08d1 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Fri, 3 Jan 2025 21:24:46 +0200 Subject: [PATCH] GPU: Add sw texture copies --- include/renderer.hpp | 1 + src/core/renderer_gl/renderer_gl.cpp | 2 ++ src/core/renderer_mtl/renderer_mtl.cpp | 2 +- src/renderer.cpp | 38 ++++++++++++++++++++++++++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/include/renderer.hpp b/include/renderer.hpp index b458ecce..ca28455f 100644 --- a/include/renderer.hpp +++ b/include/renderer.hpp @@ -53,6 +53,7 @@ class Renderer { EmulatorConfig* emulatorConfig = nullptr; + void doSoftwareTextureCopy(u32 inputAddr, u32 outputAddr, u32 copySize, u32 inputWidth, u32 inputGap, u32 outputWidth, u32 outputGap); public: Renderer(GPU& gpu, const std::array& internalRegs, const std::array& externalRegs); virtual ~Renderer(); diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index c1899655..2d54e586 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -792,6 +792,8 @@ void RendererGL::textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 shutUpCounter++; printf("RendererGL::TextureCopy failed to locate src framebuffer!\n"); } + + doSoftwareTextureCopy(inputAddr, outputAddr, copySize, inputWidth, inputGap, outputWidth, outputGap); return; } diff --git a/src/core/renderer_mtl/renderer_mtl.cpp b/src/core/renderer_mtl/renderer_mtl.cpp index 9cf58716..14bca4d2 100644 --- a/src/core/renderer_mtl/renderer_mtl.cpp +++ b/src/core/renderer_mtl/renderer_mtl.cpp @@ -426,7 +426,7 @@ void RendererMTL::textureCopy(u32 inputAddr, u32 outputAddr, u32 totalBytes, u32 // Find the source surface. auto srcFramebuffer = getColorRenderTarget(inputAddr, PICA::ColorFmt::RGBA8, copyStride, copyHeight, false); if (!srcFramebuffer) { - Helpers::warn("RendererMTL::TextureCopy failed to locate src framebuffer!\n"); + doSoftwareTextureCopy(inputAddr, outputAddr, copySize, inputWidth, inputGap, outputWidth, outputGap); return; } nextRenderPassName = "Clear before texture copy"; diff --git a/src/renderer.cpp b/src/renderer.cpp index 6a18df85..390a3fa6 100644 --- a/src/renderer.cpp +++ b/src/renderer.cpp @@ -3,6 +3,8 @@ #include #include +#include "PICA/gpu.hpp" + Renderer::Renderer(GPU& gpu, const std::array& internalRegs, const std::array& externalRegs) : gpu(gpu), regs(internalRegs), externalRegs(externalRegs) {} Renderer::~Renderer() {} @@ -39,3 +41,39 @@ const char* Renderer::typeToString(RendererType rendererType) { default: return "Invalid"; } } + +void Renderer::doSoftwareTextureCopy(u32 inputAddr, u32 outputAddr, u32 copySize, u32 inputWidth, u32 inputGap, u32 outputWidth, u32 outputGap) { + u8* inputPointer = gpu.getPointerPhys(inputAddr); + u8* outputPointer = gpu.getPointerPhys(outputAddr); + + if (inputPointer == nullptr || outputPointer == nullptr) { + return; + } + + u32 inputBytesLeft = inputWidth; + u32 outputBytesLeft = outputWidth; + u32 copyBytesLeft = copySize; + + while (copyBytesLeft > 0) { + const u32 bytes = std::min({inputBytesLeft, outputBytesLeft, copyBytesLeft}); + std::memcpy(outputPointer, inputPointer, bytes); + + inputPointer += bytes; + outputPointer += bytes; + + inputBytesLeft -= bytes; + outputBytesLeft -= bytes; + copyBytesLeft -= bytes; + + // Apply input and output gap when an input or output line ends + if (inputBytesLeft == 0) { + inputBytesLeft = inputWidth; + inputPointer += inputGap; + } + + if (outputBytesLeft == 0) { + outputBytesLeft = outputWidth; + outputPointer += outputGap; + } + } +}