diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 5695e9c256..0e7a23b979 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -18,10 +18,12 @@ static const char* primitives_ogl[] = {"points", "lines", "triangles"}; static const char* primitives_d3d[] = {"point", "line", "triangle"}; -template -static void EmitVertex(T& out, const char* vertex, APIType ApiType, bool first_vertex = false); -template -static void EndPrimitive(T& out, APIType ApiType); +bool geometry_shader_uid_data::IsPassthrough() const +{ + const bool stereo = g_ActiveConfig.iStereoMode > 0; + const bool wireframe = g_ActiveConfig.bWireFrame; + return primitive_type == PRIMITIVE_TRIANGLES && !stereo && !wireframe; +} GeometryShaderUid GetGeometryShaderUid(u32 primitive_type) { @@ -30,30 +32,31 @@ GeometryShaderUid GetGeometryShaderUid(u32 primitive_type) memset(uid_data, 0, sizeof(geometry_shader_uid_data)); uid_data->primitive_type = primitive_type; - uid_data->wireframe = g_ActiveConfig.bWireFrame; - uid_data->msaa = g_ActiveConfig.iMultisamples > 1; - uid_data->ssaa = g_ActiveConfig.iMultisamples > 1 && g_ActiveConfig.bSSAA; - uid_data->stereo = g_ActiveConfig.iStereoMode > 0; uid_data->numTexGens = xfmem.numTexGen.numTexGens; - uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting; return out; } static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data, - const char* vertex, APIType ApiType, bool first_vertex = false); -static void EndPrimitive(ShaderCode& out, const geometry_shader_uid_data* uid_data, - APIType ApiType); + const char* vertex, APIType ApiType, bool wireframe, bool pixel_lighting, + bool first_vertex = false); +static void EndPrimitive(ShaderCode& out, const geometry_shader_uid_data* uid_data, APIType ApiType, + bool wireframe, bool pixel_lighting); ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid_data* uid_data) { ShaderCode out; // Non-uid template parameters will write to the dummy data (=> gets optimized out) + const bool wireframe = g_ActiveConfig.bWireFrame; + const bool pixel_lighting = g_ActiveConfig.bEnablePixelLighting; + const bool msaa = g_ActiveConfig.IsMSAAEnabled(); + const bool ssaa = g_ActiveConfig.IsSSAAEnabled(); + const bool stereo = g_ActiveConfig.IsStereoEnabled(); const unsigned int vertex_in = uid_data->primitive_type + 1; unsigned int vertex_out = uid_data->primitive_type == PRIMITIVE_TRIANGLES ? 3 : 4; - if (uid_data->wireframe) + if (wireframe) vertex_out++; if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan) @@ -62,16 +65,15 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid if (g_ActiveConfig.backend_info.bSupportsGSInstancing) { out.Write("layout(%s, invocations = %d) in;\n", primitives_ogl[uid_data->primitive_type], - uid_data->stereo ? 2 : 1); - out.Write("layout(%s_strip, max_vertices = %d) out;\n", - uid_data->wireframe ? "line" : "triangle", vertex_out); + stereo ? 2 : 1); + out.Write("layout(%s_strip, max_vertices = %d) out;\n", wireframe ? "line" : "triangle", + vertex_out); } else { out.Write("layout(%s) in;\n", primitives_ogl[uid_data->primitive_type]); - out.Write("layout(%s_strip, max_vertices = %d) out;\n", - uid_data->wireframe ? "line" : "triangle", - uid_data->stereo ? vertex_out * 2 : vertex_out); + out.Write("layout(%s_strip, max_vertices = %d) out;\n", wireframe ? "line" : "triangle", + stereo ? vertex_out * 2 : vertex_out); } } @@ -89,8 +91,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid "};\n"); out.Write("struct VS_OUTPUT {\n"); - GenerateVSOutputMembers(out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting, - ""); + GenerateVSOutputMembers(out, ApiType, uid_data->numTexGens, pixel_lighting, ""); out.Write("};\n"); if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan) @@ -99,17 +100,15 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid out.Write("#define InstanceID gl_InvocationID\n"); out.Write("VARYING_LOCATION(0) in VertexData {\n"); - GenerateVSOutputMembers( - out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting, - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, true, true)); + GenerateVSOutputMembers(out, ApiType, uid_data->numTexGens, pixel_lighting, + GetInterpolationQualifier(msaa, ssaa, true, true)); out.Write("} vs[%d];\n", vertex_in); out.Write("VARYING_LOCATION(0) out VertexData {\n"); - GenerateVSOutputMembers( - out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting, - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, true, false)); + GenerateVSOutputMembers(out, ApiType, uid_data->numTexGens, pixel_lighting, + GetInterpolationQualifier(msaa, ssaa, true, false)); - if (uid_data->stereo) + if (stereo) out.Write("\tflat int layer;\n"); out.Write("} ps;\n"); @@ -121,25 +120,25 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid out.Write("struct VertexData {\n"); out.Write("\tVS_OUTPUT o;\n"); - if (uid_data->stereo) + if (stereo) out.Write("\tuint layer : SV_RenderTargetArrayIndex;\n"); out.Write("};\n"); if (g_ActiveConfig.backend_info.bSupportsGSInstancing) { - out.Write("[maxvertexcount(%d)]\n[instance(%d)]\n", vertex_out, uid_data->stereo ? 2 : 1); + out.Write("[maxvertexcount(%d)]\n[instance(%d)]\n", vertex_out, stereo ? 2 : 1); out.Write("void main(%s VS_OUTPUT o[%d], inout %sStream output, in uint " "InstanceID : SV_GSInstanceID)\n{\n", primitives_d3d[uid_data->primitive_type], vertex_in, - uid_data->wireframe ? "Line" : "Triangle"); + wireframe ? "Line" : "Triangle"); } else { - out.Write("[maxvertexcount(%d)]\n", uid_data->stereo ? vertex_out * 2 : vertex_out); + out.Write("[maxvertexcount(%d)]\n", stereo ? vertex_out * 2 : vertex_out); out.Write("void main(%s VS_OUTPUT o[%d], inout %sStream output)\n{\n", primitives_d3d[uid_data->primitive_type], vertex_in, - uid_data->wireframe ? "Line" : "Triangle"); + wireframe ? "Line" : "Triangle"); } out.Write("\tVertexData ps;\n"); @@ -150,8 +149,8 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan) { out.Write("\tVS_OUTPUT start, end;\n"); - AssignVSOutputMembers(out, "start", "vs[0]", uid_data->numTexGens, uid_data->pixel_lighting); - AssignVSOutputMembers(out, "end", "vs[1]", uid_data->numTexGens, uid_data->pixel_lighting); + AssignVSOutputMembers(out, "start", "vs[0]", uid_data->numTexGens, pixel_lighting); + AssignVSOutputMembers(out, "end", "vs[1]", uid_data->numTexGens, pixel_lighting); } else { @@ -181,7 +180,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan) { out.Write("\tVS_OUTPUT center;\n"); - AssignVSOutputMembers(out, "center", "vs[0]", uid_data->numTexGens, uid_data->pixel_lighting); + AssignVSOutputMembers(out, "center", "vs[0]", uid_data->numTexGens, pixel_lighting); } else { @@ -194,7 +193,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid ".x, -" I_LINEPTPARAMS ".w / " I_LINEPTPARAMS ".y) * center.pos.w;\n"); } - if (uid_data->stereo) + if (stereo) { // If the GPU supports invocation we don't need a for loop and can simply use the // invocation identifier to determine which layer we're rendering. @@ -204,7 +203,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid out.Write("\tfor (int eye = 0; eye < 2; ++eye) {\n"); } - if (uid_data->wireframe) + if (wireframe) out.Write("\tVS_OUTPUT first;\n"); out.Write("\tfor (int i = 0; i < %d; ++i) {\n", vertex_in); @@ -212,7 +211,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan) { out.Write("\tVS_OUTPUT f;\n"); - AssignVSOutputMembers(out, "f", "vs[i]", uid_data->numTexGens, uid_data->pixel_lighting); + AssignVSOutputMembers(out, "f", "vs[i]", uid_data->numTexGens, pixel_lighting); if (g_ActiveConfig.backend_info.bSupportsDepthClamp && DriverDetails::HasBug(DriverDetails::BUG_BROKEN_CLIP_DISTANCE)) @@ -228,7 +227,7 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid out.Write("\tVS_OUTPUT f = o[i];\n"); } - if (uid_data->stereo) + if (stereo) { // Select the output layer out.Write("\tps.layer = eye;\n"); @@ -264,8 +263,8 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid } out.Write("\t}\n"); - EmitVertex(out, uid_data, "l", ApiType, true); - EmitVertex(out, uid_data, "r", ApiType); + EmitVertex(out, uid_data, "l", ApiType, wireframe, pixel_lighting, true); + EmitVertex(out, uid_data, "r", ApiType, wireframe, pixel_lighting); } else if (uid_data->primitive_type == PRIMITIVE_POINTS) { @@ -293,21 +292,21 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid } out.Write("\t}\n"); - EmitVertex(out, uid_data, "ll", ApiType, true); - EmitVertex(out, uid_data, "lr", ApiType); - EmitVertex(out, uid_data, "ul", ApiType); - EmitVertex(out, uid_data, "ur", ApiType); + EmitVertex(out, uid_data, "ll", ApiType, wireframe, pixel_lighting, true); + EmitVertex(out, uid_data, "lr", ApiType, wireframe, pixel_lighting); + EmitVertex(out, uid_data, "ul", ApiType, wireframe, pixel_lighting); + EmitVertex(out, uid_data, "ur", ApiType, wireframe, pixel_lighting); } else { - EmitVertex(out, uid_data, "f", ApiType, true); + EmitVertex(out, uid_data, "f", ApiType, wireframe, pixel_lighting, true); } out.Write("\t}\n"); - EndPrimitive(out, uid_data, ApiType); + EndPrimitive(out, uid_data, ApiType, wireframe, pixel_lighting); - if (uid_data->stereo && !g_ActiveConfig.backend_info.bSupportsGSInstancing) + if (stereo && !g_ActiveConfig.backend_info.bSupportsGSInstancing) out.Write("\t}\n"); out.Write("}\n"); @@ -316,9 +315,10 @@ ShaderCode GenerateGeometryShaderCode(APIType ApiType, const geometry_shader_uid } static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data, - const char* vertex, APIType ApiType, bool first_vertex) + const char* vertex, APIType ApiType, bool wireframe, bool pixel_lighting, + bool first_vertex) { - if (uid_data->wireframe && first_vertex) + if (wireframe && first_vertex) out.Write("\tif (i == 0) first = %s;\n", vertex); if (ApiType == APIType::OpenGL) @@ -329,14 +329,14 @@ static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data out.Write("\tgl_ClipDistance[0] = %s.clipDist0;\n", vertex); out.Write("\tgl_ClipDistance[1] = %s.clipDist1;\n", vertex); } - AssignVSOutputMembers(out, "ps", vertex, uid_data->numTexGens, uid_data->pixel_lighting); + AssignVSOutputMembers(out, "ps", vertex, uid_data->numTexGens, pixel_lighting); } else if (ApiType == APIType::Vulkan) { // Vulkan NDC space has Y pointing down (right-handed NDC space). out.Write("\tgl_Position = %s.pos;\n", vertex); out.Write("\tgl_Position.y = -gl_Position.y;\n"); - AssignVSOutputMembers(out, "ps", vertex, uid_data->numTexGens, uid_data->pixel_lighting); + AssignVSOutputMembers(out, "ps", vertex, uid_data->numTexGens, pixel_lighting); } else { @@ -349,10 +349,11 @@ static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data out.Write("\toutput.Append(ps);\n"); } -static void EndPrimitive(ShaderCode& out, const geometry_shader_uid_data* uid_data, APIType ApiType) +static void EndPrimitive(ShaderCode& out, const geometry_shader_uid_data* uid_data, APIType ApiType, + bool wireframe, bool pixel_lighting) { - if (uid_data->wireframe) - EmitVertex(out, uid_data, "first", ApiType); + if (wireframe) + EmitVertex(out, uid_data, "first", ApiType, wireframe, pixel_lighting); if (ApiType == APIType::OpenGL || ApiType == APIType::Vulkan) out.Write("\tEndPrimitive();\n"); diff --git a/Source/Core/VideoCommon/GeometryShaderGen.h b/Source/Core/VideoCommon/GeometryShaderGen.h index 03b58a0367..8c00886bc6 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.h +++ b/Source/Core/VideoCommon/GeometryShaderGen.h @@ -15,18 +15,10 @@ enum class APIType; struct geometry_shader_uid_data { u32 NumValues() const { return sizeof(geometry_shader_uid_data); } - bool IsPassthrough() const - { - return primitive_type == PRIMITIVE_TRIANGLES && !stereo && !wireframe; - } + bool IsPassthrough() const; - u32 stereo : 1; u32 numTexGens : 4; - u32 pixel_lighting : 1; u32 primitive_type : 2; - u32 wireframe : 1; - u32 msaa : 1; - u32 ssaa : 1; }; #pragma pack() diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp index cec2c5183d..0dd4e868c6 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/PixelShaderGen.cpp @@ -170,7 +170,6 @@ PixelShaderUid GetPixelShaderUid() uid_data->genMode_numindstages = bpmem.genMode.numindstages; uid_data->genMode_numtevstages = bpmem.genMode.numtevstages; uid_data->genMode_numtexgens = bpmem.genMode.numtexgens; - uid_data->per_pixel_lighting = g_ActiveConfig.bEnablePixelLighting; uid_data->bounding_box = g_ActiveConfig.BBoxUseFragmentShaderImplementation() && g_ActiveConfig.bBBoxEnable && BoundingBox::active; uid_data->rgba6_format = @@ -192,13 +191,9 @@ PixelShaderUid GetPixelShaderUid() uid_data->per_pixel_depth = per_pixel_depth; uid_data->forced_early_z = forced_early_z; - uid_data->fast_depth_calc = g_ActiveConfig.bFastDepthCalc; - uid_data->msaa = g_ActiveConfig.iMultisamples > 1; - uid_data->ssaa = g_ActiveConfig.iMultisamples > 1 && g_ActiveConfig.bSSAA; - uid_data->stereo = g_ActiveConfig.iStereoMode > 0; if (!uid_data->forced_early_z && bpmem.UseEarlyDepthTest() && - (!uid_data->fast_depth_calc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED)) + (!g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED)) { static bool warn_once = true; if (warn_once) @@ -209,7 +204,7 @@ PixelShaderUid GetPixelShaderUid() warn_once = false; } - if (uid_data->per_pixel_lighting) + if (g_ActiveConfig.bEnablePixelLighting) { // The lighting shader only needs the two color bits of the 23bit component bit array. uid_data->components = @@ -297,7 +292,7 @@ PixelShaderUid GetPixelShaderUid() } #define MY_STRUCT_OFFSET(str, elem) ((u32)((u64) & (str).elem - (u64) & (str))) - uid_data->num_values = (uid_data->per_pixel_lighting) ? + uid_data->num_values = (g_ActiveConfig.bEnablePixelLighting) ? sizeof(*uid_data) : MY_STRUCT_OFFSET(*uid_data, stagehash[numStages]); @@ -339,7 +334,7 @@ PixelShaderUid GetPixelShaderUid() } static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, int n, - APIType ApiType); + APIType ApiType, bool stereo); static void WriteTevRegular(ShaderCode& out, const char* components, int bias, int op, int clamp, int shift, bool alpha); static void SampleTexture(ShaderCode& out, const char* texcoords, const char* texswap, int texmap, @@ -354,7 +349,11 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data* { ShaderCode out; - u32 numStages = uid_data->genMode_numtevstages + 1; + const bool per_pixel_lighting = g_ActiveConfig.bEnablePixelLighting; + const bool msaa = g_ActiveConfig.IsMSAAEnabled(); + const bool ssaa = g_ActiveConfig.IsSSAAEnabled(); + const bool stereo = g_ActiveConfig.IsStereoEnabled(); + const u32 numStages = uid_data->genMode_numtevstages + 1; out.Write("//Pixel Shader for TEV stages\n"); out.Write("//%i TEV stages, %i texgens, %i IND stages\n", numStages, uid_data->genMode_numtexgens, @@ -422,7 +421,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data* "\tfloat4 " I_EFBSCALE ";\n" "};\n"); - if (uid_data->per_pixel_lighting) + if (per_pixel_lighting) { out.Write("%s", s_lighting_struct); @@ -450,8 +449,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data* } out.Write("struct VS_OUTPUT {\n"); - GenerateVSOutputMembers(out, ApiType, uid_data->genMode_numtexgens, uid_data->per_pixel_lighting, - ""); + GenerateVSOutputMembers(out, ApiType, uid_data->genMode_numtexgens, per_pixel_lighting, ""); out.Write("};\n"); if (uid_data->forced_early_z) @@ -534,36 +532,29 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data* if (g_ActiveConfig.backend_info.bSupportsGeometryShaders || ApiType == APIType::Vulkan) { out.Write("VARYING_LOCATION(0) in VertexData {\n"); - GenerateVSOutputMembers( - out, ApiType, uid_data->genMode_numtexgens, uid_data->per_pixel_lighting, - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, true, true)); + GenerateVSOutputMembers(out, ApiType, uid_data->genMode_numtexgens, per_pixel_lighting, + GetInterpolationQualifier(msaa, ssaa, true, true)); - if (uid_data->stereo) + if (stereo) out.Write("\tflat int layer;\n"); out.Write("};\n"); } else { - out.Write("%s in float4 colors_0;\n", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa)); - out.Write("%s in float4 colors_1;\n", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa)); + out.Write("%s in float4 colors_0;\n", GetInterpolationQualifier(msaa, ssaa)); + out.Write("%s in float4 colors_1;\n", GetInterpolationQualifier(msaa, ssaa)); // compute window position if needed because binding semantic WPOS is not widely supported // Let's set up attributes for (unsigned int i = 0; i < uid_data->genMode_numtexgens; ++i) { - out.Write("%s in float3 uv%d;\n", GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa), - i); + out.Write("%s in float3 uv%d;\n", GetInterpolationQualifier(msaa, ssaa), i); } - out.Write("%s in float4 clipPos;\n", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa)); - if (uid_data->per_pixel_lighting) + out.Write("%s in float4 clipPos;\n", GetInterpolationQualifier(msaa, ssaa)); + if (per_pixel_lighting) { - out.Write("%s in float3 Normal;\n", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa)); - out.Write("%s in float3 WorldPos;\n", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa)); + out.Write("%s in float3 Normal;\n", GetInterpolationQualifier(msaa, ssaa)); + out.Write("%s in float3 WorldPos;\n", GetInterpolationQualifier(msaa, ssaa)); } } @@ -585,30 +576,24 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data* " in float4 rawpos : SV_Position,\n", uid_data->per_pixel_depth ? " out float depth : SV_Depth,\n" : ""); - out.Write(" in %s float4 colors_0 : COLOR0,\n", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa)); - out.Write(" in %s float4 colors_1 : COLOR1\n", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa)); + out.Write(" in %s float4 colors_0 : COLOR0,\n", GetInterpolationQualifier(msaa, ssaa)); + out.Write(" in %s float4 colors_1 : COLOR1\n", GetInterpolationQualifier(msaa, ssaa)); // compute window position if needed because binding semantic WPOS is not widely supported for (unsigned int i = 0; i < uid_data->genMode_numtexgens; ++i) - out.Write(",\n in %s float3 uv%d : TEXCOORD%d", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa), i, i); - out.Write(",\n in %s float4 clipPos : TEXCOORD%d", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa), + out.Write(",\n in %s float3 uv%d : TEXCOORD%d", GetInterpolationQualifier(msaa, ssaa), i, i); + out.Write(",\n in %s float4 clipPos : TEXCOORD%d", GetInterpolationQualifier(msaa, ssaa), uid_data->genMode_numtexgens); - if (uid_data->per_pixel_lighting) + if (per_pixel_lighting) { - out.Write(",\n in %s float3 Normal : TEXCOORD%d", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa), + out.Write(",\n in %s float3 Normal : TEXCOORD%d", GetInterpolationQualifier(msaa, ssaa), uid_data->genMode_numtexgens + 1); - out.Write(",\n in %s float3 WorldPos : TEXCOORD%d", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa), + out.Write(",\n in %s float3 WorldPos : TEXCOORD%d", GetInterpolationQualifier(msaa, ssaa), uid_data->genMode_numtexgens + 2); } out.Write(",\n in float clipDist0 : SV_ClipDistance0\n"); out.Write(",\n in float clipDist1 : SV_ClipDistance1\n"); - if (uid_data->stereo) + if (stereo) out.Write(",\n in uint layer : SV_RenderTargetArrayIndex\n"); out.Write(" ) {\n"); } @@ -630,7 +615,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data* out.Write("\tfloat4 col0 = colors_0;\n"); out.Write("\tfloat4 col1 = colors_1;\n"); - if (uid_data->per_pixel_lighting) + if (per_pixel_lighting) { out.Write("\tfloat3 _norm0 = normalize(Normal.xyz);\n\n"); out.Write("\tfloat3 pos = WorldPos;\n"); @@ -682,12 +667,12 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data* out.Write("\ttempcoord = int2(0, 0);\n"); out.Write("\tint3 iindtex%d = ", i); - SampleTexture(out, "float2(tempcoord)", "abg", texmap, uid_data->stereo, ApiType); + SampleTexture(out, "float2(tempcoord)", "abg", texmap, stereo, ApiType); } } for (unsigned int i = 0; i < numStages; i++) - WriteStage(out, uid_data, i, ApiType); // build the equation for this stage + WriteStage(out, uid_data, i, ApiType, stereo); // build the equation for this stage { // The results of the last texenv stage are put onto the screen, @@ -728,7 +713,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data* out.Write("\tint zCoord = int(" I_ZSLOPE ".z + " I_ZSLOPE ".x * screenpos.x + " I_ZSLOPE ".y * screenpos.y);\n"); } - else if (!uid_data->fast_depth_calc) + else if (!g_ActiveConfig.bFastDepthCalc) { // FastDepth means to trust the depth generated in perspective division. // It should be correct, but it seems not to be as accurate as required. TODO: Find out why! @@ -814,7 +799,7 @@ ShaderCode GeneratePixelShaderCode(APIType ApiType, const pixel_shader_uid_data* } static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, int n, - APIType ApiType) + APIType ApiType, bool stereo) { auto& stage = uid_data->stagehash[n]; out.Write("\n\t// TEV stage %d\n", n); @@ -1013,8 +998,7 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i out.Write("\ttevcoord.xy = int2(0, 0);\n"); } out.Write("\ttextemp = "); - SampleTexture(out, "float2(tevcoord.xy)", texswap, stage.tevorders_texmap, uid_data->stereo, - ApiType); + SampleTexture(out, "float2(tevcoord.xy)", texswap, stage.tevorders_texmap, stereo, ApiType); } else { diff --git a/Source/Core/VideoCommon/PixelShaderGen.h b/Source/Core/VideoCommon/PixelShaderGen.h index 2c19d38d87..4ba7405cd7 100644 --- a/Source/Core/VideoCommon/PixelShaderGen.h +++ b/Source/Core/VideoCommon/PixelShaderGen.h @@ -18,11 +18,10 @@ struct pixel_shader_uid_data u32 num_values; // TODO: Shouldn't be a u32 u32 NumValues() const { return num_values; } u32 components : 2; - u32 pad0 : 1; + u32 pad0 : 2; u32 useDstAlpha : 1; u32 Pretest : 2; u32 nIndirectStagesUsed : 4; - u32 stereo : 1; u32 genMode_numtexgens : 4; u32 genMode_numtevstages : 4; u32 genMode_numindstages : 3; @@ -35,20 +34,16 @@ struct pixel_shader_uid_data u32 fog_fsel : 3; u32 fog_RangeBaseEnabled : 1; u32 ztex_op : 2; - u32 fast_depth_calc : 1; u32 per_pixel_depth : 1; - u32 per_pixel_lighting : 1; u32 forced_early_z : 1; u32 early_ztest : 1; u32 late_ztest : 1; u32 bounding_box : 1; u32 zfreeze : 1; - u32 msaa : 1; - u32 ssaa : 1; u32 numColorChans : 2; u32 rgba6_format : 1; u32 dither : 1; - u32 pad : 12; + u32 pad : 16; u32 texMtxInfo_n_projection : 8; // 8x1 bit u32 tevindref_bi0 : 3; diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 9fe4bfcada..a69245bda7 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -26,11 +26,6 @@ VertexShaderUid GetVertexShaderUid() uid_data->numTexGens = xfmem.numTexGen.numTexGens; uid_data->components = VertexLoaderManager::g_current_components; - uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting; - uid_data->vertex_rounding = - g_ActiveConfig.bVertexRounding && g_ActiveConfig.iEFBScale != SCALE_1X; - uid_data->msaa = g_ActiveConfig.iMultisamples > 1; - uid_data->ssaa = g_ActiveConfig.iMultisamples > 1 && g_ActiveConfig.bSSAA; uid_data->numColorChans = xfmem.numChan.numColorChans; GetLightingShaderUid(uid_data->lighting); @@ -84,6 +79,12 @@ VertexShaderUid GetVertexShaderUid() ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_data* uid_data) { ShaderCode out; + + const bool per_pixel_lighting = g_ActiveConfig.bEnablePixelLighting; + const bool msaa = g_ActiveConfig.IsMSAAEnabled(); + const bool ssaa = g_ActiveConfig.IsSSAAEnabled(); + const bool vertex_rounding = g_ActiveConfig.UseVertexRounding(); + out.Write("%s", s_lighting_struct); // uniforms @@ -96,7 +97,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da out.Write("};\n"); out.Write("struct VS_OUTPUT {\n"); - GenerateVSOutputMembers(out, api_type, uid_data->numTexGens, uid_data->pixel_lighting, ""); + GenerateVSOutputMembers(out, api_type, uid_data->numTexGens, per_pixel_lighting, ""); out.Write("};\n"); if (api_type == APIType::OpenGL || api_type == APIType::Vulkan) @@ -130,9 +131,8 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da if (g_ActiveConfig.backend_info.bSupportsGeometryShaders || api_type == APIType::Vulkan) { out.Write("VARYING_LOCATION(0) out VertexData {\n"); - GenerateVSOutputMembers( - out, api_type, uid_data->numTexGens, uid_data->pixel_lighting, - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, true, false)); + GenerateVSOutputMembers(out, api_type, uid_data->numTexGens, per_pixel_lighting, + GetInterpolationQualifier(msaa, ssaa, true, false)); out.Write("} vs;\n"); } else @@ -142,23 +142,17 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da { if (i < uid_data->numTexGens) { - out.Write("%s out float3 uv%u;\n", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa), i); + out.Write("%s out float3 uv%u;\n", GetInterpolationQualifier(msaa, ssaa), i); } } - out.Write("%s out float4 clipPos;\n", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa)); - if (uid_data->pixel_lighting) + out.Write("%s out float4 clipPos;\n", GetInterpolationQualifier(msaa, ssaa)); + if (per_pixel_lighting) { - out.Write("%s out float3 Normal;\n", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa)); - out.Write("%s out float3 WorldPos;\n", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa)); + out.Write("%s out float3 Normal;\n", GetInterpolationQualifier(msaa, ssaa)); + out.Write("%s out float3 WorldPos;\n", GetInterpolationQualifier(msaa, ssaa)); } - out.Write("%s out float4 colors_0;\n", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa)); - out.Write("%s out float4 colors_1;\n", - GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa)); + out.Write("%s out float4 colors_0;\n", GetInterpolationQualifier(msaa, ssaa)); + out.Write("%s out float4 colors_1;\n", GetInterpolationQualifier(msaa, ssaa)); } out.Write("void main()\n{\n"); @@ -406,7 +400,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da // clipPos/w needs to be done in pixel shader, not here out.Write("o.clipPos = o.pos;\n"); - if (uid_data->pixel_lighting) + if (per_pixel_lighting) { out.Write("o.Normal = _norm0;\n"); out.Write("o.WorldPos = pos.xyz;\n"); @@ -466,7 +460,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da // get rasterized correctly. out.Write("o.pos.xy = o.pos.xy - o.pos.w * " I_PIXELCENTERCORRECTION ".xy;\n"); - if (uid_data->vertex_rounding) + if (vertex_rounding) { // By now our position is in clip space // however, higher resolutions than the Wii outputs @@ -493,7 +487,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da { if (g_ActiveConfig.backend_info.bSupportsGeometryShaders || api_type == APIType::Vulkan) { - AssignVSOutputMembers(out, "vs", "o", uid_data->numTexGens, uid_data->pixel_lighting); + AssignVSOutputMembers(out, "vs", "o", uid_data->numTexGens, per_pixel_lighting); } else { @@ -502,7 +496,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da for (unsigned int i = 0; i < uid_data->numTexGens; ++i) out.Write("uv%d.xyz = o.tex%d;\n", i, i); out.Write("clipPos = o.clipPos;\n"); - if (uid_data->pixel_lighting) + if (per_pixel_lighting) { out.Write("Normal = o.Normal;\n"); out.Write("WorldPos = o.WorldPos;\n"); diff --git a/Source/Core/VideoCommon/VertexShaderGen.h b/Source/Core/VideoCommon/VertexShaderGen.h index 0fa8e88815..8c6f14f0e6 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.h +++ b/Source/Core/VideoCommon/VertexShaderGen.h @@ -37,14 +37,10 @@ struct vertex_shader_uid_data u32 numTexGens : 4; u32 numColorChans : 2; u32 dualTexTrans_enabled : 1; - u32 pixel_lighting : 1; - u32 msaa : 1; u32 texMtxInfo_n_projection : 16; // Stored separately to guarantee that the texMtxInfo struct is // 8 bits wide - u32 ssaa : 1; - u32 vertex_rounding : 1; - u32 pad : 14; + u32 pad : 18; struct { diff --git a/Source/Core/VideoCommon/VideoConfig.cpp b/Source/Core/VideoCommon/VideoConfig.cpp index 7dc68abb72..d53e903cee 100644 --- a/Source/Core/VideoCommon/VideoConfig.cpp +++ b/Source/Core/VideoCommon/VideoConfig.cpp @@ -187,3 +187,19 @@ bool VideoConfig::IsVSync() { return bVSync && !Core::GetIsThrottlerTempDisabled(); } + +bool VideoConfig::IsStereoEnabled() const +{ + return iStereoMode > 0; +} + +bool VideoConfig::IsMSAAEnabled() const +{ + return iMultisamples > 1; +} + +bool VideoConfig::IsSSAAEnabled() const +{ + return iMultisamples > 1 && bSSAA && backend_info.bSupportsSSAA; +} + diff --git a/Source/Core/VideoCommon/VideoConfig.h b/Source/Core/VideoCommon/VideoConfig.h index e706cea1c3..dd7dd88fa4 100644 --- a/Source/Core/VideoCommon/VideoConfig.h +++ b/Source/Core/VideoCommon/VideoConfig.h @@ -223,6 +223,13 @@ struct VideoConfig final { return backend_info.bSupportsGPUTextureDecoding && bEnableGPUTextureDecoding; } + bool UseVertexRounding() const { return bVertexRounding && iEFBScale != SCALE_1X; } + bool IsStereoEnabled() const; + bool IsMSAAEnabled() const; + bool IsSSAAEnabled() const; + // Host config contains the settings which can influence generated shaders. + u32 GetHostConfigBits() const; + std::string GetHostConfigFilename() const; }; extern VideoConfig g_Config;