From 95a891758943ee0a514e7593f9095a6f95d3f470 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sat, 8 Jul 2023 14:51:09 +0300 Subject: [PATCH 01/13] renderer_gl: Implement stencil testing --- include/PICA/regs.hpp | 2 + include/renderer_gl/renderer_gl.hpp | 3 +- src/core/renderer_gl/renderer_gl.cpp | 55 ++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 1 deletion(-) diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp index e1c9a819..85cfe60e 100644 --- a/include/PICA/regs.hpp +++ b/include/PICA/regs.hpp @@ -55,6 +55,8 @@ namespace PICA { BlendFunc = 0x101, BlendColour = 0x103, AlphaTestConfig = 0x104, + StencilTest = 0x105, + StencilOp = 0x106, DepthAndColorMask = 0x107, DepthBufferFormat = 0x116, ColourBufferFormat = 0x117, diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index 3c729d76..18f52a1c 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -61,6 +61,7 @@ class RendererGL final : public Renderer { MAKE_LOG_FUNCTION(log, rendererLogger) void setupBlending(); + void setupStencilTest(bool stencilEnable); void bindDepthBuffer(); void setupTextureEnvState(); void bindTexturesToSlots(); @@ -79,4 +80,4 @@ class RendererGL final : public Renderer { // Take a screenshot of the screen and store it in a file void screenshot(const std::string& name) override; -}; \ No newline at end of file +}; diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 0126b3b8..91c70bba 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -205,6 +205,51 @@ void RendererGL::setupBlending() { } } +void RendererGL::setupStencilTest(bool stencilEnable) { + if (!stencilEnable) { + OpenGL::disableStencil(); + return; + } + + static constexpr std::array stencilFuncs = { + GL_NEVER, + GL_ALWAYS, + GL_EQUAL, + GL_NOTEQUAL, + GL_LESS, + GL_LEQUAL, + GL_GREATER, + GL_GEQUAL + }; + OpenGL::enableStencil(); + + const u32 stencilConfig = regs[PICA::InternalRegs::StencilTest]; + const u32 stencilFunc = getBits<4, 3>(stencilConfig); + const u32 stencilBufferMask = getBits<8, 8>(stencilConfig); + const s32 reference = s8(getBits<16, 8>(stencilConfig)); // Signed reference value + const u32 stencilRefMask = getBits<24, 8>(stencilConfig); + + glStencilFunc(stencilFuncs[stencilFunc], reference, stencilRefMask); + glStencilMask(stencilBufferMask); + + static constexpr std::array stencilOps = { + GL_KEEP, + GL_ZERO, + GL_REPLACE, + GL_INCR, + GL_DECR, + GL_INVERT, + GL_INCR_WRAP, + GL_DECR_WRAP + }; + const u32 stencilOpConfig = regs[PICA::InternalRegs::StencilOp]; + const u32 stencilFailOp = getBits<0, 3>(stencilOpConfig); + const u32 depthFailOp = getBits<4, 3>(stencilOpConfig); + const u32 passOp = getBits<8, 3>(stencilOpConfig); + + glStencilOp(stencilOps[stencilFailOp], stencilOps[depthFailOp], stencilOps[passOp]); +} + void RendererGL::setupTextureEnvState() { // TODO: Only update uniforms when the TEV config changed. Use an UBO potentially. @@ -356,6 +401,9 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span v GLsizei viewportHeight = GLsizei(f24::fromRaw(regs[PICA::InternalRegs::ViewportHeight] & 0xffffff).toFloat32() * 2.0f); OpenGL::setViewport(viewportWidth, viewportHeight); + const u32 stencilConfig = regs[PICA::InternalRegs::StencilTest]; + const bool stencilEnable = getBit<0>(stencilConfig); + // Note: The code below must execute after we've bound the colour buffer & its framebuffer // Because it attaches a depth texture to the aforementioned colour buffer if (depthEnable) { @@ -371,9 +419,15 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span v bindDepthBuffer(); } else { gl.disableDepth(); + + if (stencilEnable) { + bindDepthBuffer(); + } } } + setupStencilTest(stencilEnable); + vbo.bufferVertsSub(vertices); OpenGL::draw(primitiveTopology, GLsizei(vertices.size())); } @@ -476,6 +530,7 @@ void RendererGL::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u gl.disableBlend(); gl.disableDepth(); gl.disableScissor(); + OpenGL::disableStencil(); gl.setColourMask(true, true, true, true); gl.useProgram(displayProgram); gl.bindVAO(dummyVAO); From 6f7874227c7beece1c721a38b54cd4d8de93219e Mon Sep 17 00:00:00 2001 From: GPUCode Date: Wed, 26 Jul 2023 22:08:20 +0300 Subject: [PATCH 02/13] renderer_gl: Implement logic op --- include/PICA/regs.hpp | 3 ++- include/renderer_gl/renderer_gl.hpp | 1 + src/core/renderer_gl/renderer_gl.cpp | 25 +++++++++++++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp index 85cfe60e..53f74a9e 100644 --- a/include/PICA/regs.hpp +++ b/include/PICA/regs.hpp @@ -53,6 +53,7 @@ namespace PICA { // Framebuffer registers ColourOperation = 0x100, BlendFunc = 0x101, + LogicOp = 0x102, BlendColour = 0x103, AlphaTestConfig = 0x104, StencilTest = 0x105, @@ -294,4 +295,4 @@ namespace PICA { GeometryPrimitive = 3, }; -} // namespace PICA \ No newline at end of file +} // namespace PICA diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index 18f52a1c..94720e92 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -62,6 +62,7 @@ class RendererGL final : public Renderer { MAKE_LOG_FUNCTION(log, rendererLogger) void setupBlending(); void setupStencilTest(bool stencilEnable); + void setupLogicOp(); void bindDepthBuffer(); void setupTextureEnvState(); void bindTexturesToSlots(); diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 91c70bba..e67ef44d 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -250,6 +250,30 @@ void RendererGL::setupStencilTest(bool stencilEnable) { glStencilOp(stencilOps[stencilFailOp], stencilOps[depthFailOp], stencilOps[passOp]); } +void RendererGL::setupLogicOp() { + const u32 logicOp = getBits<0, 4>(regs[PICA::InternalRegs::LogicOp]); + static constexpr std::array logicOps = { + GL_CLEAR, + GL_AND, + GL_AND_REVERSE, + GL_COPY, + GL_SET, + GL_COPY_INVERTED, + GL_NOOP, + GL_INVERT, + GL_NAND, + GL_OR, + GL_NOR, + GL_XOR, + GL_EQUIV, + GL_AND_INVERTED, + GL_OR_REVERSE, + GL_OR_INVERTED, + }; + + glLogicOp(logicOps[logicOp]); +} + void RendererGL::setupTextureEnvState() { // TODO: Only update uniforms when the TEV config changed. Use an UBO potentially. @@ -427,6 +451,7 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span v } setupStencilTest(stencilEnable); + setupLogicOp(); vbo.bufferVertsSub(vertices); OpenGL::draw(primitiveTopology, GLsizei(vertices.size())); From 50bcf3b61766114bb65a07702ac3024bd1fd2694 Mon Sep 17 00:00:00 2001 From: GPUCode Date: Wed, 26 Jul 2023 22:13:41 +0300 Subject: [PATCH 03/13] renderer_gl: Respect depth-stencil write flag --- include/PICA/regs.hpp | 1 + src/core/renderer_gl/renderer_gl.cpp | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/PICA/regs.hpp b/include/PICA/regs.hpp index 53f74a9e..ee8105cd 100644 --- a/include/PICA/regs.hpp +++ b/include/PICA/regs.hpp @@ -59,6 +59,7 @@ namespace PICA { StencilTest = 0x105, StencilOp = 0x106, DepthAndColorMask = 0x107, + DepthBufferWrite = 0x115, DepthBufferFormat = 0x116, ColourBufferFormat = 0x117, DepthBufferLoc = 0x11C, diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index e67ef44d..dc21b744 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -225,10 +225,12 @@ void RendererGL::setupStencilTest(bool stencilEnable) { const u32 stencilConfig = regs[PICA::InternalRegs::StencilTest]; const u32 stencilFunc = getBits<4, 3>(stencilConfig); - const u32 stencilBufferMask = getBits<8, 8>(stencilConfig); const s32 reference = s8(getBits<16, 8>(stencilConfig)); // Signed reference value const u32 stencilRefMask = getBits<24, 8>(stencilConfig); + const bool stencilWrite = regs[PICA::InternalRegs::DepthBufferWrite]; + const u32 stencilBufferMask = stencilWrite ? getBits<8, 8>(stencilConfig) : 0; + glStencilFunc(stencilFuncs[stencilFunc], reference, stencilRefMask); glStencilMask(stencilBufferMask); @@ -381,6 +383,7 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span v poop.bind(OpenGL::DrawAndReadFramebuffer); const u32 depthControl = regs[PICA::InternalRegs::DepthAndColorMask]; + const bool depthWrite = regs[PICA::InternalRegs::DepthBufferWrite]; const bool depthEnable = depthControl & 1; const bool depthWriteEnable = getBit<12>(depthControl); const int depthFunc = getBits<4, 3>(depthControl); @@ -432,7 +435,7 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span v // Because it attaches a depth texture to the aforementioned colour buffer if (depthEnable) { gl.enableDepth(); - gl.setDepthMask(depthWriteEnable ? GL_TRUE : GL_FALSE); + gl.setDepthMask(depthWriteEnable && depthWrite ? GL_TRUE : GL_FALSE); gl.setDepthFunc(depthModes[depthFunc]); bindDepthBuffer(); } else { From c6c71bb9b226b6353582f599ef17d97e0fc54373 Mon Sep 17 00:00:00 2001 From: GPUCode Date: Wed, 26 Jul 2023 22:34:39 +0300 Subject: [PATCH 04/13] renderer_gl: Implement semi proper clears --- include/renderer_gl/opengl.hpp | 12 +++---- include/renderer_gl/surfaces.hpp | 8 ++++- src/core/renderer_gl/renderer_gl.cpp | 41 ++++++++++++++++++----- src/core/services/gsp_gpu.cpp | 50 ++++++++++++++-------------- 4 files changed, 71 insertions(+), 40 deletions(-) diff --git a/include/renderer_gl/opengl.hpp b/include/renderer_gl/opengl.hpp index f8328799..c1ceb4c7 100644 --- a/include/renderer_gl/opengl.hpp +++ b/include/renderer_gl/opengl.hpp @@ -333,18 +333,18 @@ namespace OpenGL { void bind(FramebufferTypes target) const { bind(static_cast(target)); } void free() { glDeleteFramebuffers(1, &m_handle); } - void createWithTexture(Texture& tex, GLenum mode = GL_FRAMEBUFFER, GLenum textureType = GL_TEXTURE_2D) { + void createWithTexture(Texture& tex, GLenum mode = GL_FRAMEBUFFER, GLenum attachment = GL_COLOR_ATTACHMENT0, GLenum textureType = GL_TEXTURE_2D) { m_textureType = textureType; create(); bind(mode); - glFramebufferTexture2D(mode, GL_COLOR_ATTACHMENT0, textureType, tex.handle(), 0); + glFramebufferTexture2D(mode, attachment, textureType, tex.handle(), 0); } - void createWithReadTexture(Texture& tex, GLenum textureType = GL_TEXTURE_2D) { - createWithTexture(tex, GL_READ_FRAMEBUFFER, textureType); + void createWithReadTexture(Texture& tex, GLenum attachment = GL_COLOR_ATTACHMENT0, GLenum textureType = GL_TEXTURE_2D) { + createWithTexture(tex, GL_READ_FRAMEBUFFER, attachment, textureType); } - void createWithDrawTexture(Texture& tex, GLenum textureType = GL_TEXTURE_2D) { - createWithTexture(tex, GL_DRAW_FRAMEBUFFER, textureType); + void createWithDrawTexture(Texture& tex, GLenum attachment = GL_COLOR_ATTACHMENT0, GLenum textureType = GL_TEXTURE_2D) { + createWithTexture(tex, GL_DRAW_FRAMEBUFFER, attachment, textureType); } void createWithTextureMSAA(Texture& tex, GLenum mode = GL_FRAMEBUFFER) { diff --git a/include/renderer_gl/surfaces.hpp b/include/renderer_gl/surfaces.hpp index 1d46e28e..a77729c4 100644 --- a/include/renderer_gl/surfaces.hpp +++ b/include/renderer_gl/surfaces.hpp @@ -86,6 +86,7 @@ struct DepthBuffer { Interval range; // OpenGL texture used for storing depth/stencil OpenGL::Texture texture; + OpenGL::Framebuffer fbo; DepthBuffer() : valid(false) {} @@ -127,6 +128,11 @@ struct DepthBuffer { texture.setMagFilter(OpenGL::Nearest); glBindTexture(GL_TEXTURE_2D, prevTexture); + + fbo.createWithDrawTexture(texture, fmt == GL_DEPTH_STENCIL ? GL_DEPTH_STENCIL_ATTACHMENT : GL_DEPTH_ATTACHMENT); + + if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE) + Helpers::panic("Incomplete framebuffer"); } void free() { @@ -144,4 +150,4 @@ struct DepthBuffer { size_t sizeInBytes() { return (size_t)size.x() * (size_t)size.y() * PICA::sizePerPixel(format); } -}; \ No newline at end of file +}; diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index dc21b744..c1c79b2f 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -472,14 +472,8 @@ void RendererGL::display() { } void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) { - return; log("GPU: Clear buffer\nStart: %08X End: %08X\nValue: %08X Control: %08X\n", startAddress, endAddress, value, control); - const float r = float(getBits<24, 8>(value)) / 255.0f; - const float g = float(getBits<16, 8>(value)) / 255.0f; - const float b = float(getBits<8, 8>(value)) / 255.0f; - const float a = float(value & 0xff) / 255.0f; - if (startAddress == topScreenBuffer) { log("GPU: Cleared top screen\n"); } else if (startAddress == bottomScreenBuffer) { @@ -489,8 +483,39 @@ void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 co log("GPU: Clearing some unknown buffer\n"); } - OpenGL::setClearColor(r, g, b, a); - OpenGL::clearColor(); + const auto color = colourBufferCache.findFromAddress(startAddress); + if (color) { + const float r = getBits<24, 8>(value) / 255.0f; + const float g = getBits<16, 8>(value) / 255.0f; + const float b = getBits<8, 8>(value) / 255.0f; + const float a = (value & 0xff) / 255.0f; + color->get().fbo.bind(OpenGL::DrawFramebuffer); + gl.setColourMask(true, true, true, true); + OpenGL::setClearColor(r, g, b, a); + OpenGL::clearColor(); + return; + } + const auto depth = depthBufferCache.findFromAddress(startAddress); + if (depth) { + float depthVal; + const auto format = depth->get().format; + if (format == DepthFmt::Depth16) { + depthVal = (value & 0xffff) / 65535.0f; + } else { + depthVal = (value & 0xffffff) / 16777215.0f; + } + depth->get().fbo.bind(OpenGL::DrawFramebuffer); + OpenGL::setDepthMask(true); + OpenGL::setClearDepth(depthVal); + OpenGL::clearDepth(); + if (format == DepthFmt::Depth24Stencil8) { + const u8 stencil = (value >> 24); + OpenGL::setStencilMask(0xFF); + OpenGL::setClearStencil(stencil); + } + return; + } + Helpers::warn("GPU: No buffer found!\n"); } OpenGL::Framebuffer RendererGL::getColourFBO() { diff --git a/src/core/services/gsp_gpu.cpp b/src/core/services/gsp_gpu.cpp index 5179aec8..5d4b27a4 100644 --- a/src/core/services/gsp_gpu.cpp +++ b/src/core/services/gsp_gpu.cpp @@ -299,6 +299,28 @@ void GPUService::processCommandBuffer() { } } +static u32 VaddrToPaddr(u32 addr) { + if (addr >= VirtualAddrs::VramStart && addr < (VirtualAddrs::VramStart + VirtualAddrs::VramSize)) [[likely]] { + return addr - VirtualAddrs::VramStart + PhysicalAddrs::VRAM; + } + + else if (addr >= VirtualAddrs::LinearHeapStartOld && addr < VirtualAddrs::LinearHeapEndOld) { + return addr - VirtualAddrs::LinearHeapStartOld + PhysicalAddrs::FCRAM; + } + + else if (addr >= VirtualAddrs::LinearHeapStartNew && addr < VirtualAddrs::LinearHeapEndNew) { + return addr - VirtualAddrs::LinearHeapStartNew + PhysicalAddrs::FCRAM; + } + + else if (addr == 0) { + return 0; + } + + Helpers::warn("[GSP::GPU VaddrToPaddr] Unknown virtual address %08X", addr); + // Obviously garbage address + return 0xF3310932; +} + // Fill 2 GPU framebuffers, buf0 and buf1, using a specific word value void GPUService::memoryFill(u32* cmd) { u32 control = cmd[7]; @@ -316,38 +338,16 @@ void GPUService::memoryFill(u32* cmd) { u32 control1 = control >> 16; if (start0 != 0) { - gpu.clearBuffer(start0, end0, value0, control0); + gpu.clearBuffer(VaddrToPaddr(start0), VaddrToPaddr(end0), value0, control0); requestInterrupt(GPUInterrupt::PSC0); } if (start1 != 0) { - gpu.clearBuffer(start1, end1, value1, control1); + gpu.clearBuffer(VaddrToPaddr(start1), VaddrToPaddr(end1), value1, control1); requestInterrupt(GPUInterrupt::PSC1); } } -static u32 VaddrToPaddr(u32 addr) { - if (addr >= VirtualAddrs::VramStart && addr < (VirtualAddrs::VramStart + VirtualAddrs::VramSize)) [[likely]] { - return addr - VirtualAddrs::VramStart + PhysicalAddrs::VRAM; - } - - else if (addr >= VirtualAddrs::LinearHeapStartOld && addr < VirtualAddrs::LinearHeapEndOld) { - return addr - VirtualAddrs::LinearHeapStartOld + PhysicalAddrs::FCRAM; - } - - else if (addr >= VirtualAddrs::LinearHeapStartNew && addr < VirtualAddrs::LinearHeapEndNew) { - return addr - VirtualAddrs::LinearHeapStartNew + PhysicalAddrs::FCRAM; - } - - else if (addr == 0) { - return 0; - } - - Helpers::warn("[GSP::GPU VaddrToPaddr] Unknown virtual address %08X", addr); - // Obviously garbage address - return 0xF3310932; -} - void GPUService::triggerDisplayTransfer(u32* cmd) { const u32 inputAddr = VaddrToPaddr(cmd[1]); const u32 outputAddr = VaddrToPaddr(cmd[2]); @@ -394,4 +394,4 @@ void GPUService::triggerTextureCopy(u32* cmd) { // This uses the transfer engine and thus needs to fire a PPF interrupt. // NSMB2 relies on this requestInterrupt(GPUInterrupt::PPF); -} \ No newline at end of file +} From b4cc743608ea6ff12fbb6bbe0ca70b8046641a1d Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Thu, 27 Jul 2023 15:34:21 +0300 Subject: [PATCH 05/13] [GL] Add stencil enable to state tracker --- include/renderer_gl/gl_state.hpp | 16 ++++++++++++++++ src/core/renderer_gl/gl_state.cpp | 6 ++++++ src/core/renderer_gl/renderer_gl.cpp | 6 +++--- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/include/renderer_gl/gl_state.hpp b/include/renderer_gl/gl_state.hpp index 82531c7a..78e8a386 100644 --- a/include/renderer_gl/gl_state.hpp +++ b/include/renderer_gl/gl_state.hpp @@ -21,6 +21,7 @@ struct GLStateManager { bool blendEnabled; bool depthEnabled; bool scissorEnabled; + bool stencilEnabled; // Colour/depth masks bool redMask, greenMask, blueMask, alphaMask; @@ -40,6 +41,7 @@ struct GLStateManager { void resetVBO(); void resetProgram(); void resetScissor(); + void resetStencil(); void enableDepth() { if (!depthEnabled) { @@ -83,6 +85,20 @@ struct GLStateManager { } } + void enableStencil() { + if (!stencilEnabled) { + stencilEnabled = true; + OpenGL::enableStencil(); + } + } + + void disableStencil() { + if (stencilEnabled) { + stencilEnabled = false; + OpenGL::disableStencil(); + } + } + void bindVAO(GLuint handle) { if (boundVAO != handle) { boundVAO = handle; diff --git a/src/core/renderer_gl/gl_state.cpp b/src/core/renderer_gl/gl_state.cpp index 691eb7b6..e965f944 100644 --- a/src/core/renderer_gl/gl_state.cpp +++ b/src/core/renderer_gl/gl_state.cpp @@ -26,6 +26,11 @@ void GLStateManager::resetScissor() { OpenGL::setScissor(0, 0, 0, 0); } +void GLStateManager::resetStencil() { + stencilEnabled = false; + OpenGL::disableStencil(); +} + void GLStateManager::resetVAO() { boundVAO = 0; glBindVertexArray(0); @@ -50,4 +55,5 @@ void GLStateManager::reset() { resetVBO(); resetProgram(); resetScissor(); + resetStencil(); } \ No newline at end of file diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index c1c79b2f..fc25ef5d 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -207,7 +207,7 @@ void RendererGL::setupBlending() { void RendererGL::setupStencilTest(bool stencilEnable) { if (!stencilEnable) { - OpenGL::disableStencil(); + gl.disableStencil(); return; } @@ -221,7 +221,7 @@ void RendererGL::setupStencilTest(bool stencilEnable) { GL_GREATER, GL_GEQUAL }; - OpenGL::enableStencil(); + gl.enableStencil(); const u32 stencilConfig = regs[PICA::InternalRegs::StencilTest]; const u32 stencilFunc = getBits<4, 3>(stencilConfig); @@ -583,7 +583,7 @@ void RendererGL::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u gl.disableBlend(); gl.disableDepth(); gl.disableScissor(); - OpenGL::disableStencil(); + gl.disableStencil(); gl.setColourMask(true, true, true, true); gl.useProgram(displayProgram); gl.bindVAO(dummyVAO); From 1d3b078dfb09497e4dbdf07cfa9d5ab7d0283e5d Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Thu, 27 Jul 2023 18:01:18 +0300 Subject: [PATCH 06/13] Convert warn to log --- src/core/renderer_gl/renderer_gl.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index fc25ef5d..5bd0efa3 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -273,6 +273,7 @@ void RendererGL::setupLogicOp() { GL_OR_INVERTED, }; + // TODO: Enable logic op lmao glLogicOp(logicOps[logicOp]); } @@ -495,6 +496,7 @@ void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 co OpenGL::clearColor(); return; } + const auto depth = depthBufferCache.findFromAddress(startAddress); if (depth) { float depthVal; @@ -515,7 +517,8 @@ void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 co } return; } - Helpers::warn("GPU: No buffer found!\n"); + + log("[RendererGL::ClearBuffer] No buffer found!\n"); } OpenGL::Framebuffer RendererGL::getColourFBO() { From 79a341a297c7ceb63b34e4ce2abcb3c210d9d2a7 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Thu, 27 Jul 2023 18:17:14 +0300 Subject: [PATCH 07/13] [GL] Fix depth mask getting corrupted, remove dead code --- src/core/renderer_gl/renderer_gl.cpp | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 5bd0efa3..08ac1f11 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -461,9 +461,6 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span v OpenGL::draw(primitiveTopology, GLsizei(vertices.size())); } -constexpr u32 topScreenBuffer = 0x1f000000; -constexpr u32 bottomScreenBuffer = 0x1f05dc00; - void RendererGL::display() { gl.disableScissor(); @@ -475,15 +472,6 @@ void RendererGL::display() { void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) { log("GPU: Clear buffer\nStart: %08X End: %08X\nValue: %08X Control: %08X\n", startAddress, endAddress, value, control); - if (startAddress == topScreenBuffer) { - log("GPU: Cleared top screen\n"); - } else if (startAddress == bottomScreenBuffer) { - log("GPU: Tried to clear bottom screen\n"); - return; - } else { - log("GPU: Clearing some unknown buffer\n"); - } - const auto color = colourBufferCache.findFromAddress(startAddress); if (color) { const float r = getBits<24, 8>(value) / 255.0f; @@ -507,14 +495,16 @@ void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 co depthVal = (value & 0xffffff) / 16777215.0f; } depth->get().fbo.bind(OpenGL::DrawFramebuffer); - OpenGL::setDepthMask(true); + gl.setDepthMask(true); OpenGL::setClearDepth(depthVal); OpenGL::clearDepth(); if (format == DepthFmt::Depth24Stencil8) { const u8 stencil = (value >> 24); OpenGL::setStencilMask(0xFF); OpenGL::setClearStencil(stencil); + OpenGL::clearStencil(); } + return; } From 60655febba3df90bbbe770b0dafbe405def1d5ef Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Thu, 27 Jul 2023 19:39:49 +0300 Subject: [PATCH 08/13] [GL] Disable scissor in clearBuffer --- src/core/renderer_gl/renderer_gl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 08ac1f11..19958026 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -471,6 +471,7 @@ void RendererGL::display() { void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 control) { log("GPU: Clear buffer\nStart: %08X End: %08X\nValue: %08X Control: %08X\n", startAddress, endAddress, value, control); + gl.disableScissor(); const auto color = colourBufferCache.findFromAddress(startAddress); if (color) { From 1ea0b39a3bf89f95aed6348dd2b1b0c29e61bd9d Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Thu, 27 Jul 2023 21:47:39 +0300 Subject: [PATCH 09/13] [GL] Fix glClear call --- src/core/renderer_gl/renderer_gl.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 19958026..200b7757 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -488,6 +488,8 @@ void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 co const auto depth = depthBufferCache.findFromAddress(startAddress); if (depth) { + depth->get().fbo.bind(OpenGL::DrawFramebuffer); + float depthVal; const auto format = depth->get().format; if (format == DepthFmt::Depth16) { @@ -495,15 +497,17 @@ void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 co } else { depthVal = (value & 0xffffff) / 16777215.0f; } - depth->get().fbo.bind(OpenGL::DrawFramebuffer); + gl.setDepthMask(true); OpenGL::setClearDepth(depthVal); - OpenGL::clearDepth(); + if (format == DepthFmt::Depth24Stencil8) { const u8 stencil = (value >> 24); - OpenGL::setStencilMask(0xFF); + OpenGL::setStencilMask(0xff); OpenGL::setClearStencil(stencil); - OpenGL::clearStencil(); + OpenGL::clearDepthAndStencil(); + } else { + OpenGL::clearDepth(); } return; From 64fa9704687706ad1b274b1ae8947fc3b02ad084 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Thu, 27 Jul 2023 21:57:50 +0300 Subject: [PATCH 10/13] [GL] Actually implement logic ops --- include/renderer_gl/renderer_gl.hpp | 1 - src/core/renderer_gl/renderer_gl.cpp | 43 +++++++++------------------- 2 files changed, 14 insertions(+), 30 deletions(-) diff --git a/include/renderer_gl/renderer_gl.hpp b/include/renderer_gl/renderer_gl.hpp index 94720e92..18f52a1c 100644 --- a/include/renderer_gl/renderer_gl.hpp +++ b/include/renderer_gl/renderer_gl.hpp @@ -62,7 +62,6 @@ class RendererGL final : public Renderer { MAKE_LOG_FUNCTION(log, rendererLogger) void setupBlending(); void setupStencilTest(bool stencilEnable); - void setupLogicOp(); void bindDepthBuffer(); void setupTextureEnvState(); void bindTexturesToSlots(); diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index 200b7757..e41dd2bd 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -149,8 +149,6 @@ void RendererGL::initGraphicsContext(SDL_Window* window) { // Set up the OpenGL blending context to match the emulated PICA void RendererGL::setupBlending() { - const bool blendingEnabled = (regs[PICA::InternalRegs::ColourOperation] & (1 << 8)) != 0; - // Map of PICA blending equations to OpenGL blending equations. The unused blending equations are equivalent to equation 0 (add) static constexpr std::array blendingEquations = { GL_FUNC_ADD, GL_FUNC_SUBTRACT, GL_FUNC_REVERSE_SUBTRACT, GL_MIN, GL_MAX, GL_FUNC_ADD, GL_FUNC_ADD, GL_FUNC_ADD, @@ -176,10 +174,21 @@ void RendererGL::setupBlending() { GL_ONE, }; - if (!blendingEnabled) { - gl.disableBlend(); + static constexpr std::array logicOps = { + GL_CLEAR, GL_AND, GL_AND_REVERSE, GL_COPY, GL_SET, GL_COPY_INVERTED, GL_NOOP, GL_INVERT, + GL_NAND, GL_OR, GL_NOR, GL_XOR, GL_EQUIV, GL_AND_INVERTED, GL_OR_REVERSE, GL_OR_INVERTED, + }; + + // Shows if blending is enabled. If it is not enabled, then logic ops are enabled instead + const bool blendingEnabled = (regs[PICA::InternalRegs::ColourOperation] & (1 << 8)) != 0; + + if (!blendingEnabled) { // Logic ops are enabled + const u32 logicOp = getBits<0, 4>(regs[PICA::InternalRegs::LogicOp]); + glLogicOp(logicOps[logicOp]); + glEnable(GL_COLOR_LOGIC_OP); } else { gl.enableBlend(); + glDisable(GL_COLOR_LOGIC_OP); // Get blending equations const u32 blendControl = regs[PICA::InternalRegs::BlendFunc]; @@ -252,30 +261,6 @@ void RendererGL::setupStencilTest(bool stencilEnable) { glStencilOp(stencilOps[stencilFailOp], stencilOps[depthFailOp], stencilOps[passOp]); } -void RendererGL::setupLogicOp() { - const u32 logicOp = getBits<0, 4>(regs[PICA::InternalRegs::LogicOp]); - static constexpr std::array logicOps = { - GL_CLEAR, - GL_AND, - GL_AND_REVERSE, - GL_COPY, - GL_SET, - GL_COPY_INVERTED, - GL_NOOP, - GL_INVERT, - GL_NAND, - GL_OR, - GL_NOR, - GL_XOR, - GL_EQUIV, - GL_AND_INVERTED, - GL_OR_REVERSE, - GL_OR_INVERTED, - }; - - // TODO: Enable logic op lmao - glLogicOp(logicOps[logicOp]); -} void RendererGL::setupTextureEnvState() { // TODO: Only update uniforms when the TEV config changed. Use an UBO potentially. @@ -455,7 +440,6 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span v } setupStencilTest(stencilEnable); - setupLogicOp(); vbo.bufferVertsSub(vertices); OpenGL::draw(primitiveTopology, GLsizei(vertices.size())); @@ -579,6 +563,7 @@ void RendererGL::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u screenFramebuffer.bind(OpenGL::DrawFramebuffer); gl.disableBlend(); + glDisable(GL_COLOR_LOGIC_OP); gl.disableDepth(); gl.disableScissor(); gl.disableStencil(); From adb78bf838ef50b71e7880a44a8375bd92fae10d Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Fri, 28 Jul 2023 01:35:49 +0300 Subject: [PATCH 11/13] [GL] More state stuff --- include/renderer_gl/gl_state.hpp | 44 ++++++++++++++++++++++++++++ include/renderer_gl/opengl.hpp | 2 ++ src/core/renderer_gl/gl_state.cpp | 12 ++++++++ src/core/renderer_gl/renderer_gl.cpp | 16 +++++----- 4 files changed, 67 insertions(+), 7 deletions(-) diff --git a/include/renderer_gl/gl_state.hpp b/include/renderer_gl/gl_state.hpp index 78e8a386..a6c8d1f9 100644 --- a/include/renderer_gl/gl_state.hpp +++ b/include/renderer_gl/gl_state.hpp @@ -1,6 +1,7 @@ #pragma once #include +#include "helpers.hpp" #include "opengl.hpp" // GL state manager object for use in the OpenGL GPU renderer and potentially other things in the future (such as a potential ImGui GUI) @@ -18,10 +19,16 @@ // backend-agnostic as possible struct GLStateManager { + // We only support 6 clipping planes in our state manager because that's the minimum for GL_MAX_CLIP_PLANES + // And nobody needs more than 6 clip planes anyways + static constexpr GLint clipPlaneCount = 6; + bool blendEnabled; + bool logicOpEnabled; bool depthEnabled; bool scissorEnabled; bool stencilEnabled; + u32 enabledClipPlanes; // Bitfield of enabled clip planes // Colour/depth masks bool redMask, greenMask, blueMask, alphaMask; @@ -35,6 +42,7 @@ struct GLStateManager { void reset(); void resetBlend(); + void resetClipping(); void resetColourMask(); void resetDepth(); void resetVAO(); @@ -99,6 +107,42 @@ struct GLStateManager { } } + void enableLogicOp() { + if (!logicOpEnabled) { + logicOpEnabled = true; + OpenGL::enableLogicOp(); + } + } + + void disableLogicOp() { + if (logicOpEnabled) { + logicOpEnabled = false; + OpenGL::disableLogicOp(); + } + } + + void enableClipPlane(GLuint index) { + if (index >= clipPlaneCount) [[unlikely]] { + Helpers::panic("Enabled invalid clipping plane %d\n", index); + } + + if ((enabledClipPlanes & (1 << index)) == 0) { + enabledClipPlanes |= 1 << index; // Enable relevant bit in clipping plane bitfield + OpenGL::enableClipPlane(index); // Enable plane + } + } + + void disableClipPlane(GLuint index) { + if (index >= clipPlaneCount) [[unlikely]] { + Helpers::panic("Disabled invalid clipping plane %d\n", index); + } + + if ((enabledClipPlanes & (1 << index)) != 0) { + enabledClipPlanes ^= 1 << index; // Disable relevant bit in bitfield by flipping it + OpenGL::disableClipPlane(index); // Disable plane + } + } + void bindVAO(GLuint handle) { if (boundVAO != handle) { boundVAO = handle; diff --git a/include/renderer_gl/opengl.hpp b/include/renderer_gl/opengl.hpp index c1ceb4c7..8a52b1d6 100644 --- a/include/renderer_gl/opengl.hpp +++ b/include/renderer_gl/opengl.hpp @@ -519,6 +519,8 @@ namespace OpenGL { static void disableScissor() { glDisable(GL_SCISSOR_TEST); } static void enableBlend() { glEnable(GL_BLEND); } static void disableBlend() { glDisable(GL_BLEND); } + static void enableLogicOp() { glEnable(GL_COLOR_LOGIC_OP); } + static void disableLogicOp() { glDisable(GL_COLOR_LOGIC_OP); } static void enableDepth() { glEnable(GL_DEPTH_TEST); } static void disableDepth() { glDisable(GL_DEPTH_TEST); } static void enableStencil() { glEnable(GL_STENCIL_TEST); } diff --git a/src/core/renderer_gl/gl_state.cpp b/src/core/renderer_gl/gl_state.cpp index e965f944..6d073128 100644 --- a/src/core/renderer_gl/gl_state.cpp +++ b/src/core/renderer_gl/gl_state.cpp @@ -2,7 +2,18 @@ void GLStateManager::resetBlend() { blendEnabled = false; + logicOpEnabled = false; + OpenGL::disableBlend(); + OpenGL::disableLogicOp(); +} + +void GLStateManager::resetClipping() { + // Disable all (supported) clip planes + enabledClipPlanes = 0; + for (int i = 0; i < clipPlaneCount; i++) { + OpenGL::disableClipPlane(i); + } } void GLStateManager::resetColourMask() { @@ -48,6 +59,7 @@ void GLStateManager::resetProgram() { void GLStateManager::reset() { resetBlend(); + resetClipping(); resetColourMask(); resetDepth(); diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index e41dd2bd..ddbffd98 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -185,10 +185,12 @@ void RendererGL::setupBlending() { if (!blendingEnabled) { // Logic ops are enabled const u32 logicOp = getBits<0, 4>(regs[PICA::InternalRegs::LogicOp]); glLogicOp(logicOps[logicOp]); - glEnable(GL_COLOR_LOGIC_OP); + + // If logic ops are enabled we don't need to disable blending because they override it + gl.enableLogicOp(); } else { gl.enableBlend(); - glDisable(GL_COLOR_LOGIC_OP); + gl.disableLogicOp(); // Get blending equations const u32 blendControl = regs[PICA::InternalRegs::BlendFunc]; @@ -359,9 +361,9 @@ void RendererGL::drawVertices(PICA::PrimType primType, std::span v gl.bindVAO(vao); gl.useProgram(triangleProgram); - OpenGL::enableClipPlane(0); // Clipping plane 0 is always enabled + gl.enableClipPlane(0); // Clipping plane 0 is always enabled if (regs[PICA::InternalRegs::ClipEnable] & 1) { - OpenGL::enableClipPlane(1); + gl.enableClipPlane(1); } setupBlending(); @@ -563,7 +565,7 @@ void RendererGL::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u screenFramebuffer.bind(OpenGL::DrawFramebuffer); gl.disableBlend(); - glDisable(GL_COLOR_LOGIC_OP); + gl.disableLogicOp(); gl.disableDepth(); gl.disableScissor(); gl.disableStencil(); @@ -571,8 +573,8 @@ void RendererGL::displayTransfer(u32 inputAddr, u32 outputAddr, u32 inputSize, u gl.useProgram(displayProgram); gl.bindVAO(dummyVAO); - OpenGL::disableClipPlane(0); - OpenGL::disableClipPlane(1); + gl.disableClipPlane(0); + gl.disableClipPlane(1); // Hack: Detect whether we are writing to the top or bottom screen by checking output gap and drawing to the proper part of the output texture // We consider output gap == 320 to mean bottom, and anything else to mean top From 73321856c8ce52d38e7f60a722214d22ea6952b4 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Fri, 28 Jul 2023 02:24:26 +0300 Subject: [PATCH 12/13] Mooore --- include/renderer_gl/gl_state.hpp | 16 ++++++++ include/renderer_gl/opengl.hpp | 55 +++++++++++++++------------- src/core/renderer_gl/gl_state.cpp | 5 +++ src/core/renderer_gl/renderer_gl.cpp | 6 +-- 4 files changed, 53 insertions(+), 29 deletions(-) diff --git a/include/renderer_gl/gl_state.hpp b/include/renderer_gl/gl_state.hpp index a6c8d1f9..98f589e0 100644 --- a/include/renderer_gl/gl_state.hpp +++ b/include/renderer_gl/gl_state.hpp @@ -34,11 +34,13 @@ struct GLStateManager { bool redMask, greenMask, blueMask, alphaMask; bool depthMask; + GLuint stencilMask; GLuint boundVAO; GLuint boundVBO; GLuint currentProgram; GLenum depthFunc; + GLenum logicOp; void reset(); void resetBlend(); @@ -121,6 +123,13 @@ struct GLStateManager { } } + void setLogicOp(GLenum op) { + if (logicOp != op) { + logicOp = op; + OpenGL::setLogicOp(op); + } + } + void enableClipPlane(GLuint index) { if (index >= clipPlaneCount) [[unlikely]] { Helpers::panic("Enabled invalid clipping plane %d\n", index); @@ -143,6 +152,13 @@ struct GLStateManager { } } + void setStencilMask(GLuint mask) { + if (stencilMask != mask) { + stencilMask = mask; + OpenGL::setStencilMask(mask); + } + } + void bindVAO(GLuint handle) { if (boundVAO != handle) { boundVAO = handle; diff --git a/include/renderer_gl/opengl.hpp b/include/renderer_gl/opengl.hpp index 8a52b1d6..e129f6b6 100644 --- a/include/renderer_gl/opengl.hpp +++ b/include/renderer_gl/opengl.hpp @@ -497,42 +497,45 @@ namespace OpenGL { }; static void setClearColor(float val) { glClearColor(val, val, val, val); } - static void setClearColor(float r, float g, float b, float a) { glClearColor(r, g, b, a); } - static void setClearDepth(float depth) { glClearDepthf(depth); } - static void setClearStencil(GLint stencil) { glClearStencil(stencil); } - static void clearColor() { glClear(GL_COLOR_BUFFER_BIT); } - static void clearDepth() { glClear(GL_DEPTH_BUFFER_BIT); } - static void clearStencil() { glClear(GL_STENCIL_BUFFER_BIT); } - static void clearColorAndDepth() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } - static void clearColorAndStencil() { glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } - static void clearDepthAndStencil() { glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } - static void clearAll() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } + static void setClearColor(float r, float g, float b, float a) { glClearColor(r, g, b, a); } + static void setClearDepth(float depth) { glClearDepthf(depth); } + static void setClearStencil(GLint stencil) { glClearStencil(stencil); } + static void clearColor() { glClear(GL_COLOR_BUFFER_BIT); } + static void clearDepth() { glClear(GL_DEPTH_BUFFER_BIT); } + static void clearStencil() { glClear(GL_STENCIL_BUFFER_BIT); } + static void clearColorAndDepth() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); } + static void clearColorAndStencil() { glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } + static void clearDepthAndStencil() { glClear(GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } + static void clearAll() { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); } - static void setViewport(GLsizei width, GLsizei height) { glViewport(0, 0, width, height); } - static void setViewport(GLsizei x, GLsizei y, GLsizei width, GLsizei height) { glViewport(x, y, width, height); } - static void setScissor(GLsizei width, GLsizei height) { glScissor(0, 0, width, height); } - static void setScissor(GLsizei x, GLsizei y, GLsizei width, GLsizei height) { glScissor(x, y, width, height); } - static void setStencilMask(GLuint mask) { glStencilMask(mask); } + static void setViewport(GLsizei width, GLsizei height) { glViewport(0, 0, width, height); } + static void setViewport(GLsizei x, GLsizei y, GLsizei width, GLsizei height) { glViewport(x, y, width, height); } + static void setScissor(GLsizei width, GLsizei height) { glScissor(0, 0, width, height); } + static void setScissor(GLsizei x, GLsizei y, GLsizei width, GLsizei height) { glScissor(x, y, width, height); } + static void setStencilMask(GLuint mask) { glStencilMask(mask); } - static void bindScreenFramebuffer() { glBindFramebuffer(GL_FRAMEBUFFER, 0); } - static void enableScissor() { glEnable(GL_SCISSOR_TEST); } - static void disableScissor() { glDisable(GL_SCISSOR_TEST); } - static void enableBlend() { glEnable(GL_BLEND); } - static void disableBlend() { glDisable(GL_BLEND); } + static void bindScreenFramebuffer() { glBindFramebuffer(GL_FRAMEBUFFER, 0); } + static void enableScissor() { glEnable(GL_SCISSOR_TEST); } + static void disableScissor() { glDisable(GL_SCISSOR_TEST); } + static void enableBlend() { glEnable(GL_BLEND); } + static void disableBlend() { glDisable(GL_BLEND); } static void enableLogicOp() { glEnable(GL_COLOR_LOGIC_OP); } static void disableLogicOp() { glDisable(GL_COLOR_LOGIC_OP); } - static void enableDepth() { glEnable(GL_DEPTH_TEST); } - static void disableDepth() { glDisable(GL_DEPTH_TEST); } - static void enableStencil() { glEnable(GL_STENCIL_TEST); } - static void disableStencil() { glDisable(GL_STENCIL_TEST); } + static void enableDepth() { glEnable(GL_DEPTH_TEST); } + static void disableDepth() { glDisable(GL_DEPTH_TEST); } + static void enableStencil() { glEnable(GL_STENCIL_TEST); } + static void disableStencil() { glDisable(GL_STENCIL_TEST); } - static void enableClipPlane(GLuint index) { glEnable(GL_CLIP_DISTANCE0 + index); } + static void enableClipPlane(GLuint index) { glEnable(GL_CLIP_DISTANCE0 + index); } static void disableClipPlane(GLuint index) { glDisable(GL_CLIP_DISTANCE0 + index); } - static void setDepthFunc(DepthFunc func) { glDepthFunc(static_cast(func)); } + static void setDepthFunc(DepthFunc func) { glDepthFunc(static_cast(func)); } static void setColourMask(GLboolean r, GLboolean g, GLboolean b, GLboolean a) { glColorMask(r, g, b, a); } static void setDepthMask(GLboolean mask) { glDepthMask(mask); } + // TODO: Add a proper enum for this + static void setLogicOp(GLenum op) { glLogicOp(op); } + enum Primitives { Triangle = GL_TRIANGLES, Triangles = Triangle, diff --git a/src/core/renderer_gl/gl_state.cpp b/src/core/renderer_gl/gl_state.cpp index 6d073128..4a512f44 100644 --- a/src/core/renderer_gl/gl_state.cpp +++ b/src/core/renderer_gl/gl_state.cpp @@ -3,9 +3,11 @@ void GLStateManager::resetBlend() { blendEnabled = false; logicOpEnabled = false; + logicOp = GL_COPY; OpenGL::disableBlend(); OpenGL::disableLogicOp(); + OpenGL::setLogicOp(GL_COPY); } void GLStateManager::resetClipping() { @@ -39,7 +41,10 @@ void GLStateManager::resetScissor() { void GLStateManager::resetStencil() { stencilEnabled = false; + stencilMask = 0xff; + OpenGL::disableStencil(); + OpenGL::setStencilMask(0xff); } void GLStateManager::resetVAO() { diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index ddbffd98..f140893d 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -184,7 +184,7 @@ void RendererGL::setupBlending() { if (!blendingEnabled) { // Logic ops are enabled const u32 logicOp = getBits<0, 4>(regs[PICA::InternalRegs::LogicOp]); - glLogicOp(logicOps[logicOp]); + gl.setLogicOp(logicOps[logicOp]); // If logic ops are enabled we don't need to disable blending because they override it gl.enableLogicOp(); @@ -243,7 +243,7 @@ void RendererGL::setupStencilTest(bool stencilEnable) { const u32 stencilBufferMask = stencilWrite ? getBits<8, 8>(stencilConfig) : 0; glStencilFunc(stencilFuncs[stencilFunc], reference, stencilRefMask); - glStencilMask(stencilBufferMask); + gl.setStencilMask(stencilBufferMask); static constexpr std::array stencilOps = { GL_KEEP, @@ -489,7 +489,7 @@ void RendererGL::clearBuffer(u32 startAddress, u32 endAddress, u32 value, u32 co if (format == DepthFmt::Depth24Stencil8) { const u8 stencil = (value >> 24); - OpenGL::setStencilMask(0xff); + gl.setStencilMask(0xff); OpenGL::setClearStencil(stencil); OpenGL::clearDepthAndStencil(); } else { From c7cad054e2b540a61c8ffe7d3cae2870851412be Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Fri, 28 Jul 2023 03:12:28 +0300 Subject: [PATCH 13/13] Update renderer_gl.cpp --- src/core/renderer_gl/renderer_gl.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/core/renderer_gl/renderer_gl.cpp b/src/core/renderer_gl/renderer_gl.cpp index f140893d..afe08b12 100644 --- a/src/core/renderer_gl/renderer_gl.cpp +++ b/src/core/renderer_gl/renderer_gl.cpp @@ -242,6 +242,7 @@ void RendererGL::setupStencilTest(bool stencilEnable) { const bool stencilWrite = regs[PICA::InternalRegs::DepthBufferWrite]; const u32 stencilBufferMask = stencilWrite ? getBits<8, 8>(stencilConfig) : 0; + // TODO: Throw stencilFunc/stencilOp to the GL state manager glStencilFunc(stencilFuncs[stencilFunc], reference, stencilRefMask); gl.setStencilMask(stencilBufferMask);