Skip to content

Fix MSL for OpImageQueryLod on a vector larger than needed #2350

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <metal_stdlib>
#include <simd/simd.h>

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<float> Texture0 [[texture(0)]], texture2d_array<float> Texture1 [[texture(1)]], texture3d<float> Texture2 [[texture(2)]], texturecube<float> Texture3 [[texture(3)]], texturecube_array<float> 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;
}

37 changes: 37 additions & 0 deletions reference/shaders-msl/asm/frag/image-query-lod-vec4.msl22.asm.frag
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
#include <metal_stdlib>
#include <simd/simd.h>

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<float> Texture0 [[texture(0)]], texture2d_array<float> Texture1 [[texture(1)]], texture3d<float> Texture2 [[texture(2)]], texturecube<float> Texture3 [[texture(3)]], texturecube_array<float> 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;
}

82 changes: 82 additions & 0 deletions shaders-msl/asm/frag/image-query-lod-vec4.msl22.asm.frag
Original file line number Diff line number Diff line change
@@ -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
26 changes: 24 additions & 2 deletions spirv_msl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<SPIRCombinedImageSampler>(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;
}
Expand Down
Loading