From 53c402dbc5cc25a62a1640ba8062fb8b2ebc1461 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Thu, 14 Jan 2016 18:51:37 +1300 Subject: Multithreadded Shadergen: First Pass over vertex/lighting Shadergens The only code which touches xfmem is code which writes directly into uid_data. All the rest now read their parameters out of uid_data. I also simplified the lighting code so it always generated seperate codepaths for alpha and color channels instead of trying to combine them on the off-chance that the same equation works for all 4 channels. As modern (post 2008) GPUs generally don't calcualte all 4 channels in a single vector, this optimisation is pointless. The shader compiler will undo it during the GLSL/HLSL to IR step. Bug Fix: The about optimisation was also broken, applying the color light equation to the alpha light channel instead of the alpha light euqation. But doesn't look like anything trigged this bug. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 123 ++++++++++++++-------------- 1 file changed, 60 insertions(+), 63 deletions(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 618d097370..464ce00a30 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -18,14 +18,12 @@ template static T GenerateVertexShader(API_TYPE api_type) { T out; - const u32 components = VertexLoaderManager::g_current_components; // Non-uid template parameters will write to the dummy data (=> gets optimized out) vertex_shader_uid_data dummy_data; vertex_shader_uid_data* uid_data = out.template GetUidData(); - if (uid_data != nullptr) - memset(uid_data, 0, sizeof(*uid_data)); - else + if (uid_data == nullptr) uid_data = &dummy_data; + memset(uid_data, 0, sizeof(*uid_data)); _assert_(bpmem.genMode.numtexgens == xfmem.numTexGen.numTexGens); _assert_(bpmem.genMode.numcolchans == xfmem.numChan.numColorChans); @@ -46,30 +44,30 @@ static T GenerateVertexShader(API_TYPE api_type) out.Write("};\n"); uid_data->numTexGens = xfmem.numTexGen.numTexGens; - uid_data->components = components; + uid_data->components = VertexLoaderManager::g_current_components; uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting; if (api_type == API_OPENGL) { out.Write("in float4 rawpos; // ATTR%d,\n", SHADER_POSITION_ATTRIB); - if (components & VB_HAS_POSMTXIDX) + if (uid_data->components & VB_HAS_POSMTXIDX) out.Write("in int posmtx; // ATTR%d,\n", SHADER_POSMTX_ATTRIB); - if (components & VB_HAS_NRM0) + if (uid_data->components & VB_HAS_NRM0) out.Write("in float3 rawnorm0; // ATTR%d,\n", SHADER_NORM0_ATTRIB); - if (components & VB_HAS_NRM1) + if (uid_data->components & VB_HAS_NRM1) out.Write("in float3 rawnorm1; // ATTR%d,\n", SHADER_NORM1_ATTRIB); - if (components & VB_HAS_NRM2) + if (uid_data->components & VB_HAS_NRM2) out.Write("in float3 rawnorm2; // ATTR%d,\n", SHADER_NORM2_ATTRIB); - if (components & VB_HAS_COL0) + if (uid_data->components & VB_HAS_COL0) out.Write("in float4 color0; // ATTR%d,\n", SHADER_COLOR0_ATTRIB); - if (components & VB_HAS_COL1) + if (uid_data->components & VB_HAS_COL1) out.Write("in float4 color1; // ATTR%d,\n", SHADER_COLOR1_ATTRIB); for (int i = 0; i < 8; ++i) { - u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0 << i)); - if ((components & (VB_HAS_UV0 << i)) || hastexmtx) + u32 hastexmtx = (uid_data->components & (VB_HAS_TEXMTXIDX0 << i)); + if ((uid_data->components & (VB_HAS_UV0 << i)) || hastexmtx) out.Write("in float%d tex%d; // ATTR%d,\n", hastexmtx ? 3 : 2, i, SHADER_TEXTURE0_ATTRIB + i); } @@ -85,13 +83,13 @@ static T GenerateVertexShader(API_TYPE api_type) // Let's set up attributes for (u32 i = 0; i < 8; ++i) { - if (i < xfmem.numTexGen.numTexGens) + if (i < uid_data->numTexGens) { out.Write("%s out float3 uv%u;\n", GetInterpolationQualifier(), i); } } out.Write("%s out float4 clipPos;\n", GetInterpolationQualifier()); - if (g_ActiveConfig.bEnablePixelLighting) + if (uid_data->pixel_lighting) { out.Write("%s out float3 Normal;\n", GetInterpolationQualifier()); out.Write("%s out float3 WorldPos;\n", GetInterpolationQualifier()); @@ -107,23 +105,23 @@ static T GenerateVertexShader(API_TYPE api_type) out.Write("VS_OUTPUT main(\n"); // inputs - if (components & VB_HAS_NRM0) + if (uid_data->components & VB_HAS_NRM0) out.Write(" float3 rawnorm0 : NORMAL0,\n"); - if (components & VB_HAS_NRM1) + if (uid_data->components & VB_HAS_NRM1) out.Write(" float3 rawnorm1 : NORMAL1,\n"); - if (components & VB_HAS_NRM2) + if (uid_data->components & VB_HAS_NRM2) out.Write(" float3 rawnorm2 : NORMAL2,\n"); - if (components & VB_HAS_COL0) + if (uid_data->components & VB_HAS_COL0) out.Write(" float4 color0 : COLOR0,\n"); - if (components & VB_HAS_COL1) + if (uid_data->components & VB_HAS_COL1) out.Write(" float4 color1 : COLOR1,\n"); for (int i = 0; i < 8; ++i) { - u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0 << i)); - if ((components & (VB_HAS_UV0 << i)) || hastexmtx) + u32 hastexmtx = (uid_data->components & (VB_HAS_TEXMTXIDX0 << i)); + if ((uid_data->components & (VB_HAS_UV0 << i)) || hastexmtx) out.Write(" float%d tex%d : TEXCOORD%d,\n", hastexmtx ? 3 : 2, i, i); } - if (components & VB_HAS_POSMTXIDX) + if (uid_data->components & VB_HAS_POSMTXIDX) out.Write(" int posmtx : BLENDINDICES,\n"); out.Write(" float4 rawpos : POSITION) {\n"); } @@ -131,26 +129,26 @@ static T GenerateVertexShader(API_TYPE api_type) out.Write("VS_OUTPUT o;\n"); // transforms - if (components & VB_HAS_POSMTXIDX) + if (uid_data->components & VB_HAS_POSMTXIDX) { out.Write("float4 pos = float4(dot(" I_TRANSFORMMATRICES "[posmtx], rawpos), dot(" I_TRANSFORMMATRICES "[posmtx+1], rawpos), dot(" I_TRANSFORMMATRICES "[posmtx+2], rawpos), 1);\n"); - if (components & VB_HAS_NRMALL) + if (uid_data->components & VB_HAS_NRMALL) { out.Write("int normidx = posmtx & 31;\n"); out.Write("float3 N0 = " I_NORMALMATRICES "[normidx].xyz, N1 = " I_NORMALMATRICES "[normidx+1].xyz, N2 = " I_NORMALMATRICES "[normidx+2].xyz;\n"); } - if (components & VB_HAS_NRM0) + if (uid_data->components & VB_HAS_NRM0) out.Write("float3 _norm0 = normalize(float3(dot(N0, rawnorm0), dot(N1, rawnorm0), dot(N2, " "rawnorm0)));\n"); - if (components & VB_HAS_NRM1) + if (uid_data->components & VB_HAS_NRM1) out.Write( "float3 _norm1 = float3(dot(N0, rawnorm1), dot(N1, rawnorm1), dot(N2, rawnorm1));\n"); - if (components & VB_HAS_NRM2) + if (uid_data->components & VB_HAS_NRM2) out.Write( "float3 _norm2 = float3(dot(N0, rawnorm2), dot(N1, rawnorm2), dot(N2, rawnorm2));\n"); } @@ -158,21 +156,21 @@ static T GenerateVertexShader(API_TYPE api_type) { out.Write("float4 pos = float4(dot(" I_POSNORMALMATRIX "[0], rawpos), dot(" I_POSNORMALMATRIX "[1], rawpos), dot(" I_POSNORMALMATRIX "[2], rawpos), 1.0);\n"); - if (components & VB_HAS_NRM0) + if (uid_data->components & VB_HAS_NRM0) out.Write("float3 _norm0 = normalize(float3(dot(" I_POSNORMALMATRIX "[3].xyz, rawnorm0), dot(" I_POSNORMALMATRIX "[4].xyz, rawnorm0), dot(" I_POSNORMALMATRIX "[5].xyz, rawnorm0)));\n"); - if (components & VB_HAS_NRM1) + if (uid_data->components & VB_HAS_NRM1) out.Write("float3 _norm1 = float3(dot(" I_POSNORMALMATRIX "[3].xyz, rawnorm1), dot(" I_POSNORMALMATRIX "[4].xyz, rawnorm1), dot(" I_POSNORMALMATRIX "[5].xyz, rawnorm1));\n"); - if (components & VB_HAS_NRM2) + if (uid_data->components & VB_HAS_NRM2) out.Write("float3 _norm2 = float3(dot(" I_POSNORMALMATRIX "[3].xyz, rawnorm2), dot(" I_POSNORMALMATRIX "[4].xyz, rawnorm2), dot(" I_POSNORMALMATRIX "[5].xyz, rawnorm2));\n"); } - if (!(components & VB_HAS_NRM0)) + if (!(uid_data->components & VB_HAS_NRM0)) out.Write("float3 _norm0 = float3(0.0, 0.0, 0.0);\n"); out.Write("o.pos = float4(dot(" I_PROJECTION "[0], pos), dot(" I_PROJECTION @@ -183,19 +181,19 @@ static T GenerateVertexShader(API_TYPE api_type) "float dist, dist2, attn;\n"); uid_data->numColorChans = xfmem.numChan.numColorChans; - if (xfmem.numChan.numColorChans == 0) + if (uid_data->numColorChans == 0) { - if (components & VB_HAS_COL0) + if (uid_data->components & VB_HAS_COL0) out.Write("o.colors_0 = color0;\n"); else out.Write("o.colors_0 = float4(1.0, 1.0, 1.0, 1.0);\n"); } - GenerateLightingShader(out, uid_data->lighting, components, "color", "o.colors_"); + GenerateLightingShader(out, uid_data->lighting, uid_data->components, "color", "o.colors_"); - if (xfmem.numChan.numColorChans < 2) + if (uid_data->numColorChans < 2) { - if (components & VB_HAS_COL1) + if (uid_data->components & VB_HAS_COL1) out.Write("o.colors_1 = color1;\n"); else out.Write("o.colors_1 = o.colors_0;\n"); @@ -203,20 +201,21 @@ static T GenerateVertexShader(API_TYPE api_type) // transform texcoords out.Write("float4 coord = float4(0.0, 0.0, 1.0, 1.0);\n"); - for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i) + for (unsigned int i = 0; i < uid_data->numTexGens; ++i) { - TexMtxInfo& texinfo = xfmem.texMtxInfo[i]; + auto& texinfo = uid_data->texMtxInfo[i]; out.Write("{\n"); out.Write("coord = float4(0.0, 0.0, 1.0, 1.0);\n"); - uid_data->texMtxInfo[i].sourcerow = xfmem.texMtxInfo[i].sourcerow; + texinfo.sourcerow = xfmem.texMtxInfo[i].sourcerow; + texinfo.texgentype = xfmem.texMtxInfo[i].texgentype; switch (texinfo.sourcerow) { case XF_SRCGEOM_INROW: out.Write("coord.xyz = rawpos.xyz;\n"); break; case XF_SRCNORMAL_INROW: - if (components & VB_HAS_NRM0) + if (uid_data->components & VB_HAS_NRM0) { out.Write("coord.xyz = rawnorm0.xyz;\n"); } @@ -226,20 +225,20 @@ static T GenerateVertexShader(API_TYPE api_type) texinfo.texgentype == XF_TEXGEN_COLOR_STRGBC1); break; case XF_SRCBINORMAL_T_INROW: - if (components & VB_HAS_NRM1) + if (uid_data->components & VB_HAS_NRM1) { out.Write("coord.xyz = rawnorm1.xyz;\n"); } break; case XF_SRCBINORMAL_B_INROW: - if (components & VB_HAS_NRM2) + if (uid_data->components & VB_HAS_NRM2) { out.Write("coord.xyz = rawnorm2.xyz;\n"); } break; default: _assert_(texinfo.sourcerow <= XF_SRCTEX7_INROW); - if (components & (VB_HAS_UV0 << (texinfo.sourcerow - XF_SRCTEX0_INROW))) + if (uid_data->components & (VB_HAS_UV0 << (texinfo.sourcerow - XF_SRCTEX0_INROW))) out.Write("coord = float4(tex%d.x, tex%d.y, 1.0, 1.0);\n", texinfo.sourcerow - XF_SRCTEX0_INROW, texinfo.sourcerow - XF_SRCTEX0_INROW); break; @@ -250,16 +249,15 @@ static T GenerateVertexShader(API_TYPE api_type) out.Write("coord.z = 1.0;\n"); // first transformation - uid_data->texMtxInfo[i].texgentype = xfmem.texMtxInfo[i].texgentype; switch (texinfo.texgentype) { case XF_TEXGEN_EMBOSS_MAP: // calculate tex coords into bump map - if (components & (VB_HAS_NRM1 | VB_HAS_NRM2)) + if (uid_data->components & (VB_HAS_NRM1 | VB_HAS_NRM2)) { // transform the light dir into tangent space - uid_data->texMtxInfo[i].embosslightshift = xfmem.texMtxInfo[i].embosslightshift; - uid_data->texMtxInfo[i].embosssourceshift = xfmem.texMtxInfo[i].embosssourceshift; + texinfo.embosslightshift = xfmem.texMtxInfo[i].embosslightshift; + texinfo.embosssourceshift = xfmem.texMtxInfo[i].embosssourceshift; out.Write("ldir = normalize(" LIGHT_POS ".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(texinfo.embosslightshift)); out.Write( @@ -271,7 +269,7 @@ static T GenerateVertexShader(API_TYPE api_type) // The following assert was triggered in House of the Dead Overkill and Star Wars Rogue // Squadron 2 //_assert_(0); // should have normals - uid_data->texMtxInfo[i].embosssourceshift = xfmem.texMtxInfo[i].embosssourceshift; + texinfo.embosssourceshift = xfmem.texMtxInfo[i].embosssourceshift; out.Write("o.tex%d.xyz = o.tex%d.xyz;\n", i, texinfo.embosssourceshift); } @@ -285,10 +283,10 @@ static T GenerateVertexShader(API_TYPE api_type) case XF_TEXGEN_REGULAR: default: uid_data->texMtxInfo_n_projection |= xfmem.texMtxInfo[i].projection << i; - if (components & (VB_HAS_TEXMTXIDX0 << i)) + if (uid_data->components & (VB_HAS_TEXMTXIDX0 << i)) { out.Write("int tmp = int(tex%d.z);\n", i); - if (texinfo.projection == XF_TEXPROJ_STQ) + if (((uid_data->texMtxInfo_n_projection >> i) & 1) == XF_TEXPROJ_STQ) out.Write("o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES "[tmp]), dot(coord, " I_TRANSFORMMATRICES "[tmp+1]), dot(coord, " I_TRANSFORMMATRICES "[tmp+2]));\n", @@ -300,7 +298,7 @@ static T GenerateVertexShader(API_TYPE api_type) } else { - if (texinfo.projection == XF_TEXPROJ_STQ) + if (((uid_data->texMtxInfo_n_projection >> i) & 1) == XF_TEXPROJ_STQ) out.Write("o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES "[%d]), dot(coord, " I_TEXMATRICES "[%d]), dot(coord, " I_TEXMATRICES "[%d]));\n", @@ -315,18 +313,17 @@ static T GenerateVertexShader(API_TYPE api_type) uid_data->dualTexTrans_enabled = xfmem.dualTexTrans.enabled; // CHECKME: does this only work for regular tex gen types? - if (xfmem.dualTexTrans.enabled && texinfo.texgentype == XF_TEXGEN_REGULAR) + if (uid_data->dualTexTrans_enabled && texinfo.texgentype == XF_TEXGEN_REGULAR) { - const PostMtxInfo& postInfo = xfmem.postMtxInfo[i]; + auto& postInfo = uid_data->postMtxInfo[i]; - uid_data->postMtxInfo[i].index = xfmem.postMtxInfo[i].index; - int postidx = postInfo.index; + postInfo.index = xfmem.postMtxInfo[i].index; out.Write("float4 P0 = " I_POSTTRANSFORMMATRICES "[%d];\n" "float4 P1 = " I_POSTTRANSFORMMATRICES "[%d];\n" "float4 P2 = " I_POSTTRANSFORMMATRICES "[%d];\n", - postidx & 0x3f, (postidx + 1) & 0x3f, (postidx + 2) & 0x3f); + postInfo.index & 0x3f, (postInfo.index + 1) & 0x3f, (postInfo.index + 2) & 0x3f); - uid_data->postMtxInfo[i].normalize = xfmem.postMtxInfo[i].normalize; + postInfo.normalize = xfmem.postMtxInfo[i].normalize; if (postInfo.normalize) out.Write("o.tex%d.xyz = normalize(o.tex%d.xyz);\n", i, i); @@ -342,15 +339,15 @@ static T GenerateVertexShader(API_TYPE api_type) // clipPos/w needs to be done in pixel shader, not here out.Write("o.clipPos = o.pos;\n"); - if (g_ActiveConfig.bEnablePixelLighting) + if (uid_data->pixel_lighting) { out.Write("o.Normal = _norm0;\n"); out.Write("o.WorldPos = pos.xyz;\n"); - if (components & VB_HAS_COL0) + if (uid_data->components & VB_HAS_COL0) out.Write("o.colors_0 = color0;\n"); - if (components & VB_HAS_COL1) + if (uid_data->components & VB_HAS_COL1) out.Write("o.colors_1 = color1;\n"); } @@ -396,10 +393,10 @@ static T GenerateVertexShader(API_TYPE api_type) { // TODO: Pass interface blocks between shader stages even if geometry shaders // are not supported, however that will require at least OpenGL 3.2 support. - for (unsigned int i = 0; i < xfmem.numTexGen.numTexGens; ++i) + 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 (g_ActiveConfig.bEnablePixelLighting) + if (uid_data->pixel_lighting) { out.Write("Normal = o.Normal;\n"); out.Write("WorldPos = o.WorldPos;\n"); -- cgit v1.2.3 From 4969415f38e2d29666e550aa94608559a3e001a4 Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sat, 16 Jan 2016 22:56:49 +1300 Subject: Remove global refrences from common code. Bug Fix: Previously vertex shaders and geometery shaders didn't track antialaising state in their UIDs, which could cause AA bugs on directx. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 34 +++++++++++++++++++---------- 1 file changed, 22 insertions(+), 12 deletions(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 464ce00a30..f417988a21 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -39,13 +39,15 @@ static T GenerateVertexShader(API_TYPE api_type) out.Write(s_shader_uniforms); out.Write("};\n"); - out.Write("struct VS_OUTPUT {\n"); - GenerateVSOutputMembers(out, api_type, ""); - out.Write("};\n"); - uid_data->numTexGens = xfmem.numTexGen.numTexGens; uid_data->components = VertexLoaderManager::g_current_components; uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting; + uid_data->msaa = g_ActiveConfig.iMultisamples > 1; + uid_data->ssaa = g_ActiveConfig.iMultisamples > 1 && g_ActiveConfig.bSSAA; + + out.Write("struct VS_OUTPUT {\n"); + GenerateVSOutputMembers(out, api_type, uid_data->numTexGens, uid_data->pixel_lighting, ""); + out.Write("};\n"); if (api_type == API_OPENGL) { @@ -75,7 +77,9 @@ static T GenerateVertexShader(API_TYPE api_type) if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) { out.Write("out VertexData {\n"); - GenerateVSOutputMembers(out, api_type, GetInterpolationQualifier(true, false)); + GenerateVSOutputMembers( + out, api_type, uid_data->numTexGens, uid_data->pixel_lighting, + GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, false, true)); out.Write("} vs;\n"); } else @@ -85,17 +89,23 @@ static T GenerateVertexShader(API_TYPE api_type) { if (i < uid_data->numTexGens) { - out.Write("%s out float3 uv%u;\n", GetInterpolationQualifier(), i); + out.Write("%s out float3 uv%u;\n", + GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa), i); } } - out.Write("%s out float4 clipPos;\n", GetInterpolationQualifier()); + out.Write("%s out float4 clipPos;\n", + GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa)); if (uid_data->pixel_lighting) { - out.Write("%s out float3 Normal;\n", GetInterpolationQualifier()); - out.Write("%s out float3 WorldPos;\n", GetInterpolationQualifier()); + 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 float4 colors_0;\n", GetInterpolationQualifier()); - out.Write("%s out float4 colors_1;\n", GetInterpolationQualifier()); + 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("void main()\n{\n"); @@ -387,7 +397,7 @@ static T GenerateVertexShader(API_TYPE api_type) { if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) { - AssignVSOutputMembers(out, "vs", "o"); + AssignVSOutputMembers(out, "vs", "o", uid_data->numTexGens, uid_data->pixel_lighting); } else { -- cgit v1.2.3 From 1a831cfc7d4c43f418ae4d65b579bf430aeb278d Mon Sep 17 00:00:00 2001 From: Scott Mansell Date: Sun, 17 Jan 2016 00:34:06 +1300 Subject: Multithreadded Shadergen: Second Pass over vertex/lighting Shadergens As much as possible, the asserts have been moved out of the GetUID function. But there are some places where asserts depend on variables that aren't stored in the shader UID. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 103 ++++++++++++++++++---------- 1 file changed, 65 insertions(+), 38 deletions(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index f417988a21..77444e7dfc 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -14,20 +14,73 @@ #include "VideoCommon/VertexShaderGen.h" #include "VideoCommon/VideoConfig.h" -template -static T GenerateVertexShader(API_TYPE api_type) +VertexShaderUid GetVertexShaderUid() { - T out; - // Non-uid template parameters will write to the dummy data (=> gets optimized out) - vertex_shader_uid_data dummy_data; - vertex_shader_uid_data* uid_data = out.template GetUidData(); - if (uid_data == nullptr) - uid_data = &dummy_data; + VertexShaderUid out; + vertex_shader_uid_data* uid_data = out.GetUidData(); memset(uid_data, 0, sizeof(*uid_data)); _assert_(bpmem.genMode.numtexgens == xfmem.numTexGen.numTexGens); _assert_(bpmem.genMode.numcolchans == xfmem.numChan.numColorChans); + uid_data->numTexGens = xfmem.numTexGen.numTexGens; + uid_data->components = VertexLoaderManager::g_current_components; + uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting; + 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); + + // transform texcoords + for (unsigned int i = 0; i < uid_data->numTexGens; ++i) + { + auto& texinfo = uid_data->texMtxInfo[i]; + + texinfo.sourcerow = xfmem.texMtxInfo[i].sourcerow; + texinfo.texgentype = xfmem.texMtxInfo[i].texgentype; + texinfo.inputform = xfmem.texMtxInfo[i].inputform; + + // first transformation + switch (texinfo.texgentype) + { + case XF_TEXGEN_EMBOSS_MAP: // calculate tex coords into bump map + if (uid_data->components & (VB_HAS_NRM1 | VB_HAS_NRM2)) + { + // transform the light dir into tangent space + texinfo.embosslightshift = xfmem.texMtxInfo[i].embosslightshift; + texinfo.embosssourceshift = xfmem.texMtxInfo[i].embosssourceshift; + } + else + { + texinfo.embosssourceshift = xfmem.texMtxInfo[i].embosssourceshift; + } + break; + case XF_TEXGEN_COLOR_STRGBC0: + case XF_TEXGEN_COLOR_STRGBC1: + break; + case XF_TEXGEN_REGULAR: + default: + uid_data->texMtxInfo_n_projection |= xfmem.texMtxInfo[i].projection << i; + break; + } + + uid_data->dualTexTrans_enabled = xfmem.dualTexTrans.enabled; + // CHECKME: does this only work for regular tex gen types? + if (uid_data->dualTexTrans_enabled && texinfo.texgentype == XF_TEXGEN_REGULAR) + { + auto& postInfo = uid_data->postMtxInfo[i]; + postInfo.index = xfmem.postMtxInfo[i].index; + postInfo.normalize = xfmem.postMtxInfo[i].normalize; + } + } + + return out; +} + +ShaderCode GenerateVertexShaderCode(API_TYPE api_type, const vertex_shader_uid_data* uid_data) +{ + ShaderCode out; out.Write("%s", s_lighting_struct); // uniforms @@ -39,14 +92,8 @@ static T GenerateVertexShader(API_TYPE api_type) out.Write(s_shader_uniforms); out.Write("};\n"); - uid_data->numTexGens = xfmem.numTexGen.numTexGens; - uid_data->components = VertexLoaderManager::g_current_components; - uid_data->pixel_lighting = g_ActiveConfig.bEnablePixelLighting; - uid_data->msaa = g_ActiveConfig.iMultisamples > 1; - uid_data->ssaa = g_ActiveConfig.iMultisamples > 1 && g_ActiveConfig.bSSAA; - out.Write("struct VS_OUTPUT {\n"); - GenerateVSOutputMembers(out, api_type, uid_data->numTexGens, uid_data->pixel_lighting, ""); + GenerateVSOutputMembers(out, api_type, uid_data->numTexGens, uid_data->pixel_lighting, ""); out.Write("};\n"); if (api_type == API_OPENGL) @@ -77,7 +124,7 @@ static T GenerateVertexShader(API_TYPE api_type) if (g_ActiveConfig.backend_info.bSupportsGeometryShaders) { out.Write("out VertexData {\n"); - GenerateVSOutputMembers( + GenerateVSOutputMembers( out, api_type, uid_data->numTexGens, uid_data->pixel_lighting, GetInterpolationQualifier(uid_data->msaa, uid_data->ssaa, false, true)); out.Write("} vs;\n"); @@ -190,7 +237,6 @@ static T GenerateVertexShader(API_TYPE api_type) "float3 ldir, h, cosAttn, distAttn;\n" "float dist, dist2, attn;\n"); - uid_data->numColorChans = xfmem.numChan.numColorChans; if (uid_data->numColorChans == 0) { if (uid_data->components & VB_HAS_COL0) @@ -199,7 +245,7 @@ static T GenerateVertexShader(API_TYPE api_type) out.Write("o.colors_0 = float4(1.0, 1.0, 1.0, 1.0);\n"); } - GenerateLightingShader(out, uid_data->lighting, uid_data->components, "color", "o.colors_"); + GenerateLightingShaderCode(out, uid_data->lighting, uid_data->components, "color", "o.colors_"); if (uid_data->numColorChans < 2) { @@ -217,8 +263,6 @@ static T GenerateVertexShader(API_TYPE api_type) out.Write("{\n"); out.Write("coord = float4(0.0, 0.0, 1.0, 1.0);\n"); - texinfo.sourcerow = xfmem.texMtxInfo[i].sourcerow; - texinfo.texgentype = xfmem.texMtxInfo[i].texgentype; switch (texinfo.sourcerow) { case XF_SRCGEOM_INROW: @@ -254,7 +298,7 @@ static T GenerateVertexShader(API_TYPE api_type) break; } // Input form of AB11 sets z element to 1.0 - uid_data->texMtxInfo[i].inputform = xfmem.texMtxInfo[i].inputform; + if (texinfo.inputform == XF_TEXINPUT_AB11) out.Write("coord.z = 1.0;\n"); @@ -266,8 +310,6 @@ static T GenerateVertexShader(API_TYPE api_type) if (uid_data->components & (VB_HAS_NRM1 | VB_HAS_NRM2)) { // transform the light dir into tangent space - texinfo.embosslightshift = xfmem.texMtxInfo[i].embosslightshift; - texinfo.embosssourceshift = xfmem.texMtxInfo[i].embosssourceshift; out.Write("ldir = normalize(" LIGHT_POS ".xyz - pos.xyz);\n", LIGHT_POS_PARAMS(texinfo.embosslightshift)); out.Write( @@ -279,7 +321,6 @@ static T GenerateVertexShader(API_TYPE api_type) // The following assert was triggered in House of the Dead Overkill and Star Wars Rogue // Squadron 2 //_assert_(0); // should have normals - texinfo.embosssourceshift = xfmem.texMtxInfo[i].embosssourceshift; out.Write("o.tex%d.xyz = o.tex%d.xyz;\n", i, texinfo.embosssourceshift); } @@ -292,7 +333,6 @@ static T GenerateVertexShader(API_TYPE api_type) break; case XF_TEXGEN_REGULAR: default: - uid_data->texMtxInfo_n_projection |= xfmem.texMtxInfo[i].projection << i; if (uid_data->components & (VB_HAS_TEXMTXIDX0 << i)) { out.Write("int tmp = int(tex%d.z);\n", i); @@ -321,19 +361,16 @@ static T GenerateVertexShader(API_TYPE api_type) break; } - uid_data->dualTexTrans_enabled = xfmem.dualTexTrans.enabled; // CHECKME: does this only work for regular tex gen types? if (uid_data->dualTexTrans_enabled && texinfo.texgentype == XF_TEXGEN_REGULAR) { auto& postInfo = uid_data->postMtxInfo[i]; - postInfo.index = xfmem.postMtxInfo[i].index; out.Write("float4 P0 = " I_POSTTRANSFORMMATRICES "[%d];\n" "float4 P1 = " I_POSTTRANSFORMMATRICES "[%d];\n" "float4 P2 = " I_POSTTRANSFORMMATRICES "[%d];\n", postInfo.index & 0x3f, (postInfo.index + 1) & 0x3f, (postInfo.index + 2) & 0x3f); - postInfo.normalize = xfmem.postMtxInfo[i].normalize; if (postInfo.normalize) out.Write("o.tex%d.xyz = normalize(o.tex%d.xyz);\n", i, i); @@ -425,13 +462,3 @@ static T GenerateVertexShader(API_TYPE api_type) return out; } - -VertexShaderUid GetVertexShaderUid(API_TYPE api_type) -{ - return GenerateVertexShader(api_type); -} - -ShaderCode GenerateVertexShaderCode(API_TYPE api_type) -{ - return GenerateVertexShader(api_type); -} -- cgit v1.2.3