From 686ac6812b5ac8e34030d01c2b8d672592e751fb Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Sun, 7 May 2017 13:22:16 +0200 Subject: [PATCH] HLSL: Can pass down combined image samplers as arguments. --- .../combined-texture-sampler-parameter.frag | 44 ++++++++++++++++++ .../combined-texture-sampler-parameter.frag | 31 +++++++++++++ spirv_hlsl.cpp | 45 +++++++++++++++++-- spirv_hlsl.hpp | 2 + 4 files changed, 119 insertions(+), 3 deletions(-) create mode 100644 reference/shaders-hlsl/frag/combined-texture-sampler-parameter.frag create mode 100644 shaders-hlsl/frag/combined-texture-sampler-parameter.frag diff --git a/reference/shaders-hlsl/frag/combined-texture-sampler-parameter.frag b/reference/shaders-hlsl/frag/combined-texture-sampler-parameter.frag new file mode 100644 index 00000000..68b59e92 --- /dev/null +++ b/reference/shaders-hlsl/frag/combined-texture-sampler-parameter.frag @@ -0,0 +1,44 @@ +Texture2D uSampler; +SamplerState _uSampler_sampler; +Texture2D uSamplerShadow; +SamplerComparisonState _uSamplerShadow_sampler; + +static float FragColor; + +struct SPIRV_Cross_Output +{ + float FragColor : SV_Target0; +}; + +float4 samp2(Texture2D s, SamplerState _s_sampler) +{ + return s.Sample(_s_sampler, float2(1.0f, 1.0f)) + s.Load(int3(int2(10, 10), 0)); +} + +float4 samp3(Texture2D s, SamplerState _s_sampler) +{ + return samp2(s, _s_sampler); +} + +float samp4(Texture2D s, SamplerComparisonState _s_sampler) +{ + return s.SampleCmp(_s_sampler, float3(1.0f, 1.0f, 1.0f).xy, float3(1.0f, 1.0f, 1.0f).z); +} + +float samp(Texture2D s0, SamplerState _s0_sampler, Texture2D s1, SamplerComparisonState _s1_sampler) +{ + return samp3(s0, _s0_sampler).x + samp4(s1, _s1_sampler); +} + +void frag_main() +{ + FragColor = samp(uSampler, _uSampler_sampler, uSamplerShadow, _uSamplerShadow_sampler); +} + +SPIRV_Cross_Output main() +{ + frag_main(); + SPIRV_Cross_Output stage_output; + stage_output.FragColor = FragColor; + return stage_output; +} diff --git a/shaders-hlsl/frag/combined-texture-sampler-parameter.frag b/shaders-hlsl/frag/combined-texture-sampler-parameter.frag new file mode 100644 index 00000000..cf306318 --- /dev/null +++ b/shaders-hlsl/frag/combined-texture-sampler-parameter.frag @@ -0,0 +1,31 @@ +#version 310 es +precision mediump float; + +layout(set = 0, binding = 1) uniform mediump sampler2D uSampler; +layout(set = 0, binding = 1) uniform mediump sampler2DShadow uSamplerShadow; +layout(location = 0) out float FragColor; + +vec4 samp2(sampler2D s) +{ + return texture(s, vec2(1.0)) + texelFetch(s, ivec2(10), 0); +} + +vec4 samp3(sampler2D s) +{ + return samp2(s); +} + +float samp4(mediump sampler2DShadow s) +{ + return texture(s, vec3(1.0)); +} + +float samp(sampler2D s0, mediump sampler2DShadow s1) +{ + return samp3(s0).x + samp4(s1); +} + +void main() +{ + FragColor = samp(uSampler, uSamplerShadow); +} diff --git a/spirv_hlsl.cpp b/spirv_hlsl.cpp index 505ef792..6d711e89 100644 --- a/spirv_hlsl.cpp +++ b/spirv_hlsl.cpp @@ -892,6 +892,34 @@ void CompilerHLSL::emit_push_constant_block(const SPIRVariable &) statement("constant block"); } +string CompilerHLSL::to_sampler_expression(uint32_t id) +{ + return join("_", to_expression(id), "_sampler"); +} + +string CompilerHLSL::to_func_call_arg(uint32_t id) +{ + string arg_str = CompilerGLSL::to_func_call_arg(id); + + if (options.shader_model <= 30) + return arg_str; + + // Manufacture automatic sampler arg if the arg is a SampledImage texture and we're in modern HLSL. + auto *var = maybe_get(id); + if (var) + { + auto &type = get(var->basetype); + + // We don't have to consider combined image samplers here via OpSampledImage because + // those variables cannot be passed as arguments to functions. + // Only global SampledImage variables may be used as arguments. + if (type.basetype == SPIRType::SampledImage) + arg_str += ", " + to_sampler_expression(id); + } + + return arg_str; +} + void CompilerHLSL::emit_function_prototype(SPIRFunction &func, uint64_t return_flags) { auto &execution = get_entry_point(); @@ -930,6 +958,17 @@ void CompilerHLSL::emit_function_prototype(SPIRFunction &func, uint64_t return_f add_local_variable_name(arg.id); decl += argument_decl(arg); + + // Flatten a combined sampler to two separate arguments in modern HLSL. + auto &arg_type = get(arg.type); + if (options.shader_model > 30 && arg_type.basetype == SPIRType::SampledImage) + { + // Manufacture automatic sampler arg for SampledImage texture + decl += ", "; + if (arg_type.basetype == SPIRType::SampledImage) + decl += join(arg_type.image.depth ? "SamplerComparisonState " : "SamplerState ", to_sampler_expression(arg.id)); + } + if (&arg != &func.arguments.back()) decl += ", "; @@ -1355,7 +1394,7 @@ void CompilerHLSL::emit_texture_op(const Instruction &i) if (combined_image) sampler_expr = to_expression(combined_image->sampler); else - sampler_expr = join("_", img_expr, "_sampler"); + sampler_expr = to_sampler_expression(img); expr += sampler_expr; } @@ -1501,9 +1540,9 @@ void CompilerHLSL::emit_modern_uniform(const SPIRVariable &var) { // For combined image samplers, also emit a combined image sampler. if (type.image.depth) - statement("SamplerComparisonState _", to_name(var.self), "_sampler;"); + statement("SamplerComparisonState ", to_sampler_expression(var.self), ";"); else - statement("SamplerState _", to_name(var.self), "_sampler;"); + statement("SamplerState ", to_sampler_expression(var.self), ";"); } break; } diff --git a/spirv_hlsl.hpp b/spirv_hlsl.hpp index e2060ae4..6ff56ff7 100644 --- a/spirv_hlsl.hpp +++ b/spirv_hlsl.hpp @@ -83,6 +83,8 @@ private: std::string layout_for_member(const SPIRType &type, uint32_t index) override; std::string to_interpolation_qualifiers(uint64_t flags) override; std::string bitcast_glsl_op(const SPIRType &result_type, const SPIRType &argument_type) override; + std::string to_func_call_arg(uint32_t id) override; + std::string to_sampler_expression(uint32_t id); const char *to_storage_qualifiers_glsl(const SPIRVariable &var) override;