From 28c7113e41a70e278e033094d3088e58eeb00c88 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sat, 16 Jan 2016 23:49:39 +1300 Subject: [PATCH] Multithreadded Shadergen: Second Pass over geometery Shadergen --- .../VideoBackends/D3D/GeometryShaderCache.cpp | 6 +- .../Core/VideoBackends/D3D12/ShaderCache.cpp | 7 +- .../Core/VideoBackends/Null/ShaderCache.cpp | 2 +- Source/Core/VideoBackends/Null/ShaderCache.h | 18 ++-- .../VideoBackends/OGL/ProgramShaderCache.cpp | 7 +- Source/Core/VideoCommon/GeometryShaderGen.cpp | 95 +++++++++---------- Source/Core/VideoCommon/GeometryShaderGen.h | 5 +- 7 files changed, 69 insertions(+), 71 deletions(-) diff --git a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp index f899f7f078..72a9c6bb4c 100644 --- a/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D/GeometryShaderCache.cpp @@ -196,10 +196,10 @@ void GeometryShaderCache::Shutdown() bool GeometryShaderCache::SetShader(u32 primitive_type) { - GeometryShaderUid uid = GetGeometryShaderUid(primitive_type, API_D3D); + GeometryShaderUid uid = GetGeometryShaderUid(primitive_type); if (g_ActiveConfig.bEnableShaderDebugging) { - ShaderCode code = GenerateGeometryShaderCode(primitive_type, API_D3D); + ShaderCode code = GenerateGeometryShaderCode(primitive_type, API_D3D, uid.GetUidData()); geometry_uid_checker.AddToIndexAndCheck(code, uid, "Geometry", "g"); } @@ -235,7 +235,7 @@ bool GeometryShaderCache::SetShader(u32 primitive_type) } // Need to compile a new shader - ShaderCode code = GenerateGeometryShaderCode(primitive_type, API_D3D); + ShaderCode code = GenerateGeometryShaderCode(primitive_type, API_D3D, uid.GetUidData()); D3DBlob* pbytecode; if (!D3D::CompileGeometryShader(code.GetBuffer(), &pbytecode)) diff --git a/Source/Core/VideoBackends/D3D12/ShaderCache.cpp b/Source/Core/VideoBackends/D3D12/ShaderCache.cpp index 2f93956003..677d50f426 100644 --- a/Source/Core/VideoBackends/D3D12/ShaderCache.cpp +++ b/Source/Core/VideoBackends/D3D12/ShaderCache.cpp @@ -162,7 +162,7 @@ void ShaderCache::LoadAndSetActiveShaders(DSTALPHA_MODE ps_dst_alpha_mode, u32 g { SetCurrentPrimitiveTopology(gs_primitive_type); - GeometryShaderUid gs_uid = GetGeometryShaderUid(gs_primitive_type, API_D3D); + GeometryShaderUid gs_uid = GetGeometryShaderUid(gs_primitive_type); PixelShaderUid ps_uid = GetPixelShaderUid(ps_dst_alpha_mode, API_D3D); VertexShaderUid vs_uid = GetVertexShaderUid(API_D3D); @@ -219,7 +219,7 @@ void ShaderCache::HandleGSUIDChange(GeometryShaderUid gs_uid, u32 gs_primitive_t if (g_ActiveConfig.bEnableShaderDebugging) { - ShaderCode code = GenerateGeometryShaderCode(gs_primitive_type, API_D3D); + ShaderCode code = GenerateGeometryShaderCode(gs_primitive_type, API_D3D, gs_uid.GetUidData()); s_geometry_uid_checker.AddToIndexAndCheck(code, gs_uid, "Geometry", "g"); } @@ -236,7 +236,8 @@ void ShaderCache::HandleGSUIDChange(GeometryShaderUid gs_uid, u32 gs_primitive_t } else { - ShaderCode gs_code = GenerateGeometryShaderCode(gs_primitive_type, API_D3D); + ShaderCode gs_code = + GenerateGeometryShaderCode(gs_primitive_type, API_D3D, gs_uid.GetUidData()); ID3DBlob* gs_bytecode = nullptr; if (!D3D::CompileGeometryShader(gs_code.GetBuffer(), &gs_bytecode)) diff --git a/Source/Core/VideoBackends/Null/ShaderCache.cpp b/Source/Core/VideoBackends/Null/ShaderCache.cpp index e0fa000765..19dcc778d4 100644 --- a/Source/Core/VideoBackends/Null/ShaderCache.cpp +++ b/Source/Core/VideoBackends/Null/ShaderCache.cpp @@ -59,7 +59,7 @@ bool ShaderCache::SetShader(DSTALPHA_MODE dst_alpha_mode, u32 primitive_typ } // Need to compile a new shader - ShaderCode code = GenerateCode(dst_alpha_mode, primitive_type, API_OPENGL); + ShaderCode code = GenerateCode(dst_alpha_mode, primitive_type, API_OPENGL, uid); m_shaders.emplace(uid, code.GetBuffer()); GFX_DEBUGGER_PAUSE_AT(NEXT_PIXEL_SHADER_CHANGE, true); diff --git a/Source/Core/VideoBackends/Null/ShaderCache.h b/Source/Core/VideoBackends/Null/ShaderCache.h index 833c8acf36..3ef3479ed2 100644 --- a/Source/Core/VideoBackends/Null/ShaderCache.h +++ b/Source/Core/VideoBackends/Null/ShaderCache.h @@ -27,7 +27,7 @@ public: protected: virtual Uid GetUid(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, API_TYPE api_type) = 0; virtual ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, - API_TYPE api_type) = 0; + API_TYPE api_type, Uid uid) = 0; private: std::map m_shaders; @@ -47,8 +47,8 @@ protected: { return GetVertexShaderUid(api_type); } - ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, - API_TYPE api_type) override + ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, API_TYPE api_type, + VertexShaderUid uid) override { return GenerateVertexShaderCode(api_type); } @@ -63,12 +63,12 @@ protected: GeometryShaderUid GetUid(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, API_TYPE api_type) override { - return GetGeometryShaderUid(primitive_type, api_type); + return GetGeometryShaderUid(primitive_type); } - ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, - API_TYPE api_type) override + ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, API_TYPE api_type, + GeometryShaderUid uid) override { - return GenerateGeometryShaderCode(primitive_type, api_type); + return GenerateGeometryShaderCode(primitive_type, api_type, uid.GetUidData()); } }; @@ -83,8 +83,8 @@ protected: { return GetPixelShaderUid(dst_alpha_mode, api_type); } - ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, - API_TYPE api_type) override + ShaderCode GenerateCode(DSTALPHA_MODE dst_alpha_mode, u32 primitive_type, API_TYPE api_type, + PixelShaderUid) override { return GeneratePixelShaderCode(dst_alpha_mode, api_type); } diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp index 9ec9684224..4f1a5deb11 100644 --- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp +++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp @@ -214,7 +214,7 @@ SHADER* ProgramShaderCache::SetShader(DSTALPHA_MODE dstAlphaMode, u32 primitive_ ShaderCode gcode; if (g_ActiveConfig.backend_info.bSupportsGeometryShaders && !uid.guid.GetUidData()->IsPassthrough()) - gcode = GenerateGeometryShaderCode(primitive_type, API_OPENGL); + gcode = GenerateGeometryShaderCode(primitive_type, API_OPENGL, uid.guid.GetUidData()); if (g_ActiveConfig.bEnableShaderDebugging) { @@ -399,7 +399,7 @@ void ProgramShaderCache::GetShaderId(SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, { uid->puid = GetPixelShaderUid(dstAlphaMode, API_OPENGL); uid->vuid = GetVertexShaderUid(API_OPENGL); - uid->guid = GetGeometryShaderUid(primitive_type, API_OPENGL); + uid->guid = GetGeometryShaderUid(primitive_type); if (g_ActiveConfig.bEnableShaderDebugging) { @@ -409,7 +409,8 @@ void ProgramShaderCache::GetShaderId(SHADERUID* uid, DSTALPHA_MODE dstAlphaMode, ShaderCode vcode = GenerateVertexShaderCode(API_OPENGL); vertex_uid_checker.AddToIndexAndCheck(vcode, uid->vuid, "Vertex", "v"); - ShaderCode gcode = GenerateGeometryShaderCode(primitive_type, API_OPENGL); + ShaderCode gcode = + GenerateGeometryShaderCode(primitive_type, API_OPENGL, uid->guid.GetUidData()); geometry_uid_checker.AddToIndexAndCheck(gcode, uid->guid, "Geometry", "g"); } } diff --git a/Source/Core/VideoCommon/GeometryShaderGen.cpp b/Source/Core/VideoCommon/GeometryShaderGen.cpp index 6aa6b4951b..f509072f8e 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.cpp +++ b/Source/Core/VideoCommon/GeometryShaderGen.cpp @@ -20,34 +20,40 @@ static void EmitVertex(T& out, const char* vertex, API_TYPE ApiType, bool first_ template static void EndPrimitive(T& out, API_TYPE ApiType); -template -static void EmitVertex(T& out, geometry_shader_uid_data* uid_data, const char* vertex, - API_TYPE ApiType, bool first_vertex = false); -template -static void EndPrimitive(T& out, geometry_shader_uid_data* uid_data, API_TYPE ApiType); - -template -static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType) +GeometryShaderUid GetGeometryShaderUid(u32 primitive_type) { - T out; - // Non-uid template parameters will write to the dummy data (=> gets optimized out) - geometry_shader_uid_data dummy_data; - geometry_shader_uid_data* uid_data = out.template GetUidData(); - if (uid_data == nullptr) - uid_data = &dummy_data; - memset(uid_data, 0, sizeof(*uid_data)); + ShaderUid out; + geometry_shader_uid_data* uid_data = out.GetUidData(); + memset(uid_data, 0, sizeof(geometry_shader_uid_data)); uid_data->primitive_type = primitive_type; - const unsigned int vertex_in = primitive_type + 1; - unsigned int vertex_out = primitive_type == PRIMITIVE_TRIANGLES ? 3 : 4; - uid_data->wireframe = g_ActiveConfig.bWireFrame; - if (uid_data->wireframe) - vertex_out++; - 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, API_TYPE ApiType, bool first_vertex = false); +static void EndPrimitive(ShaderCode& out, const geometry_shader_uid_data* uid_data, + API_TYPE ApiType); + +ShaderCode GenerateGeometryShaderCode(u32 primitive_type, API_TYPE ApiType, + const geometry_shader_uid_data* uid_data) +{ + ShaderCode out; + // Non-uid template parameters will write to the dummy data (=> gets optimized out) + + const unsigned int vertex_in = primitive_type + 1; + unsigned int vertex_out = primitive_type == PRIMITIVE_TRIANGLES ? 3 : 4; + + if (uid_data->wireframe) + vertex_out++; + if (ApiType == API_OPENGL) { // Insert layout parameters @@ -80,11 +86,10 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType) "\tint4 " I_TEXOFFSET ";\n" "};\n"); - uid_data->numTexGens = xfmem.numTexGen.numTexGens; - uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting; out.Write("struct VS_OUTPUT {\n"); - GenerateVSOutputMembers(out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting, ""); + GenerateVSOutputMembers(out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting, + ""); out.Write("};\n"); if (ApiType == API_OPENGL) @@ -93,13 +98,13 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType) out.Write("#define InstanceID gl_InvocationID\n"); out.Write("in VertexData {\n"); - GenerateVSOutputMembers( + GenerateVSOutputMembers( out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting, GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, true, true)); out.Write("} vs[%d];\n", vertex_in); out.Write("out VertexData {\n"); - GenerateVSOutputMembers( + GenerateVSOutputMembers( out, ApiType, uid_data->numTexGens, uid_data->pixel_lighting, GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, false, true)); @@ -248,8 +253,8 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType) } out.Write("\t}\n"); - EmitVertex(out, uid_data, "l", ApiType, true); - EmitVertex(out, uid_data, "r", ApiType); + EmitVertex(out, uid_data, "l", ApiType, true); + EmitVertex(out, uid_data, "r", ApiType); } else if (primitive_type == PRIMITIVE_POINTS) { @@ -277,19 +282,19 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType) } 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, true); + EmitVertex(out, uid_data, "lr", ApiType); + EmitVertex(out, uid_data, "ul", ApiType); + EmitVertex(out, uid_data, "ur", ApiType); } else { - EmitVertex(out, uid_data, "f", ApiType, true); + EmitVertex(out, uid_data, "f", ApiType, true); } out.Write("\t}\n"); - EndPrimitive(out, uid_data, ApiType); + EndPrimitive(out, uid_data, ApiType); if (uid_data->stereo && !g_ActiveConfig.backend_info.bSupportsGSInstancing) out.Write("\t}\n"); @@ -299,9 +304,8 @@ static T GenerateGeometryShader(u32 primitive_type, API_TYPE ApiType) return out; } -template -static void EmitVertex(T& out, geometry_shader_uid_data* uid_data, const char* vertex, - API_TYPE ApiType, bool first_vertex) +static void EmitVertex(ShaderCode& out, const geometry_shader_uid_data* uid_data, + const char* vertex, API_TYPE ApiType, bool first_vertex) { if (uid_data->wireframe && first_vertex) out.Write("\tif (i == 0) first = %s;\n", vertex); @@ -321,24 +325,15 @@ static void EmitVertex(T& out, geometry_shader_uid_data* uid_data, const char* v else out.Write("\toutput.Append(ps);\n"); } -template -static void EndPrimitive(T& out, geometry_shader_uid_data* uid_data, API_TYPE ApiType) + +static void EndPrimitive(ShaderCode& out, const geometry_shader_uid_data* uid_data, + API_TYPE ApiType) { if (uid_data->wireframe) - EmitVertex(out, uid_data, "first", ApiType); + EmitVertex(out, uid_data, "first", ApiType); if (ApiType == API_OPENGL) out.Write("\tEndPrimitive();\n"); else out.Write("\toutput.RestartStrip();\n"); } - -GeometryShaderUid GetGeometryShaderUid(u32 primitive_type, API_TYPE ApiType) -{ - return GenerateGeometryShader(primitive_type, ApiType); -} - -ShaderCode GenerateGeometryShaderCode(u32 primitive_type, API_TYPE ApiType) -{ - return GenerateGeometryShader(primitive_type, ApiType); -} diff --git a/Source/Core/VideoCommon/GeometryShaderGen.h b/Source/Core/VideoCommon/GeometryShaderGen.h index fcf4f9c8db..0d10078836 100644 --- a/Source/Core/VideoCommon/GeometryShaderGen.h +++ b/Source/Core/VideoCommon/GeometryShaderGen.h @@ -31,5 +31,6 @@ struct geometry_shader_uid_data typedef ShaderUid GeometryShaderUid; -ShaderCode GenerateGeometryShaderCode(u32 primitive_type, API_TYPE ApiType); -GeometryShaderUid GetGeometryShaderUid(u32 primitive_type, API_TYPE ApiType); +ShaderCode GenerateGeometryShaderCode(u32 primitive_type, API_TYPE ApiType, + const geometry_shader_uid_data* uid_data); +GeometryShaderUid GetGeometryShaderUid(u32 primitive_type);