diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index a29c987c11..93385d8aa3 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -125,6 +125,33 @@ static bool IsReallyAClear(const TransformedVertex *transformed, int numVerts, f return true; } +static int ColorIndexOffset(int prim, GEShadeMode shadeMode, bool clearMode) { + if (shadeMode != GE_SHADE_FLAT || clearMode) { + return 0; + } + + switch (prim) { + case GE_PRIM_LINES: + case GE_PRIM_LINE_STRIP: + return 1; + + case GE_PRIM_TRIANGLES: + case GE_PRIM_TRIANGLE_STRIP: + return 2; + + case GE_PRIM_TRIANGLE_FAN: + return 1; + + case GE_PRIM_RECTANGLES: + // We already use BR color when expanding, so no need to offset. + return 0; + + default: + break; + } + return 0; +} + void SoftwareTransform( int prim, int vertexCount, u32 vertType, u16 *&inds, int indexType, const DecVtxFormat &decVtxFormat, int &maxIndex, TransformedVertex *&drawBuffer, int &numTrans, bool &drawIndexed, const SoftwareTransformParams *params, SoftwareTransformResult *result) { @@ -168,6 +195,11 @@ void SoftwareTransform( fog_slope = 1.0f; } + int colorIndOffset = 0; + if (params->provokeFlatFirst) { + colorIndOffset = ColorIndexOffset(prim, gstate.getShadeMode(), gstate.isModeClear()); + } + VertexReader reader(decoded, decVtxFormat, vertType); if (throughmode) { for (int index = 0; index < maxIndex; index++) { @@ -178,7 +210,13 @@ void SoftwareTransform( reader.ReadPos(vert.pos); if (reader.hasColor0()) { - reader.ReadColor0_8888(vert.color0); + if (colorIndOffset != 0 && index + colorIndOffset < maxIndex) { + reader.Goto(index + colorIndOffset); + reader.ReadColor0_8888(vert.color0); + reader.Goto(index); + } else { + reader.ReadColor0_8888(vert.color0); + } } else { vert.color0_32 = gstate.getMaterialAmbientRGBA(); } @@ -260,7 +298,13 @@ void SoftwareTransform( // Perform lighting here if enabled. don't need to check through, it's checked above. Vec4f unlitColor = Vec4f(1, 1, 1, 1); if (reader.hasColor0()) { - reader.ReadColor0(&unlitColor.x); + if (colorIndOffset != 0 && index + colorIndOffset < maxIndex) { + reader.Goto(index + colorIndOffset); + reader.ReadColor0(&unlitColor.x); + reader.Goto(index); + } else { + reader.ReadColor0(&unlitColor.x); + } } else { unlitColor = Vec4f::FromRGBA(gstate.getMaterialAmbientRGBA()); } diff --git a/GPU/Common/SoftwareTransformCommon.h b/GPU/Common/SoftwareTransformCommon.h index 9bc2e4da49..a7efc396c9 100644 --- a/GPU/Common/SoftwareTransformCommon.h +++ b/GPU/Common/SoftwareTransformCommon.h @@ -46,6 +46,7 @@ struct SoftwareTransformParams { TextureCacheCommon *texCache; bool allowClear; bool allowSeparateAlphaClear; + bool provokeFlatFirst; }; void SoftwareTransform(int prim, int vertexCount, u32 vertexType, u16 *&inds, int indexType, const DecVtxFormat &decVtxFormat, int &maxIndex, TransformedVertex *&drawBuffer, diff --git a/GPU/D3D11/DrawEngineD3D11.cpp b/GPU/D3D11/DrawEngineD3D11.cpp index 2b49ae2d6e..4651c38290 100644 --- a/GPU/D3D11/DrawEngineD3D11.cpp +++ b/GPU/D3D11/DrawEngineD3D11.cpp @@ -587,6 +587,7 @@ rotateVBO: params.texCache = textureCache_; params.allowClear = true; params.allowSeparateAlphaClear = false; // D3D11 doesn't support separate alpha clears + params.provokeFlatFirst = true; int maxIndex = indexGen.MaxIndex(); SoftwareTransform( diff --git a/GPU/Directx9/DrawEngineDX9.cpp b/GPU/Directx9/DrawEngineDX9.cpp index c72d256727..de1a85d093 100644 --- a/GPU/Directx9/DrawEngineDX9.cpp +++ b/GPU/Directx9/DrawEngineDX9.cpp @@ -545,6 +545,7 @@ rotateVBO: params.texCache = textureCache_; params.allowClear = true; params.allowSeparateAlphaClear = true; + params.provokeFlatFirst = true; int maxIndex = indexGen.MaxIndex(); SoftwareTransform( diff --git a/GPU/GLES/DrawEngineGLES.cpp b/GPU/GLES/DrawEngineGLES.cpp index d79ee4efd4..79589a113b 100644 --- a/GPU/GLES/DrawEngineGLES.cpp +++ b/GPU/GLES/DrawEngineGLES.cpp @@ -553,6 +553,7 @@ rotateVBO: params.texCache = textureCache_; params.allowClear = true; params.allowSeparateAlphaClear = true; + params.provokeFlatFirst = false; int maxIndex = indexGen.MaxIndex(); int vertexCount = indexGen.VertexCount(); diff --git a/GPU/Vulkan/DrawEngineVulkan.cpp b/GPU/Vulkan/DrawEngineVulkan.cpp index 76643d6066..f68f989e7f 100644 --- a/GPU/Vulkan/DrawEngineVulkan.cpp +++ b/GPU/Vulkan/DrawEngineVulkan.cpp @@ -860,6 +860,7 @@ void DrawEngineVulkan::DoFlush() { // do not respect scissor rects. params.allowClear = g_Config.iRenderingMode != 0; params.allowSeparateAlphaClear = false; + params.provokeFlatFirst = true; int maxIndex = indexGen.MaxIndex(); SoftwareTransform(