This commit is contained in:
iwubcode 2025-02-12 08:02:40 +00:00 committed by GitHub
commit 445ac681b9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 1503 additions and 1605 deletions

View file

@ -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 =
PixelShader::WriteFullShader(m_api_type, m_host_config, uid.GetUidData(), "", "");
return g_gfx->CreateShaderFromSource(ShaderStage::Pixel, source_code.GetBuffer(),
"Custom Pixel Shader");
}

View file

@ -81,29 +81,34 @@ static void GenerateLightShader(ShaderCode& object, const LightingUidData& uid_d
// materials name is I_MATERIALS in vs and I_PMATERIALS in ps
// inColorName is color in vs and colors_ in ps
// dest is o.colors_ in vs and colors_ in ps
void GenerateLightingShaderCode(ShaderCode& object, const LightingUidData& uid_data,
std::string_view in_color_name, std::string_view dest)
void GenerateLightingShaderHeader(ShaderCode& object, const LightingUidData& uid_data)
{
for (u32 j = 0; j < NUM_XF_COLOR_CHANNELS; j++)
{
object.Write(
"vec4 dolphin_calculate_lighting_chn{}(vec4 vertex_color, vec4 pos, vec3 _normal)\n", j);
object.Write("{{\n");
object.Write("\tint4 lacc;\n"
"\tfloat3 ldir, h, cosAttn, distAttn;\n"
"\tfloat dist, dist2, attn;\n");
const bool colormatsource = !!(uid_data.matsource & (1 << j));
if (colormatsource) // from vertex
object.Write("int4 mat = int4(round({}{} * 255.0));\n", in_color_name, j);
object.Write("\tint4 mat = int4(round(vertex_color * 255.0));\n");
else // from color
object.Write("int4 mat = {}[{}];\n", I_MATERIALS, j + 2);
object.Write("\tint4 mat = {}[{}];\n", I_MATERIALS, j + 2);
if ((uid_data.enablelighting & (1 << j)) != 0)
{
if ((uid_data.ambsource & (1 << j)) != 0) // from vertex
object.Write("lacc = int4(round({}{} * 255.0));\n", in_color_name, j);
object.Write("\tlacc = int4(round(vertex_color * 255.0));\n");
else // from color
object.Write("lacc = {}[{}];\n", I_MATERIALS, j);
object.Write("\tlacc = {}[{}];\n", I_MATERIALS, j);
}
else
{
object.Write("lacc = int4(255, 255, 255, 255);\n");
object.Write("\tlacc = int4(255, 255, 255, 255);\n");
}
// check if alpha is different
@ -111,21 +116,21 @@ void GenerateLightingShaderCode(ShaderCode& object, const LightingUidData& uid_d
if (alphamatsource != colormatsource)
{
if (alphamatsource) // from vertex
object.Write("mat.w = int(round({}{}.w * 255.0));\n", in_color_name, j);
object.Write("\tmat.w = int(round(vertex_color.w * 255.0));\n");
else // from color
object.Write("mat.w = {}[{}].w;\n", I_MATERIALS, j + 2);
object.Write("\tmat.w = {}[{}].w;\n", I_MATERIALS, j + 2);
}
if ((uid_data.enablelighting & (1 << (j + 2))) != 0)
{
if ((uid_data.ambsource & (1 << (j + 2))) != 0) // from vertex
object.Write("lacc.w = int(round({}{}.w * 255.0));\n", in_color_name, j);
object.Write("\tlacc.w = int(round(vertex_color.w * 255.0));\n");
else // from color
object.Write("lacc.w = {}[{}].w;\n", I_MATERIALS, j);
object.Write("\tlacc.w = {}[{}].w;\n", I_MATERIALS, j);
}
else
{
object.Write("lacc.w = 255;\n");
object.Write("\tlacc.w = 255;\n");
}
if ((uid_data.enablelighting & (1 << j)) != 0) // Color lights
@ -144,9 +149,9 @@ void GenerateLightingShaderCode(ShaderCode& object, const LightingUidData& uid_d
GenerateLightShader(object, uid_data, i, j + 2, true);
}
}
object.Write("lacc = clamp(lacc, 0, 255);\n");
object.Write("{}{} = float4((mat * (lacc + (lacc >> 7))) >> 8) / 255.0;\n", dest, j);
object.Write("}}\n");
object.Write("\tlacc = clamp(lacc, 0, 255);\n");
object.Write("\treturn vec4((mat * (lacc + (lacc >> 7))) >> 8) / 255.0;\n");
object.Write("}}\n\n");
}
}
@ -176,47 +181,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 GenerateLightingImpl(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);
@ -225,60 +192,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);
}
}
@ -286,20 +252,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
@ -307,21 +273,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;
@ -331,12 +297,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);
GenerateLightingImpl(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
@ -345,11 +311,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);
GenerateLightingImpl(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);
}
}

View file

@ -44,10 +44,6 @@ constexpr char s_lighting_struct[] = "struct Light {\n"
"\tfloat4 dir;\n"
"};\n";
void GenerateLightingShaderCode(ShaderCode& object, const LightingUidData& uid_data,
std::string_view in_color_name, std::string_view dest);
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);

File diff suppressed because it is too large Load diff

View file

@ -158,15 +158,24 @@ 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);
ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& host_config,
const pixel_shader_uid_data* uid_data,
const CustomPixelShaderContents& custom_details);
void WritePixelShaderCommonHeader(ShaderCode& out, APIType api_type,
const ShaderHostConfig& host_config, bool bounding_box,
const CustomPixelShaderContents& custom_details);
void ClearUnusedPixelShaderUidBits(APIType api_type, const ShaderHostConfig& host_config,
PixelShaderUid* uid);
PixelShaderUid GetPixelShaderUid();
namespace PixelShader
{
constexpr std::string_view fragment_definition =
"void fragment(in DolphinFragmentInput frag_input, out DolphinFragmentOutput frag_output)";
void WriteFragmentDefinitions(APIType api_type, const ShaderHostConfig& host_config,
const pixel_shader_uid_data* uid_data, ShaderCode& out,
bool as_comment);
void WriteFragmentBody(APIType api_type, const ShaderHostConfig& host_config,
const pixel_shader_uid_data* uid_data, ShaderCode& out);
ShaderCode WriteFullShader(APIType api_type, const ShaderHostConfig& host_config,
const pixel_shader_uid_data* uid_data, std::string_view custom_pixel,
std::string_view custom_uniforms);
} // namespace PixelShader

View file

@ -433,7 +433,7 @@ void ShaderCache::CompileMissingPipelines()
std::unique_ptr<AbstractShader> ShaderCache::CompileVertexShader(const VertexShaderUid& uid) const
{
const ShaderCode source_code =
GenerateVertexShaderCode(m_api_type, m_host_config, uid.GetUidData());
VertexShader::WriteFullShader(m_api_type, m_host_config, uid.GetUidData(), "", "");
return g_gfx->CreateShaderFromSource(ShaderStage::Vertex, source_code.GetBuffer());
}
@ -449,7 +449,7 @@ ShaderCache::CompileVertexUberShader(const UberShader::VertexShaderUid& uid) con
std::unique_ptr<AbstractShader> ShaderCache::CompilePixelShader(const PixelShaderUid& uid) const
{
const ShaderCode source_code =
GeneratePixelShaderCode(m_api_type, m_host_config, uid.GetUidData(), {});
PixelShader::WriteFullShader(m_api_type, m_host_config, uid.GetUidData(), "", "");
return g_gfx->CreateShaderFromSource(ShaderStage::Pixel, source_code.GetBuffer());
}

View file

@ -363,95 +363,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");
}

View file

@ -345,5 +345,3 @@ struct CustomPixelShaderContents
bool operator==(const CustomPixelShaderContents& other) const = default;
};
void WriteCustomShaderStructDef(ShaderCode* out, u32 numtexgens);

View file

@ -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;
@ -334,12 +77,6 @@ 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);
}
if (per_pixel_lighting)
WriteLightingFunction(out);
@ -768,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,
@ -798,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];",
@ -850,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)
@ -879,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.
@ -1237,78 +926,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");
@ -1506,24 +1123,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{

File diff suppressed because it is too large Load diff

View file

@ -91,3 +91,19 @@ using VertexShaderUid = ShaderUid<vertex_shader_uid_data>;
VertexShaderUid GetVertexShaderUid();
ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& host_config,
const vertex_shader_uid_data* uid_data);
namespace VertexShader
{
constexpr std::string_view vertex_definition =
"void vertex(in DolphinVertexInput vertex_input, out DolphinVertexOutput vertex_output)";
void WriteVertexStructs(APIType api_type, const ShaderHostConfig& host_config,
const vertex_shader_uid_data* uid_data, ShaderCode& out);
void WriteVertexDefines(APIType api_type, const ShaderHostConfig& host_config,
const vertex_shader_uid_data* uid_data, ShaderCode& out);
void WriteVertexBody(APIType api_type, const ShaderHostConfig& host_config,
const vertex_shader_uid_data* uid_data, ShaderCode& out);
ShaderCode WriteFullShader(APIType api_type, const ShaderHostConfig& host_config,
const vertex_shader_uid_data* uid_data, std::string_view custom_vertex,
std::string_view custom_uniforms);
} // namespace VertexShader