mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Prepare for more GLSL testing
This commit is contained in:
parent
3d36049b65
commit
2c0a3c2e23
5 changed files with 142 additions and 117 deletions
|
@ -137,3 +137,15 @@ enum DoLightComputation {
|
|||
LIGHT_SHADE,
|
||||
LIGHT_FULL,
|
||||
};
|
||||
|
||||
struct GLSLShaderCompat {
|
||||
const char *varying;
|
||||
const char *attribute;
|
||||
const char *fragColor0;
|
||||
const char *fragColor1;
|
||||
const char *texture;
|
||||
const char *texelFetch;
|
||||
const char *lastFragData;
|
||||
bool glslES30;
|
||||
bool bitwiseOps;
|
||||
};
|
||||
|
|
|
@ -66,6 +66,21 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
|
|||
|
||||
StencilValueType replaceAlphaWithStencilType = (StencilValueType)id.Bits(FS_BIT_REPLACE_ALPHA_WITH_STENCIL_TYPE, 4);
|
||||
|
||||
// Output some compatibility defines
|
||||
switch (lang) {
|
||||
case ShaderLanguage::HLSL_DX9:
|
||||
WRITE(p, "#define DISCARD clip(-1)\n");
|
||||
break;
|
||||
case ShaderLanguage::HLSL_D3D11:
|
||||
case ShaderLanguage::HLSL_D3D11_LEVEL9:
|
||||
WRITE(p, "#define DISCARD discard\n");
|
||||
break;
|
||||
}
|
||||
WRITE(p, "#define vec2 float2\n");
|
||||
WRITE(p, "#define vec3 float3\n");
|
||||
WRITE(p, "#define vec4 float4\n");
|
||||
WRITE(p, "#define splat3(x) float3(x, x, x)\n");
|
||||
|
||||
if (lang == HLSL_DX9) {
|
||||
if (doTexture)
|
||||
WRITE(p, "sampler tex : register(s0);\n");
|
||||
|
@ -288,7 +303,7 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
|
|||
} else {
|
||||
// NEVER has been logged as used by games, although it makes little sense - statically failing.
|
||||
// Maybe we could discard the drawcall, but it's pretty rare. Let's just statically discard here.
|
||||
WRITE(p, " clip(-1);\n");
|
||||
WRITE(p, " DISCARD;\n");
|
||||
}
|
||||
} else {
|
||||
const char *alphaTestFuncs[] = { "#", "#", " != ", " == ", " >= ", " > ", " <= ", " < " }; // never/always don't make sense
|
||||
|
@ -298,11 +313,11 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
|
|||
WRITE(p, " if ((roundAndScaleTo255i(v.a) & u_alphacolormask.a) %s u_alphacolorref.a) discard;\n", alphaTestFuncs[alphaTestFunc]);
|
||||
} else {
|
||||
// TODO: Use a texture to lookup bitwise ops?
|
||||
WRITE(p, " if (roundAndScaleTo255f(v.a) %s u_alphacolorref.a) clip(-1);\n", alphaTestFuncs[alphaTestFunc]);
|
||||
WRITE(p, " if (roundAndScaleTo255f(v.a) %s u_alphacolorref.a) DISCARD;\n", alphaTestFuncs[alphaTestFunc]);
|
||||
}
|
||||
} else {
|
||||
// This means NEVER. See above.
|
||||
WRITE(p, lang == HLSL_DX9 ? " clip(-1);\n" : " discard;\n");
|
||||
WRITE(p, " DISCARD;\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -317,14 +332,14 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
|
|||
// When testing against 0 (common), we can avoid some math.
|
||||
// 0.002 is approximately half of 1.0 / 255.0.
|
||||
if (colorTestFunc == GE_COMP_NOTEQUAL) {
|
||||
WRITE(p, " if (v.r < 0.002 && v.g < 0.002 && v.b < 0.002) clip(-1);\n");
|
||||
WRITE(p, " if (v.r < 0.002 && v.g < 0.002 && v.b < 0.002) DISCARD;\n");
|
||||
} else if (colorTestFunc != GE_COMP_NEVER) {
|
||||
// Anything else is a test for == 0.
|
||||
WRITE(p, " if (v.r > 0.002 || v.g > 0.002 || v.b > 0.002) clip(-1);\n");
|
||||
WRITE(p, " if (v.r > 0.002 || v.g > 0.002 || v.b > 0.002) DISCARD;\n");
|
||||
} else {
|
||||
// NEVER has been logged as used by games, although it makes little sense - statically failing.
|
||||
// Maybe we could discard the drawcall, but it's pretty rare. Let's just statically discard here.
|
||||
WRITE(p, lang == HLSL_DX9 ? " clip(-1);\n" : " discard;\n");
|
||||
WRITE(p, " DISCARD;\n");
|
||||
}
|
||||
} else {
|
||||
const char *colorTestFuncs[] = { "#", "#", " != ", " == " }; // never/always don't make sense
|
||||
|
@ -335,15 +350,15 @@ bool GenerateFragmentShaderHLSL(const FShaderID &id, char *buffer, ShaderLanguag
|
|||
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);
|
||||
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(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);
|
||||
WRITE(p, " if ((colortest.r %s u_alphacolorref.r) && (colortest.g %s u_alphacolorref.g) && (colortest.b %s u_alphacolorref.b)) DISCARD;\n", test, test, test);
|
||||
}
|
||||
}
|
||||
else {
|
||||
WRITE(p, lang == HLSL_DX9 ? " clip(-1);\n" : " discard;\n");
|
||||
WRITE(p, " DISCARD;\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -95,6 +95,12 @@ bool GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage
|
|||
numBoneWeights = 1 + id.Bits(VS_BIT_BONES, 3);
|
||||
}
|
||||
|
||||
// Output some compatibility defines
|
||||
WRITE(p, "#define vec2 float2\n");
|
||||
WRITE(p, "#define vec3 float3\n");
|
||||
WRITE(p, "#define vec4 float4\n");
|
||||
WRITE(p, "#define splat3(x) float3(x, x, x)\n");
|
||||
|
||||
if (lang == HLSL_DX9) {
|
||||
WRITE(p, "#pragma warning( disable : 3571 )\n");
|
||||
if (isModeThrough) {
|
||||
|
|
|
@ -42,16 +42,16 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
*uniformMask = 0;
|
||||
// In GLSL ES 3.0, you use "in" variables instead of varying.
|
||||
|
||||
bool glslES30 = false;
|
||||
const char *varying = "varying";
|
||||
const char *fragColor0 = "gl_FragColor";
|
||||
const char *fragColor1 = "fragColor1";
|
||||
const char *texture = "texture2D";
|
||||
const char *texelFetch = NULL;
|
||||
GLSLShaderCompat compat{};
|
||||
compat.varying = "varying";
|
||||
compat.fragColor0 = "gl_FragColor";
|
||||
compat.fragColor1 = "fragColor1";
|
||||
compat.texture = "texture2D";
|
||||
compat.texelFetch = NULL;
|
||||
compat.bitwiseOps = false;
|
||||
compat.lastFragData = nullptr;
|
||||
bool highpFog = false;
|
||||
bool highpTexcoord = false;
|
||||
bool bitwiseOps = false;
|
||||
const char *lastFragData = nullptr;
|
||||
|
||||
ReplaceAlphaType stencilToAlpha = static_cast<ReplaceAlphaType>(id.Bits(FS_BIT_STENCIL_TO_ALPHA, 2));
|
||||
|
||||
|
@ -59,11 +59,11 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
// ES doesn't support dual source alpha :(
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300)) {
|
||||
WRITE(p, "#version 300 es\n"); // GLSL ES 3.0
|
||||
fragColor0 = "fragColor0";
|
||||
texture = "texture";
|
||||
glslES30 = true;
|
||||
bitwiseOps = true;
|
||||
texelFetch = "texelFetch";
|
||||
compat.fragColor0 = "fragColor0";
|
||||
compat.texture = "texture";
|
||||
compat.glslES30 = true;
|
||||
compat.bitwiseOps = true;
|
||||
compat.texelFetch = "texelFetch";
|
||||
|
||||
if (stencilToAlpha == REPLACE_ALPHA_DUALSOURCE && gl_extensions.EXT_blend_func_extended) {
|
||||
WRITE(p, "#extension GL_EXT_blend_func_extended : require\n");
|
||||
|
@ -72,12 +72,12 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
WRITE(p, "#version 100\n"); // GLSL ES 1.0
|
||||
if (gl_extensions.EXT_gpu_shader4) {
|
||||
WRITE(p, "#extension GL_EXT_gpu_shader4 : enable\n");
|
||||
bitwiseOps = true;
|
||||
texelFetch = "texelFetch2D";
|
||||
compat.bitwiseOps = true;
|
||||
compat.texelFetch = "texelFetch2D";
|
||||
}
|
||||
if (gl_extensions.EXT_blend_func_extended) {
|
||||
// Oldy moldy GLES, so use the fixed output name.
|
||||
fragColor1 = "gl_SecondaryFragColorEXT";
|
||||
compat.fragColor1 = "gl_SecondaryFragColorEXT";
|
||||
|
||||
if (stencilToAlpha == REPLACE_ALPHA_DUALSOURCE && gl_extensions.EXT_blend_func_extended) {
|
||||
WRITE(p, "#extension GL_EXT_blend_func_extended : require\n");
|
||||
|
@ -93,17 +93,17 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)) {
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300) && gl_extensions.EXT_shader_framebuffer_fetch) {
|
||||
WRITE(p, "#extension GL_EXT_shader_framebuffer_fetch : require\n");
|
||||
lastFragData = "fragColor0";
|
||||
compat.lastFragData = "fragColor0";
|
||||
} else if (gl_extensions.EXT_shader_framebuffer_fetch) {
|
||||
WRITE(p, "#extension GL_EXT_shader_framebuffer_fetch : require\n");
|
||||
lastFragData = "gl_LastFragData[0]";
|
||||
compat.lastFragData = "gl_LastFragData[0]";
|
||||
} else if (gl_extensions.NV_shader_framebuffer_fetch) {
|
||||
// GL_NV_shader_framebuffer_fetch is available on mobile platform and ES 2.0 only but not on desktop.
|
||||
WRITE(p, "#extension GL_NV_shader_framebuffer_fetch : require\n");
|
||||
lastFragData = "gl_LastFragData[0]";
|
||||
compat.lastFragData = "gl_LastFragData[0]";
|
||||
} else if (gl_extensions.ARM_shader_framebuffer_fetch) {
|
||||
WRITE(p, "#extension GL_ARM_shader_framebuffer_fetch : require\n");
|
||||
lastFragData = "gl_LastFragColorARM";
|
||||
compat.lastFragData = "gl_LastFragColorARM";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,16 +111,16 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
} else {
|
||||
if (!gl_extensions.ForceGL2 || gl_extensions.IsCoreContext) {
|
||||
if (gl_extensions.VersionGEThan(3, 3, 0)) {
|
||||
fragColor0 = "fragColor0";
|
||||
texture = "texture";
|
||||
glslES30 = true;
|
||||
bitwiseOps = true;
|
||||
texelFetch = "texelFetch";
|
||||
compat.fragColor0 = "fragColor0";
|
||||
compat.texture = "texture";
|
||||
compat.glslES30 = true;
|
||||
compat.bitwiseOps = true;
|
||||
compat.texelFetch = "texelFetch";
|
||||
WRITE(p, "#version 330\n");
|
||||
} else if (gl_extensions.VersionGEThan(3, 0, 0)) {
|
||||
fragColor0 = "fragColor0";
|
||||
bitwiseOps = true;
|
||||
texelFetch = "texelFetch";
|
||||
compat.fragColor0 = "fragColor0";
|
||||
compat.bitwiseOps = true;
|
||||
compat.texelFetch = "texelFetch";
|
||||
WRITE(p, "#version 130\n");
|
||||
if (gl_extensions.EXT_gpu_shader4) {
|
||||
WRITE(p, "#extension GL_EXT_gpu_shader4 : enable\n");
|
||||
|
@ -129,8 +129,8 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
WRITE(p, "#version 110\n");
|
||||
if (gl_extensions.EXT_gpu_shader4) {
|
||||
WRITE(p, "#extension GL_EXT_gpu_shader4 : enable\n");
|
||||
bitwiseOps = true;
|
||||
texelFetch = "texelFetch2D";
|
||||
compat.bitwiseOps = true;
|
||||
compat.texelFetch = "texelFetch2D";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,8 +141,8 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
WRITE(p, "#define highp\n");
|
||||
}
|
||||
|
||||
if (glslES30 || gl_extensions.IsCoreContext) {
|
||||
varying = "in";
|
||||
if (compat.glslES30 || gl_extensions.IsCoreContext) {
|
||||
compat.varying = "in";
|
||||
}
|
||||
|
||||
bool lmode = id.Bit(FS_BIT_LMODE);
|
||||
|
@ -180,7 +180,7 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
}
|
||||
|
||||
const char *shading = "";
|
||||
if (glslES30)
|
||||
if (compat.glslES30)
|
||||
shading = doFlatShading ? "flat" : "";
|
||||
|
||||
if (doTexture)
|
||||
|
@ -189,7 +189,7 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
if (!isModeClear && replaceBlend > REPLACE_BLEND_STANDARD) {
|
||||
*uniformMask |= DIRTY_SHADERBLEND;
|
||||
if (!gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH) && replaceBlend == REPLACE_BLEND_COPY_FBO) {
|
||||
if (!texelFetch) {
|
||||
if (!compat.texelFetch) {
|
||||
WRITE(p, "uniform vec2 u_fbotexSize;\n");
|
||||
}
|
||||
WRITE(p, "uniform sampler2D fbotex;\n");
|
||||
|
@ -216,7 +216,7 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
} else {
|
||||
*uniformMask |= DIRTY_ALPHACOLORREF;
|
||||
WRITE(p, "uniform vec4 u_alphacolorref;\n");
|
||||
if (bitwiseOps && ((enableColorTest && !colorTestAgainstZero) || (enableAlphaTest && !alphaTestAgainstZero))) {
|
||||
if (compat.bitwiseOps && ((enableColorTest && !colorTestAgainstZero) || (enableAlphaTest && !alphaTestAgainstZero))) {
|
||||
*uniformMask |= DIRTY_ALPHACOLORMASK;
|
||||
WRITE(p, "uniform ivec4 u_alphacolormask;\n");
|
||||
}
|
||||
|
@ -239,21 +239,21 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
WRITE(p, "uniform vec3 u_texenv;\n");
|
||||
}
|
||||
|
||||
WRITE(p, "%s %s vec4 v_color0;\n", shading, varying);
|
||||
WRITE(p, "%s %s vec4 v_color0;\n", shading, compat.varying);
|
||||
if (lmode)
|
||||
WRITE(p, "%s %s vec3 v_color1;\n", shading, varying);
|
||||
WRITE(p, "%s %s vec3 v_color1;\n", shading, compat.varying);
|
||||
if (enableFog) {
|
||||
*uniformMask |= DIRTY_FOGCOLOR;
|
||||
WRITE(p, "uniform vec3 u_fogcolor;\n");
|
||||
WRITE(p, "%s %s float v_fogdepth;\n", varying, highpFog ? "highp" : "mediump");
|
||||
WRITE(p, "%s %s float v_fogdepth;\n", compat.varying, highpFog ? "highp" : "mediump");
|
||||
}
|
||||
if (doTexture) {
|
||||
WRITE(p, "%s %s vec3 v_texcoord;\n", varying, highpTexcoord ? "highp" : "mediump");
|
||||
WRITE(p, "%s %s vec3 v_texcoord;\n", compat.varying, highpTexcoord ? "highp" : "mediump");
|
||||
}
|
||||
|
||||
if (!g_Config.bFragmentTestCache) {
|
||||
if (enableAlphaTest && !alphaTestAgainstZero) {
|
||||
if (bitwiseOps) {
|
||||
if (compat.bitwiseOps) {
|
||||
WRITE(p, "int roundAndScaleTo255i(in float x) { return int(floor(x * 255.0 + 0.5)); }\n");
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) {
|
||||
WRITE(p, "float roundTo255thf(in mediump float x) { mediump float y = x + (0.5/255.0); return y - fract(y * 255.0) * (1.0 / 255.0); }\n");
|
||||
|
@ -262,7 +262,7 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
}
|
||||
}
|
||||
if (enableColorTest && !colorTestAgainstZero) {
|
||||
if (bitwiseOps) {
|
||||
if (compat.bitwiseOps) {
|
||||
WRITE(p, "ivec3 roundAndScaleTo255iv(in vec3 x) { return ivec3(floor(x * 255.0 + 0.5)); }\n");
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) {
|
||||
WRITE(p, "vec3 roundTo255thv(in vec3 x) { vec3 y = x + (0.5/255.0); return y - fract(y * 255.0) * (1.0 / 255.0); }\n");
|
||||
|
@ -272,9 +272,9 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
}
|
||||
}
|
||||
|
||||
if (!strcmp(fragColor0, "fragColor0")) {
|
||||
if (!strcmp(compat.fragColor0, "fragColor0")) {
|
||||
const char *qualifierColor0 = "out";
|
||||
if (lastFragData && !strcmp(lastFragData, fragColor0)) {
|
||||
if (compat.lastFragData && !strcmp(compat.lastFragData, compat.fragColor0)) {
|
||||
qualifierColor0 = "inout";
|
||||
}
|
||||
// Output the output color definitions.
|
||||
|
@ -353,9 +353,9 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
|
||||
if (!shaderDepal) {
|
||||
if (doTextureProjection) {
|
||||
WRITE(p, " vec4 t = %sProj(tex, %s);\n", texture, texcoord);
|
||||
WRITE(p, " vec4 t = %sProj(tex, %s);\n", compat.texture, texcoord);
|
||||
} else {
|
||||
WRITE(p, " vec4 t = %s(tex, %s.xy);\n", texture, texcoord);
|
||||
WRITE(p, " vec4 t = %s(tex, %s.xy);\n", compat.texture, texcoord);
|
||||
}
|
||||
} else {
|
||||
if (doTextureProjection) {
|
||||
|
@ -375,10 +375,10 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
WRITE(p, " } else {\n");
|
||||
WRITE(p, " uv_round = uv;\n");
|
||||
WRITE(p, " }\n");
|
||||
WRITE(p, " vec4 t = %s(tex, uv_round);\n", texture);
|
||||
WRITE(p, " vec4 t1 = %sOffset(tex, uv_round, ivec2(1, 0));\n", texture);
|
||||
WRITE(p, " vec4 t2 = %sOffset(tex, uv_round, ivec2(0, 1));\n", texture);
|
||||
WRITE(p, " vec4 t3 = %sOffset(tex, uv_round, ivec2(1, 1));\n", texture);
|
||||
WRITE(p, " vec4 t = %s(tex, uv_round);\n", compat.texture);
|
||||
WRITE(p, " vec4 t1 = %sOffset(tex, uv_round, ivec2(1, 0));\n", compat.texture);
|
||||
WRITE(p, " vec4 t2 = %sOffset(tex, uv_round, ivec2(0, 1));\n", compat.texture);
|
||||
WRITE(p, " vec4 t3 = %sOffset(tex, uv_round, ivec2(1, 1));\n", compat.texture);
|
||||
WRITE(p, " int depalMask = (u_depal & 0xFF);\n");
|
||||
WRITE(p, " int depalShift = ((u_depal >> 8) & 0xFF);\n");
|
||||
WRITE(p, " int depalOffset = (((u_depal >> 16) & 0xFF) << 4);\n");
|
||||
|
@ -552,12 +552,12 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
WRITE(p, " %s\n", discardStatement);
|
||||
}
|
||||
} else if (g_Config.bFragmentTestCache) {
|
||||
WRITE(p, " float aResult = %s(testtex, vec2(%s, 0)).a;\n", texture, alphaTestXCoord.c_str());
|
||||
WRITE(p, " float aResult = %s(testtex, vec2(%s, 0)).a;\n", compat.texture, alphaTestXCoord.c_str());
|
||||
WRITE(p, " if (aResult < 0.5) %s\n", discardStatement);
|
||||
} else {
|
||||
const char *alphaTestFuncs[] = { "#", "#", " != ", " == ", " >= ", " > ", " <= ", " < " };
|
||||
if (alphaTestFuncs[alphaTestFunc][0] != '#') {
|
||||
if (bitwiseOps) {
|
||||
if (compat.bitwiseOps) {
|
||||
WRITE(p, " if ((roundAndScaleTo255i(v.a) & u_alphacolormask.a) %s int(u_alphacolorref.a)) %s\n", alphaTestFuncs[alphaTestFunc], discardStatement);
|
||||
} else if (gl_extensions.gpuVendor == GPU_VENDOR_IMGTEC) {
|
||||
// Work around bad PVR driver problem where equality check + discard just doesn't work.
|
||||
|
@ -589,9 +589,9 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
WRITE(p, " %s\n", discardStatement);
|
||||
}
|
||||
} else if (g_Config.bFragmentTestCache) {
|
||||
WRITE(p, " float rResult = %s(testtex, vec2(vScale256.r, 0)).r;\n", texture);
|
||||
WRITE(p, " float gResult = %s(testtex, vec2(vScale256.g, 0)).g;\n", texture);
|
||||
WRITE(p, " float bResult = %s(testtex, vec2(vScale256.b, 0)).b;\n", texture);
|
||||
WRITE(p, " float rResult = %s(testtex, vec2(vScale256.r, 0)).r;\n", compat.texture);
|
||||
WRITE(p, " float gResult = %s(testtex, vec2(vScale256.g, 0)).g;\n", compat.texture);
|
||||
WRITE(p, " float bResult = %s(testtex, vec2(vScale256.b, 0)).b;\n", compat.texture);
|
||||
if (colorTestFunc == GE_COMP_EQUAL) {
|
||||
// Equal means all parts must be equal (so discard if any is not.)
|
||||
WRITE(p, " if (rResult < 0.5 || gResult < 0.5 || bResult < 0.5) %s\n", discardStatement);
|
||||
|
@ -602,7 +602,7 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
} else {
|
||||
const char *colorTestFuncs[] = { "#", "#", " != ", " == " };
|
||||
if (colorTestFuncs[colorTestFunc][0] != '#') {
|
||||
if (bitwiseOps) {
|
||||
if (compat.bitwiseOps) {
|
||||
// Apparently GLES3 does not support vector bitwise ops.
|
||||
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)";
|
||||
|
@ -649,11 +649,11 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
// If we have NV_shader_framebuffer_fetch / EXT_shader_framebuffer_fetch, we skip the blit.
|
||||
// We can just read the prev value more directly.
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_ANY_FRAMEBUFFER_FETCH)) {
|
||||
WRITE(p, " lowp vec4 destColor = %s;\n", lastFragData);
|
||||
} else if (!texelFetch) {
|
||||
WRITE(p, " lowp vec4 destColor = %s(fbotex, gl_FragCoord.xy * u_fbotexSize.xy);\n", texture);
|
||||
WRITE(p, " lowp vec4 destColor = %s;\n", compat.lastFragData);
|
||||
} else if (!compat.texelFetch) {
|
||||
WRITE(p, " lowp vec4 destColor = %s(fbotex, gl_FragCoord.xy * u_fbotexSize.xy);\n", compat.texture);
|
||||
} else {
|
||||
WRITE(p, " lowp vec4 destColor = %s(fbotex, ivec2(gl_FragCoord.x, gl_FragCoord.y), 0);\n", texelFetch);
|
||||
WRITE(p, " lowp vec4 destColor = %s(fbotex, ivec2(gl_FragCoord.x, gl_FragCoord.y), 0);\n", compat.texelFetch);
|
||||
}
|
||||
|
||||
const char *srcFactor = "vec3(1.0)";
|
||||
|
@ -755,16 +755,16 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
|
||||
switch (stencilToAlpha) {
|
||||
case REPLACE_ALPHA_DUALSOURCE:
|
||||
WRITE(p, " %s = vec4(v.rgb, %s);\n", fragColor0, replacedAlpha.c_str());
|
||||
WRITE(p, " %s = vec4(0.0, 0.0, 0.0, v.a);\n", fragColor1);
|
||||
WRITE(p, " %s = vec4(v.rgb, %s);\n", compat.fragColor0, replacedAlpha.c_str());
|
||||
WRITE(p, " %s = vec4(0.0, 0.0, 0.0, v.a);\n", compat.fragColor1);
|
||||
break;
|
||||
|
||||
case REPLACE_ALPHA_YES:
|
||||
WRITE(p, " %s = vec4(v.rgb, %s);\n", fragColor0, replacedAlpha.c_str());
|
||||
WRITE(p, " %s = vec4(v.rgb, %s);\n", compat.fragColor0, replacedAlpha.c_str());
|
||||
break;
|
||||
|
||||
case REPLACE_ALPHA_NO:
|
||||
WRITE(p, " %s = v;\n", fragColor0);
|
||||
WRITE(p, " %s = v;\n", compat.fragColor0);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -775,10 +775,10 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
LogicOpReplaceType replaceLogicOpType = (LogicOpReplaceType)id.Bits(FS_BIT_REPLACE_LOGIC_OP_TYPE, 2);
|
||||
switch (replaceLogicOpType) {
|
||||
case LOGICOPTYPE_ONE:
|
||||
WRITE(p, " %s.rgb = vec3(1.0, 1.0, 1.0);\n", fragColor0);
|
||||
WRITE(p, " %s.rgb = vec3(1.0, 1.0, 1.0);\n", compat.fragColor0);
|
||||
break;
|
||||
case LOGICOPTYPE_INVERT:
|
||||
WRITE(p, " %s.rgb = vec3(1.0, 1.0, 1.0) - %s.rgb;\n", fragColor0, fragColor0);
|
||||
WRITE(p, " %s.rgb = vec3(1.0, 1.0, 1.0) - %s.rgb;\n", compat.fragColor0, compat.fragColor0);
|
||||
break;
|
||||
case LOGICOPTYPE_NORMAL:
|
||||
break;
|
||||
|
@ -788,15 +788,6 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni
|
|||
return false;
|
||||
}
|
||||
|
||||
#ifdef DEBUG_SHADER
|
||||
if (doTexture) {
|
||||
WRITE(p, " %s = texture2D(tex, v_texcoord.xy);\n", fragColor0);
|
||||
WRITE(p, " %s += vec4(0.3,0,0.3,0.3);\n", fragColor0);
|
||||
} else {
|
||||
WRITE(p, " %s = vec4(1,0,1,1);\n", fragColor0);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) {
|
||||
const double scale = DepthSliceFactor() * 65535.0;
|
||||
|
||||
|
|
|
@ -94,24 +94,25 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM
|
|||
// #define USE_FOR_LOOP
|
||||
|
||||
// In GLSL ES 3.0, you use "out" variables instead.
|
||||
bool glslES30 = false;
|
||||
const char *varying = "varying";
|
||||
const char *attribute = "attribute";
|
||||
GLSLShaderCompat compat{};
|
||||
compat.glslES30 = false;
|
||||
compat.varying = "varying";
|
||||
compat.attribute = "attribute";
|
||||
const char * const * boneWeightDecl = boneWeightAttrDecl;
|
||||
const char *texelFetch = NULL;
|
||||
compat.texelFetch = NULL;
|
||||
bool highpFog = false;
|
||||
bool highpTexcoord = false;
|
||||
|
||||
if (gl_extensions.IsGLES) {
|
||||
if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300)) {
|
||||
WRITE(p, "#version 300 es\n");
|
||||
glslES30 = true;
|
||||
texelFetch = "texelFetch";
|
||||
compat.glslES30 = true;
|
||||
compat.texelFetch = "texelFetch";
|
||||
} else {
|
||||
WRITE(p, "#version 100\n"); // GLSL ES 1.0
|
||||
if (gl_extensions.EXT_gpu_shader4) {
|
||||
WRITE(p, "#extension GL_EXT_gpu_shader4 : enable\n");
|
||||
texelFetch = "texelFetch2D";
|
||||
compat.texelFetch = "texelFetch2D";
|
||||
}
|
||||
}
|
||||
WRITE(p, "precision highp float;\n");
|
||||
|
@ -123,20 +124,20 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM
|
|||
} else {
|
||||
if (!gl_extensions.ForceGL2 || gl_extensions.IsCoreContext) {
|
||||
if (gl_extensions.VersionGEThan(3, 3, 0)) {
|
||||
glslES30 = true;
|
||||
compat.glslES30 = true;
|
||||
WRITE(p, "#version 330\n");
|
||||
texelFetch = "texelFetch";
|
||||
compat.texelFetch = "texelFetch";
|
||||
} else if (gl_extensions.VersionGEThan(3, 0, 0)) {
|
||||
WRITE(p, "#version 130\n");
|
||||
if (gl_extensions.EXT_gpu_shader4) {
|
||||
WRITE(p, "#extension GL_EXT_gpu_shader4 : enable\n");
|
||||
texelFetch = "texelFetch";
|
||||
compat.texelFetch = "texelFetch";
|
||||
}
|
||||
} else {
|
||||
WRITE(p, "#version 110\n");
|
||||
if (gl_extensions.EXT_gpu_shader4) {
|
||||
WRITE(p, "#extension GL_EXT_gpu_shader4 : enable\n");
|
||||
texelFetch = "texelFetch2D";
|
||||
compat.texelFetch = "texelFetch2D";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -148,9 +149,9 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM
|
|||
}
|
||||
WRITE(p, "#define splat3(x) vec3(x)\n");
|
||||
|
||||
if (glslES30 || gl_extensions.IsCoreContext) {
|
||||
attribute = "in";
|
||||
varying = "out";
|
||||
if (compat.glslES30 || gl_extensions.IsCoreContext) {
|
||||
compat.attribute = "in";
|
||||
compat.varying = "out";
|
||||
boneWeightDecl = boneWeightInDecl;
|
||||
}
|
||||
|
||||
|
@ -186,7 +187,7 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM
|
|||
bool flipNormalTess = id.Bit(VS_BIT_NORM_REVERSE_TESS);
|
||||
|
||||
const char *shading = "";
|
||||
if (glslES30)
|
||||
if (compat.glslES30)
|
||||
shading = doFlatShading ? "flat " : "";
|
||||
|
||||
DoLightComputation doLight[4] = { LIGHT_OFF, LIGHT_OFF, LIGHT_OFF, LIGHT_OFF };
|
||||
|
@ -212,31 +213,31 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM
|
|||
}
|
||||
|
||||
if (useHWTransform)
|
||||
WRITE(p, "%s vec3 position;\n", attribute);
|
||||
WRITE(p, "%s vec3 position;\n", compat.attribute);
|
||||
else
|
||||
WRITE(p, "%s vec4 position;\n", attribute); // need to pass the fog coord in w
|
||||
WRITE(p, "%s vec4 position;\n", compat.attribute); // need to pass the fog coord in w
|
||||
*attrMask |= 1 << ATTR_POSITION;
|
||||
|
||||
if (useHWTransform && hasNormal) {
|
||||
WRITE(p, "%s mediump vec3 normal;\n", attribute);
|
||||
WRITE(p, "%s mediump vec3 normal;\n", compat.attribute);
|
||||
*attrMask |= 1 << ATTR_NORMAL;
|
||||
}
|
||||
|
||||
bool texcoordVec3In = false;
|
||||
if (doTexture && hasTexcoord) {
|
||||
if (!useHWTransform && doTextureProjection && !isModeThrough) {
|
||||
WRITE(p, "%s vec3 texcoord;\n", attribute);
|
||||
WRITE(p, "%s vec3 texcoord;\n", compat.attribute);
|
||||
texcoordVec3In = true;
|
||||
} else {
|
||||
WRITE(p, "%s vec2 texcoord;\n", attribute);
|
||||
WRITE(p, "%s vec2 texcoord;\n", compat.attribute);
|
||||
}
|
||||
*attrMask |= 1 << ATTR_TEXCOORD;
|
||||
}
|
||||
if (hasColor) {
|
||||
WRITE(p, "%s lowp vec4 color0;\n", attribute);
|
||||
WRITE(p, "%s lowp vec4 color0;\n", compat.attribute);
|
||||
*attrMask |= 1 << ATTR_COLOR0;
|
||||
if (lmode && !useHWTransform) { // only software transform supplies color1 as vertex data
|
||||
WRITE(p, "%s lowp vec3 color1;\n", attribute);
|
||||
WRITE(p, "%s lowp vec3 color1;\n", compat.attribute);
|
||||
*attrMask |= 1 << ATTR_COLOR1;
|
||||
}
|
||||
}
|
||||
|
@ -335,21 +336,21 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM
|
|||
*uniformMask |= DIRTY_CULLRANGE;
|
||||
}
|
||||
|
||||
WRITE(p, "%s%s lowp vec4 v_color0;\n", shading, varying);
|
||||
WRITE(p, "%s%s lowp vec4 v_color0;\n", shading, compat.varying);
|
||||
if (lmode) {
|
||||
WRITE(p, "%s%s lowp vec3 v_color1;\n", shading, varying);
|
||||
WRITE(p, "%s%s lowp vec3 v_color1;\n", shading, compat.varying);
|
||||
}
|
||||
|
||||
if (doTexture) {
|
||||
WRITE(p, "%s %s vec3 v_texcoord;\n", varying, highpTexcoord ? "highp" : "mediump");
|
||||
WRITE(p, "%s %s vec3 v_texcoord;\n", compat.varying, highpTexcoord ? "highp" : "mediump");
|
||||
}
|
||||
|
||||
if (enableFog) {
|
||||
// See the fragment shader generator
|
||||
if (highpFog) {
|
||||
WRITE(p, "%s highp float v_fogdepth;\n", varying);
|
||||
WRITE(p, "%s highp float v_fogdepth;\n", compat.varying);
|
||||
} else {
|
||||
WRITE(p, "%s mediump float v_fogdepth;\n", varying);
|
||||
WRITE(p, "%s mediump float v_fogdepth;\n", compat.varying);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -416,17 +417,17 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM
|
|||
for (int j = 0; j < 4; j++) {
|
||||
WRITE(p, " index_u = (%i + point_pos.x);\n", j);
|
||||
WRITE(p, " index_v = (%i + point_pos.y);\n", i);
|
||||
WRITE(p, " _pos[%i] = %s(u_tess_points, ivec2(index_u, index_v), 0).xyz;\n", i * 4 + j, texelFetch);
|
||||
WRITE(p, " _pos[%i] = %s(u_tess_points, ivec2(index_u, index_v), 0).xyz;\n", i * 4 + j, compat.texelFetch);
|
||||
if (doTexture && hasTexcoordTess)
|
||||
WRITE(p, " _tex[%i] = %s(u_tess_points, ivec2(index_u + u_spline_counts, index_v), 0).xy;\n", i * 4 + j, texelFetch);
|
||||
WRITE(p, " _tex[%i] = %s(u_tess_points, ivec2(index_u + u_spline_counts, index_v), 0).xy;\n", i * 4 + j, compat.texelFetch);
|
||||
if (hasColorTess)
|
||||
WRITE(p, " _col[%i] = %s(u_tess_points, ivec2(index_u + u_spline_counts * 2, index_v), 0).rgba;\n", i * 4 + j, texelFetch);
|
||||
WRITE(p, " _col[%i] = %s(u_tess_points, ivec2(index_u + u_spline_counts * 2, index_v), 0).rgba;\n", i * 4 + j, compat.texelFetch);
|
||||
}
|
||||
}
|
||||
|
||||
// Basis polynomials as weight coefficients
|
||||
WRITE(p, " vec4 basis_u = %s(u_tess_weights_u, %s, 0);\n", texelFetch, "ivec2(weight_idx.x * 2, 0)");
|
||||
WRITE(p, " vec4 basis_v = %s(u_tess_weights_v, %s, 0);\n", texelFetch, "ivec2(weight_idx.y * 2, 0)");
|
||||
WRITE(p, " vec4 basis_u = %s(u_tess_weights_u, %s, 0);\n", compat.texelFetch, "ivec2(weight_idx.x * 2, 0)");
|
||||
WRITE(p, " vec4 basis_v = %s(u_tess_weights_v, %s, 0);\n", compat.texelFetch, "ivec2(weight_idx.y * 2, 0)");
|
||||
WRITE(p, " mat4 basis = outerProduct(basis_u, basis_v);\n");
|
||||
|
||||
// Tessellate
|
||||
|
@ -443,8 +444,8 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM
|
|||
WRITE(p, " tess.col = u_matambientalpha;\n");
|
||||
if (hasNormalTess) {
|
||||
// Derivatives as weight coefficients
|
||||
WRITE(p, " vec4 deriv_u = %s(u_tess_weights_u, %s, 0);\n", texelFetch, "ivec2(weight_idx.x * 2 + 1, 0)");
|
||||
WRITE(p, " vec4 deriv_v = %s(u_tess_weights_v, %s, 0);\n", texelFetch, "ivec2(weight_idx.y * 2 + 1, 0)");
|
||||
WRITE(p, " vec4 deriv_u = %s(u_tess_weights_u, %s, 0);\n", compat.texelFetch, "ivec2(weight_idx.x * 2 + 1, 0)");
|
||||
WRITE(p, " vec4 deriv_v = %s(u_tess_weights_v, %s, 0);\n", compat.texelFetch, "ivec2(weight_idx.y * 2 + 1, 0)");
|
||||
|
||||
WRITE(p, " vec3 du = tess_sample(_pos, outerProduct(deriv_u, basis_v));\n");
|
||||
WRITE(p, " vec3 dv = tess_sample(_pos, outerProduct(basis_u, deriv_v));\n");
|
||||
|
|
Loading…
Add table
Reference in a new issue