diff --git a/GPU/Common/FragmentShaderGenerator.cpp b/GPU/Common/FragmentShaderGenerator.cpp index 9224b0799943..d45f8391e7b5 100644 --- a/GPU/Common/FragmentShaderGenerator.cpp +++ b/GPU/Common/FragmentShaderGenerator.cpp @@ -302,7 +302,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu } WRITE(p, "struct PS_IN {\n"); - if (doTexture) { + if (doTexture || compat.shaderLanguage == HLSL_D3D11) { + // In D3D11, if we always have a texcoord in the VS, we always need it in the PS too for the structs to match. WRITE(p, " vec3 v_texcoord: TEXCOORD0;\n"); } const char *colorInterpolation = doFlatShading && compat.shaderLanguage == HLSL_D3D11 ? "nointerpolation " : ""; diff --git a/GPU/Common/ShaderId.cpp b/GPU/Common/ShaderId.cpp index 605b1a16578c..cc9875a6ef52 100644 --- a/GPU/Common/ShaderId.cpp +++ b/GPU/Common/ShaderId.cpp @@ -23,7 +23,6 @@ std::string VertexShaderDesc(const VShaderID &id) { if (id.Bit(VS_BIT_HAS_NORMAL)) desc << "N "; if (id.Bit(VS_BIT_LMODE)) desc << "LM "; if (id.Bit(VS_BIT_NORM_REVERSE)) desc << "RevN "; - if (id.Bit(VS_BIT_DO_TEXTURE)) desc << "Tex "; int uvgMode = id.Bits(VS_BIT_UVGEN_MODE, 2); if (uvgMode == GE_TEXMAP_TEXTURE_MATRIX) { int uvprojMode = id.Bits(VS_BIT_UVPROJ_MODE, 2); @@ -100,8 +99,6 @@ void ComputeVertexShaderID(VShaderID *id_out, VertexDecoder *vertexDecoder, bool } if (doTexture) { - id.SetBit(VS_BIT_DO_TEXTURE); - // UV generation mode. doShadeMapping is implicitly stored here. id.SetBits(VS_BIT_UVGEN_MODE, 2, gstate.getUVGenMode()); } diff --git a/GPU/Common/ShaderId.h b/GPU/Common/ShaderId.h index 54b18b771365..406d12931c2f 100644 --- a/GPU/Common/ShaderId.h +++ b/GPU/Common/ShaderId.h @@ -11,8 +11,9 @@ enum VShaderBit : uint8_t { VS_BIT_LMODE = 0, VS_BIT_IS_THROUGH = 1, + // bit 2 is free. VS_BIT_HAS_COLOR = 3, - VS_BIT_DO_TEXTURE = 4, + // bit 4 is free. VS_BIT_VERTEX_RANGE_CULLING = 5, VS_BIT_SIMPLE_STEREO = 6, // 7 is free. diff --git a/GPU/Common/ShaderUniforms.h b/GPU/Common/ShaderUniforms.h index 02e16a14584b..a3db480c4aad 100644 --- a/GPU/Common/ShaderUniforms.h +++ b/GPU/Common/ShaderUniforms.h @@ -87,39 +87,39 @@ struct alignas(16) UB_VS_Lights { }; static const char * const ub_vs_lightsStr = -R"( vec4 u_ambient; - vec3 u_matdiffuse; - vec4 u_matspecular; - vec3 u_matemissive; - uint u_lightControl; // light ubershader - vec3 u_lightpos0; - vec3 u_lightpos1; - vec3 u_lightpos2; - vec3 u_lightpos3; - vec3 u_lightdir0; - vec3 u_lightdir1; - vec3 u_lightdir2; - vec3 u_lightdir3; - vec3 u_lightatt0; - vec3 u_lightatt1; - vec3 u_lightatt2; - vec3 u_lightatt3; - vec4 u_lightangle_spotCoef0; - vec4 u_lightangle_spotCoef1; - vec4 u_lightangle_spotCoef2; - vec4 u_lightangle_spotCoef3; - vec3 u_lightambient0; - vec3 u_lightambient1; - vec3 u_lightambient2; - vec3 u_lightambient3; - vec3 u_lightdiffuse0; - vec3 u_lightdiffuse1; - vec3 u_lightdiffuse2; - vec3 u_lightdiffuse3; - vec3 u_lightspecular0; - vec3 u_lightspecular1; - vec3 u_lightspecular2; - vec3 u_lightspecular3; +R"( vec4 u_ambient; + vec3 u_matdiffuse; + vec4 u_matspecular; + vec3 u_matemissive; + uint u_lightControl; // light ubershader + vec3 u_lightpos0; + vec3 u_lightpos1; + vec3 u_lightpos2; + vec3 u_lightpos3; + vec3 u_lightdir0; + vec3 u_lightdir1; + vec3 u_lightdir2; + vec3 u_lightdir3; + vec3 u_lightatt0; + vec3 u_lightatt1; + vec3 u_lightatt2; + vec3 u_lightatt3; + vec4 u_lightangle_spotCoef0; + vec4 u_lightangle_spotCoef1; + vec4 u_lightangle_spotCoef2; + vec4 u_lightangle_spotCoef3; + vec3 u_lightambient0; + vec3 u_lightambient1; + vec3 u_lightambient2; + vec3 u_lightambient3; + vec3 u_lightdiffuse0; + vec3 u_lightdiffuse1; + vec3 u_lightdiffuse2; + vec3 u_lightdiffuse3; + vec3 u_lightspecular0; + vec3 u_lightspecular1; + vec3 u_lightspecular2; + vec3 u_lightspecular3; )"; // With some cleverness, we could get away with uploading just half this when only the four or five first diff --git a/GPU/Common/VertexShaderGenerator.cpp b/GPU/Common/VertexShaderGenerator.cpp index 69ed532e2541..55d380fb6367 100644 --- a/GPU/Common/VertexShaderGenerator.cpp +++ b/GPU/Common/VertexShaderGenerator.cpp @@ -171,7 +171,6 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag bool isModeThrough = id.Bit(VS_BIT_IS_THROUGH); bool lmode = id.Bit(VS_BIT_LMODE); - bool doTexture = id.Bit(VS_BIT_DO_TEXTURE); GETexMapMode uvGenMode = static_cast(id.Bits(VS_BIT_UVGEN_MODE, 2)); bool doTextureTransform = uvGenMode == GE_TEXMAP_TEXTURE_MATRIX; @@ -271,12 +270,13 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag if (!useHWTransform) WRITE(p, "layout (location = %d) in float fog;\n", (int)PspAttributeLocation::NORMAL); - if (doTexture && hasTexcoord) { + if (hasTexcoord) { if (!useHWTransform && doTextureTransform && !isModeThrough) { WRITE(p, "layout (location = %d) in vec3 texcoord;\n", (int)PspAttributeLocation::TEXCOORD); texCoordInVec3 = true; - } else + } else { WRITE(p, "layout (location = %d) in vec2 texcoord;\n", (int)PspAttributeLocation::TEXCOORD); + } } if (hasColor) { WRITE(p, "layout (location = %d) in vec4 color0;\n", (int)PspAttributeLocation::COLOR0); @@ -287,9 +287,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag WRITE(p, "layout (location = 1) %sout lowp vec4 v_color0;\n", shading); WRITE(p, "layout (location = 2) %sout lowp vec3 v_color1;\n", shading); - if (doTexture) { - WRITE(p, "layout (location = 0) out highp vec3 v_texcoord;\n"); - } + WRITE(p, "layout (location = 0) out highp vec3 v_texcoord;\n"); WRITE(p, "layout (location = 3) out highp float v_fogdepth;\n"); @@ -316,7 +314,6 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag WRITE(p, "vec4 u_matambientalpha : register(c%i);\n", CONST_VS_MATAMBIENTALPHA); // matambient + matalpha if (useHWTransform) { - // When transforming by hardware, we need a great deal more uniforms... WRITE(p, "mat3x4 u_world : register(c%i);\n", CONST_VS_WORLD); WRITE(p, "mat3x4 u_view : register(c%i);\n", CONST_VS_VIEW); if (doTextureTransform) @@ -330,9 +327,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag } #endif } - if (doTexture) { - WRITE(p, "vec4 u_uvscaleoffset : register(c%i);\n", CONST_VS_UVSCALEOFFSET); - } + WRITE(p, "vec4 u_uvscaleoffset : register(c%i);\n", CONST_VS_UVSCALEOFFSET); // No need for light ubershader support here, D3D9 doesn't do it. for (int i = 0; i < 4; i++) { if (doLight[i] != LIGHT_OFF) { @@ -384,7 +379,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag if (enableBones) { WRITE(p, " %s", boneWeightAttrDeclHLSL[numBoneWeights]); } - if (doTexture && hasTexcoord) { + if (hasTexcoord) { WRITE(p, " vec2 texcoord : TEXCOORD0;\n"); } if (hasColor) { @@ -398,12 +393,13 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag } else { WRITE(p, "struct VS_IN {\n"); WRITE(p, " vec4 position : POSITION;\n"); - if (doTexture && hasTexcoord) { + if (hasTexcoord) { if (doTextureTransform && !isModeThrough) { texCoordInVec3 = true; WRITE(p, " vec3 texcoord : TEXCOORD0;\n"); - } else + } else { WRITE(p, " vec2 texcoord : TEXCOORD0;\n"); + } } if (hasColor) { WRITE(p, " vec4 color0 : COLOR0;\n"); @@ -417,9 +413,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag } WRITE(p, "struct VS_OUT {\n"); - if (doTexture) { - WRITE(p, " vec3 v_texcoord : TEXCOORD0;\n"); - } + WRITE(p, " vec3 v_texcoord : TEXCOORD0;\n"); const char *colorInterpolation = doFlatShading && compat.shaderLanguage == HLSL_D3D11 ? "nointerpolation " : ""; WRITE(p, " %svec4 v_color0 : COLOR0;\n", colorInterpolation); WRITE(p, " vec3 v_color1 : COLOR1;\n"); @@ -471,7 +465,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag *attrMask |= 1 << ATTR_NORMAL; } - if (doTexture && hasTexcoord) { + if (hasTexcoord) { if (!useHWTransform && doTextureTransform && !isModeThrough) { WRITE(p, "%s vec3 texcoord;\n", compat.attribute); texCoordInVec3 = true; @@ -480,6 +474,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag } *attrMask |= 1 << ATTR_TEXCOORD; } + if (hasColor) { WRITE(p, "%s lowp vec4 color0;\n", compat.attribute); *attrMask |= 1 << ATTR_COLOR0; @@ -524,10 +519,9 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag *uniformMask |= DIRTY_BONEMATRIX0 << i; } } - if (doTexture) { - WRITE(p, "uniform vec4 u_uvscaleoffset;\n"); - *uniformMask |= DIRTY_UVSCALEOFFSET; - } + WRITE(p, "uniform vec4 u_uvscaleoffset;\n"); + *uniformMask |= DIRTY_UVSCALEOFFSET; + if (lightUberShader) { p.C("uniform uint u_lightControl;\n"); *uniformMask |= DIRTY_LIGHT_CONTROL; @@ -597,9 +591,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag WRITE(p, "%s%s lowp vec4 v_color0;\n", shading, compat.varying_vs); 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_vs, highpTexcoord ? "highp" : "mediump"); - } + WRITE(p, "%s %s vec3 v_texcoord;\n", compat.varying_vs, highpTexcoord ? "highp" : "mediump"); // See the fragment shader generator if (highpFog) { @@ -695,8 +687,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag WRITE(p, "struct Tess {\n"); WRITE(p, " vec3 pos;\n"); - if (doTexture) - WRITE(p, " vec2 tex;\n"); + WRITE(p, " vec2 tex;\n"); WRITE(p, " vec4 col;\n"); if (hasNormalTess) WRITE(p, " vec3 nrm;\n"); @@ -722,7 +713,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag for (int j = 0; j < 4; j++) { WRITE(p, " index = (%i + point_pos.y) * int(u_spline_counts) + (%i + point_pos.x);\n", i, j); WRITE(p, " _pos[%i] = tess_data[index].pos.xyz;\n", i * 4 + j); - if (doTexture && hasTexcoordTess) + if (hasTexcoordTess) WRITE(p, " _tex[%i] = tess_data[index].tex.xy;\n", i * 4 + j); if (hasColorTess) WRITE(p, " _col[%i] = tess_data[index].col;\n", i * 4 + j); @@ -740,7 +731,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag 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, compat.texelFetch); - if (doTexture && hasTexcoordTess) + if (hasTexcoordTess) 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, compat.texelFetch); @@ -755,12 +746,10 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag // Tessellate WRITE(p, " tess.pos = tess_sample(_pos, basis);\n"); - if (doTexture) { - if (hasTexcoordTess) - WRITE(p, " tess.tex = tess_sample(_tex, basis);\n"); - else - WRITE(p, " tess.tex = normal.xy;\n"); - } + if (hasTexcoordTess) + WRITE(p, " tess.tex = tess_sample(_tex, basis);\n"); + else + WRITE(p, " tess.tex = normal.xy;\n"); if (hasColorTess) WRITE(p, " tess.col = tess_sample(_col, basis);\n"); else @@ -794,7 +783,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag } else if (compat.shaderLanguage == HLSL_D3D9 || compat.shaderLanguage == HLSL_D3D11) { WRITE(p, "VS_OUT main(VS_IN In) {\n"); WRITE(p, " VS_OUT Out;\n"); - if (doTexture && hasTexcoord) { + if (hasTexcoord) { if (texCoordInVec3) { WRITE(p, " vec3 texcoord = In.texcoord;\n"); } else { @@ -825,12 +814,10 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag if (!useHWTransform) { // Simple pass-through of vertex data to fragment shader - if (doTexture) { - if (texCoordInVec3) { - WRITE(p, " %sv_texcoord = texcoord;\n", compat.vsOutPrefix); - } else { - WRITE(p, " %sv_texcoord = vec3(texcoord, 1.0);\n", compat.vsOutPrefix); - } + if (texCoordInVec3) { + WRITE(p, " %sv_texcoord = texcoord;\n", compat.vsOutPrefix); + } else { + WRITE(p, " %sv_texcoord = vec3(texcoord, 1.0);\n", compat.vsOutPrefix); } if (hasColor) { WRITE(p, " %sv_color0 = color0;\n", compat.vsOutPrefix); @@ -1201,7 +1188,7 @@ bool GenerateVertexShader(const VShaderID &id, char *buffer, const ShaderLanguag bool scaleUV = !isModeThrough && (uvGenMode == GE_TEXMAP_TEXTURE_COORDS || uvGenMode == GE_TEXMAP_UNKNOWN); // Step 3: UV generation - if (doTexture) { + { switch (uvGenMode) { case GE_TEXMAP_TEXTURE_COORDS: // Scale-offset. Easy. case GE_TEXMAP_UNKNOWN: // Not sure what this is, but Riviera uses it. Treating as coords works. diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 79a63be54c23..479d4f5669a8 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -868,7 +868,6 @@ LinkedShader *ShaderManagerGLES::ApplyFragmentShader(VShaderID VSID, Shader *vs, shaderSwitchDirtyUniforms_ = 0; if (ls == nullptr) { - _dbg_assert_(FSID.Bit(FS_BIT_DO_TEXTURE) == VSID.Bit(VS_BIT_DO_TEXTURE)); _dbg_assert_(FSID.Bit(FS_BIT_FLATSHADE) == VSID.Bit(VS_BIT_FLATSHADE)); // Check if we can link these. @@ -960,7 +959,8 @@ enum class CacheDetectFlags { }; #define CACHE_HEADER_MAGIC 0x83277592 -#define CACHE_VERSION 24 +#define CACHE_VERSION 25 + struct CacheHeader { uint32_t magic; uint32_t version; diff --git a/GPU/Vulkan/PipelineManagerVulkan.cpp b/GPU/Vulkan/PipelineManagerVulkan.cpp index cb74b326e74d..9a137804f832 100644 --- a/GPU/Vulkan/PipelineManagerVulkan.cpp +++ b/GPU/Vulkan/PipelineManagerVulkan.cpp @@ -287,7 +287,7 @@ static VulkanPipeline *CreateVulkanPipeline(VulkanRenderManager *renderManager, attributeCount = SetupVertexAttribs(attrs, *decFmt); vertexStride = decFmt->stride; } else { - bool needsUV = vs->GetID().Bit(VS_BIT_DO_TEXTURE); + bool needsUV = true; bool needsColor1 = vs->GetID().Bit(VS_BIT_LMODE); attributeCount = SetupVertexAttribsPretransformed(attrs, needsUV, needsColor1, true); vertexStride = (int)sizeof(TransformedVertex); diff --git a/GPU/Vulkan/ShaderManagerVulkan.cpp b/GPU/Vulkan/ShaderManagerVulkan.cpp index d1c3b52d0b57..aec9faf5eeaf 100644 --- a/GPU/Vulkan/ShaderManagerVulkan.cpp +++ b/GPU/Vulkan/ShaderManagerVulkan.cpp @@ -320,13 +320,8 @@ void ShaderManagerVulkan::GetShaders(int prim, VertexDecoder *decoder, VulkanVer GSID = lastGSID_; } - _dbg_assert_(FSID.Bit(FS_BIT_DO_TEXTURE) == VSID.Bit(VS_BIT_DO_TEXTURE)); _dbg_assert_(FSID.Bit(FS_BIT_FLATSHADE) == VSID.Bit(VS_BIT_FLATSHADE)); - if (GSID.Bit(GS_BIT_ENABLED)) { - _dbg_assert_(GSID.Bit(GS_BIT_DO_TEXTURE) == VSID.Bit(VS_BIT_DO_TEXTURE)); - } - // Just update uniforms if this is the same shader as last time. if (lastVShader_ != nullptr && lastFShader_ != nullptr && VSID == lastVSID_ && FSID == lastFSID_ && GSID == lastGSID_) { *vshader = lastVShader_; @@ -516,7 +511,8 @@ enum class VulkanCacheDetectFlags { }; #define CACHE_HEADER_MAGIC 0xff51f420 -#define CACHE_VERSION 38 +#define CACHE_VERSION 39 + struct VulkanCacheHeader { uint32_t magic; uint32_t version;