summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2025-03-23 15:21:48 -0400
committerGitHub <noreply@github.com>2025-03-23 15:21:48 -0400
commitcef4d8fb761aeb38137d29e8348330c7df03e54f (patch)
tree204f1f85deca0fd4199b9cfd81dd5f9296434d73 /Source/Core/VideoCommon
parentf50d2ee86c5e7530887e8e78b6611c01ccb7bbc8 (diff)
parent8e253518e6f8b918dffe7361faf897c16eabc6d3 (diff)
Merge pull request #13432 from iwubcode/custom_pixel_fragment
VideoCommon: move to a 'process_fragment()' function to simplify custom shaders
Diffstat (limited to 'Source/Core/VideoCommon')
-rw-r--r--Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.cpp7
-rw-r--r--Source/Core/VideoCommon/LightingShaderGen.cpp115
-rw-r--r--Source/Core/VideoCommon/LightingShaderGen.h5
-rw-r--r--Source/Core/VideoCommon/PixelShaderGen.cpp567
-rw-r--r--Source/Core/VideoCommon/PixelShaderGen.h14
-rw-r--r--Source/Core/VideoCommon/ShaderCache.cpp2
-rw-r--r--Source/Core/VideoCommon/ShaderGenCommon.cpp92
-rw-r--r--Source/Core/VideoCommon/ShaderGenCommon.h2
-rw-r--r--Source/Core/VideoCommon/UberShaderPixel.cpp406
-rw-r--r--Source/Core/VideoCommon/UberShaderPixel.h3
10 files changed, 302 insertions, 911 deletions
diff --git a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.cpp b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.cpp
index cff6e7b6a6..56f8ec1b3b 100644
--- a/Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.cpp
+++ b/Source/Core/VideoCommon/GraphicsModSystem/Runtime/CustomShaderCache.cpp
@@ -346,8 +346,8 @@ std::unique_ptr<AbstractShader>
CustomShaderCache::CompilePixelShader(const PixelShaderUid& uid,
const CustomShaderInstance& custom_shaders) const
{
- const ShaderCode source_code = GeneratePixelShaderCode(
- m_api_type, m_host_config, uid.GetUidData(), custom_shaders.pixel_contents);
+ const ShaderCode source_code =
+ GeneratePixelShaderCode(m_api_type, m_host_config, uid.GetUidData(), {});
return g_gfx->CreateShaderFromSource(ShaderStage::Pixel, source_code.GetBuffer(),
"Custom Pixel Shader");
}
@@ -356,8 +356,7 @@ std::unique_ptr<AbstractShader>
CustomShaderCache::CompilePixelShader(const UberShader::PixelShaderUid& uid,
const CustomShaderInstance& custom_shaders) const
{
- const ShaderCode source_code =
- GenPixelShader(m_api_type, m_host_config, uid.GetUidData(), custom_shaders.pixel_contents);
+ const ShaderCode source_code = GenPixelShader(m_api_type, m_host_config, uid.GetUidData());
return g_gfx->CreateShaderFromSource(ShaderStage::Pixel, source_code.GetBuffer(),
"Custom Uber Pixel Shader");
}
diff --git a/Source/Core/VideoCommon/LightingShaderGen.cpp b/Source/Core/VideoCommon/LightingShaderGen.cpp
index 130fb6f46d..be9d10c78a 100644
--- a/Source/Core/VideoCommon/LightingShaderGen.cpp
+++ b/Source/Core/VideoCommon/LightingShaderGen.cpp
@@ -179,47 +179,9 @@ void GetLightingShaderUid(LightingUidData& uid_data)
}
}
-void GenerateCustomLightingHeaderDetails(ShaderCode* out, u32 enablelighting, u32 light_mask)
-{
- u32 light_count = 0;
- for (u32 j = 0; j < NUM_XF_COLOR_CHANNELS; j++)
- {
- if ((enablelighting & (1 << j)) != 0) // Color lights
- {
- for (int i = 0; i < 8; ++i)
- {
- if ((light_mask & (1 << (i + 8 * j))) != 0)
- {
- light_count++;
- }
- }
- }
- if ((enablelighting & (1 << (j + 2))) != 0) // Alpha lights
- {
- for (int i = 0; i < 8; ++i)
- {
- if ((light_mask & (1 << (i + 8 * (j + 2)))) != 0)
- {
- light_count++;
- }
- }
- }
- }
- if (light_count > 0)
- {
- out->Write("\tCustomShaderLightData[{}] light;\n", light_count);
- }
- else
- {
- // Cheat so shaders compile
- out->Write("\tCustomShaderLightData[1] light;\n", light_count);
- }
- out->Write("\tint light_count;\n");
-}
-
-static void GenerateLighting(ShaderCode* out, const LightingUidData& uid_data, int index,
- int litchan_index, u32 channel_index, u32 custom_light_index,
- bool alpha)
+static void GenerateCustomLightingImpl(ShaderCode* out, const LightingUidData& uid_data, int index,
+ int litchan_index, u32 channel_index, u32 custom_light_index,
+ bool alpha)
{
const auto attnfunc =
static_cast<AttenuationFunc>((uid_data.attnfunc >> (2 * litchan_index)) & 0x3);
@@ -228,60 +190,59 @@ static void GenerateLighting(ShaderCode* out, const LightingUidData& uid_data, i
const std::string name = fmt::format("lights_chan{}_{}", channel_index, light_type);
out->Write("\t{{\n");
- out->Write("\t\tcustom_data.{}[{}].direction = " LIGHT_DIR ".xyz;\n", name, custom_light_index,
+ out->Write("\t\tfrag_input.{}[{}].direction = " LIGHT_DIR ".xyz;\n", name, custom_light_index,
LIGHT_DIR_PARAMS(index));
- out->Write("\t\tcustom_data.{}[{}].position = " LIGHT_POS ".xyz;\n", name, custom_light_index,
+ out->Write("\t\tfrag_input.{}[{}].position = " LIGHT_POS ".xyz;\n", name, custom_light_index,
LIGHT_POS_PARAMS(index));
- out->Write("\t\tcustom_data.{}[{}].cosatt = " LIGHT_COSATT ";\n", name, custom_light_index,
+ out->Write("\t\tfrag_input.{}[{}].cosatt = " LIGHT_COSATT ";\n", name, custom_light_index,
LIGHT_COSATT_PARAMS(index));
- out->Write("\t\tcustom_data.{}[{}].distatt = " LIGHT_DISTATT ";\n", name, custom_light_index,
+ out->Write("\t\tfrag_input.{}[{}].distatt = " LIGHT_DISTATT ";\n", name, custom_light_index,
LIGHT_DISTATT_PARAMS(index));
- out->Write("\t\tcustom_data.{}[{}].attenuation_type = {};\n", name, custom_light_index,
+ out->Write("\t\tfrag_input.{}[{}].attenuation_type = {};\n", name, custom_light_index,
static_cast<u32>(attnfunc));
if (alpha)
{
- out->Write("\t\tcustom_data.{}[{}].color = float3(" LIGHT_COL
+ out->Write("\t\tfrag_input.{}[{}].color = float3(" LIGHT_COL
") / float3(255.0, 255.0, 255.0);\n",
name, custom_light_index, LIGHT_COL_PARAMS(index, alpha ? "a" : "rgb"));
}
else
{
- out->Write("\t\tcustom_data.{}[{}].color = " LIGHT_COL " / float3(255.0, 255.0, 255.0);\n",
- name, custom_light_index, LIGHT_COL_PARAMS(index, alpha ? "a" : "rgb"));
+ out->Write("\t\tfrag_input.{}[{}].color = " LIGHT_COL " / float3(255.0, 255.0, 255.0);\n", name,
+ custom_light_index, LIGHT_COL_PARAMS(index, alpha ? "a" : "rgb"));
}
out->Write("\t}}\n");
}
-void GenerateCustomLightingImplementation(ShaderCode* out, const LightingUidData& uid_data,
- std::string_view in_color_name)
+void GenerateCustomLighting(ShaderCode* out, const LightingUidData& uid_data)
{
for (u32 i = 0; i < 8; i++)
{
for (u32 channel_index = 0; channel_index < NUM_XF_COLOR_CHANNELS; channel_index++)
{
- out->Write("\tcustom_data.lights_chan{}_color[{}].direction = float3(0, 0, 0);\n",
+ out->Write("\tfrag_input.lights_chan{}_color[{}].direction = float3(0, 0, 0);\n",
channel_index, i);
- out->Write("\tcustom_data.lights_chan{}_color[{}].position = float3(0, 0, 0);\n",
+ out->Write("\tfrag_input.lights_chan{}_color[{}].position = float3(0, 0, 0);\n",
channel_index, i);
- out->Write("\tcustom_data.lights_chan{}_color[{}].color = float3(0, 0, 0);\n", channel_index,
+ out->Write("\tfrag_input.lights_chan{}_color[{}].color = float3(0, 0, 0);\n", channel_index,
i);
- out->Write("\tcustom_data.lights_chan{}_color[{}].cosatt = float4(0, 0, 0, 0);\n",
+ out->Write("\tfrag_input.lights_chan{}_color[{}].cosatt = float4(0, 0, 0, 0);\n",
channel_index, i);
- out->Write("\tcustom_data.lights_chan{}_color[{}].distatt = float4(0, 0, 0, 0);\n",
+ out->Write("\tfrag_input.lights_chan{}_color[{}].distatt = float4(0, 0, 0, 0);\n",
channel_index, i);
- out->Write("\tcustom_data.lights_chan{}_color[{}].attenuation_type = 0;\n", channel_index, i);
+ out->Write("\tfrag_input.lights_chan{}_color[{}].attenuation_type = 0;\n", channel_index, i);
- out->Write("\tcustom_data.lights_chan{}_alpha[{}].direction = float3(0, 0, 0);\n",
+ out->Write("\tfrag_input.lights_chan{}_alpha[{}].direction = float3(0, 0, 0);\n",
channel_index, i);
- out->Write("\tcustom_data.lights_chan{}_alpha[{}].position = float3(0, 0, 0);\n",
+ out->Write("\tfrag_input.lights_chan{}_alpha[{}].position = float3(0, 0, 0);\n",
channel_index, i);
- out->Write("\tcustom_data.lights_chan{}_alpha[{}].color = float3(0, 0, 0);\n", channel_index,
+ out->Write("\tfrag_input.lights_chan{}_alpha[{}].color = float3(0, 0, 0);\n", channel_index,
i);
- out->Write("\tcustom_data.lights_chan{}_alpha[{}].cosatt = float4(0, 0, 0, 0);\n",
+ out->Write("\tfrag_input.lights_chan{}_alpha[{}].cosatt = float4(0, 0, 0, 0);\n",
channel_index, i);
- out->Write("\tcustom_data.lights_chan{}_alpha[{}].distatt = float4(0, 0, 0, 0);\n",
+ out->Write("\tfrag_input.lights_chan{}_alpha[{}].distatt = float4(0, 0, 0, 0);\n",
channel_index, i);
- out->Write("\tcustom_data.lights_chan{}_alpha[{}].attenuation_type = 0;\n", channel_index, i);
+ out->Write("\tfrag_input.lights_chan{}_alpha[{}].attenuation_type = 0;\n", channel_index, i);
}
}
@@ -289,20 +250,20 @@ void GenerateCustomLightingImplementation(ShaderCode* out, const LightingUidData
{
const bool colormatsource = !!(uid_data.matsource & (1 << j));
if (colormatsource) // from vertex
- out->Write("custom_data.base_material[{}] = {}{};\n", j, in_color_name, j);
+ out->Write("frag_input.base_material[{}] = frag_input.color_{};\n", j, j);
else // from color
- out->Write("custom_data.base_material[{}] = {}[{}] / 255.0;\n", j, I_MATERIALS, j + 2);
+ out->Write("frag_input.base_material[{}] = {}[{}] / 255.0;\n", j, I_MATERIALS, j + 2);
if ((uid_data.enablelighting & (1 << j)) != 0)
{
if ((uid_data.ambsource & (1 << j)) != 0) // from vertex
- out->Write("custom_data.ambient_lighting[{}] = {}{};\n", j, in_color_name, j);
+ out->Write("frag_input.ambient_lighting[{}] = frag_input.color_{};\n", j, j);
else // from color
- out->Write("custom_data.ambient_lighting[{}] = {}[{}] / 255.0;\n", j, I_MATERIALS, j);
+ out->Write("frag_input.ambient_lighting[{}] = {}[{}] / 255.0;\n", j, I_MATERIALS, j);
}
else
{
- out->Write("custom_data.ambient_lighting[{}] = float4(1, 1, 1, 1);\n", j);
+ out->Write("frag_input.ambient_lighting[{}] = float4(1, 1, 1, 1);\n", j);
}
// check if alpha is different
@@ -310,21 +271,21 @@ void GenerateCustomLightingImplementation(ShaderCode* out, const LightingUidData
if (alphamatsource != colormatsource)
{
if (alphamatsource) // from vertex
- out->Write("custom_data.base_material[{}].w = {}{}.w;\n", j, in_color_name, j);
+ out->Write("frag_input.base_material[{}].w = frag_input.color_{}.w;\n", j, j);
else // from color
- out->Write("custom_data.base_material[{}].w = {}[{}].w / 255.0;\n", j, I_MATERIALS, j + 2);
+ out->Write("frag_input.base_material[{}].w = {}[{}].w / 255.0;\n", j, I_MATERIALS, j + 2);
}
if ((uid_data.enablelighting & (1 << (j + 2))) != 0)
{
if ((uid_data.ambsource & (1 << (j + 2))) != 0) // from vertex
- out->Write("custom_data.ambient_lighting[{}].w = {}{}.w;\n", j, in_color_name, j);
+ out->Write("frag_input.ambient_lighting[{}].w = frag_input.color_{}.w;\n", j, j);
else // from color
- out->Write("custom_data.ambient_lighting[{}].w = {}[{}].w / 255.0;\n", j, I_MATERIALS, j);
+ out->Write("frag_input.ambient_lighting[{}].w = {}[{}].w / 255.0;\n", j, I_MATERIALS, j);
}
else
{
- out->Write("custom_data.ambient_lighting[{}].w = 1;\n", j);
+ out->Write("frag_input.ambient_lighting[{}].w = 1;\n", j);
}
u32 light_count = 0;
@@ -334,12 +295,12 @@ void GenerateCustomLightingImplementation(ShaderCode* out, const LightingUidData
{
if ((uid_data.light_mask & (1 << (i + 8 * j))) != 0)
{
- GenerateLighting(out, uid_data, i, j, j, light_count, false);
+ GenerateCustomLightingImpl(out, uid_data, i, j, j, light_count, false);
light_count++;
}
}
}
- out->Write("\tcustom_data.light_chan{}_color_count = {};\n", j, light_count);
+ out->Write("\tfrag_input.light_chan{}_color_count = {};\n", j, light_count);
light_count = 0;
if ((uid_data.enablelighting & (1 << (j + 2))) != 0) // Alpha lights
@@ -348,11 +309,11 @@ void GenerateCustomLightingImplementation(ShaderCode* out, const LightingUidData
{
if ((uid_data.light_mask & (1 << (i + 8 * (j + 2)))) != 0)
{
- GenerateLighting(out, uid_data, i, j + 2, j, light_count, true);
+ GenerateCustomLightingImpl(out, uid_data, i, j + 2, j, light_count, true);
light_count++;
}
}
}
- out->Write("\tcustom_data.light_chan{}_alpha_count = {};\n", j, light_count);
+ out->Write("\tfrag_input.light_chan{}_alpha_count = {};\n", j, light_count);
}
}
diff --git a/Source/Core/VideoCommon/LightingShaderGen.h b/Source/Core/VideoCommon/LightingShaderGen.h
index 3e146cc07f..e7d6f1ed13 100644
--- a/Source/Core/VideoCommon/LightingShaderGen.h
+++ b/Source/Core/VideoCommon/LightingShaderGen.h
@@ -46,7 +46,4 @@ constexpr char s_lighting_struct[] = "struct Light {\n"
void GenerateLightingShaderHeader(ShaderCode& object, const LightingUidData& uid_data);
void GetLightingShaderUid(LightingUidData& uid_data);
-
-void GenerateCustomLightingHeaderDetails(ShaderCode* out, u32 enablelighting, u32 light_mask);
-void GenerateCustomLightingImplementation(ShaderCode* out, const LightingUidData& uid_data,
- std::string_view in_color_name);
+void GenerateCustomLighting(ShaderCode* out, const LightingUidData& uid_data);
diff --git a/Source/Core/VideoCommon/PixelShaderGen.cpp b/Source/Core/VideoCommon/PixelShaderGen.cpp
index 1b9e491a40..ce90ecd42b 100644
--- a/Source/Core/VideoCommon/PixelShaderGen.cpp
+++ b/Source/Core/VideoCommon/PixelShaderGen.cpp
@@ -345,8 +345,7 @@ void ClearUnusedPixelShaderUidBits(APIType api_type, const ShaderHostConfig& hos
}
void WritePixelShaderCommonHeader(ShaderCode& out, APIType api_type,
- const ShaderHostConfig& host_config, bool bounding_box,
- const CustomPixelShaderContents& custom_details)
+ const ShaderHostConfig& host_config, bool bounding_box)
{
// dot product for integer vectors
out.Write("int idot(int3 x, int3 y)\n"
@@ -427,14 +426,6 @@ void WritePixelShaderCommonHeader(ShaderCode& out, APIType api_type,
out.Write("}};\n");
}
- if (!custom_details.shaders.empty() &&
- !custom_details.shaders.back().material_uniform_block.empty())
- {
- out.Write("UBO_BINDING(std140, 3) uniform CustomShaderBlock {{\n");
- out.Write("{}", custom_details.shaders.back().material_uniform_block);
- out.Write("}} custom_uniforms;\n");
- }
-
if (bounding_box)
{
out.Write("SSBO_BINDING(0) coherent buffer BBox {{\n"
@@ -761,132 +752,8 @@ uint WrapCoord(int coord, uint wrap, int size) {{
}
}
-void WriteCustomShaderStructImpl(ShaderCode* out, u32 num_stages, bool per_pixel_lighting,
- const pixel_shader_uid_data* uid_data)
-{
- out->Write("\tCustomShaderData custom_data;\n");
-
- if (per_pixel_lighting)
- {
- out->Write("\tcustom_data.position = WorldPos;\n");
- out->Write("\tcustom_data.normal = Normal;\n");
- }
- else
- {
- out->Write("\tcustom_data.position = float3(0, 0, 0);\n");
- out->Write("\tcustom_data.normal = float3(0, 0, 0);\n");
- }
-
- if (uid_data->genMode_numtexgens == 0) [[unlikely]]
- {
- out->Write("\tcustom_data.texcoord[0] = float3(0, 0, 0);\n");
- }
- else
- {
- for (u32 i = 0; i < uid_data->genMode_numtexgens; ++i)
- {
- out->Write("\tif (tex{0}.z == 0.0)\n", i);
- out->Write("\t{{\n");
- out->Write("\t\tcustom_data.texcoord[{0}] = tex{0};\n", i);
- out->Write("\t}}\n");
- out->Write("\telse {{\n");
- out->Write("\t\tcustom_data.texcoord[{0}] = float3(tex{0}.xy / tex{0}.z, 0);\n", i);
- out->Write("\t}}\n");
- }
- }
-
- for (u32 i = 0; i < 8; i++)
- {
- // Shader compilation complains if every index isn't initialized
- out->Write("\tcustom_data.texmap_to_texcoord_index[{0}] = 0;\n", i);
- }
-
- for (u32 i = 0; i < uid_data->genMode_numindstages; ++i)
- {
- if ((uid_data->nIndirectStagesUsed & (1U << i)) != 0)
- {
- u32 texcoord = uid_data->GetTevindirefCoord(i);
- const u32 texmap = uid_data->GetTevindirefMap(i);
-
- // Quirk: when the tex coord is not less than the number of tex gens (i.e. the tex coord does
- // not exist), then tex coord 0 is used (though sometimes glitchy effects happen on console).
- // This affects the Mario portrait in Luigi's Mansion, where the developers forgot to set
- // the number of tex gens to 2 (bug 11462).
- if (texcoord >= uid_data->genMode_numtexgens)
- texcoord = 0;
-
- out->Write("\tcustom_data.texmap_to_texcoord_index[{}] = {};\n", texmap, texcoord);
- }
- }
- out->Write("\tcustom_data.texcoord_count = {};\n", uid_data->genMode_numtexgens);
-
- // Try and do a best guess on what the texcoord index is
- // Note: one issue with this would be textures that are used
- // multiple times in the same draw but with different texture coordinates.
- // In that scenario, only the last texture coordinate would be defined.
- // This issue can be seen in how Rogue Squadron 2 does bump mapping
- for (u32 i = 0; i < num_stages; i++)
- {
- auto& tevstage = uid_data->stagehash[i];
- // Quirk: when the tex coord is not less than the number of tex gens (i.e. the tex coord does
- // not exist), then tex coord 0 is used (though sometimes glitchy effects happen on console).
- u32 texcoord = tevstage.tevorders_texcoord;
- const bool has_tex_coord = texcoord < uid_data->genMode_numtexgens;
- if (!has_tex_coord)
- texcoord = 0;
-
- out->Write("\tcustom_data.texmap_to_texcoord_index[{}] = {};\n", tevstage.tevorders_texmap,
- texcoord);
- }
-
- if (per_pixel_lighting)
- GenerateCustomLightingImplementation(out, uid_data->lighting, "colors_");
-
- for (u32 i = 0; i < 16; i++)
- {
- // Shader compilation complains if every struct isn't initialized
-
- // Color Input
- for (u32 j = 0; j < 4; j++)
- {
- out->Write("\tcustom_data.tev_stages[{}].input_color[{}].input_type = "
- "CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_UNUSED;\n",
- i, j);
- out->Write("\tcustom_data.tev_stages[{}].input_color[{}].value = "
- "float3(0, 0, 0);\n",
- i, j);
- }
-
- // Alpha Input
- for (u32 j = 0; j < 4; j++)
- {
- out->Write("\tcustom_data.tev_stages[{}].input_alpha[{}].input_type = "
- "CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_UNUSED;\n",
- i, j);
- out->Write("\tcustom_data.tev_stages[{}].input_alpha[{}].value = "
- "float(0);\n",
- i, j);
- }
-
- // Texmap
- out->Write("\tcustom_data.tev_stages[{}].texmap = 0u;\n", i);
-
- // Output
- out->Write("\tcustom_data.tev_stages[{}].output_color = "
- "float4(0, 0, 0, 0);\n",
- i);
- }
-
- // Actual data will be filled out in the tev stage code, just set the
- // stage count for now
- out->Write("\tcustom_data.tev_stage_count = {};\n", num_stages);
-
- // Time
- out->Write("\tcustom_data.time_ms = time_ms;\n");
-}
-
static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, int n,
- APIType api_type, bool stereo, bool has_custom_shaders);
+ APIType api_type, bool stereo);
static void WriteTevRegular(ShaderCode& out, std::string_view components, TevBias bias, TevOp op,
bool clamp, TevScale scale);
static void WriteAlphaTest(ShaderCode& out, const pixel_shader_uid_data* uid_data, APIType api_type,
@@ -898,9 +765,14 @@ static void WriteColor(ShaderCode& out, APIType api_type, const pixel_shader_uid
bool use_dual_source);
static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data);
+static void WriteEmulatedFragmentBodyHeader(APIType api_type, const ShaderHostConfig& host_config,
+ const pixel_shader_uid_data* uid_data, ShaderCode& out);
+static void WriteFragmentDefinitions(APIType api_type, const ShaderHostConfig& host_config,
+ const pixel_shader_uid_data* uid_data, ShaderCode& out);
+
ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& host_config,
const pixel_shader_uid_data* uid_data,
- const CustomPixelShaderContents& custom_details)
+ CustomPixelContents custom_contents)
{
ShaderCode out;
@@ -917,15 +789,7 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos
// Stuff that is shared between ubershaders and pixelgen.
WriteBitfieldExtractHeader(out, api_type, host_config);
- WritePixelShaderCommonHeader(out, api_type, host_config, uid_data->bounding_box, custom_details);
-
- // Custom shader details
- WriteCustomShaderStructDef(&out, uid_data->genMode_numtexgens);
- for (std::size_t i = 0; i < custom_details.shaders.size(); i++)
- {
- const auto& shader_details = custom_details.shaders[i];
- out.Write(fmt::runtime(shader_details.custom_shader), i);
- }
+ WritePixelShaderCommonHeader(out, api_type, host_config, uid_data->bounding_box);
out.Write("\n#define sampleTextureWrapper(texmap, uv, layer) "
"sampleTexture(texmap, samp[texmap], uv, layer)\n");
@@ -1057,22 +921,39 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos
}
}
+ if (!custom_contents.uniforms.empty())
+ {
+ out.Write("UBO_BINDING(std140, 3) uniform CustomShaderBlock {{\n");
+ out.Write("{}", custom_contents.uniforms);
+ out.Write("}} custom_uniforms;\n");
+ }
+
if (per_pixel_lighting)
{
GenerateLightingShaderHeader(out, uid_data->lighting);
}
- out.Write("void main()\n{{\n");
- out.Write("\tfloat4 rawpos = gl_FragCoord;\n");
+ WriteFragmentDefinitions(api_type, host_config, uid_data, out);
+ WriteEmulatedFragmentBodyHeader(api_type, host_config, uid_data, out);
- bool has_custom_shaders = false;
- if (std::any_of(custom_details.shaders.begin(), custom_details.shaders.end(),
- [](const std::optional<CustomPixelShader>& ps) { return ps.has_value(); }))
+ if (custom_contents.shader.empty())
{
- WriteCustomShaderStructImpl(&out, numStages, per_pixel_lighting, uid_data);
- has_custom_shaders = true;
+ out.Write("void process_fragment(in DolphinFragmentInput frag_input, out DolphinFragmentOutput "
+ "frag_output)\n");
+ out.Write("{{\n");
+
+ out.Write("\tdolphin_process_emulated_fragment(frag_input, frag_output);\n");
+
+ out.Write("}}\n");
+ }
+ else
+ {
+ out.Write("{}\n", custom_contents.shader);
}
+ out.Write("void main()\n{{\n");
+ out.Write("\tfloat4 rawpos = gl_FragCoord;\n");
+
if (use_framebuffer_fetch)
{
// Store off a copy of the initial framebuffer value.
@@ -1107,112 +988,31 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos
out.Write("\tint layer = 0;\n");
}
- out.Write("\tint4 c0 = " I_COLORS "[1], c1 = " I_COLORS "[2], c2 = " I_COLORS
- "[3], prev = " I_COLORS "[0];\n"
- "\tint4 rastemp = int4(0, 0, 0, 0), rawtextemp = int4(0, 0, 0, 0), "
- "textemp = int4(0, 0, 0, 0), konsttemp = int4(0, 0, 0, 0);\n"
- "\tint3 comp16 = int3(1, 256, 0), comp24 = int3(1, 256, 256*256);\n"
- "\tint alphabump=0;\n"
- "\tint3 tevcoord=int3(0, 0, 0);\n"
- "\tint2 wrappedcoord=int2(0,0), tempcoord=int2(0,0);\n"
- "\tint4 "
- "tevin_a=int4(0,0,0,0),tevin_b=int4(0,0,0,0),tevin_c=int4(0,0,0,0),tevin_d=int4(0,0,0,"
- "0);\n\n"); // tev combiner inputs
-
- // On GLSL, input variables must not be assigned to.
- // This is why we declare these variables locally instead.
- out.Write("\tfloat4 col0 = colors_0;\n"
- "\tfloat4 col1 = colors_1;\n");
-
+ out.Write("\tDolphinFragmentInput frag_input;\n");
+ out.Write("\tfrag_input.color_0 = colors_0;\n");
+ out.Write("\tfrag_input.color_1 = colors_1;\n");
+ out.Write("\tfrag_input.layer = layer;\n");
if (per_pixel_lighting)
{
- out.Write("\tfloat3 _normal = normalize(Normal.xyz);\n\n"
- "\tfloat3 pos = WorldPos;\n");
-
- // TODO: Our current constant usage code isn't able to handle more than one buffer.
- // So we can't mark the VS constant as used here. But keep them here as reference.
- // out.SetConstantsUsed(C_PLIGHT_COLORS, C_PLIGHT_COLORS+7); // TODO: Can be optimized further
- // out.SetConstantsUsed(C_PLIGHTS, C_PLIGHTS+31); // TODO: Can be optimized further
- // out.SetConstantsUsed(C_PMATERIALS, C_PMATERIALS+3);
- for (u32 chan = 0; chan < uid_data->numColorChans; chan++)
- {
- out.Write("\tcol{0} = dolphin_calculate_lighting_chn{0}(colors_{0}, pos, _normal);\n", chan);
- }
- // The number of colors available to TEV is determined by numColorChans.
- // Normally this is performed in the vertex shader after lighting, but with per-pixel lighting,
- // we need to perform it here. (It needs to be done after lighting, as what was originally
- // black might become a different color after lighting).
- if (uid_data->numColorChans == 0)
- out.Write("col0 = float4(0.0, 0.0, 0.0, 0.0);\n");
- if (uid_data->numColorChans <= 1)
- out.Write("col1 = float4(0.0, 0.0, 0.0, 0.0);\n");
- }
-
- if (uid_data->genMode_numtexgens == 0)
- {
- // TODO: This is a hack to ensure that shaders still compile when setting out of bounds tex
- // coord indices to 0. Ideally, it shouldn't exist at all, but the exact behavior hasn't been
- // tested.
- out.Write("\tint2 fixpoint_uv0 = int2(0, 0);\n\n");
+ out.Write("\tfrag_input.normal = normalize(Normal);\n");
+ out.Write("\tfrag_input.position = WorldPos;\n");
}
else
{
- out.SetConstantsUsed(C_TEXDIMS, C_TEXDIMS + uid_data->genMode_numtexgens - 1);
- for (u32 i = 0; i < uid_data->genMode_numtexgens; ++i)
- {
- out.Write("\tint2 fixpoint_uv{} = int2(", i);
- out.Write("(tex{}.z == 0.0 ? tex{}.xy : tex{}.xy / tex{}.z)", i, i, i, i);
- out.Write(" * float2(" I_TEXDIMS "[{}].zw * 128));\n", i);
- // TODO: S24 overflows here?
- }
+ out.Write("\tfrag_input.normal = vec3(0, 0, 0);\n");
+ out.Write("\tfrag_input.position = vec3(0, 0, 0);\n");
}
-
- for (u32 i = 0; i < uid_data->genMode_numindstages; ++i)
+ for (u32 i = 0; i < uid_data->genMode_numtexgens; i++)
{
- if ((uid_data->nIndirectStagesUsed & (1U << i)) != 0)
- {
- u32 texcoord = uid_data->GetTevindirefCoord(i);
- const u32 texmap = uid_data->GetTevindirefMap(i);
-
- // Quirk: when the tex coord is not less than the number of tex gens (i.e. the tex coord does
- // not exist), then tex coord 0 is used (though sometimes glitchy effects happen on console).
- // This affects the Mario portrait in Luigi's Mansion, where the developers forgot to set
- // the number of tex gens to 2 (bug 11462).
- if (texcoord >= uid_data->genMode_numtexgens)
- texcoord = 0;
-
- out.SetConstantsUsed(C_INDTEXSCALE + i / 2, C_INDTEXSCALE + i / 2);
- out.Write("\ttempcoord = fixpoint_uv{} >> " I_INDTEXSCALE "[{}].{};\n", texcoord, i / 2,
- (i & 1) ? "zw" : "xy");
-
- out.Write("\tint3 iindtex{0} = sampleTextureWrapper({1}u, tempcoord, layer).abg;\n", i,
- texmap);
- }
+ out.Write("\tfrag_input.tex{0} = tex{0};\n", i);
}
- for (u32 i = 0; i < numStages; i++)
- {
- // Build the equation for this stage
- WriteStage(out, uid_data, i, api_type, stereo, has_custom_shaders);
- }
+ if (!custom_contents.shader.empty())
+ GenerateCustomLighting(&out, uid_data->lighting);
- {
- // The results of the last texenv stage are put onto the screen,
- // regardless of the used destination register
- TevStageCombiner::ColorCombiner last_cc;
- TevStageCombiner::AlphaCombiner last_ac;
- last_cc.hex = uid_data->stagehash[uid_data->genMode_numtevstages].cc;
- last_ac.hex = uid_data->stagehash[uid_data->genMode_numtevstages].ac;
- if (last_cc.dest != TevOutput::Prev)
- {
- out.Write("\tprev.rgb = {};\n", tev_c_output_table[last_cc.dest]);
- }
- if (last_ac.dest != TevOutput::Prev)
- {
- out.Write("\tprev.a = {};\n", tev_a_output_table[last_ac.dest]);
- }
- }
- out.Write("\tprev = prev & 255;\n");
+ out.Write("\tDolphinFragmentOutput frag_output;\n");
+ out.Write("\tprocess_fragment(frag_input, frag_output);\n");
+ out.Write("\tivec4 prev = frag_output.main & 255;\n");
// NOTE: Fragment may not be discarded if alpha test always fails and early depth test is enabled
// (in this case we need to write a depth value if depth test passes regardless of the alpha
@@ -1292,10 +1092,11 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos
// ztextures anyway
if (uid_data->ztex_op != ZTexOp::Disabled && !skip_ztexture)
{
- // use the texture input of the last texture stage (textemp), hopefully this has been read and
+ // use the texture input of the last texture stage, hopefully this has been read and
// is in correct format...
out.SetConstantsUsed(C_ZBIAS, C_ZBIAS + 1);
- out.Write("\tzCoord = idot(" I_ZBIAS "[0].xyzw, rawtextemp.xyzw) + " I_ZBIAS "[1].w {};\n",
+ out.Write("\tzCoord = idot(" I_ZBIAS "[0].xyzw, frag_output.last_texture.xyzw) + " I_ZBIAS
+ "[1].w {};\n",
(uid_data->ztex_op == ZTexOp::Add) ? "+ zCoord" : "");
out.Write("\tzCoord = zCoord & 0xFFFFFF;\n");
}
@@ -1319,23 +1120,6 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos
WriteFog(out, uid_data);
- for (std::size_t i = 0; i < custom_details.shaders.size(); i++)
- {
- const auto& shader_details = custom_details.shaders[i];
-
- if (!shader_details.custom_shader.empty())
- {
- out.Write("\t{{\n");
- out.Write("\t\tcustom_data.final_color = float4(prev.r / 255.0, prev.g / 255.0, prev.b "
- "/ 255.0, prev.a / 255.0);\n");
- out.Write("\t\tCustomShaderOutput custom_output = {}_{}(custom_data);\n",
- CUSTOM_PIXELSHADER_COLOR_FUNC, i);
- out.Write("\t\tprev = int4(custom_output.main_rt.r * 255, custom_output.main_rt.g * 255, "
- "custom_output.main_rt.b * 255, custom_output.main_rt.a * 255);\n");
- out.Write("\t}}\n\n");
- }
- }
-
if (uid_data->logic_op_enable)
WriteLogicOp(out, uid_data);
else if (uid_data->emulate_logic_op_with_blend)
@@ -1360,7 +1144,7 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos
}
static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, int n,
- APIType api_type, bool stereo, bool has_custom_shaders)
+ APIType api_type, bool stereo)
{
using Common::EnumMap;
@@ -1755,58 +1539,6 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
out.Write(", -1024, 1023)");
out.Write(";\n");
-
- if (has_custom_shaders)
- {
- // Color input
- out.Write(
- "\tcustom_data.tev_stages[{}].input_color[0].value = {} / float3(255.0, 255.0, 255.0);\n",
- n, tev_c_input_table[cc.a]);
- out.Write("\tcustom_data.tev_stages[{}].input_color[0].input_type = {};\n", n,
- tev_c_input_type[cc.a]);
- out.Write(
- "\tcustom_data.tev_stages[{}].input_color[1].value = {} / float3(255.0, 255.0, 255.0);\n",
- n, tev_c_input_table[cc.b]);
- out.Write("\tcustom_data.tev_stages[{}].input_color[1].input_type = {};\n", n,
- tev_c_input_type[cc.b]);
- out.Write(
- "\tcustom_data.tev_stages[{}].input_color[2].value = {} / float3(255.0, 255.0, 255.0);\n",
- n, tev_c_input_table[cc.c]);
- out.Write("\tcustom_data.tev_stages[{}].input_color[2].input_type = {};\n", n,
- tev_c_input_type[cc.c]);
- out.Write(
- "\tcustom_data.tev_stages[{}].input_color[3].value = {} / float3(255.0, 255.0, 255.0);\n",
- n, tev_c_input_table[cc.d]);
- out.Write("\tcustom_data.tev_stages[{}].input_color[3].input_type = {};\n", n,
- tev_c_input_type[cc.d]);
-
- // Alpha input
- out.Write("\tcustom_data.tev_stages[{}].input_alpha[0].value = {} / float(255.0);\n", n,
- tev_a_input_table[ac.a]);
- out.Write("\tcustom_data.tev_stages[{}].input_alpha[0].input_type = {};\n", n,
- tev_a_input_type[ac.a]);
- out.Write("\tcustom_data.tev_stages[{}].input_alpha[1].value = {} / float(255.0);\n", n,
- tev_a_input_table[ac.b]);
- out.Write("\tcustom_data.tev_stages[{}].input_alpha[1].input_type = {};\n", n,
- tev_a_input_type[ac.b]);
- out.Write("\tcustom_data.tev_stages[{}].input_alpha[2].value = {} / float(255.0);\n", n,
- tev_a_input_table[ac.c]);
- out.Write("\tcustom_data.tev_stages[{}].input_alpha[2].input_type = {};\n", n,
- tev_a_input_type[ac.c]);
- out.Write("\tcustom_data.tev_stages[{}].input_alpha[3].value = {} / float(255.0);\n", n,
- tev_a_input_table[ac.d]);
- out.Write("\tcustom_data.tev_stages[{}].input_alpha[3].input_type = {};\n", n,
- tev_a_input_type[ac.d]);
-
- // Texmap
- out.Write("\tcustom_data.tev_stages[{}].texmap = {}u;\n", n, stage.tevorders_texmap);
-
- // Output
- out.Write("\tcustom_data.tev_stages[{}].output_color.rgb = {} / float3(255.0, 255.0, 255.0);\n",
- n, tev_c_output_table[cc.dest]);
- out.Write("\tcustom_data.tev_stages[{}].output_color.a = {} / float(255.0);\n", n,
- tev_a_output_table[ac.dest]);
- }
}
static void WriteTevRegular(ShaderCode& out, std::string_view components, TevBias bias, TevOp op,
@@ -2187,3 +1919,198 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data)
out.Write("\treal_ocol0 = blend_result;\n");
}
+
+void WriteFragmentBody(APIType api_type, const ShaderHostConfig& host_config,
+ const pixel_shader_uid_data* uid_data, ShaderCode& out)
+{
+ const bool per_pixel_lighting = host_config.per_pixel_lighting;
+ const bool stereo = host_config.stereo;
+ const u32 numStages = uid_data->genMode_numtevstages + 1;
+
+ out.Write("\tvec4 col0 = frag_input.color_0;\n");
+ out.Write("\tvec4 col1 = frag_input.color_1;\n");
+ out.Write("\tint layer = frag_input.layer;\n");
+
+ out.Write("\tint4 c0 = " I_COLORS "[1], c1 = " I_COLORS "[2], c2 = " I_COLORS
+ "[3], prev = " I_COLORS "[0];\n"
+ "\tint4 rastemp = int4(0, 0, 0, 0), rawtextemp = int4(0, 0, 0, 0), "
+ "textemp = int4(0, 0, 0, 0), konsttemp = int4(0, 0, 0, 0);\n"
+ "\tint3 comp16 = int3(1, 256, 0), comp24 = int3(1, 256, 256*256);\n"
+ "\tint alphabump=0;\n"
+ "\tint3 tevcoord=int3(0, 0, 0);\n"
+ "\tint2 wrappedcoord=int2(0,0), tempcoord=int2(0,0);\n"
+ "\tint4 "
+ "tevin_a=int4(0,0,0,0),tevin_b=int4(0,0,0,0),tevin_c=int4(0,0,0,0),tevin_d=int4(0,0,0,"
+ "0);\n\n"); // tev combiner inputs
+
+ if (per_pixel_lighting)
+ {
+ if (uid_data->numColorChans > 0)
+ {
+ out.Write("\tcol0 = dolphin_calculate_lighting_chn0(col0, frag_input.position, "
+ "frag_input.normal);\n");
+ }
+ else
+ {
+ // The number of colors available to TEV is determined by numColorChans.
+ // We have to provide the fields to match the interface, so set to zero if it's not enabled.
+ out.Write("\tcol0 = vec4(0.0, 0.0, 0.0, 0.0);\n");
+ }
+
+ if (uid_data->numColorChans == 2)
+ {
+ out.Write("\tcol1 = dolphin_calculate_lighting_chn1(col1, frag_input.position, "
+ "frag_input.normal);\n");
+ }
+ else
+ {
+ // The number of colors available to TEV is determined by numColorChans.
+ // We have to provide the fields to match the interface, so set to zero if it's not enabled.
+ out.Write("\tcol1 = vec4(0.0, 0.0, 0.0, 0.0);\n");
+ }
+ }
+
+ if (uid_data->genMode_numtexgens == 0)
+ {
+ // TODO: This is a hack to ensure that shaders still compile when setting out of bounds tex
+ // coord indices to 0. Ideally, it shouldn't exist at all, but the exact behavior hasn't been
+ // tested.
+ out.Write("\tint2 fixpoint_uv0 = int2(0, 0);\n\n");
+ }
+ else
+ {
+ out.SetConstantsUsed(C_TEXDIMS, C_TEXDIMS + uid_data->genMode_numtexgens - 1);
+ for (u32 i = 0; i < uid_data->genMode_numtexgens; ++i)
+ {
+ out.Write("\tint2 fixpoint_uv{} = int2(", i);
+ out.Write("(frag_input.tex{}.z == 0.0 ? frag_input.tex{}.xy : frag_input.tex{}.xy / "
+ "frag_input.tex{}.z)",
+ i, i, i, i);
+ out.Write(" * float2(" I_TEXDIMS "[{}].zw * 128));\n", i);
+ // TODO: S24 overflows here?
+ }
+ }
+
+ for (u32 i = 0; i < uid_data->genMode_numindstages; ++i)
+ {
+ if ((uid_data->nIndirectStagesUsed & (1U << i)) != 0)
+ {
+ u32 texcoord = uid_data->GetTevindirefCoord(i);
+ const u32 texmap = uid_data->GetTevindirefMap(i);
+
+ // Quirk: when the tex coord is not less than the number of tex gens (i.e. the tex coord
+ // does not exist), then tex coord 0 is used (though sometimes glitchy effects happen on
+ // console). This affects the Mario portrait in Luigi's Mansion, where the developers forgot
+ // to set the number of tex gens to 2 (bug 11462).
+ if (texcoord >= uid_data->genMode_numtexgens)
+ texcoord = 0;
+
+ out.SetConstantsUsed(C_INDTEXSCALE + i / 2, C_INDTEXSCALE + i / 2);
+ out.Write("\ttempcoord = fixpoint_uv{} >> " I_INDTEXSCALE "[{}].{};\n", texcoord, i / 2,
+ (i & 1) ? "zw" : "xy");
+
+ out.Write("\tint3 iindtex{0} = sampleTextureWrapper({1}u, tempcoord, layer).abg;\n", i,
+ texmap);
+ }
+ }
+
+ for (u32 i = 0; i < numStages; i++)
+ {
+ // Build the equation for this stage
+ WriteStage(out, uid_data, i, api_type, stereo);
+ }
+
+ {
+ // The results of the last texenv stage are put onto the screen,
+ // regardless of the used destination register
+ TevStageCombiner::ColorCombiner last_cc;
+ TevStageCombiner::AlphaCombiner last_ac;
+ last_cc.hex = uid_data->stagehash[uid_data->genMode_numtevstages].cc;
+ last_ac.hex = uid_data->stagehash[uid_data->genMode_numtevstages].ac;
+ if (last_cc.dest != TevOutput::Prev)
+ {
+ out.Write("\tprev.rgb = {};\n", tev_c_output_table[last_cc.dest]);
+ }
+ if (last_ac.dest != TevOutput::Prev)
+ {
+ out.Write("\tprev.a = {};\n", tev_a_output_table[last_ac.dest]);
+ }
+ }
+
+ out.Write("\tfrag_output.last_texture = rawtextemp;\n");
+ out.Write("\tfrag_output.main = prev;\n");
+}
+
+static void WriteFragmentDefinitions(APIType api_type, const ShaderHostConfig& host_config,
+ const pixel_shader_uid_data* uid_data, ShaderCode& out)
+{
+ out.Write("struct DolphinLightData\n");
+ out.Write("{{\n");
+ out.Write("\tfloat3 position;\n");
+ out.Write("\tfloat3 direction;\n");
+ out.Write("\tfloat3 color;\n");
+ out.Write("\tuint attenuation_type;\n");
+ out.Write("\tfloat4 cosatt;\n");
+ out.Write("\tfloat4 distatt;\n");
+ out.Write("}};\n\n");
+
+ out.Write("struct DolphinFragmentInput\n");
+ out.Write("{{\n");
+ out.Write("\tvec4 color_0;\n");
+ out.Write("\tvec4 color_1;\n");
+ out.Write("\tint layer;\n");
+ out.Write("\tvec3 normal;\n");
+ out.Write("\tvec3 position;\n");
+ for (u32 i = 0; i < uid_data->genMode_numtexgens; i++)
+ {
+ out.Write("\tvec3 tex{};\n", i);
+ }
+ for (u32 i = uid_data->genMode_numtexgens; i < 8; i++)
+ {
+ out.Write("\tvec3 tex{};\n", i);
+ }
+ out.Write("\n");
+
+ out.Write("\tDolphinLightData[8] lights_chan0_color;\n");
+ out.Write("\tDolphinLightData[8] lights_chan0_alpha;\n");
+ out.Write("\tDolphinLightData[8] lights_chan1_color;\n");
+ out.Write("\tDolphinLightData[8] lights_chan1_alpha;\n");
+ out.Write("\tfloat4[2] ambient_lighting;\n");
+ out.Write("\tfloat4[2] base_material;\n");
+ out.Write("\tuint light_chan0_color_count;\n");
+ out.Write("\tuint light_chan0_alpha_count;\n");
+ out.Write("\tuint light_chan1_color_count;\n");
+ out.Write("\tuint light_chan1_alpha_count;\n");
+
+ out.Write("}};\n\n");
+
+ out.Write("struct DolphinFragmentOutput\n");
+ out.Write("{{\n");
+ out.Write("\tivec4 main;\n");
+ out.Write("\tivec4 last_texture;\n");
+ out.Write("}};\n\n");
+
+ // CUSTOM_SHADER_LIGHTING_ATTENUATION_TYPE "enum" values
+ out.Write("const uint CUSTOM_SHADER_LIGHTING_ATTENUATION_TYPE_NONE = {}u;\n",
+ static_cast<u32>(AttenuationFunc::None));
+ out.Write("const uint CUSTOM_SHADER_LIGHTING_ATTENUATION_TYPE_POINT = {}u;\n",
+ static_cast<u32>(AttenuationFunc::Spec));
+ out.Write("const uint CUSTOM_SHADER_LIGHTING_ATTENUATION_TYPE_DIR = {}u;\n",
+ static_cast<u32>(AttenuationFunc::Dir));
+ out.Write("const uint CUSTOM_SHADER_LIGHTING_ATTENUATION_TYPE_SPOT = {}u;\n",
+ static_cast<u32>(AttenuationFunc::Spot));
+}
+
+static void WriteEmulatedFragmentBodyHeader(APIType api_type, const ShaderHostConfig& host_config,
+ const pixel_shader_uid_data* uid_data, ShaderCode& out)
+{
+ constexpr std::string_view emulated_fragment_definition =
+ "void dolphin_process_emulated_fragment(in DolphinFragmentInput frag_input, out "
+ "DolphinFragmentOutput frag_output)";
+ out.Write("{}\n", emulated_fragment_definition);
+ out.Write("{{\n");
+
+ WriteFragmentBody(api_type, host_config, uid_data, out);
+
+ out.Write("}}\n");
+}
diff --git a/Source/Core/VideoCommon/PixelShaderGen.h b/Source/Core/VideoCommon/PixelShaderGen.h
index e5dd43d754..f8c0fa96c5 100644
--- a/Source/Core/VideoCommon/PixelShaderGen.h
+++ b/Source/Core/VideoCommon/PixelShaderGen.h
@@ -158,15 +158,19 @@ struct pixel_shader_uid_data
using PixelShaderUid = ShaderUid<pixel_shader_uid_data>;
-void WriteCustomShaderStructImpl(ShaderCode* out, u32 num_stages, bool per_pixel_lighting,
- const pixel_shader_uid_data* uid_data);
+struct CustomPixelContents
+{
+ std::string_view shader = "";
+ std::string_view uniforms = "";
+};
ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& host_config,
const pixel_shader_uid_data* uid_data,
- const CustomPixelShaderContents& custom_details);
+ CustomPixelContents custom_contents);
void WritePixelShaderCommonHeader(ShaderCode& out, APIType api_type,
- const ShaderHostConfig& host_config, bool bounding_box,
- const CustomPixelShaderContents& custom_details);
+ const ShaderHostConfig& host_config, bool bounding_box);
+void WriteFragmentBody(APIType api_type, const ShaderHostConfig& host_config,
+ const pixel_shader_uid_data* uid_data, ShaderCode& out);
void ClearUnusedPixelShaderUidBits(APIType api_type, const ShaderHostConfig& host_config,
PixelShaderUid* uid);
PixelShaderUid GetPixelShaderUid();
diff --git a/Source/Core/VideoCommon/ShaderCache.cpp b/Source/Core/VideoCommon/ShaderCache.cpp
index 22939e9b90..96f3a67e18 100644
--- a/Source/Core/VideoCommon/ShaderCache.cpp
+++ b/Source/Core/VideoCommon/ShaderCache.cpp
@@ -457,7 +457,7 @@ std::unique_ptr<AbstractShader>
ShaderCache::CompilePixelUberShader(const UberShader::PixelShaderUid& uid) const
{
const ShaderCode source_code =
- UberShader::GenPixelShader(m_api_type, m_host_config, uid.GetUidData(), {});
+ UberShader::GenPixelShader(m_api_type, m_host_config, uid.GetUidData());
return g_gfx->CreateShaderFromSource(ShaderStage::Pixel, source_code.GetBuffer(),
fmt::to_string(*uid.GetUidData()));
}
diff --git a/Source/Core/VideoCommon/ShaderGenCommon.cpp b/Source/Core/VideoCommon/ShaderGenCommon.cpp
index ec251c3cce..26463f4476 100644
--- a/Source/Core/VideoCommon/ShaderGenCommon.cpp
+++ b/Source/Core/VideoCommon/ShaderGenCommon.cpp
@@ -362,95 +362,3 @@ const char* GetInterpolationQualifier(bool msaa, bool ssaa, bool in_glsl_interfa
return "sample";
}
}
-
-void WriteCustomShaderStructDef(ShaderCode* out, u32 numtexgens)
-{
- // Bump this when there are breaking changes to the API
- out->Write("#define CUSTOM_SHADER_API_VERSION 1;\n");
-
- // CUSTOM_SHADER_LIGHTING_ATTENUATION_TYPE "enum" values
- out->Write("const uint CUSTOM_SHADER_LIGHTING_ATTENUATION_TYPE_NONE = {}u;\n",
- static_cast<u32>(AttenuationFunc::None));
- out->Write("const uint CUSTOM_SHADER_LIGHTING_ATTENUATION_TYPE_POINT = {}u;\n",
- static_cast<u32>(AttenuationFunc::Spec));
- out->Write("const uint CUSTOM_SHADER_LIGHTING_ATTENUATION_TYPE_DIR = {}u;\n",
- static_cast<u32>(AttenuationFunc::Dir));
- out->Write("const uint CUSTOM_SHADER_LIGHTING_ATTENUATION_TYPE_SPOT = {}u;\n",
- static_cast<u32>(AttenuationFunc::Spot));
-
- out->Write("struct CustomShaderOutput\n");
- out->Write("{{\n");
- out->Write("\tfloat4 main_rt;\n");
- out->Write("}};\n\n");
-
- out->Write("struct CustomShaderLightData\n");
- out->Write("{{\n");
- out->Write("\tfloat3 position;\n");
- out->Write("\tfloat3 direction;\n");
- out->Write("\tfloat3 color;\n");
- out->Write("\tuint attenuation_type;\n");
- out->Write("\tfloat4 cosatt;\n");
- out->Write("\tfloat4 distatt;\n");
- out->Write("}};\n\n");
-
- // CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE "enum" values
- out->Write("const uint CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_PREV = 0u;\n");
- out->Write("const uint CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_COLOR = 1u;\n");
- out->Write("const uint CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_TEX = 2u;\n");
- out->Write("const uint CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_RAS = 3u;\n");
- out->Write("const uint CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_KONST = 4u;\n");
- out->Write("const uint CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_NUMERIC = 5u;\n");
- out->Write("const uint CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_UNUSED = 6u;\n");
-
- out->Write("struct CustomShaderTevStageInputColor\n");
- out->Write("{{\n");
- out->Write("\tuint input_type;\n");
- out->Write("\tfloat3 value;\n");
- out->Write("}};\n\n");
-
- out->Write("struct CustomShaderTevStageInputAlpha\n");
- out->Write("{{\n");
- out->Write("\tuint input_type;\n");
- out->Write("\tfloat value;\n");
- out->Write("}};\n\n");
-
- out->Write("struct CustomShaderTevStage\n");
- out->Write("{{\n");
- out->Write("\tCustomShaderTevStageInputColor[4] input_color;\n");
- out->Write("\tCustomShaderTevStageInputAlpha[4] input_alpha;\n");
- out->Write("\tuint texmap;\n");
- out->Write("\tfloat4 output_color;\n");
- out->Write("}};\n\n");
-
- // Custom structure for data we pass to custom shader hooks
- out->Write("struct CustomShaderData\n");
- out->Write("{{\n");
- out->Write("\tfloat3 position;\n");
- out->Write("\tfloat3 normal;\n");
- if (numtexgens == 0)
- {
- // Cheat so shaders compile
- out->Write("\tfloat3[1] texcoord;\n");
- }
- else
- {
- out->Write("\tfloat3[{}] texcoord;\n", numtexgens);
- }
- out->Write("\tuint texcoord_count;\n");
- out->Write("\tuint[8] texmap_to_texcoord_index;\n");
- out->Write("\tCustomShaderLightData[8] lights_chan0_color;\n");
- out->Write("\tCustomShaderLightData[8] lights_chan0_alpha;\n");
- out->Write("\tCustomShaderLightData[8] lights_chan1_color;\n");
- out->Write("\tCustomShaderLightData[8] lights_chan1_alpha;\n");
- out->Write("\tfloat4[2] ambient_lighting;\n");
- out->Write("\tfloat4[2] base_material;\n");
- out->Write("\tuint light_chan0_color_count;\n");
- out->Write("\tuint light_chan0_alpha_count;\n");
- out->Write("\tuint light_chan1_color_count;\n");
- out->Write("\tuint light_chan1_alpha_count;\n");
- out->Write("\tCustomShaderTevStage[16] tev_stages;\n");
- out->Write("\tuint tev_stage_count;\n");
- out->Write("\tfloat4 final_color;\n");
- out->Write("\tuint time_ms;\n");
- out->Write("}};\n\n");
-}
diff --git a/Source/Core/VideoCommon/ShaderGenCommon.h b/Source/Core/VideoCommon/ShaderGenCommon.h
index 4723cbfc79..7d2c80f086 100644
--- a/Source/Core/VideoCommon/ShaderGenCommon.h
+++ b/Source/Core/VideoCommon/ShaderGenCommon.h
@@ -345,5 +345,3 @@ struct CustomPixelShaderContents
bool operator==(const CustomPixelShaderContents& other) const = default;
};
-
-void WriteCustomShaderStructDef(ShaderCode* out, u32 numtexgens);
diff --git a/Source/Core/VideoCommon/UberShaderPixel.cpp b/Source/Core/VideoCommon/UberShaderPixel.cpp
index ef59414619..94ce2e2dbb 100644
--- a/Source/Core/VideoCommon/UberShaderPixel.cpp
+++ b/Source/Core/VideoCommon/UberShaderPixel.cpp
@@ -17,263 +17,6 @@
namespace UberShader
{
-namespace
-{
-void WriteCustomShaderStructImpl(ShaderCode* out, u32 num_texgen, bool per_pixel_lighting)
-{
- out->Write("\tCustomShaderData custom_data;\n");
- if (per_pixel_lighting)
- {
- out->Write("\tcustom_data.position = WorldPos;\n");
- out->Write("\tcustom_data.normal = Normal;\n");
- }
- else
- {
- out->Write("\tcustom_data.position = float3(0, 0, 0);\n");
- out->Write("\tcustom_data.normal = float3(0, 0, 0);\n");
- }
-
- if (num_texgen == 0) [[unlikely]]
- {
- out->Write("\tcustom_data.texcoord[0] = float3(0, 0, 0);\n");
- }
- else
- {
- for (u32 i = 0; i < num_texgen; ++i)
- {
- out->Write("\tif (tex{0}.z == 0.0)\n", i);
- out->Write("\t{{\n");
- out->Write("\t\tcustom_data.texcoord[{0}] = tex{0};\n", i);
- out->Write("\t}}\n");
- out->Write("\telse {{\n");
- out->Write("\t\tcustom_data.texcoord[{0}] = float3(tex{0}.xy / tex{0}.z, 0);\n", i);
- out->Write("\t}}\n");
- }
- }
-
- out->Write("\tcustom_data.texcoord_count = {};\n", num_texgen);
-
- for (u32 i = 0; i < 8; i++)
- {
- // Shader compilation complains if every index isn't initialized
- out->Write("\tcustom_data.texmap_to_texcoord_index[{0}] = {0};\n", i);
- }
-
- for (u32 i = 0; i < NUM_XF_COLOR_CHANNELS; i++)
- {
- out->Write("\tcustom_data.base_material[{}] = vec4(0, 0, 0, 1);\n", i);
- out->Write("\tcustom_data.ambient_lighting[{}] = vec4(0, 0, 0, 1);\n", i);
-
- // Shader compilation errors can throw if not everything is initialized
- for (u32 light_count_index = 0; light_count_index < 8; light_count_index++)
- {
- // Color
- out->Write("\tcustom_data.lights_chan{}_color[{}].direction = float3(0, 0, 0);\n", i,
- light_count_index);
- out->Write("\tcustom_data.lights_chan{}_color[{}].position = float3(0, 0, 0);\n", i,
- light_count_index);
- out->Write("\tcustom_data.lights_chan{}_color[{}].color = float3(0, 0, 0);\n", i,
- light_count_index);
- out->Write("\tcustom_data.lights_chan{}_color[{}].cosatt = float4(0, 0, 0, 0);\n", i,
- light_count_index);
- out->Write("\tcustom_data.lights_chan{}_color[{}].distatt = float4(0, 0, 0, 0);\n", i,
- light_count_index);
- out->Write("\tcustom_data.lights_chan{}_color[{}].attenuation_type = 0;\n", i,
- light_count_index);
-
- // Alpha
- out->Write("\tcustom_data.lights_chan{}_alpha[{}].direction = float3(0, 0, 0);\n", i,
- light_count_index);
- out->Write("\tcustom_data.lights_chan{}_alpha[{}].position = float3(0, 0, 0);\n", i,
- light_count_index);
- out->Write("\tcustom_data.lights_chan{}_alpha[{}].color = float3(0, 0, 0);\n", i,
- light_count_index);
- out->Write("\tcustom_data.lights_chan{}_alpha[{}].cosatt = float4(0, 0, 0, 0);\n", i,
- light_count_index);
- out->Write("\tcustom_data.lights_chan{}_alpha[{}].distatt = float4(0, 0, 0, 0);\n", i,
- light_count_index);
- out->Write("\tcustom_data.lights_chan{}_alpha[{}].attenuation_type = 0;\n", i,
- light_count_index);
- }
-
- out->Write("\tcustom_data.light_chan{}_color_count = 0;\n", i);
- out->Write("\tcustom_data.light_chan{}_alpha_count = 0;\n", i);
- }
-
- if (num_texgen > 0) [[likely]]
- {
- out->Write("\n");
- out->Write("\tfor(uint stage = 0u; stage <= num_stages; stage++)\n");
- out->Write("\t{{\n");
- out->Write("\t\tStageState ss;\n");
- out->Write("\t\tss.order = bpmem_tevorder(stage>>1);\n");
- out->Write("\t\tif ((stage & 1u) == 1u)\n");
- out->Write("\t\t\tss.order = ss.order >> {};\n\n",
- int(TwoTevStageOrders().enable_tex_odd.StartBit() -
- TwoTevStageOrders().enable_tex_even.StartBit()));
- out->Write("\t\tuint texmap = {};\n",
- BitfieldExtract<&TwoTevStageOrders::texcoord_even>("ss.order"));
- // Shader compilation is weird, shader arrays can't use indexing by variable
- // to set values unless the variable is an index in a for loop.
- // So instead we have to do this if check nonsense
- for (u32 i = 0; i < 8; i++)
- {
- out->Write("\t\tif (texmap == {})\n", i);
- out->Write("\t\t{{\n");
- out->Write("\t\t\tcustom_data.texmap_to_texcoord_index[{}] = selectTexCoordIndex(texmap);\n",
- i);
- out->Write("\t\t}}\n");
- }
- out->Write("\t}}\n");
- }
-
- if (per_pixel_lighting)
- {
- out->Write("\tuint light_count = 0;\n");
- out->Write("\tfor (uint chan = 0u; chan < {}u; chan++)\n", NUM_XF_COLOR_CHANNELS);
- out->Write("\t{{\n");
- out->Write("\t\tuint colorreg = xfmem_color(chan);\n");
- out->Write("\t\tuint alphareg = xfmem_alpha(chan);\n");
- for (const auto& color_type : std::array<std::string_view, 2>{"colorreg", "alphareg"})
- {
- if (color_type == "colorreg")
- {
- out->Write("\t\tcustom_data.base_material[0] = " I_MATERIALS "[2u] / 255.0; \n");
- out->Write("\t\tif ({} != 0u)\n", BitfieldExtract<&LitChannel::enablelighting>(color_type));
- out->Write("\t\t\tcustom_data.base_material[0] = colors_0; \n");
- }
- else
- {
- out->Write("custom_data.base_material[1].w = " I_MATERIALS "[3u].w / 255.0; \n");
- out->Write("\t\tif ({} != 0u)\n", BitfieldExtract<&LitChannel::enablelighting>(color_type));
- out->Write("\t\t\tcustom_data.base_material[1].w = colors_1.w; \n");
- }
- out->Write("\t\tif ({} != 0u)\n", BitfieldExtract<&LitChannel::enablelighting>(color_type));
- out->Write("\t\t{{\n");
- out->Write("\t\t\tuint light_mask = {} | ({} << 4u);\n",
- BitfieldExtract<&LitChannel::lightMask0_3>(color_type),
- BitfieldExtract<&LitChannel::lightMask4_7>(color_type));
- out->Write("\t\t\tuint attnfunc = {};\n", BitfieldExtract<&LitChannel::attnfunc>(color_type));
- out->Write("\t\t\tfor (uint light_index = 0u; light_index < 8u; light_index++)\n");
- out->Write("\t\t\t{{\n");
- out->Write("\t\t\t\tif ((light_mask & (1u << light_index)) != 0u)\n");
- out->Write("\t\t\t\t{{\n");
- // Shader compilation is weird, shader arrays can't use indexing by variable
- // to set values unless the variable is an index in a for loop.
- // So instead we have to do this if check nonsense
- for (u32 light_count_index = 0; light_count_index < 8; light_count_index++)
- {
- out->Write("\t\t\t\t\tif (light_index == {})\n", light_count_index);
- out->Write("\t\t\t\t\t{{\n");
- if (color_type == "colorreg")
- {
- for (u32 channel_index = 0; channel_index < NUM_XF_COLOR_CHANNELS; channel_index++)
- {
- out->Write("\t\t\t\t\t\tif (chan == {})\n", channel_index);
- out->Write("\t\t\t\t\t\t{{\n");
- out->Write("\t\t\t\t\t\t\tcustom_data.lights_chan{}_color[{}].direction = " I_LIGHTS
- "[light_index].dir.xyz;\n",
- channel_index, light_count_index);
- out->Write("\t\t\t\t\t\t\tcustom_data.lights_chan{}_color[{}].position = " I_LIGHTS
- "[light_index].pos.xyz;\n",
- channel_index, light_count_index);
- out->Write("\t\t\t\t\t\t\tcustom_data.lights_chan{}_color[{}].cosatt = " I_LIGHTS
- "[light_index].cosatt;\n",
- channel_index, light_count_index);
- out->Write("\t\t\t\t\t\t\tcustom_data.lights_chan{}_color[{}].distatt = " I_LIGHTS
- "[light_index].distatt;\n",
- channel_index, light_count_index);
- out->Write(
- "\t\t\t\t\t\t\tcustom_data.lights_chan{}_color[{}].attenuation_type = attnfunc;\n",
- channel_index, light_count_index);
- out->Write("\t\t\t\t\t\t\tcustom_data.lights_chan{}_color[{}].color = " I_LIGHTS
- "[light_index].color.rgb / float3(255.0, 255.0, 255.0);\n",
- channel_index, light_count_index);
- out->Write("\t\t\t\t\t\t\tcustom_data.light_chan{}_color_count += 1;\n", channel_index);
- out->Write("\t\t\t\t\t\t}}\n");
- }
- }
- else
- {
- for (u32 channel_index = 0; channel_index < NUM_XF_COLOR_CHANNELS; channel_index++)
- {
- out->Write("\t\t\t\t\t\tif (chan == {})\n", channel_index);
- out->Write("\t\t\t\t\t\t{{\n");
- out->Write("\t\t\t\t\t\t\tcustom_data.lights_chan{}_alpha[{}].direction = " I_LIGHTS
- "[light_index].dir.xyz;\n",
- channel_index, light_count_index);
- out->Write("\t\t\t\t\t\t\tcustom_data.lights_chan{}_alpha[{}].position = " I_LIGHTS
- "[light_index].pos.xyz;\n",
- channel_index, light_count_index);
- out->Write("\t\t\t\t\t\t\tcustom_data.lights_chan{}_alpha[{}].cosatt = " I_LIGHTS
- "[light_index].cosatt;\n",
- channel_index, light_count_index);
- out->Write("\t\t\t\t\t\t\tcustom_data.lights_chan{}_alpha[{}].distatt = " I_LIGHTS
- "[light_index].distatt;\n",
- channel_index, light_count_index);
- out->Write(
- "\t\t\t\t\t\t\tcustom_data.lights_chan{}_alpha[{}].attenuation_type = attnfunc;\n",
- channel_index, light_count_index);
- out->Write("\t\t\t\t\t\t\tcustom_data.lights_chan{}_alpha[{}].color = float3(" I_LIGHTS
- "[light_index].color.a) / float3(255.0, 255.0, 255.0);\n",
- channel_index, light_count_index);
- out->Write("\t\t\t\t\t\t\tcustom_data.light_chan{}_alpha_count += 1;\n", channel_index);
- out->Write("\t\t\t\t\t\t}}\n");
- }
- }
-
- out->Write("\t\t\t\t\t}}\n");
- }
- out->Write("\t\t\t\t}}\n");
- out->Write("\t\t\t}}\n");
- out->Write("\t\t}}\n");
- }
- out->Write("\t}}\n");
- }
-
- for (u32 i = 0; i < 16; i++)
- {
- // Shader compilation complains if every struct isn't initialized
-
- // Color Input
- for (u32 j = 0; j < 4; j++)
- {
- out->Write("\tcustom_data.tev_stages[{}].input_color[{}].input_type = "
- "CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_UNUSED;\n",
- i, j);
- out->Write("\tcustom_data.tev_stages[{}].input_color[{}].value = "
- "float3(0, 0, 0);\n",
- i, j);
- }
-
- // Alpha Input
- for (u32 j = 0; j < 4; j++)
- {
- out->Write("\tcustom_data.tev_stages[{}].input_alpha[{}].input_type = "
- "CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_UNUSED;\n",
- i, j);
- out->Write("\tcustom_data.tev_stages[{}].input_alpha[{}].value = "
- "float(0);\n",
- i, j);
- }
-
- // Texmap
- out->Write("\tcustom_data.tev_stages[{}].texmap = 0u;\n", i);
-
- // Output
- out->Write("\tcustom_data.tev_stages[{}].output_color = "
- "float4(0, 0, 0, 0);\n",
- i);
- }
-
- // Actual data will be filled out in the tev stage code, just set the
- // stage count for now
- out->Write("\tcustom_data.tev_stage_count = num_stages;\n");
-
- // Time
- out->Write("\tcustom_data.time_ms = time_ms;\n");
-}
-} // namespace
PixelShaderUid GetPixelShaderUid()
{
PixelShaderUid out;
@@ -313,8 +56,7 @@ void ClearUnusedPixelShaderUidBits(APIType api_type, const ShaderHostConfig& hos
}
ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
- const pixel_ubershader_uid_data* uid_data,
- const CustomPixelShaderContents& custom_details)
+ const pixel_ubershader_uid_data* uid_data)
{
const bool per_pixel_lighting = host_config.per_pixel_lighting;
const bool msaa = host_config.msaa;
@@ -333,13 +75,7 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
out.Write("// {}\n", *uid_data);
WriteBitfieldExtractHeader(out, api_type, host_config);
- WritePixelShaderCommonHeader(out, api_type, host_config, bounding_box, custom_details);
- WriteCustomShaderStructDef(&out, numTexgen);
- for (std::size_t i = 0; i < custom_details.shaders.size(); i++)
- {
- const auto& shader_details = custom_details.shaders[i];
- out.Write(fmt::runtime(shader_details.custom_shader), i);
- }
+ WritePixelShaderCommonHeader(out, api_type, host_config, bounding_box);
if (per_pixel_lighting)
WriteLightingFunction(out);
@@ -769,25 +505,6 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
"return int3(0, 0, 0);", // ZERO
};
- static constexpr Common::EnumMap<std::string_view, TevColorArg::Zero> tev_c_input_type{
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_PREV;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_PREV;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_COLOR;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_COLOR;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_COLOR;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_COLOR;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_COLOR;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_COLOR;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_TEX;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_TEX;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_RAS;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_RAS;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_NUMERIC;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_NUMERIC;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_KONST;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_NUMERIC;",
- };
-
static constexpr Common::EnumMap<std::string_view, TevAlphaArg::Zero> tev_a_input_table{
"return s.Reg[0].a;", // APREV,
"return s.Reg[1].a;", // A0,
@@ -799,17 +516,6 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
"return 0;", // ZERO
};
- static constexpr Common::EnumMap<std::string_view, TevAlphaArg::Zero> tev_a_input_type{
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_PREV;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_COLOR;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_COLOR;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_COLOR;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_TEX;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_RAS;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_KONST;",
- "return CUSTOM_SHADER_TEV_STAGE_INPUT_TYPE_NUMERIC;",
- };
-
static constexpr Common::EnumMap<std::string_view, TevOutput::Color2> tev_regs_lookup_table{
"return s.Reg[0];",
"return s.Reg[1];",
@@ -851,16 +557,6 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
out.Write("}}\n"
"\n");
- out.Write("// Helper function for Custom Shader Input Type\n"
- "uint getColorInputType(uint index) {{\n");
- WriteSwitch(out, api_type, "index", tev_c_input_type, 2, false);
- out.Write("}}\n"
- "\n"
- "uint getAlphaInputType(uint index) {{\n");
- WriteSwitch(out, api_type, "index", tev_a_input_type, 2, false);
- out.Write("}}\n"
- "\n");
-
// Since the fixed-point texture coodinate variables aren't global, we need to pass
// them to the select function. This applies to all backends.
if (numTexgen > 0)
@@ -880,14 +576,6 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
out.Write(" uint num_stages = {};\n\n",
BitfieldExtract<&GenMode::numtevstages>("bpmem_genmode"));
- bool has_custom_shader_details = false;
- if (std::any_of(custom_details.shaders.begin(), custom_details.shaders.end(),
- [](const std::optional<CustomPixelShader>& ps) { return ps.has_value(); }))
- {
- WriteCustomShaderStructImpl(&out, numTexgen, per_pixel_lighting);
- has_custom_shader_details = true;
- }
-
if (use_framebuffer_fetch)
{
// Store off a copy of the initial framebuffer value.
@@ -1239,78 +927,6 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
"\n"
" // Write result to the correct input register of the next stage\n");
WriteSwitch(out, api_type, "alpha_dest", tev_a_set_table, 6, true);
- if (has_custom_shader_details)
- {
- for (u32 stage_index = 0; stage_index < 16; stage_index++)
- {
- out.Write("\tif (stage == {}u) {{\n", stage_index);
- // Color input
- out.Write("\t\tcustom_data.tev_stages[{}].input_color[0].value = color_A / float3(255.0, "
- "255.0, 255.0);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].input_color[0].input_type = "
- "getColorInputType(color_a);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].input_color[1].value = color_B / float3(255.0, "
- "255.0, 255.0);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].input_color[1].input_type = "
- "getColorInputType(color_b);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].input_color[2].value = color_C / float3(255.0, "
- "255.0, 255.0);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].input_color[2].input_type = "
- "getColorInputType(color_c);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].input_color[3].value = color_D / float3(255.0, "
- "255.0, 255.0);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].input_color[3].input_type = "
- "getColorInputType(color_c);\n",
- stage_index);
-
- // Alpha input
- out.Write("\t\tcustom_data.tev_stages[{}].input_alpha[0].value = alpha_A / float(255.0);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].input_alpha[0].input_type = "
- "getAlphaInputType(alpha_a);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].input_alpha[1].value = alpha_B / float(255.0);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].input_alpha[1].input_type = "
- "getAlphaInputType(alpha_b);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].input_alpha[2].value = alpha_C / float(255.0);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].input_alpha[2].input_type = "
- "getAlphaInputType(alpha_c);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].input_alpha[3].value = alpha_D / float(255.0);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].input_alpha[3].input_type = "
- "getAlphaInputType(alpha_d);\n",
- stage_index);
-
- if (numTexgen != 0)
- {
- // Texmap
- out.Write("\t\tif (texture_enabled) {{\n");
- out.Write("\t\t\tuint sampler_num = {};\n",
- BitfieldExtract<&TwoTevStageOrders::texmap_even>("ss.order"));
- out.Write("\t\tcustom_data.tev_stages[{}].texmap = sampler_num;\n", stage_index);
- out.Write("\t\t}}\n");
- }
-
- // Output
- out.Write("\t\tcustom_data.tev_stages[{}].output_color.rgb = color / float3(255.0, 255.0, "
- "255.0);\n",
- stage_index);
- out.Write("\t\tcustom_data.tev_stages[{}].output_color.a = alpha / float(255.0);\n",
- stage_index);
- out.Write("\t}}\n");
- }
- }
out.Write(" }}\n");
out.Write(" }} // Main TEV loop\n");
out.Write("\n");
@@ -1508,24 +1124,6 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
" }}\n"
"\n");
- for (std::size_t i = 0; i < custom_details.shaders.size(); i++)
- {
- const auto& shader_details = custom_details.shaders[i];
-
- if (!shader_details.custom_shader.empty())
- {
- out.Write("\t{{\n");
- out.Write("\t\tcustom_data.final_color = float4(TevResult.r / 255.0, TevResult.g / 255.0, "
- "TevResult.b / 255.0, TevResult.a / 255.0);\n");
- out.Write("\t\tCustomShaderOutput custom_output = {}_{}(custom_data);\n",
- CUSTOM_PIXELSHADER_COLOR_FUNC, i);
- out.Write(
- "\t\tTevResult = int4(custom_output.main_rt.r * 255, custom_output.main_rt.g * 255, "
- "custom_output.main_rt.b * 255, custom_output.main_rt.a * 255);\n");
- out.Write("\t}}\n\n");
- }
- }
-
if (use_framebuffer_fetch)
{
static constexpr std::array<const char*, 16> logic_op_mode{
diff --git a/Source/Core/VideoCommon/UberShaderPixel.h b/Source/Core/VideoCommon/UberShaderPixel.h
index 80560688ca..aa3d6c7625 100644
--- a/Source/Core/VideoCommon/UberShaderPixel.h
+++ b/Source/Core/VideoCommon/UberShaderPixel.h
@@ -29,8 +29,7 @@ using PixelShaderUid = ShaderUid<pixel_ubershader_uid_data>;
PixelShaderUid GetPixelShaderUid();
ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
- const pixel_ubershader_uid_data* uid_data,
- const CustomPixelShaderContents& custom_details);
+ const pixel_ubershader_uid_data* uid_data);
void EnumeratePixelShaderUids(const std::function<void(const PixelShaderUid&)>& callback);
void ClearUnusedPixelShaderUidBits(APIType api_type, const ShaderHostConfig& host_config,