From f171d82590f6f9d14c9bfa3943a72c6b67e0e8be Mon Sep 17 00:00:00 2001 From: Hans-Kristian Arntzen Date: Tue, 11 Jun 2019 11:10:16 +0200 Subject: [PATCH] MSL: Support MinLod operand. --- .../asm/frag/min-lod.msl22.asm.frag | 22 ++++++++++ .../asm/frag/min-lod.msl22.asm.frag | 22 ++++++++++ shaders-msl/asm/frag/min-lod.msl22.asm.frag | 42 +++++++++++++++++++ spirv_glsl.cpp | 13 ++++-- spirv_glsl.hpp | 3 +- spirv_hlsl.cpp | 5 +++ spirv_msl.cpp | 21 ++++++++-- spirv_msl.hpp | 4 +- 8 files changed, 122 insertions(+), 10 deletions(-) create mode 100644 reference/opt/shaders-msl/asm/frag/min-lod.msl22.asm.frag create mode 100644 reference/shaders-msl/asm/frag/min-lod.msl22.asm.frag create mode 100644 shaders-msl/asm/frag/min-lod.msl22.asm.frag diff --git a/reference/opt/shaders-msl/asm/frag/min-lod.msl22.asm.frag b/reference/opt/shaders-msl/asm/frag/min-lod.msl22.asm.frag new file mode 100644 index 00000000..5193b2cd --- /dev/null +++ b/reference/opt/shaders-msl/asm/frag/min-lod.msl22.asm.frag @@ -0,0 +1,22 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float2 vUV [[user(locn0)]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]], texture2d uSampler [[texture(0)]], sampler uSamplerSmplr [[sampler(0)]]) +{ + main0_out out = {}; + out.FragColor = uSampler.sample(uSamplerSmplr, in.vUV, min_lod_clamp(4.0)); + return out; +} + diff --git a/reference/shaders-msl/asm/frag/min-lod.msl22.asm.frag b/reference/shaders-msl/asm/frag/min-lod.msl22.asm.frag new file mode 100644 index 00000000..5193b2cd --- /dev/null +++ b/reference/shaders-msl/asm/frag/min-lod.msl22.asm.frag @@ -0,0 +1,22 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float4 FragColor [[color(0)]]; +}; + +struct main0_in +{ + float2 vUV [[user(locn0)]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]], texture2d uSampler [[texture(0)]], sampler uSamplerSmplr [[sampler(0)]]) +{ + main0_out out = {}; + out.FragColor = uSampler.sample(uSamplerSmplr, in.vUV, min_lod_clamp(4.0)); + return out; +} + diff --git a/shaders-msl/asm/frag/min-lod.msl22.asm.frag b/shaders-msl/asm/frag/min-lod.msl22.asm.frag new file mode 100644 index 00000000..0d30e169 --- /dev/null +++ b/shaders-msl/asm/frag/min-lod.msl22.asm.frag @@ -0,0 +1,42 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 7 +; Bound: 21 +; Schema: 0 + OpCapability Shader + OpCapability MinLod + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %FragColor %vUV + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 450 + OpName %main "main" + OpName %FragColor "FragColor" + OpName %uSampler "uSampler" + OpName %vUV "vUV" + OpDecorate %FragColor Location 0 + OpDecorate %uSampler DescriptorSet 0 + OpDecorate %uSampler Binding 0 + OpDecorate %vUV Location 0 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %float = OpTypeFloat 32 + %v4float = OpTypeVector %float 4 +%_ptr_Output_v4float = OpTypePointer Output %v4float + %FragColor = OpVariable %_ptr_Output_v4float Output + %10 = OpTypeImage %float 2D 0 0 0 1 Unknown + %11 = OpTypeSampledImage %10 +%_ptr_UniformConstant_11 = OpTypePointer UniformConstant %11 + %uSampler = OpVariable %_ptr_UniformConstant_11 UniformConstant + %v2float = OpTypeVector %float 2 +%_ptr_Input_v2float = OpTypePointer Input %v2float + %vUV = OpVariable %_ptr_Input_v2float Input + %float_4 = OpConstant %float 4 + %main = OpFunction %void None %3 + %5 = OpLabel + %14 = OpLoad %11 %uSampler + %18 = OpLoad %v2float %vUV + %20 = OpImageSampleImplicitLod %v4float %14 %18 MinLod %float_4 + OpStore %FragColor %20 + OpReturn + OpFunctionEnd diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index b4d888ad..b6e3b07a 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -4700,6 +4700,7 @@ void CompilerGLSL::emit_texture_op(const Instruction &i) uint32_t offset = 0; uint32_t coffsets = 0; uint32_t sample = 0; + uint32_t minlod = 0; uint32_t flags = 0; if (length) @@ -4725,14 +4726,15 @@ void CompilerGLSL::emit_texture_op(const Instruction &i) test(offset, ImageOperandsOffsetMask); test(coffsets, ImageOperandsConstOffsetsMask); test(sample, ImageOperandsSampleMask); + test(minlod, ImageOperandsMinLodMask); string expr; bool forward = false; expr += to_function_name(img, imgtype, !!fetch, !!gather, !!proj, !!coffsets, (!!coffset || !!offset), - (!!grad_x || !!grad_y), !!dref, lod); + (!!grad_x || !!grad_y), !!dref, lod, minlod); expr += "("; expr += to_function_args(img, imgtype, fetch, gather, proj, coord, coord_components, dref, grad_x, grad_y, lod, - coffset, offset, bias, comp, sample, &forward); + coffset, offset, bias, comp, sample, minlod, &forward); expr += ")"; // texture(samplerXShadow) returns float. shadowX() returns vec4. Swizzle here. @@ -4797,8 +4799,11 @@ bool CompilerGLSL::expression_is_constant_null(uint32_t id) const // For some subclasses, the function is a method on the specified image. string CompilerGLSL::to_function_name(uint32_t tex, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj, bool has_array_offsets, bool has_offset, bool has_grad, bool, - uint32_t lod) + uint32_t lod, uint32_t minlod) { + if (minlod != 0) + SPIRV_CROSS_THROW("Sparse texturing not yet supported."); + string fname; // textureLod on sampler2DArrayShadow and samplerCubeShadow does not exist in GLSL for some reason. @@ -4877,7 +4882,7 @@ std::string CompilerGLSL::convert_separate_image_to_expression(uint32_t id) string CompilerGLSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj, uint32_t coord, uint32_t coord_components, uint32_t dref, uint32_t grad_x, uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, - uint32_t bias, uint32_t comp, uint32_t sample, bool *p_forward) + uint32_t bias, uint32_t comp, uint32_t sample, uint32_t /*minlod*/, bool *p_forward) { string farg_str; if (is_fetch) diff --git a/spirv_glsl.hpp b/spirv_glsl.hpp index 6ca281fd..f7f20c64 100644 --- a/spirv_glsl.hpp +++ b/spirv_glsl.hpp @@ -257,11 +257,12 @@ protected: virtual std::string to_func_call_arg(uint32_t id); virtual std::string to_function_name(uint32_t img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj, bool has_array_offsets, bool has_offset, bool has_grad, - bool has_dref, uint32_t lod); + bool has_dref, uint32_t lod, uint32_t minlod); virtual std::string to_function_args(uint32_t img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj, uint32_t coord, uint32_t coord_components, uint32_t dref, uint32_t grad_x, uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias, uint32_t comp, uint32_t sample, + uint32_t minlod, bool *p_forward); virtual void emit_buffer_block(const SPIRVariable &type); virtual void emit_push_constant_block(const SPIRVariable &var); diff --git a/spirv_hlsl.cpp b/spirv_hlsl.cpp index d2dcdfb8..c129966f 100644 --- a/spirv_hlsl.cpp +++ b/spirv_hlsl.cpp @@ -2536,6 +2536,7 @@ void CompilerHLSL::emit_texture_op(const Instruction &i) uint32_t offset = 0; uint32_t coffsets = 0; uint32_t sample = 0; + uint32_t minlod = 0; uint32_t flags = 0; if (length) @@ -2562,10 +2563,14 @@ void CompilerHLSL::emit_texture_op(const Instruction &i) test(offset, ImageOperandsOffsetMask); test(coffsets, ImageOperandsConstOffsetsMask); test(sample, ImageOperandsSampleMask); + test(minlod, ImageOperandsMinLodMask); string expr; string texop; + if (minlod != 0) + SPIRV_CROSS_THROW("MinLod texture operand not supported in HLSL."); + if (op == OpImageFetch) { if (hlsl_options.shader_model < 40) diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 3a827c65..01bb4262 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -3849,7 +3849,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction) statement(join( to_expression(img_id), ".write(", remap_swizzle(store_type, texel_type.vecsize, to_expression(texel_id)), ", ", - to_function_args(img_id, img_type, true, false, false, coord_id, 0, 0, 0, 0, lod, 0, 0, 0, 0, 0, &forward), + to_function_args(img_id, img_type, true, false, false, coord_id, 0, 0, 0, 0, lod, 0, 0, 0, 0, 0, 0, &forward), ");")); if (p_var && variable_storage_is_aliased(*p_var)) @@ -4661,7 +4661,7 @@ void CompilerMSL::emit_function_prototype(SPIRFunction &func, const Bitset &) // Returns the texture sampling function string for the specified image and sampling characteristics. string CompilerMSL::to_function_name(uint32_t img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool, bool, - bool has_offset, bool, bool has_dref, uint32_t) + bool has_offset, bool, bool has_dref, uint32_t, uint32_t) { // Special-case gather. We have to alter the component being looked up // in the swizzle case. @@ -4721,7 +4721,7 @@ string CompilerMSL::to_function_name(uint32_t img, const SPIRType &imgtype, bool string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj, uint32_t coord, uint32_t, uint32_t dref, uint32_t grad_x, uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias, uint32_t comp, - uint32_t sample, bool *p_forward) + uint32_t sample, uint32_t minlod, bool *p_forward) { string farg_str; if (!is_fetch) @@ -4978,6 +4978,20 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool farg_str += ", gradient" + grad_opt + "(" + to_expression(grad_x) + ", " + to_expression(grad_y) + ")"; } + if (minlod) + { + if (msl_options.is_macos()) + { + if (!msl_options.supports_msl_version(2, 2)) + SPIRV_CROSS_THROW("min_lod_clamp() is only supported in MSL 2.2+ and up on macOS."); + } + else if (msl_options.is_ios()) + SPIRV_CROSS_THROW("min_lod_clamp() is not supported on iOS."); + + forward = forward && should_forward(minlod); + farg_str += ", min_lod_clamp(" + to_expression(minlod) + ")"; + } + // Add offsets string offset_expr; if (coffset && !is_fetch) @@ -5026,6 +5040,7 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool if (sample) { + forward = forward && should_forward(sample); farg_str += ", "; farg_str += to_expression(sample); } diff --git a/spirv_msl.hpp b/spirv_msl.hpp index 09782610..798c3eff 100644 --- a/spirv_msl.hpp +++ b/spirv_msl.hpp @@ -398,11 +398,11 @@ protected: std::string to_name(uint32_t id, bool allow_alias = true) const override; std::string to_function_name(uint32_t img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj, bool has_array_offsets, bool has_offset, bool has_grad, bool has_dref, - uint32_t lod) override; + uint32_t lod, uint32_t minlod) override; std::string to_function_args(uint32_t img, const SPIRType &imgtype, bool is_fetch, bool is_gather, bool is_proj, uint32_t coord, uint32_t coord_components, uint32_t dref, uint32_t grad_x, uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias, - uint32_t comp, uint32_t sample, bool *p_forward) override; + uint32_t comp, uint32_t sample, uint32_t minlod, bool *p_forward) override; std::string to_initializer_expression(const SPIRVariable &var) override; std::string unpack_expression_type(std::string expr_str, const SPIRType &type, uint32_t packed_type_id) override; std::string bitcast_glsl_op(const SPIRType &result_type, const SPIRType &argument_type) override;