summaryrefslogtreecommitdiff
path: root/Source/Core/VideoCommon/UberShaderPixel.cpp
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2022-07-08 15:29:58 -0400
committerGitHub <noreply@github.com>2022-07-08 15:29:58 -0400
commit828afc67356c2299c6056d618eb6b7afe4c843b9 (patch)
treecb7809cf9aad689968ec209e8d886b5457ca68dc /Source/Core/VideoCommon/UberShaderPixel.cpp
parent7cc89f5642cab3b91aef1c8255af857a1607ddf6 (diff)
parenta8b52663479effc0f404f7c0f8b52bc0ee37b742 (diff)
Merge pull request #10673 from iwubcode/spirv-backends
D3D: Generate HLSL from SPIRV*
Diffstat (limited to 'Source/Core/VideoCommon/UberShaderPixel.cpp')
-rw-r--r--Source/Core/VideoCommon/UberShaderPixel.cpp260
1 files changed, 99 insertions, 161 deletions
diff --git a/Source/Core/VideoCommon/UberShaderPixel.cpp b/Source/Core/VideoCommon/UberShaderPixel.cpp
index a96b15c83d..de1aaa72f7 100644
--- a/Source/Core/VideoCommon/UberShaderPixel.cpp
+++ b/Source/Core/VideoCommon/UberShaderPixel.cpp
@@ -72,93 +72,88 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
if (per_pixel_lighting)
WriteLightingFunction(out);
- // Shader inputs/outputs in GLSL (HLSL is in main).
- if (api_type == APIType::OpenGL || api_type == APIType::Vulkan)
- {
#ifdef __APPLE__
- // Framebuffer fetch is only supported by Metal, so ensure that we're running Vulkan (MoltenVK)
- // if we want to use it.
- if (api_type == APIType::Vulkan)
+ // Framebuffer fetch is only supported by Metal, so ensure that we're running Vulkan (MoltenVK)
+ // if we want to use it.
+ if (api_type == APIType::Vulkan)
+ {
+ if (use_dual_source)
{
- if (use_dual_source)
- {
- out.Write("FRAGMENT_OUTPUT_LOCATION_INDEXED(0, 0) out vec4 {};\n"
- "FRAGMENT_OUTPUT_LOCATION_INDEXED(0, 1) out vec4 ocol1;\n",
- use_framebuffer_fetch ? "real_ocol0" : "ocol0");
- }
- else
- {
- // Metal doesn't support a single unified variable for both input and output,
- // so when using framebuffer fetch, we declare the input separately below.
- out.Write("FRAGMENT_OUTPUT_LOCATION(0) out vec4 {};\n",
- use_framebuffer_fetch ? "real_ocol0" : "ocol0");
- }
-
- if (use_framebuffer_fetch)
- {
- // Subpass inputs will be converted to framebuffer fetch by SPIRV-Cross.
- out.Write("INPUT_ATTACHMENT_BINDING(0, 0, 0) uniform subpassInput in_ocol0;\n");
- }
+ out.Write("FRAGMENT_OUTPUT_LOCATION_INDEXED(0, 0) out vec4 {};\n"
+ "FRAGMENT_OUTPUT_LOCATION_INDEXED(0, 1) out vec4 ocol1;\n",
+ use_framebuffer_fetch ? "real_ocol0" : "ocol0");
}
else
-#endif
{
- bool has_broken_decoration =
- DriverDetails::HasBug(DriverDetails::BUG_BROKEN_FRAGMENT_SHADER_INDEX_DECORATION);
-
- out.Write("{} {} vec4 {};\n",
- has_broken_decoration ? "FRAGMENT_OUTPUT_LOCATION(0)" :
- "FRAGMENT_OUTPUT_LOCATION_INDEXED(0, 0)",
- use_framebuffer_fetch ? "FRAGMENT_INOUT" : "out",
+ // Metal doesn't support a single unified variable for both input and output,
+ // so when using framebuffer fetch, we declare the input separately below.
+ out.Write("FRAGMENT_OUTPUT_LOCATION(0) out vec4 {};\n",
use_framebuffer_fetch ? "real_ocol0" : "ocol0");
+ }
- if (use_dual_source)
- {
- out.Write("{} out vec4 ocol1;\n", has_broken_decoration ?
- "FRAGMENT_OUTPUT_LOCATION(1)" :
- "FRAGMENT_OUTPUT_LOCATION_INDEXED(0, 1)");
- }
+ if (use_framebuffer_fetch)
+ {
+ // Subpass inputs will be converted to framebuffer fetch by SPIRV-Cross.
+ out.Write("INPUT_ATTACHMENT_BINDING(0, 0, 0) uniform subpassInput in_ocol0;\n");
}
+ }
+ else
+#endif
+ {
+ bool has_broken_decoration =
+ DriverDetails::HasBug(DriverDetails::BUG_BROKEN_FRAGMENT_SHADER_INDEX_DECORATION);
- if (per_pixel_depth)
- out.Write("#define depth gl_FragDepth\n");
+ out.Write("{} {} {} {};\n",
+ has_broken_decoration ? "FRAGMENT_OUTPUT_LOCATION(0)" :
+ "FRAGMENT_OUTPUT_LOCATION_INDEXED(0, 0)",
+ use_framebuffer_fetch ? "FRAGMENT_INOUT" : "out",
+ uid_data->uint_output ? "uvec4" : "vec4",
+ use_framebuffer_fetch ? "real_ocol0" : "ocol0");
- if (host_config.backend_geometry_shaders)
+ if (use_dual_source)
{
- out.Write("VARYING_LOCATION(0) in VertexData {{\n");
- GenerateVSOutputMembers(out, api_type, numTexgen, host_config,
- GetInterpolationQualifier(msaa, ssaa, true, true));
+ out.Write("{} out {} ocol1;\n",
+ has_broken_decoration ? "FRAGMENT_OUTPUT_LOCATION(1)" :
+ "FRAGMENT_OUTPUT_LOCATION_INDEXED(0, 1)",
+ uid_data->uint_output ? "uvec4" : "vec4");
+ }
+ }
+
+ if (per_pixel_depth)
+ out.Write("#define depth gl_FragDepth\n");
- if (stereo)
- out.Write(" flat int layer;\n");
+ if (host_config.backend_geometry_shaders)
+ {
+ out.Write("VARYING_LOCATION(0) in VertexData {{\n");
+ GenerateVSOutputMembers(out, api_type, numTexgen, host_config,
+ GetInterpolationQualifier(msaa, ssaa, true, true), ShaderStage::Pixel);
- out.Write("}};\n\n");
+ out.Write("}};\n\n");
+ }
+ else
+ {
+ // Let's set up attributes
+ u32 counter = 0;
+ out.Write("VARYING_LOCATION({}) {} in float4 colors_0;\n", counter++,
+ GetInterpolationQualifier(msaa, ssaa));
+ out.Write("VARYING_LOCATION({}) {} in float4 colors_1;\n", counter++,
+ GetInterpolationQualifier(msaa, ssaa));
+ for (u32 i = 0; i < numTexgen; ++i)
+ {
+ out.Write("VARYING_LOCATION({}) {} in float3 tex{};\n", counter++,
+ GetInterpolationQualifier(msaa, ssaa), i);
}
- else
+ if (!host_config.fast_depth_calc)
{
- // Let's set up attributes
- u32 counter = 0;
- out.Write("VARYING_LOCATION({}) {} in float4 colors_0;\n", counter++,
+ out.Write("VARYING_LOCATION({}) {} in float4 clipPos;\n", counter++,
GetInterpolationQualifier(msaa, ssaa));
- out.Write("VARYING_LOCATION({}) {} in float4 colors_1;\n", counter++,
+ }
+ if (per_pixel_lighting)
+ {
+ out.Write("VARYING_LOCATION({}) {} in float3 Normal;\n", counter++,
+ GetInterpolationQualifier(msaa, ssaa));
+ out.Write("VARYING_LOCATION({}) {} in float3 WorldPos;\n", counter++,
GetInterpolationQualifier(msaa, ssaa));
- for (u32 i = 0; i < numTexgen; ++i)
- {
- out.Write("VARYING_LOCATION({}) {} in float3 tex{};\n", counter++,
- GetInterpolationQualifier(msaa, ssaa), i);
- }
- if (!host_config.fast_depth_calc)
- {
- out.Write("VARYING_LOCATION({}) {} in float4 clipPos;\n", counter++,
- GetInterpolationQualifier(msaa, ssaa));
- }
- if (per_pixel_lighting)
- {
- out.Write("VARYING_LOCATION({}) {} in float3 Normal;\n", counter++,
- GetInterpolationQualifier(msaa, ssaa));
- out.Write("VARYING_LOCATION({}) {} in float3 WorldPos;\n", counter++,
- GetInterpolationQualifier(msaa, ssaa));
- }
}
}
@@ -243,10 +238,7 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
// Doesn't look like DirectX supports this. Oh well the code path is here just in case it
// supports this in the future.
out.Write("int4 sampleTextureWrapper(uint texmap, int2 uv, int layer) {{\n");
- if (api_type == APIType::OpenGL || api_type == APIType::Vulkan)
- out.Write(" return sampleTexture(texmap, samp[texmap], uv, layer);\n");
- else if (api_type == APIType::D3D)
- out.Write(" return sampleTexture(texmap, tex[texmap], samp[texmap], uv, layer);\n");
+ out.Write(" return sampleTexture(texmap, samp[texmap], uv, layer);\n");
out.Write("}}\n\n");
}
else
@@ -259,15 +251,7 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
" switch(sampler_num) {{\n");
for (int i = 0; i < 8; i++)
{
- if (api_type == APIType::OpenGL || api_type == APIType::Vulkan)
- {
- out.Write(" case {0}u: return sampleTexture({0}u, samp[{0}u], uv, layer);\n", i);
- }
- else if (api_type == APIType::D3D)
- {
- out.Write(" case {0}u: return sampleTexture({0}u, tex[{0}u], samp[{0}u], uv, layer);\n",
- i);
- }
+ out.Write(" case {0}u: return sampleTexture({0}u, samp[{0}u], uv, layer);\n", i);
}
out.Write(" }}\n"
"}}\n\n");
@@ -522,85 +506,44 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
out.Write(")\n\n");
}
- if (api_type == APIType::OpenGL || api_type == APIType::Vulkan)
- {
- if (early_depth && host_config.backend_early_z)
- out.Write("FORCE_EARLY_Z;\n");
-
- out.Write("void main()\n{{\n");
- out.Write(" float4 rawpos = gl_FragCoord;\n");
+ if (early_depth && host_config.backend_early_z)
+ out.Write("FORCE_EARLY_Z;\n");
- if (use_framebuffer_fetch)
- {
- // Store off a copy of the initial framebuffer value.
- //
- // If FB_FETCH_VALUE isn't defined (i.e. no special keyword for fetching from the
- // framebuffer), we read from real_ocol0.
- out.Write("#ifdef FB_FETCH_VALUE\n"
- " float4 initial_ocol0 = FB_FETCH_VALUE;\n"
- "#else\n"
- " float4 initial_ocol0 = real_ocol0;\n"
- "#endif\n");
-
- // QComm's Adreno driver doesn't seem to like using the framebuffer_fetch value as an
- // intermediate value with multiple reads & modifications, so we pull out the "real" output
- // value above and use a temporary for calculations, then set the output value once at the
- // end of the shader.
- out.Write(" float4 ocol0;\n");
- }
+ out.Write("void main()\n{{\n");
+ out.Write(" float4 rawpos = gl_FragCoord;\n");
- if (use_shader_blend)
- {
- out.Write(" float4 ocol1;\n");
- }
- }
- else // D3D
+ if (use_framebuffer_fetch)
{
- if (early_depth && host_config.backend_early_z)
- out.Write("[earlydepthstencil]\n");
+ // Store off a copy of the initial framebuffer value.
+ //
+ // If FB_FETCH_VALUE isn't defined (i.e. no special keyword for fetching from the
+ // framebuffer), we read from real_ocol0.
+ out.Write("#ifdef FB_FETCH_VALUE\n"
+ " float4 initial_ocol0 = FB_FETCH_VALUE;\n"
+ "#else\n"
+ " float4 initial_ocol0 = real_ocol0;\n"
+ "#endif\n");
+
+ // QComm's Adreno driver doesn't seem to like using the framebuffer_fetch value as an
+ // intermediate value with multiple reads & modifications, so we pull out the "real" output
+ // value above and use a temporary for calculations, then set the output value once at the
+ // end of the shader.
+ out.Write(" float4 ocol0;\n");
+ }
- out.Write("void main(\n");
- if (uid_data->uint_output)
- {
- out.Write(" out uint4 ocol0 : SV_Target,\n");
- }
- else
- {
- out.Write(" out float4 ocol0 : SV_Target0,\n"
- " out float4 ocol1 : SV_Target1,\n");
- }
- if (per_pixel_depth)
- out.Write(" out float depth : SV_Depth,\n");
- out.Write(" in float4 rawpos : SV_Position,\n");
- out.Write(" in {} float4 colors_0 : COLOR0,\n", GetInterpolationQualifier(msaa, ssaa));
- out.Write(" in {} float4 colors_1 : COLOR1", GetInterpolationQualifier(msaa, ssaa));
+ if (use_shader_blend)
+ {
+ out.Write(" float4 ocol1;\n");
+ }
- // compute window position if needed because binding semantic WPOS is not widely supported
- for (u32 i = 0; i < numTexgen; ++i)
- {
- out.Write(",\n in {} float3 tex{} : TEXCOORD{}", GetInterpolationQualifier(msaa, ssaa), i,
- i);
- }
- if (!host_config.fast_depth_calc)
- {
- out.Write("\n,\n in {} float4 clipPos : TEXCOORD{}", GetInterpolationQualifier(msaa, ssaa),
- numTexgen);
- }
- if (per_pixel_lighting)
- {
- out.Write(",\n in {} float3 Normal : TEXCOORD{}", GetInterpolationQualifier(msaa, ssaa),
- numTexgen + 1);
- out.Write(",\n in {} float3 WorldPos : TEXCOORD{}", GetInterpolationQualifier(msaa, ssaa),
- numTexgen + 2);
- }
- out.Write(",\n in float clipDist0 : SV_ClipDistance0\n"
- ",\n in float clipDist1 : SV_ClipDistance1\n");
- if (stereo)
- out.Write(",\n in uint layer : SV_RenderTargetArrayIndex\n");
- out.Write("\n ) {{\n");
+ if (host_config.backend_geometry_shaders && stereo)
+ {
+ out.Write("\tint layer = gl_Layer;\n");
+ }
+ else
+ {
+ out.Write("\tint layer = 0;\n");
}
- if (!stereo)
- out.Write(" int layer = 0;\n");
out.Write(" int3 tevcoord = int3(0, 0, 0);\n"
" State s;\n"
@@ -634,11 +577,6 @@ ShaderCode GenPixelShader(APIType api_type, const ShaderHostConfig& host_config,
BitfieldExtract<&GenMode::numtevstages>("bpmem_genmode"));
out.Write(" // Main tev loop\n");
- if (api_type == APIType::D3D)
- {
- // Tell DirectX we don't want this loop unrolled (it crashes if it tries to)
- out.Write(" [loop]\n");
- }
out.Write(" for(uint stage = 0u; stage <= num_stages; stage++)\n"
" {{\n"