From 28be6cc4ccf4f7b9b56dda253d5b994bbe32a4a8 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 24 Aug 2018 20:53:40 -0700 Subject: [PATCH 1/4] Headless: Fix graphics compare tests. Shadowing. --- headless/SDLHeadlessHost.h | 1 - headless/WindowsHeadlessHost.h | 1 - 2 files changed, 2 deletions(-) diff --git a/headless/SDLHeadlessHost.h b/headless/SDLHeadlessHost.h index daa0fe0413..3907f3ab5e 100644 --- a/headless/SDLHeadlessHost.h +++ b/headless/SDLHeadlessHost.h @@ -49,7 +49,6 @@ protected: STOPPED, }; - GraphicsContext *gfx_; volatile RenderThreadState threadState_ = RenderThreadState::IDLE; }; diff --git a/headless/WindowsHeadlessHost.h b/headless/WindowsHeadlessHost.h index 853eee1eb5..907b20cdf6 100644 --- a/headless/WindowsHeadlessHost.h +++ b/headless/WindowsHeadlessHost.h @@ -53,6 +53,5 @@ protected: HWND hWnd; HDC hDC; HGLRC hRC; - GraphicsContext *gfx_; volatile RenderThreadState threadState_ = RenderThreadState::IDLE; }; From 44b90f638de21e39f6f4622dec88016bddc4e06b Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 24 Aug 2018 20:54:38 -0700 Subject: [PATCH 2/4] SoftGPU: Apply pixel mask for clears. Turns out it's respected even in clear mode. Also, confirm logic op and blending interact. --- GPU/Software/Rasterizer.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/GPU/Software/Rasterizer.cpp b/GPU/Software/Rasterizer.cpp index f6b6e398e7..ebed8f36de 100644 --- a/GPU/Software/Rasterizer.cpp +++ b/GPU/Software/Rasterizer.cpp @@ -972,7 +972,7 @@ inline void DrawSinglePixel(const DrawingCoords &p, u16 z, u8 fog, const Vec4 Date: Fri, 24 Aug 2018 21:05:27 -0700 Subject: [PATCH 3/4] GPU: Refactor logic op simulation for better reuse. --- GPU/Common/GPUStateUtils.cpp | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 824d3827b1..2b88905d30 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -813,17 +813,7 @@ static inline bool blendColorSimilar(uint32_t a, uint32_t b, int margin = 25) { } // Try to simulate some common logic ops. -void ApplyStencilReplaceAndLogicOp(ReplaceAlphaType replaceAlphaWithStencil, GenericBlendState &blendState) { - StencilValueType stencilType = STENCIL_VALUE_KEEP; - if (replaceAlphaWithStencil == REPLACE_ALPHA_YES) { - stencilType = ReplaceAlphaWithStencilType(); - } - - // Normally, we would add src + 0, but the logic op may have us do differently. - BlendFactor srcBlend = BlendFactor::ONE; - BlendFactor dstBlend = BlendFactor::ZERO; - BlendEq blendEq = BlendEq::ADD; - +static void ApplyLogicOp(BlendFactor &srcBlend, BlendFactor &dstBlend, BlendEq &blendEq) { if (!gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { if (gstate.isLogicOpEnabled()) { switch (gstate.getLogicOp()) { @@ -876,8 +866,22 @@ void ApplyStencilReplaceAndLogicOp(ReplaceAlphaType replaceAlphaWithStencil, Gen } } } +} - // We're not blending, but we may still want to blend for stencil. +// Try to simulate some common logic ops. +void ApplyStencilReplaceAndLogicOp(ReplaceAlphaType replaceAlphaWithStencil, GenericBlendState &blendState) { + StencilValueType stencilType = STENCIL_VALUE_KEEP; + if (replaceAlphaWithStencil == REPLACE_ALPHA_YES) { + stencilType = ReplaceAlphaWithStencilType(); + } + + // Normally, we would add src + 0 with blending off, but the logic op may have us do differently. + BlendFactor srcBlend = BlendFactor::ONE; + BlendFactor dstBlend = BlendFactor::ZERO; + BlendEq blendEq = BlendEq::ADD; + ApplyLogicOp(srcBlend, dstBlend, blendEq); + + // We're not blending, but we may still want to "blend" for stencil. // This is only useful for INCR/DECR/INVERT. Others can write directly. switch (stencilType) { case STENCIL_VALUE_INCR_4: From 5c01bf61e6203d60237b0739221303712f777bb1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Fri, 24 Aug 2018 21:19:54 -0700 Subject: [PATCH 4/4] GPU: Apply logic op in more cases. It has well defined behavior with alpha blending, so let's apply it even when we're blending. Fixes #11316. --- GPU/Common/GPUStateUtils.cpp | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 2b88905d30..2e952270c3 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -814,11 +814,15 @@ static inline bool blendColorSimilar(uint32_t a, uint32_t b, int margin = 25) { // Try to simulate some common logic ops. static void ApplyLogicOp(BlendFactor &srcBlend, BlendFactor &dstBlend, BlendEq &blendEq) { + // Note: our shader solution applies logic ops BEFORE blending, not correctly after. + // This is however fine for the most common ones, like CLEAR/NOOP/SET, etc. if (!gstate_c.Supports(GPU_SUPPORTS_LOGIC_OP)) { if (gstate.isLogicOpEnabled()) { switch (gstate.getLogicOp()) { case GE_LOGIC_CLEAR: srcBlend = BlendFactor::ZERO; + dstBlend = BlendFactor::ZERO; + blendEq = BlendEq::ADD; break; case GE_LOGIC_AND: case GE_LOGIC_AND_REVERSE: @@ -846,6 +850,7 @@ static void ApplyLogicOp(BlendFactor &srcBlend, BlendFactor &dstBlend, BlendEq & case GE_LOGIC_NOOP: srcBlend = BlendFactor::ZERO; dstBlend = BlendFactor::ONE; + blendEq = BlendEq::ADD; break; case GE_LOGIC_XOR: WARN_LOG_REPORT_ONCE(d3dLogicOpOrXor, G3D, "Unsupported XOR logic op: %x", gstate.getLogicOp()); @@ -860,7 +865,9 @@ static void ApplyLogicOp(BlendFactor &srcBlend, BlendFactor &dstBlend, BlendEq & WARN_LOG_REPORT_ONCE(d3dLogicOpOrReverse, G3D, "Unsupported OR REVERSE logic op: %x", gstate.getLogicOp()); break; case GE_LOGIC_SET: + srcBlend = BlendFactor::ONE; dstBlend = BlendFactor::ONE; + blendEq = BlendEq::ADD; WARN_LOG_REPORT_ONCE(d3dLogicOpSet, G3D, "Attempted set for logic op: %x", gstate.getLogicOp()); break; } @@ -1109,6 +1116,15 @@ void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) { #endif // At this point, through all paths above, glBlendFuncA and glBlendFuncB will be set right somehow. + BlendEq colorEq; + if (gstate_c.Supports(GPU_SUPPORTS_BLEND_MINMAX)) { + colorEq = eqLookup[blendFuncEq]; + } else { + colorEq = eqLookupNoMinMax[blendFuncEq]; + } + + // Attempt to apply the logic op, if any. + ApplyLogicOp(glBlendFuncA, glBlendFuncB, colorEq); // The stencil-to-alpha in fragment shader doesn't apply here (blending is enabled), and we shouldn't // do any blending in the alpha channel as that doesn't seem to happen on PSP. So, we attempt to @@ -1178,11 +1194,7 @@ void ConvertBlendState(GenericBlendState &blendState, bool allowShaderBlend) { blendState.setFactors(glBlendFuncA, glBlendFuncB, BlendFactor::ZERO, BlendFactor::ONE); } - if (gstate_c.Supports(GPU_SUPPORTS_BLEND_MINMAX)) { - blendState.setEquation(eqLookup[blendFuncEq], alphaEq); - } else { - blendState.setEquation(eqLookupNoMinMax[blendFuncEq], alphaEq); - } + blendState.setEquation(colorEq, alphaEq); } static void ConvertStencilFunc5551(GenericStencilFuncState &state) {