diff --git a/GPU/Common/ShaderCommon.h b/GPU/Common/ShaderCommon.h index 34f1dca676..d1d25edb5e 100644 --- a/GPU/Common/ShaderCommon.h +++ b/GPU/Common/ShaderCommon.h @@ -141,13 +141,15 @@ enum DoLightComputation { struct GLSLShaderCompat { const char *versionString; - const char *varying; + const char *varying_fs; + const char *varying_vs; const char *attribute; const char *fragColor0; const char *fragColor1; const char *texture; const char *texelFetch; const char *lastFragData; + const char *framebufferFetchExtension; bool gles; bool glslES30; bool bitwiseOps; diff --git a/GPU/Directx9/VertexShaderGeneratorHLSL.cpp b/GPU/Directx9/VertexShaderGeneratorHLSL.cpp index c8b87305cb..78cb8d1265 100644 --- a/GPU/Directx9/VertexShaderGeneratorHLSL.cpp +++ b/GPU/Directx9/VertexShaderGeneratorHLSL.cpp @@ -423,29 +423,6 @@ bool GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage "a_w2.x", "a_w2.y", "a_w2.z", "a_w2.w", }; -#if defined(USE_FOR_LOOP) && defined(USE_BONE_ARRAY) - - // To loop through the weights, we unfortunately need to put them in a float array. - // GLSL ES sucks - no way to directly initialize an array! - switch (numBoneWeights) { - case 1: WRITE(p, " float w[1]; w[0] = a_w1;\n"); break; - case 2: WRITE(p, " float w[2]; w[0] = a_w1.x; w[1] = a_w1.y;\n"); break; - case 3: WRITE(p, " float w[3]; w[0] = a_w1.x; w[1] = a_w1.y; w[2] = a_w1.z;\n"); break; - case 4: WRITE(p, " float w[4]; w[0] = a_w1.x; w[1] = a_w1.y; w[2] = a_w1.z; w[3] = a_w1.w;\n"); break; - case 5: WRITE(p, " float w[5]; w[0] = a_w1.x; w[1] = a_w1.y; w[2] = a_w1.z; w[3] = a_w1.w; w[4] = a_w2;\n"); break; - case 6: WRITE(p, " float w[6]; w[0] = a_w1.x; w[1] = a_w1.y; w[2] = a_w1.z; w[3] = a_w1.w; w[4] = a_w2.x; w[5] = a_w2.y;\n"); break; - case 7: WRITE(p, " float w[7]; w[0] = a_w1.x; w[1] = a_w1.y; w[2] = a_w1.z; w[3] = a_w1.w; w[4] = a_w2.x; w[5] = a_w2.y; w[6] = a_w2.z;\n"); break; - case 8: WRITE(p, " float w[8]; w[0] = a_w1.x; w[1] = a_w1.y; w[2] = a_w1.z; w[3] = a_w1.w; w[4] = a_w2.x; w[5] = a_w2.y; w[6] = a_w2.z; w[7] = a_w2.w;\n"); break; - } - - WRITE(p, " mat4 skinMatrix = w[0] * u_bone[0];\n"); - if (numBoneWeights > 1) { - WRITE(p, " for (int i = 1; i < %i; i++) {\n", numBoneWeights); - WRITE(p, " skinMatrix += w[i] * u_bone[i];\n"); - WRITE(p, " }\n"); - } - -#else if (lang == HLSL_D3D11 || lang == HLSL_D3D11_LEVEL9) { if (numBoneWeights == 1) WRITE(p, " float4x3 skinMatrix = mul(In.a_w1, u_bone[0])"); @@ -471,7 +448,6 @@ bool GenerateVertexShaderHLSL(const VShaderID &id, char *buffer, ShaderLanguage WRITE(p, " + mul(In.%s, u_bone%i)", weightAttr, i); } } -#endif WRITE(p, ";\n"); diff --git a/GPU/GLES/FragmentShaderGeneratorGLES.cpp b/GPU/GLES/FragmentShaderGeneratorGLES.cpp index edd7629614..3747efadc4 100644 --- a/GPU/GLES/FragmentShaderGeneratorGLES.cpp +++ b/GPU/GLES/FragmentShaderGeneratorGLES.cpp @@ -37,13 +37,11 @@ // Missing: Z depth range bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uniformMask, std::string *errorString) { - char *p = buffer; - *uniformMask = 0; - // In GLSL ES 3.0, you use "in" variables instead of varying. GLSLShaderCompat compat{}; - compat.varying = "varying"; + compat.varying_vs = "varying"; + compat.varying_fs = "varying"; compat.fragColor0 = "gl_FragColor"; compat.fragColor1 = "fragColor1"; compat.texture = "texture2D"; @@ -51,10 +49,6 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni compat.bitwiseOps = false; compat.lastFragData = nullptr; compat.gles = gl_extensions.IsGLES; - bool highpFog = false; - bool highpTexcoord = false; - - ReplaceAlphaType stencilToAlpha = static_cast(id.Bits(FS_BIT_STENCIL_TO_ALPHA, 2)); if (compat.gles) { if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300)) { @@ -75,25 +69,20 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni compat.fragColor1 = "gl_SecondaryFragColorEXT"; } } - - // PowerVR needs highp to do the fog in MHU correctly. - // Others don't, and some can't handle highp in the fragment shader. - highpFog = (gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_BAD) ? true : false; - highpTexcoord = highpFog; } else { if (!gl_extensions.ForceGL2 || gl_extensions.IsCoreContext) { if (gl_extensions.VersionGEThan(3, 3, 0)) { + compat.versionString = "#version 330"; compat.fragColor0 = "fragColor0"; compat.texture = "texture"; compat.glslES30 = true; compat.bitwiseOps = true; compat.texelFetch = "texelFetch"; - compat.versionString = "#version 330"; } else if (gl_extensions.VersionGEThan(3, 0, 0)) { + compat.versionString = "#version 130"; compat.fragColor0 = "fragColor0"; compat.bitwiseOps = true; compat.texelFetch = "texelFetch"; - compat.versionString = "#version 130"; } else { compat.versionString = "#version 110"; if (gl_extensions.EXT_gpu_shader4) { @@ -104,32 +93,54 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni } } - // Here the writing starts! - WRITE(p, "%s\n", compat.versionString); - 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"); + compat.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require"; compat.lastFragData = "fragColor0"; } else if (gl_extensions.EXT_shader_framebuffer_fetch) { - WRITE(p, "#extension GL_EXT_shader_framebuffer_fetch : require\n"); + compat.framebufferFetchExtension = "#extension GL_EXT_shader_framebuffer_fetch : require"; 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"); + compat.framebufferFetchExtension = "#extension GL_NV_shader_framebuffer_fetch : require"; compat.lastFragData = "gl_LastFragData[0]"; } else if (gl_extensions.ARM_shader_framebuffer_fetch) { - WRITE(p, "#extension GL_ARM_shader_framebuffer_fetch : require\n"); + compat.framebufferFetchExtension = "#extension GL_ARM_shader_framebuffer_fetch : require"; compat.lastFragData = "gl_LastFragColorARM"; } } + if (compat.glslES30 || gl_extensions.IsCoreContext) { + compat.varying_vs = "out"; + compat.varying_fs = "in"; + compat.attribute = "in"; + } + + bool highpFog = false; + bool highpTexcoord = false; + if (compat.gles) { + // PowerVR needs highp to do the fog in MHU correctly. + // Others don't, and some can't handle highp in the fragment shader. + highpFog = (gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_BAD) ? true : false; + highpTexcoord = highpFog; + } + + ReplaceAlphaType stencilToAlpha = static_cast(id.Bits(FS_BIT_STENCIL_TO_ALPHA, 2)); + + char *p = buffer; + + // Here the writing starts! + WRITE(p, "%s\n", compat.versionString); + if (stencilToAlpha == REPLACE_ALPHA_DUALSOURCE && gl_extensions.EXT_blend_func_extended) { WRITE(p, "#extension GL_EXT_blend_func_extended : require\n"); } if (gl_extensions.EXT_gpu_shader4) { WRITE(p, "#extension GL_EXT_gpu_shader4 : enable\n"); } + if (compat.framebufferFetchExtension) { + WRITE(p, "%s\n", compat.framebufferFetchExtension); + } if (!compat.gles) { WRITE(p, "#define lowp\n"); WRITE(p, "#define mediump\n"); @@ -140,10 +151,6 @@ bool GenerateFragmentShaderGLSL(const FShaderID &id, char *buffer, uint64_t *uni WRITE(p, "#define splat3(x) vec3(x)\n"); - if (compat.glslES30 || gl_extensions.IsCoreContext) { - compat.varying = "in"; - } - bool lmode = id.Bit(FS_BIT_LMODE); bool doTexture = id.Bit(FS_BIT_DO_TEXTURE); bool enableFog = id.Bit(FS_BIT_ENABLE_FOG); @@ -238,16 +245,16 @@ 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, compat.varying); + WRITE(p, "%s %s vec4 v_color0;\n", shading, compat.varying_fs); if (lmode) - WRITE(p, "%s %s vec3 v_color1;\n", shading, compat.varying); + WRITE(p, "%s %s vec3 v_color1;\n", shading, compat.varying_fs); if (enableFog) { *uniformMask |= DIRTY_FOGCOLOR; WRITE(p, "uniform vec3 u_fogcolor;\n"); - WRITE(p, "%s %s float v_fogdepth;\n", compat.varying, highpFog ? "highp" : "mediump"); + WRITE(p, "%s %s float v_fogdepth;\n", compat.varying_fs, highpFog ? "highp" : "mediump"); } if (doTexture) { - WRITE(p, "%s %s vec3 v_texcoord;\n", compat.varying, highpTexcoord ? "highp" : "mediump"); + WRITE(p, "%s %s vec3 v_texcoord;\n", compat.varying_fs, highpTexcoord ? "highp" : "mediump"); } if (!g_Config.bFragmentTestCache) { diff --git a/GPU/GLES/VertexShaderGeneratorGLES.cpp b/GPU/GLES/VertexShaderGeneratorGLES.cpp index 0f1242e28a..5ffc4d6982 100644 --- a/GPU/GLES/VertexShaderGeneratorGLES.cpp +++ b/GPU/GLES/VertexShaderGeneratorGLES.cpp @@ -88,21 +88,17 @@ static const char * const boneWeightInDecl[9] = { // is a bit of a rare configuration, although quite common on mobile. bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrMask, uint64_t *uniformMask, std::string *errorString) { - char *p = buffer; *attrMask = 0; *uniformMask = 0; - // #define USE_FOR_LOOP // In GLSL ES 3.0, you use "out" variables instead. GLSLShaderCompat compat{}; compat.glslES30 = false; - compat.varying = "varying"; + compat.varying_vs = "varying"; + compat.varying_fs = "varying"; compat.attribute = "attribute"; - const char * const * boneWeightDecl = boneWeightAttrDecl; compat.texelFetch = nullptr; compat.gles = gl_extensions.IsGLES; - bool highpFog = false; - bool highpTexcoord = false; if (compat.gles) { if (gstate_c.Supports(GPU_SUPPORTS_GLSL_ES_300)) { @@ -115,11 +111,6 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM compat.texelFetch = "texelFetch2D"; } } - - // PowerVR needs highp to do the fog in MHU correctly. - // Others don't, and some can't handle highp in the fragment shader. - highpFog = (gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_BAD) ? true : false; - highpTexcoord = highpFog; } else { if (!gl_extensions.ForceGL2 || gl_extensions.IsCoreContext) { if (gl_extensions.VersionGEThan(3, 3, 0)) { @@ -140,6 +131,25 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM } } + if (compat.glslES30 || gl_extensions.IsCoreContext) { + compat.attribute = "in"; + compat.varying_vs = "out"; + compat.varying_fs = "in"; + } + + char *p = buffer; + // Here the writing starts! + WRITE(p, "%s\n", compat.versionString); + + bool highpFog = false; + bool highpTexcoord = false; + if (compat.gles) { + // PowerVR needs highp to do the fog in MHU correctly. + // Others don't, and some can't handle highp in the fragment shader. + highpFog = (gl_extensions.bugs & BUG_PVR_SHADER_PRECISION_BAD) ? true : false; + highpTexcoord = highpFog; + } + if (gl_extensions.EXT_gpu_shader4) { WRITE(p, "#extension GL_EXT_gpu_shader4 : enable\n"); } @@ -154,12 +164,6 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM WRITE(p, "#define highp\n"); } - if (compat.glslES30 || gl_extensions.IsCoreContext) { - compat.attribute = "in"; - compat.varying = "out"; - boneWeightDecl = boneWeightInDecl; - } - bool isModeThrough = id.Bit(VS_BIT_IS_THROUGH); bool lmode = id.Bit(VS_BIT_LMODE); bool doTexture = id.Bit(VS_BIT_DO_TEXTURE); @@ -211,6 +215,10 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM int boneWeightScale = id.Bits(VS_BIT_WEIGHT_FMTSCALE, 2); if (enableBones) { numBoneWeights = 1 + id.Bits(VS_BIT_BONES, 3); + const char * const * boneWeightDecl = boneWeightAttrDecl; + if (!strcmp(compat.attribute, "in")) { + boneWeightDecl = boneWeightInDecl; + } WRITE(p, "%s", boneWeightDecl[numBoneWeights]); *attrMask |= 1 << ATTR_W1; if (numBoneWeights >= 5) @@ -341,21 +349,21 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM *uniformMask |= DIRTY_CULLRANGE; } - WRITE(p, "%s%s lowp vec4 v_color0;\n", shading, compat.varying); + WRITE(p, "%s%s lowp vec4 v_color0;\n", shading, compat.varying_vs); if (lmode) { - WRITE(p, "%s%s lowp vec3 v_color1;\n", shading, compat.varying); + WRITE(p, "%s%s lowp vec3 v_color1;\n", shading, compat.varying_vs); } if (doTexture) { - WRITE(p, "%s %s vec3 v_texcoord;\n", compat.varying, highpTexcoord ? "highp" : "mediump"); + WRITE(p, "%s %s vec3 v_texcoord;\n", compat.varying_vs, highpTexcoord ? "highp" : "mediump"); } if (enableFog) { // See the fragment shader generator if (highpFog) { - WRITE(p, "%s highp float v_fogdepth;\n", compat.varying); + WRITE(p, "%s highp float v_fogdepth;\n", compat.varying_vs); } else { - WRITE(p, "%s mediump float v_fogdepth;\n", compat.varying); + WRITE(p, "%s mediump float v_fogdepth;\n", compat.varying_vs); } } @@ -523,30 +531,6 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM "w2.x", "w2.y", "w2.z", "w2.w", }; -#if defined(USE_FOR_LOOP) && defined(USE_BONE_ARRAY) - - // To loop through the weights, we unfortunately need to put them in a float array. - // GLSL ES sucks - no way to directly initialize an array! - switch (numBoneWeights) { - case 1: WRITE(p, " float w[1]; w[0] = w1;\n"); break; - case 2: WRITE(p, " float w[2]; w[0] = w1.x; w[1] = w1.y;\n"); break; - case 3: WRITE(p, " float w[3]; w[0] = w1.x; w[1] = w1.y; w[2] = w1.z;\n"); break; - case 4: WRITE(p, " float w[4]; w[0] = w1.x; w[1] = w1.y; w[2] = w1.z; w[3] = w1.w;\n"); break; - case 5: WRITE(p, " float w[5]; w[0] = w1.x; w[1] = w1.y; w[2] = w1.z; w[3] = w1.w; w[4] = w2;\n"); break; - case 6: WRITE(p, " float w[6]; w[0] = w1.x; w[1] = w1.y; w[2] = w1.z; w[3] = w1.w; w[4] = w2.x; w[5] = w2.y;\n"); break; - case 7: WRITE(p, " float w[7]; w[0] = w1.x; w[1] = w1.y; w[2] = w1.z; w[3] = w1.w; w[4] = w2.x; w[5] = w2.y; w[6] = w2.z;\n"); break; - case 8: WRITE(p, " float w[8]; w[0] = w1.x; w[1] = w1.y; w[2] = w1.z; w[3] = w1.w; w[4] = w2.x; w[5] = w2.y; w[6] = w2.z; w[7] = w2.w;\n"); break; - } - - WRITE(p, " mat4 skinMatrix = w[0] * u_bone[0];\n"); - if (numBoneWeights > 1) { - WRITE(p, " for (int i = 1; i < %i; i++) {\n", numBoneWeights); - WRITE(p, " skinMatrix += w[i] * u_bone[i];\n"); - WRITE(p, " }\n"); - } - -#else - #ifdef USE_BONE_ARRAY if (numBoneWeights == 1) WRITE(p, " mat4 skinMatrix = w1 * u_bone[0]"); @@ -573,8 +557,6 @@ bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrM if (numBoneWeights == 5 && i == 4) weightAttr = "w2"; WRITE(p, " + %s * u_bone%i", weightAttr, i); } -#endif - #endif WRITE(p, ";\n"); diff --git a/GPU/GLES/VertexShaderGeneratorGLES.h b/GPU/GLES/VertexShaderGeneratorGLES.h index 0260d694b5..e1287e040d 100644 --- a/GPU/GLES/VertexShaderGeneratorGLES.h +++ b/GPU/GLES/VertexShaderGeneratorGLES.h @@ -19,8 +19,6 @@ #include "Common/CommonTypes.h" -// #define USE_BONE_ARRAY - struct VShaderID; bool GenerateVertexShaderGLSL(const VShaderID &id, char *buffer, uint32_t *attrMask, uint64_t *uniformMask, std::string *errorString);