UberShaderCommon: Migrate over to fmt

Continues migration of the shader generators over to fmt.
This commit is contained in:
Lioncash 2020-10-19 21:32:20 -04:00
parent 213072b73a
commit 83db7a707c
2 changed files with 164 additions and 165 deletions

View File

@ -18,13 +18,14 @@ void WriteUberShaderCommonHeader(ShaderCode& out, APIType api_type,
// ============================================== // ==============================================
if (!host_config.backend_bitfield) if (!host_config.backend_bitfield)
{ {
out.Write("uint bitfieldExtract(uint val, int off, int size) {\n" out.WriteFmt(
"uint bitfieldExtract(uint val, int off, int size) {{\n"
" // This built-in function is only support in OpenGL 4.0+ and ES 3.1+\n" " // This built-in function is only support in OpenGL 4.0+ and ES 3.1+\n"
" // Microsoft's HLSL compiler automatically optimises this to a bitfield extract " " // Microsoft's HLSL compiler automatically optimises this to a bitfield extract "
"instruction.\n" "instruction.\n"
" uint mask = uint((1 << size) - 1);\n" " uint mask = uint((1 << size) - 1);\n"
" return uint(val >> off) & mask;\n" " return uint(val >> off) & mask;\n"
"}\n\n"); "}}\n\n");
} }
} }
@ -33,169 +34,167 @@ void WriteLightingFunction(ShaderCode& out)
// ============================================== // ==============================================
// Lighting channel calculation helper // Lighting channel calculation helper
// ============================================== // ==============================================
out.Write("int4 CalculateLighting(uint index, uint attnfunc, uint diffusefunc, float3 pos, " out.WriteFmt("int4 CalculateLighting(uint index, uint attnfunc, uint diffusefunc, float3 pos, "
"float3 normal) {\n" "float3 normal) {{\n"
" float3 ldir, h, cosAttn, distAttn;\n" " float3 ldir, h, cosAttn, distAttn;\n"
" float dist, dist2, attn;\n" " float dist, dist2, attn;\n"
"\n" "\n"
" switch (attnfunc) {\n"); " switch (attnfunc) {{\n");
out.Write(" case %uu: // LIGNTATTN_NONE\n", LIGHTATTN_NONE); out.WriteFmt(" case {}u: // LIGNTATTN_NONE\n", LIGHTATTN_NONE);
out.Write(" case %uu: // LIGHTATTN_DIR\n", LIGHTATTN_DIR); out.WriteFmt(" case {}u: // LIGHTATTN_DIR\n", LIGHTATTN_DIR);
out.Write(" ldir = normalize(" I_LIGHTS "[index].pos.xyz - pos.xyz);\n" out.WriteFmt(" ldir = normalize(" I_LIGHTS "[index].pos.xyz - pos.xyz);\n"
" attn = 1.0;\n" " attn = 1.0;\n"
" if (length(ldir) == 0.0)\n" " if (length(ldir) == 0.0)\n"
" ldir = normal;\n" " ldir = normal;\n"
" break;\n\n"); " break;\n\n");
out.Write(" case %uu: // LIGHTATTN_SPEC\n", LIGHTATTN_SPEC); out.WriteFmt(" case {}u: // LIGHTATTN_SPEC\n", LIGHTATTN_SPEC);
out.Write(" ldir = normalize(" I_LIGHTS "[index].pos.xyz - pos.xyz);\n" out.WriteFmt(" ldir = normalize(" I_LIGHTS "[index].pos.xyz - pos.xyz);\n"
" attn = (dot(normal, ldir) >= 0.0) ? max(0.0, dot(normal, " I_LIGHTS " attn = (dot(normal, ldir) >= 0.0) ? max(0.0, dot(normal, " I_LIGHTS
"[index].dir.xyz)) : 0.0;\n" "[index].dir.xyz)) : 0.0;\n"
" cosAttn = " I_LIGHTS "[index].cosatt.xyz;\n"); " cosAttn = " I_LIGHTS "[index].cosatt.xyz;\n");
out.Write(" if (diffusefunc == %uu) // LIGHTDIF_NONE\n", LIGHTDIF_NONE); out.WriteFmt(" if (diffusefunc == {}u) // LIGHTDIF_NONE\n", LIGHTDIF_NONE);
out.Write(" distAttn = " I_LIGHTS "[index].distatt.xyz;\n" out.WriteFmt(" distAttn = " I_LIGHTS "[index].distatt.xyz;\n"
" else\n" " else\n"
" distAttn = normalize(" I_LIGHTS "[index].distatt.xyz);\n" " distAttn = normalize(" I_LIGHTS "[index].distatt.xyz);\n"
" attn = max(0.0, dot(cosAttn, float3(1.0, attn, attn*attn))) / dot(distAttn, " " attn = max(0.0, dot(cosAttn, float3(1.0, attn, attn*attn))) / dot(distAttn, "
"float3(1.0, attn, attn*attn));\n" "float3(1.0, attn, attn*attn));\n"
" break;\n\n"); " break;\n\n");
out.Write(" case %uu: // LIGHTATTN_SPOT\n", LIGHTATTN_SPOT); out.WriteFmt(" case {}u: // LIGHTATTN_SPOT\n", LIGHTATTN_SPOT);
out.Write(" ldir = " I_LIGHTS "[index].pos.xyz - pos.xyz;\n" out.WriteFmt(" ldir = " I_LIGHTS "[index].pos.xyz - pos.xyz;\n"
" dist2 = dot(ldir, ldir);\n" " dist2 = dot(ldir, ldir);\n"
" dist = sqrt(dist2);\n" " dist = sqrt(dist2);\n"
" ldir = ldir / dist;\n" " ldir = ldir / dist;\n"
" attn = max(0.0, dot(ldir, " I_LIGHTS "[index].dir.xyz));\n" " attn = max(0.0, dot(ldir, " I_LIGHTS "[index].dir.xyz));\n"
" attn = max(0.0, " I_LIGHTS "[index].cosatt.x + " I_LIGHTS " attn = max(0.0, " I_LIGHTS "[index].cosatt.x + " I_LIGHTS
"[index].cosatt.y * attn + " I_LIGHTS "[index].cosatt.z * attn * attn) / dot(" I_LIGHTS "[index].cosatt.y * attn + " I_LIGHTS
"[index].cosatt.z * attn * attn) / dot(" I_LIGHTS
"[index].distatt.xyz, float3(1.0, dist, dist2));\n" "[index].distatt.xyz, float3(1.0, dist, dist2));\n"
" break;\n\n"); " break;\n\n");
out.Write(" default:\n" out.WriteFmt(" default:\n"
" attn = 1.0;\n" " attn = 1.0;\n"
" ldir = normal;\n" " ldir = normal;\n"
" break;\n" " break;\n"
" }\n" " }}\n"
"\n" "\n"
" switch (diffusefunc) {\n"); " switch (diffusefunc) {{\n");
out.Write(" case %uu: // LIGHTDIF_NONE\n", LIGHTDIF_NONE); out.WriteFmt(" case {}u: // LIGHTDIF_NONE\n", LIGHTDIF_NONE);
out.Write(" return int4(round(attn * float4(" I_LIGHTS "[index].color)));\n\n"); out.WriteFmt(" return int4(round(attn * float4(" I_LIGHTS "[index].color)));\n\n");
out.Write(" case %uu: // LIGHTDIF_SIGN\n", LIGHTDIF_SIGN); out.WriteFmt(" case {}u: // LIGHTDIF_SIGN\n", LIGHTDIF_SIGN);
out.Write(" return int4(round(attn * dot(ldir, normal) * float4(" I_LIGHTS out.WriteFmt(" return int4(round(attn * dot(ldir, normal) * float4(" I_LIGHTS
"[index].color)));\n\n"); "[index].color)));\n\n");
out.Write(" case %uu: // LIGHTDIF_CLAMP\n", LIGHTDIF_CLAMP); out.WriteFmt(" case {}u: // LIGHTDIF_CLAMP\n", LIGHTDIF_CLAMP);
out.Write(" return int4(round(attn * max(0.0, dot(ldir, normal)) * float4(" I_LIGHTS out.WriteFmt(" return int4(round(attn * max(0.0, dot(ldir, normal)) * float4(" I_LIGHTS
"[index].color)));\n\n"); "[index].color)));\n\n");
out.Write(" default:\n" out.WriteFmt(" default:\n"
" return int4(0, 0, 0, 0);\n" " return int4(0, 0, 0, 0);\n"
" }\n" " }}\n"
"}\n\n"); "}}\n\n");
} }
void WriteVertexLighting(ShaderCode& out, APIType api_type, const char* world_pos_var, void WriteVertexLighting(ShaderCode& out, APIType api_type, std::string_view world_pos_var,
const char* normal_var, const char* in_color_0_var, std::string_view normal_var, std::string_view in_color_0_var,
const char* in_color_1_var, const char* out_color_0_var, std::string_view in_color_1_var, std::string_view out_color_0_var,
const char* out_color_1_var) std::string_view out_color_1_var)
{ {
out.Write("// Lighting\n"); out.WriteFmt("// Lighting\n");
out.Write("%sfor (uint chan = 0u; chan < %zuu; chan++) {\n", out.WriteFmt("{}for (uint chan = 0u; chan < {}u; chan++) {{\n",
api_type == APIType::D3D ? "[loop] " : "", NUM_XF_COLOR_CHANNELS); api_type == APIType::D3D ? "[loop] " : "", NUM_XF_COLOR_CHANNELS);
out.Write(" uint colorreg = xfmem_color(chan);\n" out.WriteFmt(" uint colorreg = xfmem_color(chan);\n"
" uint alphareg = xfmem_alpha(chan);\n" " uint alphareg = xfmem_alpha(chan);\n"
" int4 mat = " I_MATERIALS "[chan + 2u]; \n" " int4 mat = " I_MATERIALS "[chan + 2u]; \n"
" int4 lacc = int4(255, 255, 255, 255);\n" " int4 lacc = int4(255, 255, 255, 255);\n"
"\n"); "\n");
out.Write(" if (%s != 0u) {\n", BitfieldExtract("colorreg", LitChannel().matsource).c_str()); out.WriteFmt(" if ({} != 0u) {{\n", BitfieldExtract("colorreg", LitChannel().matsource));
out.Write(" if ((components & (%uu << chan)) != 0u) // VB_HAS_COL0\n", VB_HAS_COL0); out.WriteFmt(" if ((components & ({}u << chan)) != 0u) // VB_HAS_COL0\n", VB_HAS_COL0);
out.Write(" mat.xyz = int3(round(((chan == 0u) ? %s.xyz : %s.xyz) * 255.0));\n", out.WriteFmt(" mat.xyz = int3(round(((chan == 0u) ? {}.xyz : {}.xyz) * 255.0));\n",
in_color_0_var, in_color_1_var); in_color_0_var, in_color_1_var);
out.Write(" else if ((components & %uu) != 0u) // VB_HAS_COLO0\n", VB_HAS_COL0); out.WriteFmt(" else if ((components & {}u) != 0u) // VB_HAS_COLO0\n", VB_HAS_COL0);
out.Write(" mat.xyz = int3(round(%s.xyz * 255.0));\n", in_color_0_var); out.WriteFmt(" mat.xyz = int3(round({}.xyz * 255.0));\n", in_color_0_var);
out.Write(" else\n" out.WriteFmt(" else\n"
" mat.xyz = int3(255, 255, 255);\n" " mat.xyz = int3(255, 255, 255);\n"
" }\n" " }}\n"
"\n"); "\n");
out.Write(" if (%s != 0u) {\n", BitfieldExtract("alphareg", LitChannel().matsource).c_str()); out.WriteFmt(" if ({} != 0u) {{\n", BitfieldExtract("alphareg", LitChannel().matsource));
out.Write(" if ((components & (%uu << chan)) != 0u) // VB_HAS_COL0\n", VB_HAS_COL0); out.WriteFmt(" if ((components & ({}u << chan)) != 0u) // VB_HAS_COL0\n", VB_HAS_COL0);
out.Write(" mat.w = int(round(((chan == 0u) ? %s.w : %s.w) * 255.0));\n", in_color_0_var, out.WriteFmt(" mat.w = int(round(((chan == 0u) ? {}.w : {}.w) * 255.0));\n", in_color_0_var,
in_color_1_var); in_color_1_var);
out.Write(" else if ((components & %uu) != 0u) // VB_HAS_COLO0\n", VB_HAS_COL0); out.WriteFmt(" else if ((components & {}u) != 0u) // VB_HAS_COLO0\n", VB_HAS_COL0);
out.Write(" mat.w = int(round(%s.w * 255.0));\n", in_color_0_var); out.WriteFmt(" mat.w = int(round({}.w * 255.0));\n", in_color_0_var);
out.Write(" else\n" out.WriteFmt(" else\n"
" mat.w = 255;\n" " mat.w = 255;\n"
" } else {\n" " }} else {{\n"
" mat.w = " I_MATERIALS " [chan + 2u].w;\n" " mat.w = " I_MATERIALS " [chan + 2u].w;\n"
" }\n" " }}\n"
"\n"); "\n");
out.Write(" if (%s != 0u) {\n", out.WriteFmt(" if ({} != 0u) {{\n", BitfieldExtract("colorreg", LitChannel().enablelighting));
BitfieldExtract("colorreg", LitChannel().enablelighting).c_str()); out.WriteFmt(" if ({} != 0u) {{\n", BitfieldExtract("colorreg", LitChannel().ambsource));
out.Write(" if (%s != 0u) {\n", BitfieldExtract("colorreg", LitChannel().ambsource).c_str()); out.WriteFmt(" if ((components & ({}u << chan)) != 0u) // VB_HAS_COL0\n", VB_HAS_COL0);
out.Write(" if ((components & (%uu << chan)) != 0u) // VB_HAS_COL0\n", VB_HAS_COL0); out.WriteFmt(" lacc.xyz = int3(round(((chan == 0u) ? {}.xyz : {}.xyz) * 255.0));\n",
out.Write(" lacc.xyz = int3(round(((chan == 0u) ? %s.xyz : %s.xyz) * 255.0));\n",
in_color_0_var, in_color_1_var); in_color_0_var, in_color_1_var);
out.Write(" else if ((components & %uu) != 0u) // VB_HAS_COLO0\n", VB_HAS_COL0); out.WriteFmt(" else if ((components & {}u) != 0u) // VB_HAS_COLO0\n", VB_HAS_COL0);
out.Write(" lacc.xyz = int3(round(%s.xyz * 255.0));\n", in_color_0_var); out.WriteFmt(" lacc.xyz = int3(round({}.xyz * 255.0));\n", in_color_0_var);
out.Write(" else\n" out.WriteFmt(" else\n"
" lacc.xyz = int3(255, 255, 255);\n" " lacc.xyz = int3(255, 255, 255);\n"
" } else {\n" " }} else {{\n"
" lacc.xyz = " I_MATERIALS " [chan].xyz;\n" " lacc.xyz = " I_MATERIALS " [chan].xyz;\n"
" }\n" " }}\n"
"\n"); "\n");
out.Write(" uint light_mask = %s | (%s << 4u);\n", out.WriteFmt(" uint light_mask = {} | ({} << 4u);\n",
BitfieldExtract("colorreg", LitChannel().lightMask0_3).c_str(), BitfieldExtract("colorreg", LitChannel().lightMask0_3),
BitfieldExtract("colorreg", LitChannel().lightMask4_7).c_str()); BitfieldExtract("colorreg", LitChannel().lightMask4_7));
out.Write(" uint attnfunc = %s;\n", out.WriteFmt(" uint attnfunc = {};\n", BitfieldExtract("colorreg", LitChannel().attnfunc));
BitfieldExtract("colorreg", LitChannel().attnfunc).c_str()); out.WriteFmt(" uint diffusefunc = {};\n",
out.Write(" uint diffusefunc = %s;\n", BitfieldExtract("colorreg", LitChannel().diffusefunc));
BitfieldExtract("colorreg", LitChannel().diffusefunc).c_str()); out.WriteFmt(
out.Write( " for (uint light_index = 0u; light_index < 8u; light_index++) {{\n"
" for (uint light_index = 0u; light_index < 8u; light_index++) {\n"
" if ((light_mask & (1u << light_index)) != 0u)\n" " if ((light_mask & (1u << light_index)) != 0u)\n"
" lacc.xyz += CalculateLighting(light_index, attnfunc, diffusefunc, %s, %s).xyz;\n", " lacc.xyz += CalculateLighting(light_index, attnfunc, diffusefunc, {}, {}).xyz;\n",
world_pos_var, normal_var); world_pos_var, normal_var);
out.Write(" }\n" out.WriteFmt(" }}\n"
" }\n" " }}\n"
"\n"); "\n");
out.Write(" if (%s != 0u) {\n", out.WriteFmt(" if ({} != 0u) {{\n", BitfieldExtract("alphareg", LitChannel().enablelighting));
BitfieldExtract("alphareg", LitChannel().enablelighting).c_str()); out.WriteFmt(" if ({} != 0u) {{\n", BitfieldExtract("alphareg", LitChannel().ambsource));
out.Write(" if (%s != 0u) {\n", BitfieldExtract("alphareg", LitChannel().ambsource).c_str()); out.WriteFmt(" if ((components & ({}u << chan)) != 0u) // VB_HAS_COL0\n", VB_HAS_COL0);
out.Write(" if ((components & (%uu << chan)) != 0u) // VB_HAS_COL0\n", VB_HAS_COL0); out.WriteFmt(" lacc.w = int(round(((chan == 0u) ? {}.w : {}.w) * 255.0));\n",
out.Write(" lacc.w = int(round(((chan == 0u) ? %s.w : %s.w) * 255.0));\n", in_color_0_var, in_color_0_var, in_color_1_var);
in_color_1_var); out.WriteFmt(" else if ((components & {}u) != 0u) // VB_HAS_COLO0\n", VB_HAS_COL0);
out.Write(" else if ((components & %uu) != 0u) // VB_HAS_COLO0\n", VB_HAS_COL0); out.WriteFmt(" lacc.w = int(round({}.w * 255.0));\n", in_color_0_var);
out.Write(" lacc.w = int(round(%s.w * 255.0));\n", in_color_0_var); out.WriteFmt(" else\n"
out.Write(" else\n"
" lacc.w = 255;\n" " lacc.w = 255;\n"
" } else {\n" " }} else {{\n"
" lacc.w = " I_MATERIALS " [chan].w;\n" " lacc.w = " I_MATERIALS " [chan].w;\n"
" }\n" " }}\n"
"\n"); "\n");
out.Write(" uint light_mask = %s | (%s << 4u);\n", out.WriteFmt(" uint light_mask = {} | ({} << 4u);\n",
BitfieldExtract("alphareg", LitChannel().lightMask0_3).c_str(), BitfieldExtract("alphareg", LitChannel().lightMask0_3),
BitfieldExtract("alphareg", LitChannel().lightMask4_7).c_str()); BitfieldExtract("alphareg", LitChannel().lightMask4_7));
out.Write(" uint attnfunc = %s;\n", out.WriteFmt(" uint attnfunc = {};\n", BitfieldExtract("alphareg", LitChannel().attnfunc));
BitfieldExtract("alphareg", LitChannel().attnfunc).c_str()); out.WriteFmt(" uint diffusefunc = {};\n",
out.Write(" uint diffusefunc = %s;\n", BitfieldExtract("alphareg", LitChannel().diffusefunc));
BitfieldExtract("alphareg", LitChannel().diffusefunc).c_str()); out.WriteFmt(
out.Write(" for (uint light_index = 0u; light_index < 8u; light_index++) {\n\n" " for (uint light_index = 0u; light_index < 8u; light_index++) {{\n\n"
" if ((light_mask & (1u << light_index)) != 0u)\n\n" " if ((light_mask & (1u << light_index)) != 0u)\n\n"
" lacc.w += CalculateLighting(light_index, attnfunc, diffusefunc, %s, %s).w;\n", " lacc.w += CalculateLighting(light_index, attnfunc, diffusefunc, {}, {}).w;\n",
world_pos_var, normal_var); world_pos_var, normal_var);
out.Write(" }\n" out.WriteFmt(" }}\n"
" }\n" " }}\n"
"\n"); "\n");
out.Write(" lacc = clamp(lacc, 0, 255);\n" out.WriteFmt(" lacc = clamp(lacc, 0, 255);\n"
"\n" "\n"
" // Hopefully GPUs that can support dynamic indexing will optimize this.\n" " // Hopefully GPUs that can support dynamic indexing will optimize this.\n"
" float4 lit_color = float4((mat * (lacc + (lacc >> 7))) >> 8) / 255.0;\n" " float4 lit_color = float4((mat * (lacc + (lacc >> 7))) >> 8) / 255.0;\n"
" switch (chan) {\n" " switch (chan) {{\n"
" case 0u: %s = lit_color; break;\n", " case 0u: {} = lit_color; break;\n",
out_color_0_var); out_color_0_var);
out.Write(" case 1u: %s = lit_color; break;\n", out_color_1_var); out.WriteFmt(" case 1u: {} = lit_color; break;\n", out_color_1_var);
out.Write(" }\n" out.WriteFmt(" }}\n"
"}\n" "}}\n"
"\n"); "\n");
} }
} // namespace UberShader } // namespace UberShader

View File

@ -23,10 +23,10 @@ void WriteUberShaderCommonHeader(ShaderCode& out, APIType api_type,
// Vertex lighting // Vertex lighting
void WriteLightingFunction(ShaderCode& out); void WriteLightingFunction(ShaderCode& out);
void WriteVertexLighting(ShaderCode& out, APIType api_type, const char* world_pos_var, void WriteVertexLighting(ShaderCode& out, APIType api_type, std::string_view world_pos_var,
const char* normal_var, const char* in_color_0_var, std::string_view normal_var, std::string_view in_color_0_var,
const char* in_color_1_var, const char* out_color_0_var, std::string_view in_color_1_var, std::string_view out_color_0_var,
const char* out_color_1_var); std::string_view out_color_1_var);
// bitfieldExtract generator for BitField types // bitfieldExtract generator for BitField types
template <typename T> template <typename T>