diff options
| author | JMC47 <JMC4789@gmail.com> | 2022-07-08 15:29:58 -0400 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-07-08 15:29:58 -0400 |
| commit | 828afc67356c2299c6056d618eb6b7afe4c843b9 (patch) | |
| tree | cb7809cf9aad689968ec209e8d886b5457ca68dc /Source/Core/VideoCommon/UberShaderPixel.cpp | |
| parent | 7cc89f5642cab3b91aef1c8255af857a1607ddf6 (diff) | |
| parent | a8b52663479effc0f404f7c0f8b52bc0ee37b742 (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.cpp | 260 |
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" |
