From cb06c50eba6f4eb01943c7ed603e5ab212891b8d Mon Sep 17 00:00:00 2001 From: Evan Tang Date: Mon, 8 Jul 2024 17:24:32 -0500 Subject: [PATCH] Fix MSL for OpImageQueryLod on a vector larger than needed --- .../frag/image-query-lod-vec4.msl22.asm.frag | 37 +++++++++ .../frag/image-query-lod-vec4.msl22.asm.frag | 37 +++++++++ .../frag/image-query-lod-vec4.msl22.asm.frag | 82 +++++++++++++++++++ spirv_msl.cpp | 26 +++++- 4 files changed, 180 insertions(+), 2 deletions(-) create mode 100644 reference/opt/shaders-msl/asm/frag/image-query-lod-vec4.msl22.asm.frag create mode 100644 reference/shaders-msl/asm/frag/image-query-lod-vec4.msl22.asm.frag create mode 100644 shaders-msl/asm/frag/image-query-lod-vec4.msl22.asm.frag diff --git a/reference/opt/shaders-msl/asm/frag/image-query-lod-vec4.msl22.asm.frag b/reference/opt/shaders-msl/asm/frag/image-query-lod-vec4.msl22.asm.frag new file mode 100644 index 00000000..b2bb280f --- /dev/null +++ b/reference/opt/shaders-msl/asm/frag/image-query-lod-vec4.msl22.asm.frag @@ -0,0 +1,37 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float2 LOD [[color(0)]]; +}; + +struct main0_in +{ + float4 Coord [[user(locn0)]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]], texture2d Texture0 [[texture(0)]], texture2d_array Texture1 [[texture(1)]], texture3d Texture2 [[texture(2)]], texturecube Texture3 [[texture(3)]], texturecube_array Texture4 [[texture(4)]], sampler Texture0Smplr [[sampler(0)]], sampler Texture1Smplr [[sampler(1)]], sampler Texture2Smplr [[sampler(2)]], sampler Texture3Smplr [[sampler(3)]], sampler Texture4Smplr [[sampler(4)]]) +{ + main0_out out = {}; + float2 _44; + _44.x = Texture0.calculate_clamped_lod(Texture0Smplr, in.Coord.xy); + _44.y = Texture0.calculate_unclamped_lod(Texture0Smplr, in.Coord.xy); + float2 _45; + _45.x = Texture1.calculate_clamped_lod(Texture1Smplr, in.Coord.xy); + _45.y = Texture1.calculate_unclamped_lod(Texture1Smplr, in.Coord.xy); + float2 _46; + _46.x = Texture2.calculate_clamped_lod(Texture2Smplr, in.Coord.xyz); + _46.y = Texture2.calculate_unclamped_lod(Texture2Smplr, in.Coord.xyz); + float2 _47; + _47.x = Texture3.calculate_clamped_lod(Texture3Smplr, in.Coord.xyz); + _47.y = Texture3.calculate_unclamped_lod(Texture3Smplr, in.Coord.xyz); + float2 _48; + _48.x = Texture4.calculate_clamped_lod(Texture4Smplr, in.Coord.xyz); + _48.y = Texture4.calculate_unclamped_lod(Texture4Smplr, in.Coord.xyz); + out.LOD = ((_44 + _45) + (_46 + _47)) + _48; + return out; +} + diff --git a/reference/shaders-msl/asm/frag/image-query-lod-vec4.msl22.asm.frag b/reference/shaders-msl/asm/frag/image-query-lod-vec4.msl22.asm.frag new file mode 100644 index 00000000..b2bb280f --- /dev/null +++ b/reference/shaders-msl/asm/frag/image-query-lod-vec4.msl22.asm.frag @@ -0,0 +1,37 @@ +#include +#include + +using namespace metal; + +struct main0_out +{ + float2 LOD [[color(0)]]; +}; + +struct main0_in +{ + float4 Coord [[user(locn0)]]; +}; + +fragment main0_out main0(main0_in in [[stage_in]], texture2d Texture0 [[texture(0)]], texture2d_array Texture1 [[texture(1)]], texture3d Texture2 [[texture(2)]], texturecube Texture3 [[texture(3)]], texturecube_array Texture4 [[texture(4)]], sampler Texture0Smplr [[sampler(0)]], sampler Texture1Smplr [[sampler(1)]], sampler Texture2Smplr [[sampler(2)]], sampler Texture3Smplr [[sampler(3)]], sampler Texture4Smplr [[sampler(4)]]) +{ + main0_out out = {}; + float2 _44; + _44.x = Texture0.calculate_clamped_lod(Texture0Smplr, in.Coord.xy); + _44.y = Texture0.calculate_unclamped_lod(Texture0Smplr, in.Coord.xy); + float2 _45; + _45.x = Texture1.calculate_clamped_lod(Texture1Smplr, in.Coord.xy); + _45.y = Texture1.calculate_unclamped_lod(Texture1Smplr, in.Coord.xy); + float2 _46; + _46.x = Texture2.calculate_clamped_lod(Texture2Smplr, in.Coord.xyz); + _46.y = Texture2.calculate_unclamped_lod(Texture2Smplr, in.Coord.xyz); + float2 _47; + _47.x = Texture3.calculate_clamped_lod(Texture3Smplr, in.Coord.xyz); + _47.y = Texture3.calculate_unclamped_lod(Texture3Smplr, in.Coord.xyz); + float2 _48; + _48.x = Texture4.calculate_clamped_lod(Texture4Smplr, in.Coord.xyz); + _48.y = Texture4.calculate_unclamped_lod(Texture4Smplr, in.Coord.xyz); + out.LOD = ((_44 + _45) + (_46 + _47)) + _48; + return out; +} + diff --git a/shaders-msl/asm/frag/image-query-lod-vec4.msl22.asm.frag b/shaders-msl/asm/frag/image-query-lod-vec4.msl22.asm.frag new file mode 100644 index 00000000..f1dcffd4 --- /dev/null +++ b/shaders-msl/asm/frag/image-query-lod-vec4.msl22.asm.frag @@ -0,0 +1,82 @@ +; SPIR-V +; Version: 1.0 +; Generator: Khronos Glslang Reference Front End; 6 +; Bound: 19 +; Schema: 0 + OpCapability Shader + OpCapability ImageQuery + %1 = OpExtInstImport "GLSL.std.450" + OpMemoryModel Logical GLSL450 + OpEntryPoint Fragment %main "main" %LOD %Coord + OpExecutionMode %main OriginUpperLeft + OpSource GLSL 450 + OpName %main "main" + OpName %LOD "LOD" + OpName %Coord "Coord" + OpName %Texture0 "Texture0" + OpName %Texture1 "Texture1" + OpName %Texture2 "Texture2" + OpName %Texture3 "Texture3" + OpName %Texture4 "Texture4" + OpDecorate %LOD Location 0 + OpDecorate %Coord Location 0 + OpDecorate %Texture0 DescriptorSet 0 + OpDecorate %Texture0 Binding 0 + OpDecorate %Texture1 DescriptorSet 0 + OpDecorate %Texture1 Binding 1 + OpDecorate %Texture2 DescriptorSet 0 + OpDecorate %Texture2 Binding 2 + OpDecorate %Texture3 DescriptorSet 0 + OpDecorate %Texture3 Binding 3 + OpDecorate %Texture4 DescriptorSet 0 + OpDecorate %Texture4 Binding 4 + %void = OpTypeVoid + %3 = OpTypeFunction %void + %int = OpTypeInt 32 1 + %float = OpTypeFloat 32 + %v2float = OpTypeVector %float 2 + %v4float = OpTypeVector %float 4 +%_ptr_Output_v2float = OpTypePointer Output %v2float +%_ptr_Input_v4float = OpTypePointer Input %v4float + %LOD = OpVariable %_ptr_Output_v2float Output + %Coord = OpVariable %_ptr_Input_v4float Input + %tex2d = OpTypeImage %float 2D 0 0 0 1 Unknown + %tex2darr = OpTypeImage %float 2D 0 1 0 1 Unknown + %tex3d = OpTypeImage %float 3D 0 0 0 1 Unknown + %texcube = OpTypeImage %float Cube 0 0 0 1 Unknown + %texcubearr = OpTypeImage %float Cube 0 1 0 1 Unknown + %samp2d = OpTypeSampledImage %tex2d + %samp2darr = OpTypeSampledImage %tex2darr + %samp3d = OpTypeSampledImage %tex3d + %sampcube = OpTypeSampledImage %texcube +%sampcubearr = OpTypeSampledImage %texcubearr + %pucs2d = OpTypePointer UniformConstant %samp2d + %pucs2darr = OpTypePointer UniformConstant %samp2darr + %pucs3d = OpTypePointer UniformConstant %samp3d + %pucscube = OpTypePointer UniformConstant %sampcube +%pucscubearr = OpTypePointer UniformConstant %sampcubearr + %Texture0 = OpVariable %pucs2d UniformConstant + %Texture1 = OpVariable %pucs2darr UniformConstant + %Texture2 = OpVariable %pucs3d UniformConstant + %Texture3 = OpVariable %pucscube UniformConstant + %Texture4 = OpVariable %pucscubearr UniformConstant + %main = OpFunction %void None %3 + %5 = OpLabel + %coord = OpLoad %v4float %Coord + %t0 = OpLoad %samp2d %Texture0 + %t1 = OpLoad %samp2darr %Texture1 + %t2 = OpLoad %samp3d %Texture2 + %t3 = OpLoad %sampcube %Texture3 + %t4 = OpLoad %sampcubearr %Texture4 + %l0 = OpImageQueryLod %v2float %t0 %coord + %l1 = OpImageQueryLod %v2float %t1 %coord + %l2 = OpImageQueryLod %v2float %t2 %coord + %l3 = OpImageQueryLod %v2float %t3 %coord + %l4 = OpImageQueryLod %v2float %t4 %coord + %10 = OpFAdd %v2float %l0 %l1 + %11 = OpFAdd %v2float %l2 %l3 + %12 = OpFAdd %v2float %10 %11 + %13 = OpFAdd %v2float %12 %l4 + OpStore %LOD %13 + OpReturn + OpFunctionEnd diff --git a/spirv_msl.cpp b/spirv_msl.cpp index 251f6883..b9020f29 100644 --- a/spirv_msl.cpp +++ b/spirv_msl.cpp @@ -9258,18 +9258,40 @@ void CompilerMSL::emit_instruction(const Instruction &instruction) uint32_t coord_id = ops[3]; emit_uninitialized_temporary_expression(result_type, id); + std::string coord_expr = to_expression(coord_id); auto sampler_expr = to_sampler_expression(image_id); auto *combined = maybe_get(image_id); auto image_expr = combined ? to_expression(combined->image) : to_expression(image_id); + const SPIRType& image_type = expression_type(image_id); + const SPIRType& coord_type = expression_type(coord_id); + + switch (image_type.image.dim) + { + case Dim1D: + if (!msl_options.texture_1D_as_2D) + SPIRV_CROSS_THROW("ImageQueryLod is not supported on 1D textures."); + [[fallthrough]]; + case Dim2D: + if (coord_type.vecsize > 2) + coord_expr = enclose_expression(coord_expr) + ".xy"; + break; + case DimCube: + case Dim3D: + if (coord_type.vecsize > 3) + coord_expr = enclose_expression(coord_expr) + ".xyz"; + break; + default: + SPIRV_CROSS_THROW("Bad image type given to OpImageQueryLod"); + } // TODO: It is unclear if calculcate_clamped_lod also conditionally rounds // the reported LOD based on the sampler. NEAREST miplevel should // round the LOD, but LINEAR miplevel should not round. // Let's hope this does not become an issue ... statement(to_expression(id), ".x = ", image_expr, ".calculate_clamped_lod(", sampler_expr, ", ", - to_expression(coord_id), ");"); + coord_expr, ");"); statement(to_expression(id), ".y = ", image_expr, ".calculate_unclamped_lod(", sampler_expr, ", ", - to_expression(coord_id), ");"); + coord_expr, ");"); register_control_dependent_expression(id); break; }