From 24cc3dbc70f8cadcb228d313f0f64019b19fd434 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Mon, 30 Jan 2017 15:52:40 +0100 Subject: [PATCH] Always pass vec3 texcoord between vertex and fragment shader, to allow for some simplification. --- GPU/Common/ShaderId.cpp | 4 +-- GPU/Common/ShaderId.h | 2 +- GPU/Directx9/PixelShaderGeneratorDX9.cpp | 5 +-- GPU/Directx9/VertexShaderGeneratorDX9.cpp | 34 +++++++++---------- GPU/GLES/FragmentShaderGeneratorGLES.cpp | 7 ++-- GPU/GLES/ShaderManagerGLES.cpp | 2 ++ GPU/GLES/VertexShaderGeneratorGLES.cpp | 35 ++++++++++---------- GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp | 7 ++-- GPU/Vulkan/VertexShaderGeneratorVulkan.cpp | 29 ++++++++-------- 9 files changed, 56 insertions(+), 69 deletions(-) diff --git a/GPU/Common/ShaderId.cpp b/GPU/Common/ShaderId.cpp index 06f4b440c0..1f19d2f085 100644 --- a/GPU/Common/ShaderId.cpp +++ b/GPU/Common/ShaderId.cpp @@ -22,7 +22,7 @@ std::string VertexShaderDesc(const ShaderID &id) { if (id.Bit(VS_BIT_ENABLE_FOG)) desc << "Fog "; if (id.Bit(VS_BIT_NORM_REVERSE)) desc << "RevN "; if (id.Bit(VS_BIT_DO_TEXTURE)) desc << "Tex "; - if (id.Bit(VS_BIT_DO_TEXTURE_PROJ)) desc << "TexProj "; + if (id.Bit(VS_BIT_DO_TEXTURE_TRANSFORM)) desc << "TexProj "; int uvgMode = id.Bits(VS_BIT_UVGEN_MODE, 2); const char *uvgModes[4] = { "UV ", "UVMtx ", "UVEnv ", "UVUnk " }; int ls0 = id.Bits(VS_BIT_LS0, 2); @@ -83,7 +83,7 @@ void ComputeVertexShaderID(ShaderID *id_out, u32 vertType, bool useHWTransform) if (doTexture) { id.SetBit(VS_BIT_DO_TEXTURE); - id.SetBit(VS_BIT_DO_TEXTURE_PROJ, doTextureProjection); + id.SetBit(VS_BIT_DO_TEXTURE_TRANSFORM, doTextureProjection); } if (useHWTransform) { diff --git a/GPU/Common/ShaderId.h b/GPU/Common/ShaderId.h index 599b4cadc8..0d2f27713c 100644 --- a/GPU/Common/ShaderId.h +++ b/GPU/Common/ShaderId.h @@ -11,7 +11,7 @@ enum { VS_BIT_ENABLE_FOG = 2, VS_BIT_HAS_COLOR = 3, VS_BIT_DO_TEXTURE = 4, - VS_BIT_DO_TEXTURE_PROJ = 6, + VS_BIT_DO_TEXTURE_TRANSFORM = 6, VS_BIT_USE_HW_TRANSFORM = 8, VS_BIT_HAS_NORMAL = 9, // conditioned on hw transform VS_BIT_NORM_REVERSE = 10, diff --git a/GPU/Directx9/PixelShaderGeneratorDX9.cpp b/GPU/Directx9/PixelShaderGeneratorDX9.cpp index 8a14540990..9a08965cfa 100644 --- a/GPU/Directx9/PixelShaderGeneratorDX9.cpp +++ b/GPU/Directx9/PixelShaderGeneratorDX9.cpp @@ -112,10 +112,7 @@ bool GenerateFragmentShaderDX9(const ShaderID &id, char *buffer) { WRITE(p, "struct PS_IN {\n"); if (doTexture) { - if (doTextureProjection) - WRITE(p, " float3 v_texcoord: TEXCOORD0;\n"); - else - WRITE(p, " float2 v_texcoord: TEXCOORD0;\n"); + WRITE(p, " float3 v_texcoord: TEXCOORD0;\n"); } WRITE(p, " float4 v_color0: COLOR0;\n"); if (lmode) { diff --git a/GPU/Directx9/VertexShaderGeneratorDX9.cpp b/GPU/Directx9/VertexShaderGeneratorDX9.cpp index b73b034378..fbdcc6739c 100644 --- a/GPU/Directx9/VertexShaderGeneratorDX9.cpp +++ b/GPU/Directx9/VertexShaderGeneratorDX9.cpp @@ -61,7 +61,7 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) { bool isModeThrough = id.Bit(VS_BIT_IS_THROUGH); bool lmode = id.Bit(VS_BIT_LMODE) && !isModeThrough; // TODO: Different expression than in shaderIDgen bool doTexture = id.Bit(VS_BIT_DO_TEXTURE); - bool doTextureProjection = id.Bit(VS_BIT_DO_TEXTURE_PROJ); + bool doTextureTransform = id.Bit(VS_BIT_DO_TEXTURE_TRANSFORM); GETexMapMode uvGenMode = static_cast(id.Bits(VS_BIT_UVGEN_MODE, 2)); @@ -122,7 +122,7 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) { // When transforming by hardware, we need a great deal more uniforms... WRITE(p, "float4x3 u_world : register(c%i);\n", CONST_VS_WORLD); WRITE(p, "float4x3 u_view : register(c%i);\n", CONST_VS_VIEW); - if (doTextureProjection) + if (doTextureTransform) WRITE(p, "float4x3 u_texmtx : register(c%i);\n", CONST_VS_TEXMTX); if (enableBones) { #ifdef USE_BONE_ARRAY @@ -176,6 +176,7 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) { } // And the "varyings". + bool texCoordInVec3 = false; if (useHWTransform) { WRITE(p, "struct VS_IN { \n"); if (enableBones) { @@ -197,8 +198,10 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) { WRITE(p, "struct VS_IN {\n"); WRITE(p, " float4 position : POSITION;\n"); if (doTexture && hasTexcoord) { - if (doTextureProjection && !throughmode) + if (doTextureTransform && !throughmode) { + texCoordInVec3 = true; WRITE(p, " float3 texcoord : TEXCOORD0;\n"); + } else WRITE(p, " float2 texcoord : TEXCOORD0;\n"); } @@ -215,10 +218,7 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) { WRITE(p, "struct VS_OUT {\n"); WRITE(p, " float4 gl_Position : POSITION;\n"); if (doTexture) { - if (doTextureProjection) - WRITE(p, " float3 v_texcoord: TEXCOORD0;\n"); - else - WRITE(p, " float2 v_texcoord: TEXCOORD0;\n"); + WRITE(p, " float3 v_texcoord : TEXCOORD0;\n"); } WRITE(p, " float4 v_color0 : COLOR0;\n"); if (lmode) @@ -248,14 +248,10 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) { if (!useHWTransform) { // Simple pass-through of vertex data to fragment shader if (doTexture) { - if (doTextureProjection) { - if (throughmode) { - WRITE(p, " Out.v_texcoord = float3(In.texcoord.x, In.texcoord.y, 1.0);\n"); - } else { - WRITE(p, " Out.v_texcoord = In.texcoord;\n"); - } + if (texCoordInVec3) { + WRITE(p, " Out.v_texcoord = In.texcoord;\n"); } else { - WRITE(p, " Out.v_texcoord = In.texcoord.xy;\n"); + WRITE(p, " Out.v_texcoord = float3(In.texcoord, 1.0);\n"); } } if (hasColor) { @@ -505,15 +501,15 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) { case GE_TEXMAP_UNKNOWN: // Not sure what this is, but Riviera uses it. Treating as coords works. if (scaleUV) { if (hasTexcoord) { - WRITE(p, " Out.v_texcoord = In.texcoord * u_uvscaleoffset.xy;\n"); + WRITE(p, " Out.v_texcoord = float3(In.texcoord.xy * u_uvscaleoffset.xy, 0.0);\n"); } else { - WRITE(p, " Out.v_texcoord = float2(0.0, 0.0);\n"); + WRITE(p, " Out.v_texcoord = float3(0.0, 0.0, 0.0);\n"); } } else { if (hasTexcoord) { - WRITE(p, " Out.v_texcoord = In.texcoord * u_uvscaleoffset.xy + u_uvscaleoffset.zw;\n"); + WRITE(p, " Out.v_texcoord = float3(In.texcoord.xy * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n"); } else { - WRITE(p, " Out.v_texcoord = u_uvscaleoffset.zw;\n"); + WRITE(p, " Out.v_texcoord = float3(u_uvscaleoffset.zw, 0.0);\n"); } } break; @@ -553,7 +549,7 @@ void GenerateVertexShaderDX9(const ShaderID &id, char *buffer) { break; case GE_TEXMAP_ENVIRONMENT_MAP: // Shade mapping - use dots from light sources. - WRITE(p, " Out.v_texcoord.xy = u_uvscaleoffset.xy * float2(1.0 + dot(normalize(u_lightpos%i), worldnormal), 1.0 + dot(normalize(u_lightpos%i), worldnormal)) * 0.5;\n", ls0, ls1); + WRITE(p, " Out.v_texcoord = float3(u_uvscaleoffset.xy * float2(1.0 + dot(normalize(u_lightpos%i), worldnormal), 1.0 + dot(normalize(u_lightpos%i), worldnormal)) * 0.5, 0.0);\n", ls0, ls1); break; default: diff --git a/GPU/GLES/FragmentShaderGeneratorGLES.cpp b/GPU/GLES/FragmentShaderGeneratorGLES.cpp index 5204773945..52b2aa09e4 100644 --- a/GPU/GLES/FragmentShaderGeneratorGLES.cpp +++ b/GPU/GLES/FragmentShaderGeneratorGLES.cpp @@ -227,10 +227,7 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer) { WRITE(p, "%s %s float v_fogdepth;\n", varying, highpFog ? "highp" : "mediump"); } if (doTexture) { - if (doTextureProjection) - WRITE(p, "%s %s vec3 v_texcoord;\n", varying, highpTexcoord ? "highp" : "mediump"); - else - WRITE(p, "%s %s vec2 v_texcoord;\n", varying, highpTexcoord ? "highp" : "mediump"); + WRITE(p, "%s %s vec3 v_texcoord;\n", varying, highpTexcoord ? "highp" : "mediump"); } if (!g_Config.bFragmentTestCache) { @@ -329,7 +326,7 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer) { if (doTextureProjection) { WRITE(p, " vec4 t = %sProj(tex, %s);\n", texture, texcoord); } else { - WRITE(p, " vec4 t = %s(tex, %s);\n", texture, texcoord); + WRITE(p, " vec4 t = %s(tex, %s.xy);\n", texture, texcoord); } WRITE(p, " vec4 p = v_color0;\n"); diff --git a/GPU/GLES/ShaderManagerGLES.cpp b/GPU/GLES/ShaderManagerGLES.cpp index 5a8ceaa035..1756dfae29 100644 --- a/GPU/GLES/ShaderManagerGLES.cpp +++ b/GPU/GLES/ShaderManagerGLES.cpp @@ -43,6 +43,8 @@ #include "GPU/GLES/DrawEngineGLES.h" #include "FramebufferManagerGLES.h" +#define SHADERLOG + Shader::Shader(const char *code, uint32_t glShaderType, bool useHWTransform) : failed_(false), useHWTransform_(useHWTransform) { PROFILE_THIS_SCOPE("shadercomp"); diff --git a/GPU/GLES/VertexShaderGeneratorGLES.cpp b/GPU/GLES/VertexShaderGeneratorGLES.cpp index 5ac1cd88c4..3eef8f06cc 100644 --- a/GPU/GLES/VertexShaderGeneratorGLES.cpp +++ b/GPU/GLES/VertexShaderGeneratorGLES.cpp @@ -166,7 +166,7 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) { bool isModeThrough = id.Bit(VS_BIT_IS_THROUGH); bool lmode = id.Bit(VS_BIT_LMODE) && !isModeThrough; // TODO: Different expression than in shaderIDgen bool doTexture = id.Bit(VS_BIT_DO_TEXTURE); - bool doTextureProjection = id.Bit(VS_BIT_DO_TEXTURE_PROJ); + bool doTextureProjection = id.Bit(VS_BIT_DO_TEXTURE_TRANSFORM); GETexMapMode uvGenMode = static_cast(id.Bits(VS_BIT_UVGEN_MODE, 2)); @@ -225,11 +225,14 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) { if (useHWTransform && hasNormal) WRITE(p, "%s mediump vec3 normal;\n", attribute); + bool texcoordVec3In = false; if (doTexture && hasTexcoord) { - if (!useHWTransform && doTextureProjection && !throughmode) + if (!useHWTransform && doTextureProjection && !throughmode) { WRITE(p, "%s vec3 texcoord;\n", attribute); - else + texcoordVec3In = true; + } else { WRITE(p, "%s vec2 texcoord;\n", attribute); + } } if (hasColor) { WRITE(p, "%s lowp vec4 color0;\n", attribute); @@ -315,11 +318,7 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) { } if (doTexture) { - if (doTextureProjection) { - WRITE(p, "%s %s vec3 v_texcoord;\n", varying, highpTexcoord ? "highp" : "mediump"); - } else { - WRITE(p, "%s %s vec2 v_texcoord;\n", varying, highpTexcoord ? "highp" : "mediump"); - } + WRITE(p, "%s %s vec3 v_texcoord;\n", varying, highpTexcoord ? "highp" : "mediump"); } if (enableFog) { @@ -430,10 +429,10 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) { if (!useHWTransform) { // Simple pass-through of vertex data to fragment shader if (doTexture) { - if (throughmode && doTextureProjection) { - WRITE(p, " v_texcoord = vec3(texcoord, 1.0);\n"); - } else { + if (texcoordVec3In) { WRITE(p, " v_texcoord = texcoord;\n"); + } else { + WRITE(p, " v_texcoord = vec3(texcoord, 1.0);\n"); } } if (hasColor) { @@ -803,20 +802,20 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) { if (doBezier || doSpline) // TODO: Need fix? // Fix to avoid temporarily texture animation bug with hardware tessellation. - WRITE(p, " v_texcoord = tex * u_uvscaleoffset.xy + u_uvscaleoffset.zw;\n"); + WRITE(p, " v_texcoord = vec3(tex * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n"); else - WRITE(p, " v_texcoord = texcoord * u_uvscaleoffset.xy;\n"); + WRITE(p, " v_texcoord = vec3(texcoord.xy * u_uvscaleoffset.xy, 0.0);\n"); } else { - WRITE(p, " v_texcoord = vec2(0.0);\n"); + WRITE(p, " v_texcoord = vec3(0.0);\n"); } } else { if (hasTexcoord) { if (doBezier || doSpline) - WRITE(p, " v_texcoord = tex * u_uvscaleoffset.xy + u_uvscaleoffset.zw;\n"); + WRITE(p, " v_texcoord = vec3(tex * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n"); else - WRITE(p, " v_texcoord = texcoord * u_uvscaleoffset.xy + u_uvscaleoffset.zw;\n"); + WRITE(p, " v_texcoord = vec3(texcoord.xy * u_uvscaleoffset.xy + u_uvscaleoffset.zw, 0.0);\n"); } else { - WRITE(p, " v_texcoord = u_uvscaleoffset.zw;\n"); + WRITE(p, " v_texcoord = vec3(u_uvscaleoffset.zw, 0.0);\n"); } } break; @@ -857,7 +856,7 @@ void GenerateVertexShader(const ShaderID &id, char *buffer) { break; case GE_TEXMAP_ENVIRONMENT_MAP: // Shade mapping - use dots from light sources. - WRITE(p, " v_texcoord = u_uvscaleoffset.xy * vec2(1.0 + dot(normalize(u_lightpos%i), worldnormal), 1.0 + dot(normalize(u_lightpos%i), worldnormal)) * 0.5;\n", ls0, ls1); + WRITE(p, " v_texcoord = vec3(u_uvscaleoffset.xy * vec2(1.0 + dot(normalize(u_lightpos%i), worldnormal), 1.0 + dot(normalize(u_lightpos%i), worldnormal)) * 0.5);\n", ls0, ls1); break; default: diff --git a/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp b/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp index 9b7147f236..f434d16b34 100644 --- a/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/FragmentShaderGeneratorVulkan.cpp @@ -98,10 +98,7 @@ bool GenerateVulkanGLSLFragmentShader(const ShaderID &id, char *buffer) { WRITE(p, "layout (location = 3) in float v_fogdepth;\n"); } if (doTexture) { - if (doTextureProjection) - WRITE(p, "layout (location = 0) in vec3 v_texcoord;\n"); - else - WRITE(p, "layout (location = 0) in vec2 v_texcoord;\n"); + WRITE(p, "layout (location = 0) in vec3 v_texcoord;\n"); } if (enableAlphaTest && !alphaTestAgainstZero) { @@ -176,7 +173,7 @@ bool GenerateVulkanGLSLFragmentShader(const ShaderID &id, char *buffer) { if (doTextureProjection) { WRITE(p, " vec4 t = textureProj(tex, %s);\n", texcoord); } else { - WRITE(p, " vec4 t = texture(tex, %s);\n", texcoord); + WRITE(p, " vec4 t = texture(tex, %s.xy);\n", texcoord); } WRITE(p, " vec4 p = v_color0;\n"); diff --git a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp index 719bbb096c..97b211d522 100644 --- a/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp +++ b/GPU/Vulkan/VertexShaderGeneratorVulkan.cpp @@ -108,7 +108,7 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses bool isModeThrough = id.Bit(VS_BIT_IS_THROUGH); bool lmode = id.Bit(VS_BIT_LMODE) && !isModeThrough; // TODO: Different expression than in shaderIDgen bool doTexture = id.Bit(VS_BIT_DO_TEXTURE); - bool doTextureProjection = id.Bit(VS_BIT_DO_TEXTURE_PROJ); + bool doTextureTransform = id.Bit(VS_BIT_DO_TEXTURE_TRANSFORM); GETexMapMode uvGenMode = static_cast(id.Bits(VS_BIT_UVGEN_MODE, 2)); @@ -171,9 +171,12 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses if (useHWTransform && hasNormal) WRITE(p, "layout (location = %d) in vec3 normal;\n", PspAttributeLocation::NORMAL); + bool texcoordInVec3 = false; if (doTexture && hasTexcoord) { - if (!useHWTransform && doTextureProjection && !throughmode) + if (!useHWTransform && doTextureTransform && !throughmode) { WRITE(p, "layout (location = %d) in vec3 texcoord;\n", PspAttributeLocation::TEXCOORD); + texcoordInVec3 = true; + } else WRITE(p, "layout (location = %d) in vec2 texcoord;\n", PspAttributeLocation::TEXCOORD); } @@ -189,11 +192,7 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses } if (doTexture) { - if (doTextureProjection) { - WRITE(p, "layout (location = 0) out vec3 v_texcoord;\n"); - } else { - WRITE(p, "layout (location = 0) out vec2 v_texcoord;\n"); - } + WRITE(p, "layout (location = 0) out vec3 v_texcoord;\n"); } if (enableFog) { @@ -218,10 +217,10 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses if (!useHWTransform) { // Simple pass-through of vertex data to fragment shader if (doTexture) { - if (throughmode && doTextureProjection) { - WRITE(p, " v_texcoord = vec3(texcoord, 1.0);\n"); - } else { + if (texcoordInVec3) { WRITE(p, " v_texcoord = texcoord;\n"); + } else { + WRITE(p, " v_texcoord = vec3(texcoord, 1.0);\n"); } } if (hasColor) { @@ -435,15 +434,15 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses case GE_TEXMAP_UNKNOWN: // Not sure what this is, but Riviera uses it. Treating as coords works. if (scaleUV) { if (hasTexcoord) { - WRITE(p, " v_texcoord = texcoord;\n"); + WRITE(p, " v_texcoord = vec3(texcoord.xy, 0.0);\n"); } else { - WRITE(p, " v_texcoord = vec2(0.0);\n"); + WRITE(p, " v_texcoord = vec3(0.0);\n"); } } else { if (hasTexcoord) { - WRITE(p, " v_texcoord = texcoord * base.uvscaleoffset.xy + base.uvscaleoffset.zw;\n"); + WRITE(p, " v_texcoord = vec3(texcoord.xy * base.uvscaleoffset.xy + base.uvscaleoffset.zw, 0.0);\n"); } else { - WRITE(p, " v_texcoord = base.uvscaleoffset.zw;\n"); + WRITE(p, " v_texcoord = vec3(base.uvscaleoffset.zw, 0.0);\n"); } } break; @@ -484,7 +483,7 @@ bool GenerateVulkanGLSLVertexShader(const ShaderID &id, char *buffer, bool *uses break; case GE_TEXMAP_ENVIRONMENT_MAP: // Shade mapping - use dots from light sources. - WRITE(p, " v_texcoord = base.uvscaleoffset.xy * vec2(1.0 + dot(normalize(light.pos[%i]), worldnormal), 1.0 + dot(normalize(light.pos[%i]), worldnormal)) * 0.5;\n", ls0, ls1); + WRITE(p, " v_texcoord = vec3(base.uvscaleoffset.xy * vec2(1.0 + dot(normalize(light.pos[%i]), worldnormal), 1.0 + dot(normalize(light.pos[%i]), worldnormal)) * 0.5, 0.0);\n", ls0, ls1); break; default: