Separate (partially) the tracking of depth images from depth compare ops.

SPIR-V allows an image to be marked as a depth image, but with a non-depth
format. Such images should be read or sampled as vectors instead of scalars,
except when they are subject to compare operations.

Don't mark an OpSampledImage as using a compare operation just because the
image contains a depth marker. Instead, require that a compare operation
is actually used on that image.

Compiler::image_is_comparison() was really testing whether an image is a
depth image, since it incorporates the depth marker. Rename that function
to is_depth_image(), to clarify what it is really testing.

In Compiler::is_depth_image(), do not treat an image  as a depth image
if it has been explicitly marked with a color format, unless the image
is subject to compare operations.

In CompilerMSL::to_function_name(), test for compare operations
specifically, rather than assuming them from the depth-image marker.

CompilerGLSL and CompilerMSL still contain a number of internal tests that
use is_depth_image() both for testing for a depth image, and for testing
whether compare operations are being used. I've left these as they are
for now, but these should be cleaned up at some point.

Add unit tests for fetch/sample depth images with color formats and no compare ops.
This commit is contained in:
Bill Hollings 2021-11-08 15:59:45 -05:00
parent 2e0fb3a778
commit fd252b21ff
11 changed files with 526 additions and 26 deletions

View File

@ -0,0 +1,33 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct _7
{
float4 _m0[64];
};
struct main0_out
{
float4 m_3 [[color(0)]];
};
struct main0_in
{
float4 m_2 [[user(locn1)]];
};
fragment main0_out main0(main0_in in [[stage_in]], device _7& _10 [[buffer(0)]], texture2d<float> _8 [[texture(0)]])
{
main0_out out = {};
for (int _154 = 0; _154 < 64; )
{
_10._m0[_154] = _8.read(uint2(int2(_154 - 8 * (_154 / 8), _154 / 8)), 0);
_154++;
continue;
}
out.m_3 = in.m_2;
return out;
}

View File

@ -0,0 +1,33 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct _7
{
float4 _m0[64];
};
struct main0_out
{
float4 m_3 [[color(0)]];
};
struct main0_in
{
float4 m_2 [[user(locn1)]];
};
fragment main0_out main0(main0_in in [[stage_in]], device _7& _10 [[buffer(0)]], texture2d<float> _8 [[texture(0)]], sampler _9 [[sampler(0)]])
{
main0_out out = {};
for (int _158 = 0; _158 < 64; )
{
_10._m0[_158] = _8.sample(_9, (float2(int2(_158 - 8 * (_158 / 8), _158 / 8)) * float2(0.125)), level(0.0));
_158++;
continue;
}
out.m_3 = in.m_2;
return out;
}

View File

@ -0,0 +1,47 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct _7
{
float4 _m0[64];
};
struct main0_out
{
float4 m_3 [[color(0)]];
};
struct main0_in
{
float4 m_2 [[user(locn1)]];
};
static inline __attribute__((always_inline))
void _108(int _109, thread texture2d<float> v_8, device _7& v_10)
{
int2 _113 = int2(_109 - 8 * (_109 / 8), _109 / 8);
v_10._m0[_109] = v_8.read(uint2(_113), 0);
}
static inline __attribute__((always_inline))
float4 _98(float4 _119, thread texture2d<float> v_8, device _7& v_10)
{
for (int _121 = 0; _121 < 64; _121++)
{
_108(_121, v_8, v_10);
}
return _119;
}
fragment main0_out main0(main0_in in [[stage_in]], device _7& v_10 [[buffer(0)]], texture2d<float> v_8 [[texture(0)]])
{
main0_out out = {};
float4 _97 = _98(in.m_2, v_8, v_10);
out.m_3 = _97;
return out;
}

View File

@ -0,0 +1,46 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct _7
{
float4 _m0[64];
};
struct main0_out
{
float4 m_3 [[color(0)]];
};
struct main0_in
{
float4 m_2 [[user(locn1)]];
};
static inline __attribute__((always_inline))
void _108(int _109, thread texture2d<float> v_8, thread sampler v_9, device _7& v_10)
{
v_10._m0[_109] = v_8.sample(v_9, (float2(int2(_109 - 8 * (_109 / 8), _109 / 8)) / float2(8.0)), level(0.0));
}
static inline __attribute__((always_inline))
float4 _98(float4 _121, thread texture2d<float> v_8, thread sampler v_9, device _7& v_10)
{
for (int _123 = 0; _123 < 64; _123++)
{
_108(_123, v_8, v_9, v_10);
}
return _121;
}
fragment main0_out main0(main0_in in [[stage_in]], device _7& v_10 [[buffer(0)]], texture2d<float> v_8 [[texture(0)]], sampler v_9 [[sampler(0)]])
{
main0_out out = {};
float4 _97 = _98(in.m_2, v_8, v_9, v_10);
out.m_3 = _97;
return out;
}

View File

@ -0,0 +1,170 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos SPIR-V Tools Assembler; 0
; Bound: 132
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %1 "main" %2 %3 %4
OpExecutionMode %1 OriginUpperLeft
OpDecorate %3 Location 0
OpDecorate %2 Location 1
OpDecorate %4 BuiltIn FragCoord
OpDecorate %5 ArrayStride 4
OpDecorate %6 ArrayStride 16
OpMemberDecorate %7 0 Offset 0
OpDecorate %7 BufferBlock
OpDecorate %8 DescriptorSet 0
OpDecorate %8 Binding 0
OpDecorate %9 DescriptorSet 0
OpDecorate %9 Binding 1
OpDecorate %10 DescriptorSet 0
OpDecorate %10 Binding 2
%11 = OpTypeVoid
%12 = OpTypeBool
%13 = OpTypeInt 32 1
%14 = OpTypeInt 32 0
%16 = OpTypeFloat 32
%17 = OpTypeVector %13 2
%18 = OpTypeVector %14 2
%19 = OpTypeVector %16 2
%20 = OpTypeVector %13 3
%21 = OpTypeVector %14 3
%22 = OpTypeVector %16 3
%23 = OpTypeVector %13 4
%24 = OpTypeVector %14 4
%25 = OpTypeVector %16 4
%26 = OpTypeVector %12 4
%27 = OpTypeFunction %25 %25
%28 = OpTypeFunction %12
%29 = OpTypeFunction %11
%30 = OpTypePointer Input %16
%31 = OpTypePointer Input %13
%32 = OpTypePointer Input %14
%33 = OpTypePointer Input %19
%34 = OpTypePointer Input %17
%35 = OpTypePointer Input %18
%38 = OpTypePointer Input %22
%40 = OpTypePointer Input %25
%41 = OpTypePointer Input %23
%42 = OpTypePointer Input %24
%43 = OpTypePointer Output %16
%44 = OpTypePointer Output %13
%45 = OpTypePointer Output %14
%46 = OpTypePointer Output %19
%47 = OpTypePointer Output %17
%48 = OpTypePointer Output %18
%49 = OpTypePointer Output %25
%50 = OpTypePointer Output %23
%51 = OpTypePointer Output %24
%52 = OpTypePointer Function %16
%53 = OpTypePointer Function %13
%54 = OpTypePointer Function %25
%55 = OpConstant %16 1
%56 = OpConstant %16 0
%57 = OpConstant %16 0.5
%58 = OpConstant %16 -1
%59 = OpConstant %16 7
%60 = OpConstant %16 8
%61 = OpConstant %13 0
%62 = OpConstant %13 1
%63 = OpConstant %13 2
%64 = OpConstant %13 3
%65 = OpConstant %13 4
%66 = OpConstant %14 0
%67 = OpConstant %14 1
%68 = OpConstant %14 2
%69 = OpConstant %14 3
%70 = OpConstant %14 32
%71 = OpConstant %14 4
%72 = OpConstant %14 2147483647
%73 = OpConstantComposite %25 %55 %55 %55 %55
%74 = OpConstantComposite %25 %55 %56 %56 %55
%75 = OpConstantComposite %25 %57 %57 %57 %57
%76 = OpTypeArray %16 %67
%77 = OpTypeArray %16 %68
%78 = OpTypeArray %25 %69
%79 = OpTypeArray %16 %71
%80 = OpTypeArray %25 %70
%81 = OpTypePointer Input %78
%82 = OpTypePointer Input %80
%83 = OpTypePointer Output %77
%84 = OpTypePointer Output %78
%85 = OpTypePointer Output %79
%4 = OpVariable %40 Input
%3 = OpVariable %49 Output
%2 = OpVariable %40 Input
%86 = OpConstant %14 64
%87 = OpConstant %13 64
%88 = OpConstant %13 8
%89 = OpConstantComposite %19 %60 %60
%5 = OpTypeArray %16 %86
%6 = OpTypeArray %25 %86
%90 = OpTypePointer Uniform %16
%91 = OpTypePointer Uniform %25
%7 = OpTypeStruct %6
%92 = OpTypePointer Uniform %7
%10 = OpVariable %92 Uniform
%93 = OpTypeImage %16 2D 1 0 0 1 Rgba32f
%94 = OpTypePointer UniformConstant %93
%8 = OpVariable %94 UniformConstant
%95 = OpTypeSampler
%96 = OpTypePointer UniformConstant %95
%9 = OpVariable %96 UniformConstant
%97 = OpTypeSampledImage %93
%98 = OpTypeFunction %11 %13
%1 = OpFunction %11 None %29
%99 = OpLabel
%100 = OpLoad %25 %2
%101 = OpFunctionCall %25 %102 %100
OpStore %3 %101
OpReturn
OpFunctionEnd
%103 = OpFunction %12 None %28
%104 = OpLabel
%105 = OpAccessChain %30 %4 %61
%106 = OpAccessChain %30 %4 %62
%107 = OpLoad %16 %105
%108 = OpLoad %16 %106
%109 = OpFOrdEqual %12 %107 %57
%110 = OpFOrdEqual %12 %108 %57
%111 = OpLogicalAnd %12 %109 %110
OpReturnValue %111
OpFunctionEnd
%112 = OpFunction %11 None %98
%113 = OpFunctionParameter %13
%114 = OpLabel
%115 = OpSRem %13 %113 %88
%116 = OpSDiv %13 %113 %88
%117 = OpCompositeConstruct %17 %115 %116
%118 = OpConvertSToF %19 %117
%119 = OpFDiv %19 %118 %89
%120 = OpLoad %93 %8
%121 = OpImageFetch %25 %120 %117
%36 = OpAccessChain %91 %10 %61 %113
OpStore %36 %121
OpReturn
OpFunctionEnd
%102 = OpFunction %25 None %27
%122 = OpFunctionParameter %25
%123 = OpLabel
%124 = OpVariable %53 Function
OpStore %124 %61
OpBranch %125
%125 = OpLabel
%15 = OpLoad %13 %124
%126 = OpSLessThan %12 %15 %87
OpLoopMerge %127 %128 None
OpBranchConditional %126 %129 %127
%129 = OpLabel
%130 = OpLoad %13 %124
%131 = OpFunctionCall %11 %112 %130
OpBranch %128
%128 = OpLabel
%37 = OpLoad %13 %124
%39 = OpIAdd %13 %37 %62
OpStore %124 %39
OpBranch %125
%127 = OpLabel
OpReturnValue %122
OpFunctionEnd

View File

@ -0,0 +1,173 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos SPIR-V Tools Assembler; 0
; Bound: 134
; Schema: 0
OpCapability Shader
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %1 "main" %2 %3 %4
OpExecutionMode %1 OriginUpperLeft
OpDecorate %3 Location 0
OpDecorate %2 Location 1
OpDecorate %4 BuiltIn FragCoord
OpDecorate %5 ArrayStride 4
OpDecorate %6 ArrayStride 16
OpMemberDecorate %7 0 Offset 0
OpDecorate %7 BufferBlock
OpDecorate %8 DescriptorSet 0
OpDecorate %8 Binding 0
OpDecorate %9 DescriptorSet 0
OpDecorate %9 Binding 1
OpDecorate %10 DescriptorSet 0
OpDecorate %10 Binding 2
%11 = OpTypeVoid
%12 = OpTypeBool
%13 = OpTypeInt 32 1
%14 = OpTypeInt 32 0
%16 = OpTypeFloat 32
%17 = OpTypeVector %13 2
%18 = OpTypeVector %14 2
%19 = OpTypeVector %16 2
%20 = OpTypeVector %13 3
%21 = OpTypeVector %14 3
%22 = OpTypeVector %16 3
%23 = OpTypeVector %13 4
%24 = OpTypeVector %14 4
%25 = OpTypeVector %16 4
%26 = OpTypeVector %12 4
%27 = OpTypeFunction %25 %25
%28 = OpTypeFunction %12
%29 = OpTypeFunction %11
%30 = OpTypePointer Input %16
%31 = OpTypePointer Input %13
%32 = OpTypePointer Input %14
%33 = OpTypePointer Input %19
%34 = OpTypePointer Input %17
%35 = OpTypePointer Input %18
%38 = OpTypePointer Input %22
%40 = OpTypePointer Input %25
%41 = OpTypePointer Input %23
%42 = OpTypePointer Input %24
%43 = OpTypePointer Output %16
%44 = OpTypePointer Output %13
%45 = OpTypePointer Output %14
%46 = OpTypePointer Output %19
%47 = OpTypePointer Output %17
%48 = OpTypePointer Output %18
%49 = OpTypePointer Output %25
%50 = OpTypePointer Output %23
%51 = OpTypePointer Output %24
%52 = OpTypePointer Function %16
%53 = OpTypePointer Function %13
%54 = OpTypePointer Function %25
%55 = OpConstant %16 1
%56 = OpConstant %16 0
%57 = OpConstant %16 0.5
%58 = OpConstant %16 -1
%59 = OpConstant %16 7
%60 = OpConstant %16 8
%61 = OpConstant %13 0
%62 = OpConstant %13 1
%63 = OpConstant %13 2
%64 = OpConstant %13 3
%65 = OpConstant %13 4
%66 = OpConstant %14 0
%67 = OpConstant %14 1
%68 = OpConstant %14 2
%69 = OpConstant %14 3
%70 = OpConstant %14 32
%71 = OpConstant %14 4
%72 = OpConstant %14 2147483647
%73 = OpConstantComposite %25 %55 %55 %55 %55
%74 = OpConstantComposite %25 %55 %56 %56 %55
%75 = OpConstantComposite %25 %57 %57 %57 %57
%76 = OpTypeArray %16 %67
%77 = OpTypeArray %16 %68
%78 = OpTypeArray %25 %69
%79 = OpTypeArray %16 %71
%80 = OpTypeArray %25 %70
%81 = OpTypePointer Input %78
%82 = OpTypePointer Input %80
%83 = OpTypePointer Output %77
%84 = OpTypePointer Output %78
%85 = OpTypePointer Output %79
%4 = OpVariable %40 Input
%3 = OpVariable %49 Output
%2 = OpVariable %40 Input
%86 = OpConstant %14 64
%87 = OpConstant %13 64
%88 = OpConstant %13 8
%89 = OpConstantComposite %19 %60 %60
%5 = OpTypeArray %16 %86
%6 = OpTypeArray %25 %86
%90 = OpTypePointer Uniform %16
%91 = OpTypePointer Uniform %25
%7 = OpTypeStruct %6
%92 = OpTypePointer Uniform %7
%10 = OpVariable %92 Uniform
%93 = OpTypeImage %16 2D 1 0 0 1 Rgba32f
%94 = OpTypePointer UniformConstant %93
%8 = OpVariable %94 UniformConstant
%95 = OpTypeSampler
%96 = OpTypePointer UniformConstant %95
%9 = OpVariable %96 UniformConstant
%97 = OpTypeSampledImage %93
%98 = OpTypeFunction %11 %13
%1 = OpFunction %11 None %29
%99 = OpLabel
%100 = OpLoad %25 %2
%101 = OpFunctionCall %25 %102 %100
OpStore %3 %101
OpReturn
OpFunctionEnd
%103 = OpFunction %12 None %28
%104 = OpLabel
%105 = OpAccessChain %30 %4 %61
%106 = OpAccessChain %30 %4 %62
%107 = OpLoad %16 %105
%108 = OpLoad %16 %106
%109 = OpFOrdEqual %12 %107 %57
%110 = OpFOrdEqual %12 %108 %57
%111 = OpLogicalAnd %12 %109 %110
OpReturnValue %111
OpFunctionEnd
%112 = OpFunction %11 None %98
%113 = OpFunctionParameter %13
%114 = OpLabel
%115 = OpSRem %13 %113 %88
%116 = OpSDiv %13 %113 %88
%117 = OpCompositeConstruct %17 %115 %116
%118 = OpConvertSToF %19 %117
%119 = OpFDiv %19 %118 %89
%120 = OpLoad %93 %8
%121 = OpLoad %95 %9
%122 = OpSampledImage %97 %120 %121
%123 = OpImageSampleExplicitLod %25 %122 %119 Lod %56
%36 = OpAccessChain %91 %10 %61 %113
OpStore %36 %123
OpReturn
OpFunctionEnd
%102 = OpFunction %25 None %27
%124 = OpFunctionParameter %25
%125 = OpLabel
%126 = OpVariable %53 Function
OpStore %126 %61
OpBranch %127
%127 = OpLabel
%15 = OpLoad %13 %126
%128 = OpSLessThan %12 %15 %87
OpLoopMerge %129 %130 None
OpBranchConditional %128 %131 %129
%131 = OpLabel
%132 = OpLoad %13 %126
%133 = OpFunctionCall %11 %112 %132
OpBranch %130
%130 = OpLabel
%37 = OpLoad %13 %126
%39 = OpIAdd %13 %37 %62
OpStore %126 %39
OpBranch %127
%129 = OpLabel
OpReturnValue %124
OpFunctionEnd

View File

@ -4448,16 +4448,13 @@ bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_
if (length < 4)
return false;
uint32_t result_type = args[0];
uint32_t result_id = args[1];
auto &type = compiler.get<SPIRType>(result_type);
// If the underlying resource has been used for comparison then duplicate loads of that resource must be too.
// This image must be a depth image.
uint32_t result_id = args[1];
uint32_t image = args[2];
uint32_t sampler = args[3];
if (type.image.depth || dref_combined_samplers.count(result_id) != 0)
if (dref_combined_samplers.count(result_id) != 0)
{
add_hierarchy_to_comparison_ids(image);
@ -4717,9 +4714,11 @@ bool Compiler::is_desktop_only_format(spv::ImageFormat format)
return false;
}
bool Compiler::image_is_comparison(const SPIRType &type, uint32_t id) const
// An image is determined to be a depth image if it is marked as a depth image and is not also
// explicitly marked with a color format, or if there are any sample/gather compare operations on it.
bool Compiler::is_depth_image(const SPIRType &type, uint32_t id) const
{
return type.image.depth || (comparison_ids.count(id) != 0);
return (type.image.depth && type.image.format == ImageFormatUnknown) || comparison_ids.count(id);
}
bool Compiler::type_is_opaque_value(const SPIRType &type) const

View File

@ -1107,7 +1107,7 @@ protected:
Bitset combined_decoration_for_member(const SPIRType &type, uint32_t index) const;
static bool is_desktop_only_format(spv::ImageFormat format);
bool image_is_comparison(const SPIRType &type, uint32_t id) const;
bool is_depth_image(const SPIRType &type, uint32_t id) const;
void set_extended_decoration(uint32_t id, ExtendedDecorations decoration, uint32_t value = 0);
uint32_t get_extended_decoration(uint32_t id, ExtendedDecorations decoration) const;

View File

@ -6215,7 +6215,7 @@ string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtyp
// GLES has very limited support for shadow samplers.
// Basically shadow2D and shadow2DProj work through EXT_shadow_samplers,
// everything else can just throw
bool is_comparison = image_is_comparison(imgtype, tex);
bool is_comparison = is_depth_image(imgtype, tex);
if (is_comparison && is_legacy_es())
{
if (op == "texture" || op == "textureProj")
@ -6842,7 +6842,7 @@ std::string CompilerGLSL::to_texture_op(const Instruction &i, bool sparse, bool
expr += ")";
// texture(samplerXShadow) returns float. shadowX() returns vec4. Swizzle here.
if (is_legacy() && image_is_comparison(imgtype, img))
if (is_legacy() && is_depth_image(imgtype, img))
expr += ".r";
// Sampling from a texture which was deduced to be a depth image, might actually return 1 component here.
@ -6853,16 +6853,16 @@ std::string CompilerGLSL::to_texture_op(const Instruction &i, bool sparse, bool
const auto *combined = maybe_get<SPIRCombinedImageSampler>(img);
VariableID image_id = combined ? combined->image : img;
if (combined && image_is_comparison(imgtype, combined->image))
if (combined && is_depth_image(imgtype, combined->image))
image_is_depth = true;
else if (image_is_comparison(imgtype, img))
else if (is_depth_image(imgtype, img))
image_is_depth = true;
// We must also check the backing variable for the image.
// We might have loaded an OpImage, and used that handle for two different purposes.
// Once with comparison, once without.
auto *image_variable = maybe_get_backing_variable(image_id);
if (image_variable && image_is_comparison(get<SPIRType>(image_variable->basetype), image_variable->self))
if (image_variable && is_depth_image(get<SPIRType>(image_variable->basetype), image_variable->self))
image_is_depth = true;
if (image_is_depth)
@ -6930,7 +6930,7 @@ string CompilerGLSL::to_function_name(const TextureFunctionNameArguments &args)
// This happens for HLSL SampleCmpLevelZero on Texture2DArray and TextureCube.
bool workaround_lod_array_shadow_as_grad = false;
if (((imgtype.image.arrayed && imgtype.image.dim == Dim2D) || imgtype.image.dim == DimCube) &&
image_is_comparison(imgtype, tex) && args.lod)
is_depth_image(imgtype, tex) && args.lod)
{
if (!expression_is_constant_null(args.lod))
{
@ -7074,7 +7074,7 @@ string CompilerGLSL::to_function_args(const TextureFunctionArguments &args, bool
// This happens for HLSL SampleCmpLevelZero on Texture2DArray and TextureCube.
bool workaround_lod_array_shadow_as_grad =
((imgtype.image.arrayed && imgtype.image.dim == Dim2D) || imgtype.image.dim == DimCube) &&
image_is_comparison(imgtype, img) && args.lod != 0;
is_depth_image(imgtype, img) && args.lod != 0;
if (args.dref)
{
@ -13392,7 +13392,7 @@ string CompilerGLSL::image_type_glsl(const SPIRType &type, uint32_t id)
// "Shadow" state in GLSL only exists for samplers and combined image samplers.
if (((type.basetype == SPIRType::SampledImage) || (type.basetype == SPIRType::Sampler)) &&
image_is_comparison(type, id))
is_depth_image(type, id))
{
res += "Shadow";
}
@ -15831,7 +15831,7 @@ void CompilerGLSL::emit_inout_fragment_outputs_copy_to_subpass_inputs()
bool CompilerGLSL::variable_is_depth_or_compare(VariableID id) const
{
return image_is_comparison(get<SPIRType>(get<SPIRVariable>(id).basetype), id);
return is_depth_image(get<SPIRType>(get<SPIRVariable>(id).basetype), id);
}
const char *CompilerGLSL::ShaderSubgroupSupportHelper::get_extension_name(Candidate c)

View File

@ -2380,7 +2380,7 @@ void CompilerHLSL::emit_function_prototype(SPIRFunction &func, const Bitset &ret
arg_type.image.dim != DimBuffer)
{
// Manufacture automatic sampler arg for SampledImage texture
arglist.push_back(join(image_is_comparison(arg_type, arg.id) ? "SamplerComparisonState " : "SamplerState ",
arglist.push_back(join(is_depth_image(arg_type, arg.id) ? "SamplerComparisonState " : "SamplerState ",
to_sampler_expression(arg.id), type_to_array_glsl(arg_type)));
}
@ -2910,7 +2910,7 @@ void CompilerHLSL::emit_texture_op(const Instruction &i, bool sparse)
{
texop += img_expr;
if (image_is_comparison(imgtype, img))
if (is_depth_image(imgtype, img))
{
if (gather)
{
@ -3386,7 +3386,7 @@ void CompilerHLSL::emit_modern_uniform(const SPIRVariable &var)
if (type.basetype == SPIRType::SampledImage && type.image.dim != DimBuffer)
{
// For combined image samplers, also emit a combined image sampler.
if (image_is_comparison(type, var.self))
if (is_depth_image(type, var.self))
statement("SamplerComparisonState ", to_sampler_expression(var.self), type_to_array_glsl(type),
to_resource_binding_sampler(var), ";");
else

View File

@ -9393,8 +9393,6 @@ static bool needs_chroma_reconstruction(const MSLConstexprSampler *constexpr_sam
string CompilerMSL::to_function_name(const TextureFunctionNameArguments &args)
{
VariableID img = args.base.img;
auto &imgtype = *args.base.imgtype;
const MSLConstexprSampler *constexpr_sampler = nullptr;
bool is_dynamic_img_sampler = false;
if (auto *var = maybe_get_backing_variable(img))
@ -9408,8 +9406,9 @@ string CompilerMSL::to_function_name(const TextureFunctionNameArguments &args)
if (msl_options.swizzle_texture_samples && args.base.is_gather && !is_dynamic_img_sampler &&
(!constexpr_sampler || !constexpr_sampler->ycbcr_conversion_enable))
{
add_spv_func_and_recompile(imgtype.image.depth ? SPVFuncImplGatherCompareSwizzle : SPVFuncImplGatherSwizzle);
return imgtype.image.depth ? "spvGatherCompareSwizzle" : "spvGatherSwizzle";
bool is_compare = comparison_ids.count(img);
add_spv_func_and_recompile(is_compare ? SPVFuncImplGatherCompareSwizzle : SPVFuncImplGatherSwizzle);
return is_compare ? "spvGatherCompareSwizzle" : "spvGatherSwizzle";
}
auto *combined = maybe_get<SPIRCombinedImageSampler>(img);
@ -10021,7 +10020,7 @@ string CompilerMSL::to_function_args(const TextureFunctionArguments &args, bool
image_var = var->self;
}
if (image_var == 0 || !image_is_comparison(expression_type(image_var), image_var))
if (image_var == 0 || !is_depth_image(expression_type(image_var), image_var))
farg_str += ", " + to_component_argument(args.component);
}
}
@ -13631,7 +13630,7 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
// Bypass pointers because we need the real image struct
auto &img_type = get<SPIRType>(type.self).image;
if (image_is_comparison(type, id))
if (is_depth_image(type, id))
{
switch (img_type.dim)
{