From 5993dc47591d14a9ce1e32e7a143d83bd8d6fbde Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Thu, 22 Sep 2022 03:46:19 +0300 Subject: [PATCH] [PICA] Shader uploads --- CMakeLists.txt | 5 +++-- include/{ => PICA}/gpu.hpp | 2 ++ include/PICA/regs.hpp | 16 ++++++++++++++ include/PICA/shader.hpp | 41 +++++++++++++++++++++++++++++++++++ include/PICA/shader_unit.hpp | 11 ++++++++++ include/emulator.hpp | 2 +- include/services/gsp_gpu.hpp | 2 +- src/core/PICA/gpu.cpp | 3 ++- src/core/PICA/regs.cpp | 22 +++++++++++++++++-- src/core/PICA/shader_unit.cpp | 6 +++++ src/core/services/gsp_gpu.cpp | 4 ++-- 11 files changed, 105 insertions(+), 9 deletions(-) rename include/{ => PICA}/gpu.hpp (91%) create mode 100644 include/PICA/regs.hpp create mode 100644 include/PICA/shader.hpp create mode 100644 include/PICA/shader_unit.hpp create mode 100644 src/core/PICA/shader_unit.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index bb66ad95..e84d3324 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -54,7 +54,7 @@ set(SERVICE_SOURCE_FILES src/core/services/service_manager.cpp src/core/services src/core/services/fs.cpp src/core/services/gsp_gpu.cpp src/core/services/gsp_lcd.cpp src/core/services/ndm.cpp ) -set(PICA_SOURCE_FILES src/core/PICA/gpu.cpp src/core/PICA/regs.cpp) +set(PICA_SOURCE_FILES src/core/PICA/gpu.cpp src/core/PICA/regs.cpp src/core/PICA/shader_unit.cpp) set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/opengl.hpp include/termcolor.hpp include/cpu.hpp include/cpu_dynarmic.hpp include/memory.hpp include/kernel/kernel.hpp @@ -62,7 +62,8 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/opengl.hpp inc include/kernel/config_mem.hpp include/services/service_manager.hpp include/services/apt.hpp include/kernel/handles.hpp include/services/hid.hpp include/services/fs.hpp include/services/gsp_gpu.hpp include/services/gsp_lcd.hpp include/arm_defs.hpp - include/gpu.hpp include/services/ndm.hpp + include/PICA/gpu.hpp include/PICA/regs.hpp include/services/ndm.hpp + include/PICA/shader.hpp include/PICA/shader_unit.hpp ) set(THIRD_PARTY_SOURCE_FILES third_party/imgui/imgui.cpp diff --git a/include/gpu.hpp b/include/PICA/gpu.hpp similarity index 91% rename from include/gpu.hpp rename to include/PICA/gpu.hpp index d1525d8d..2b99880d 100644 --- a/include/gpu.hpp +++ b/include/PICA/gpu.hpp @@ -2,10 +2,12 @@ #include #include "helpers.hpp" #include "memory.hpp" +#include "PICA/shader_unit.hpp" class GPU { Memory& mem; static constexpr u32 regNum = 0x300; + ShaderUnit shaderUnit; std::array regs; // GPU internal registers public: diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp new file mode 100644 index 00000000..61d2f33c --- /dev/null +++ b/include/PICA/regs.hpp @@ -0,0 +1,16 @@ +#pragma once + +namespace PICAInternalRegs { + enum : u32 { + VertexShaderTransferEnd = 0x2BF, + VertexShaderTransferIndex = 0x2CB, + VertexShaderData0 = 0x2CC, + VertexShaderData1 = 0x2CD, + VertexShaderData2 = 0x2CE, + VertexShaderData3 = 0x2CF, + VertexShaderData4 = 0x2D0, + VertexShaderData5 = 0x2D1, + VertexShaderData6 = 0x2D2, + VertexShaderData7 = 0x2D3, + }; +} \ No newline at end of file diff --git a/include/PICA/shader.hpp b/include/PICA/shader.hpp new file mode 100644 index 00000000..534a5463 --- /dev/null +++ b/include/PICA/shader.hpp @@ -0,0 +1,41 @@ +#pragma once +#include +#include +#include +#include "helpers.hpp" + +class PICAShader { + int bufferIndex; // Index of the next instruction to overwrite + +public: + std::array loadedShader; // Currently loaded & active shader + std::array bufferedShader; // Shader to be transferred when the SH_CODETRANSFER_END reg gets written to + + u32 boolUniform; + std::array intUniforms; + std::array floatUniforms; + + void reset() { + loadedShader.fill(0); + bufferedShader.fill(0); + + intUniforms.fill(0); + floatUniforms.fill(0); + boolUniform = 0; + bufferIndex = 0; + } + + void finalize() { + std::memcpy(&loadedShader[0], &bufferedShader[0], 512 * sizeof(u32)); + } + + void setBufferIndex(u32 offset) { + if (offset != 0) Helpers::panic("Is this register 9 or 11 bit?"); + bufferIndex = (offset >> 2) & 511; + } + + void uploadWord(u32 word) { + bufferedShader[bufferIndex++] = word; + bufferIndex &= 511; + } +}; \ No newline at end of file diff --git a/include/PICA/shader_unit.hpp b/include/PICA/shader_unit.hpp new file mode 100644 index 00000000..3fa59bfa --- /dev/null +++ b/include/PICA/shader_unit.hpp @@ -0,0 +1,11 @@ +#pragma once +#include "PICA/shader.hpp" + +class ShaderUnit { + +public: + PICAShader vs; // Vertex shader + PICAShader gs; // Geometry shader + + void reset(); +}; \ No newline at end of file diff --git a/include/emulator.hpp b/include/emulator.hpp index 193ea536..181a178a 100644 --- a/include/emulator.hpp +++ b/include/emulator.hpp @@ -4,9 +4,9 @@ #include #include "cpu.hpp" -#include "gpu.hpp" #include "memory.hpp" #include "opengl.hpp" +#include "PICA/gpu.hpp" #include "SFML/Window.hpp" #include "SFML/Graphics.hpp" diff --git a/include/services/gsp_gpu.hpp b/include/services/gsp_gpu.hpp index 42e88d8d..9759b8b9 100644 --- a/include/services/gsp_gpu.hpp +++ b/include/services/gsp_gpu.hpp @@ -1,6 +1,6 @@ #pragma once #include -#include "gpu.hpp" +#include "PICA/gpu.hpp" #include "helpers.hpp" #include "kernel_types.hpp" #include "memory.hpp" diff --git a/src/core/PICA/gpu.cpp b/src/core/PICA/gpu.cpp index 380c25c7..a9e74b2e 100644 --- a/src/core/PICA/gpu.cpp +++ b/src/core/PICA/gpu.cpp @@ -1,8 +1,9 @@ -#include "gpu.hpp" +#include "PICA/gpu.hpp" #include void GPU::reset() { regs.fill(0); + shaderUnit.reset(); // TODO: Reset blending, texturing, etc here } diff --git a/src/core/PICA/regs.cpp b/src/core/PICA/regs.cpp index 144cc0d5..9d37df4d 100644 --- a/src/core/PICA/regs.cpp +++ b/src/core/PICA/regs.cpp @@ -1,4 +1,5 @@ -#include "gpu.hpp" +#include "PICA/gpu.hpp" +#include "PICA/regs.hpp" u32 GPU::readReg(u32 address) { printf("Ignoring read from GPU register %08X\n", address); @@ -10,7 +11,7 @@ void GPU::writeReg(u32 address, u32 value) { const u32 index = (address - 0x1EF01000) / sizeof(u32); writeInternalReg(index, value, 0xffffffff); } else { - Helpers::panic("Ignoring write to GPU register %08X. Value: %08X\n", address, value); + printf("Ignoring write to external GPU register %08X. Value: %08X\n", address, value); } } @@ -24,6 +25,8 @@ u32 GPU::readInternalReg(u32 index) { } void GPU::writeInternalReg(u32 index, u32 value, u32 mask) { + using namespace PICAInternalRegs; + if (index > regNum) { Helpers::panic("Tried to write to invalid GPU register. Index: %X, value: %08X\n", index, value); return; @@ -32,7 +35,22 @@ void GPU::writeInternalReg(u32 index, u32 value, u32 mask) { u32 currentValue = regs[index]; u32 newValue = (currentValue & ~mask) | (value & mask); // Only overwrite the bits specified by "mask" + // TODO: Figure out if things like the shader index use the unmasked value or the masked one + // We currently use the unmasked value like Citra does switch (index) { + case VertexShaderTransferEnd: + if (value != 0) shaderUnit.vs.finalize(); + break; + + case VertexShaderTransferIndex: + shaderUnit.vs.setBufferIndex(value); + break; + + case VertexShaderData0: case VertexShaderData1: case VertexShaderData2: case VertexShaderData3: + case VertexShaderData4: case VertexShaderData5: case VertexShaderData6: case VertexShaderData7: + shaderUnit.vs.uploadWord(value); + break; + default: printf("GPU: Wrote to unimplemented internal reg: %X, value: %08X\n", index, newValue); break; diff --git a/src/core/PICA/shader_unit.cpp b/src/core/PICA/shader_unit.cpp new file mode 100644 index 00000000..e3c12202 --- /dev/null +++ b/src/core/PICA/shader_unit.cpp @@ -0,0 +1,6 @@ +#include "PICA/shader_unit.hpp" + +void ShaderUnit::reset() { + vs.reset(); + gs.reset(); +} \ No newline at end of file diff --git a/src/core/services/gsp_gpu.cpp b/src/core/services/gsp_gpu.cpp index 1d67a3e0..543da71f 100644 --- a/src/core/services/gsp_gpu.cpp +++ b/src/core/services/gsp_gpu.cpp @@ -252,7 +252,7 @@ void GPUService::memoryFill(u32* cmd) { // Actually send command list (aka display list) to GPU void GPUService::processCommandList(u32* cmd) { u32 address = cmd[1] & ~7; // Buffer address - u32 size = cmd[2] * 8; // Buffer size in bytes + u32 size = cmd[2] & ~3; // Buffer size in bytes bool updateGas = cmd[3] == 1; // Update gas additive blend results (0 = don't update, 1 = update) bool flushBuffer = cmd[7] == 1; // Flush buffer (0 = don't flush, 1 = flush) @@ -305,5 +305,5 @@ void GPUService::processCommandList(u32* cmd) { } } - Helpers::panic("GPU::GSP::processCommandList. Address: %08X, size in bytes: %08X", address, size); + printf("GPU::GSP::processCommandList. Address: %08X, size in bytes: %08X\n", address, size); } \ No newline at end of file