Permalink
Browse files

GPU: Clamp after color doubling.

This is needed for blending to be correct - it blends a clamped value.
  • Loading branch information...
unknownbrackets committed Sep 10, 2018
1 parent 7031816 commit 8eb011c22d8917ca8e726cbf29c4fa954e412fc1
@@ -306,7 +306,7 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
if (enableColorTest) {
// Color doubling happens before the color test, but we try to optimize doubling when test is off.
if (enableColorDoubling) {
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
}
if (colorTestAgainstZero) {
@@ -327,14 +327,14 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
if (colorTestFuncs[colorTestFunc][0] != '#') {
const char *test = colorTestFuncs[colorTestFunc];
if (lang == HLSL_D3D11) {
WRITE(p, " uint3 v_scaled = roundAndScaleTo255iv(clamp(v.rgb, 0.0, 1.0));\n");
WRITE(p, " uint3 v_scaled = roundAndScaleTo255iv(v.rgb);\n");
WRITE(p, " uint3 v_masked = v_scaled & u_alphacolormask.rgb;\n");
WRITE(p, " uint3 colorTestRef = u_alphacolorref.rgb & u_alphacolormask.rgb;\n");
// We have to test the components separately, or we get incorrect results. See #10629.
WRITE(p, " if (v_masked.r %s colorTestRef.r && v_masked.g %s colorTestRef.g && v_masked.b %s colorTestRef.b) discard;\n", test, test, test);
} else {
// TODO: Use a texture to lookup bitwise ops instead?
WRITE(p, " float3 colortest = roundAndScaleTo255v(clamp(v.rgb, 0.0, 1.0));\n");
WRITE(p, " float3 colortest = roundAndScaleTo255v(v.rgb);\n");
WRITE(p, " if ((colortest.r %s u_alphacolorref.r) && (colortest.g %s u_alphacolorref.g) && (colortest.b %s u_alphacolorref.b)) clip(-1);\n", test, test, test);
}
}
@@ -349,8 +349,10 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
} else {
// If there's no color test, we can potentially double and replace blend at once.
if (enableColorDoubling && replaceBlend == REPLACE_BLEND_2X_SRC) {
WRITE(p, " v.rgb = v.rgb * 4.0;\n");
} else if (enableColorDoubling || replaceBlend == REPLACE_BLEND_2X_SRC) {
WRITE(p, " v.rgb = clamp(v.rgb * 4.0, 0.0, 2.0);\n");
} else if (enableColorDoubling) {
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
} else if (replaceBlend == REPLACE_BLEND_2X_SRC) {
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
}
}
@@ -560,7 +560,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, uint64_t *uniform
if (enableColorTest) {
// Color doubling happens before the color test, but we try to optimize doubling when test is off.
if (enableColorDoubling) {
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
if (g_Config.bFragmentTestCache && !colorTestAgainstZero) {
WRITE(p, " vScale256.rgb = vScale256.rgb * 2.0;\n");
}
@@ -595,7 +595,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, uint64_t *uniform
if (colorTestFuncs[colorTestFunc][0] != '#') {
if (bitwiseOps) {
// Apparently GLES3 does not support vector bitwise ops.
WRITE(p, " ivec3 v_scaled = roundAndScaleTo255iv(clamp(v.rgb, 0.0, 1.0));\n");
WRITE(p, " ivec3 v_scaled = roundAndScaleTo255iv(v.rgb);\n");
const char *maskedFragColor = "ivec3(v_scaled.r & u_alphacolormask.r, v_scaled.g & u_alphacolormask.g, v_scaled.b & u_alphacolormask.b)";
const char *maskedColorRef = "ivec3(int(u_alphacolorref.r) & u_alphacolormask.r, int(u_alphacolorref.g) & u_alphacolormask.g, int(u_alphacolorref.b) & u_alphacolormask.b)";
WRITE(p, " if (%s %s %s) %s\n", maskedFragColor, colorTestFuncs[colorTestFunc], maskedColorRef, discardStatement);
@@ -615,8 +615,10 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, uint64_t *uniform
} else {
// If there's no color test, we can potentially double and replace blend at once.
if (enableColorDoubling && replaceBlend == REPLACE_BLEND_2X_SRC) {
WRITE(p, " v.rgb = v.rgb * 4.0;\n");
} else if (enableColorDoubling || replaceBlend == REPLACE_BLEND_2X_SRC) {
WRITE(p, " v.rgb = clamp(v.rgb * 4.0, 0.0, 2.0);\n");
} else if (enableColorDoubling) {
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
} else if (replaceBlend == REPLACE_BLEND_2X_SRC) {
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
}
}
@@ -377,7 +377,7 @@ bool GenerateVulkanGLSLFragmentShader(const FShaderID &id, char *buffer) {
if (enableColorTest) {
// Color doubling happens before the color test, but we try to optimize doubling when test is off.
if (enableColorDoubling) {
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
}
if (colorTestAgainstZero) {
@@ -397,7 +397,7 @@ bool GenerateVulkanGLSLFragmentShader(const FShaderID &id, char *buffer) {
} else {
const char *colorTestFuncs[] = { "#", "#", " != ", " == " };
if (colorTestFuncs[colorTestFunc][0] != '#') {
WRITE(p, " ivec3 v_scaled = roundAndScaleTo255iv(clamp(v.rgb, 0.0, 1.0));\n");
WRITE(p, " ivec3 v_scaled = roundAndScaleTo255iv(v.rgb);\n");
WRITE(p, " if ((v_scaled & base.alphacolormask.rgb) %s (base.alphacolorref.rgb & base.alphacolormask.rgb)) %s\n", colorTestFuncs[colorTestFunc], discardStatement);
} else {
WRITE(p, " %s\n", discardStatement);
@@ -410,8 +410,10 @@ bool GenerateVulkanGLSLFragmentShader(const FShaderID &id, char *buffer) {
} else {
// If there's no color test, we can potentially double and replace blend at once.
if (enableColorDoubling && replaceBlend == REPLACE_BLEND_2X_SRC) {
WRITE(p, " v.rgb = v.rgb * 4.0;\n");
} else if (enableColorDoubling || replaceBlend == REPLACE_BLEND_2X_SRC) {
WRITE(p, " v.rgb = clamp(v.rgb * 4.0, 0.0, 2.0);\n");
} else if (enableColorDoubling) {
WRITE(p, " v.rgb = clamp(v.rgb * 2.0, 0.0, 1.0);\n");
} else if (replaceBlend == REPLACE_BLEND_2X_SRC) {
WRITE(p, " v.rgb = v.rgb * 2.0;\n");
}
}

0 comments on commit 8eb011c

Please sign in to comment.