Support OpTypeImage with depth == 2 (unknown) properly.

Track which OpSampledImages are ever used with Dref opcodes.
This commit is contained in:
Hans-Kristian Arntzen 2018-07-04 14:25:10 +02:00
parent a6814a405a
commit e044732896
18 changed files with 531 additions and 62 deletions

View File

@ -0,0 +1,31 @@
Texture2D<float4> uShadow : register(t0);
SamplerComparisonState _uShadow_sampler : register(s0);
Texture2D<float4> uTexture : register(t1);
SamplerComparisonState uSampler : register(s2);
static float3 vUV;
static float FragColor;
struct SPIRV_Cross_Input
{
float3 vUV : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float FragColor : SV_Target0;
};
void frag_main()
{
FragColor = uShadow.SampleCmp(_uShadow_sampler, vUV.xy, vUV.z) + uTexture.SampleCmp(uSampler, vUV.xy, vUV.z);
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
vUV = stage_input.vUV;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,22 @@
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float FragColor [[color(0)]];
};
struct main0_in
{
float3 vUV [[user(locn0)]];
};
fragment main0_out main0(main0_in in [[stage_in]], depth2d<float> uShadow [[texture(0)]], depth2d<float> uTexture [[texture(1)]], sampler uShadowSmplr [[sampler(0)]], sampler uSampler [[sampler(2)]])
{
main0_out out = {};
out.FragColor = uShadow.sample_compare(uShadowSmplr, in.vUV.xy, in.vUV.z) + uTexture.sample_compare(uSampler, in.vUV.xy, in.vUV.z);
return out;
}

View File

@ -0,0 +1,13 @@
#version 450
layout(binding = 0) uniform sampler2DShadow uShadow;
uniform sampler2DShadow SPIRV_Cross_CombineduTextureuSampler;
layout(location = 0) in vec3 vUV;
layout(location = 0) out float FragColor;
void main()
{
FragColor = texture(uShadow, vec3(vUV.xy, vUV.z)) + texture(SPIRV_Cross_CombineduTextureuSampler, vec3(vUV.xy, vUV.z));
}

View File

@ -0,0 +1,14 @@
#version 450
layout(set = 0, binding = 0) uniform sampler2DShadow uShadow;
layout(set = 0, binding = 1) uniform texture2D uTexture;
layout(set = 0, binding = 2) uniform samplerShadow uSampler;
layout(location = 0) in vec3 vUV;
layout(location = 0) out float FragColor;
void main()
{
FragColor = texture(uShadow, vec3(vUV.xy, vUV.z)) + texture(sampler2DShadow(uTexture, uSampler), vec3(vUV.xy, vUV.z));
}

View File

@ -0,0 +1,41 @@
Texture2D<float4> uShadow : register(t0);
SamplerComparisonState _uShadow_sampler : register(s0);
Texture2D<float4> uTexture : register(t1);
SamplerComparisonState uSampler : register(s2);
static float3 vUV;
static float FragColor;
struct SPIRV_Cross_Input
{
float3 vUV : TEXCOORD0;
};
struct SPIRV_Cross_Output
{
float FragColor : SV_Target0;
};
float sample_combined()
{
return uShadow.SampleCmp(_uShadow_sampler, vUV.xy, vUV.z);
}
float sample_separate()
{
return uTexture.SampleCmp(uSampler, vUV.xy, vUV.z);
}
void frag_main()
{
FragColor = sample_combined() + sample_separate();
}
SPIRV_Cross_Output main(SPIRV_Cross_Input stage_input)
{
vUV = stage_input.vUV;
frag_main();
SPIRV_Cross_Output stage_output;
stage_output.FragColor = FragColor;
return stage_output;
}

View File

@ -0,0 +1,34 @@
#pragma clang diagnostic ignored "-Wmissing-prototypes"
#include <metal_stdlib>
#include <simd/simd.h>
using namespace metal;
struct main0_out
{
float FragColor [[color(0)]];
};
struct main0_in
{
float3 vUV [[user(locn0)]];
};
float sample_combined(thread float3& vUV, thread depth2d<float> uShadow, thread const sampler uShadowSmplr)
{
return uShadow.sample_compare(uShadowSmplr, vUV.xy, vUV.z);
}
float sample_separate(thread float3& vUV, thread depth2d<float> uTexture, thread sampler uSampler)
{
return uTexture.sample_compare(uSampler, vUV.xy, vUV.z);
}
fragment main0_out main0(main0_in in [[stage_in]], depth2d<float> uShadow [[texture(0)]], depth2d<float> uTexture [[texture(1)]], sampler uShadowSmplr [[sampler(0)]], sampler uSampler [[sampler(2)]])
{
main0_out out = {};
out.FragColor = sample_combined(in.vUV, uShadow, uShadowSmplr) + sample_separate(in.vUV, uTexture, uSampler);
return out;
}

View File

@ -0,0 +1,23 @@
#version 450
layout(binding = 0) uniform sampler2DShadow uShadow;
uniform sampler2DShadow SPIRV_Cross_CombineduTextureuSampler;
layout(location = 0) in vec3 vUV;
layout(location = 0) out float FragColor;
float sample_combined()
{
return texture(uShadow, vec3(vUV.xy, vUV.z));
}
float sample_separate()
{
return texture(SPIRV_Cross_CombineduTextureuSampler, vec3(vUV.xy, vUV.z));
}
void main()
{
FragColor = sample_combined() + sample_separate();
}

View File

@ -0,0 +1,24 @@
#version 450
layout(set = 0, binding = 0) uniform sampler2DShadow uShadow;
layout(set = 0, binding = 1) uniform texture2D uTexture;
layout(set = 0, binding = 2) uniform samplerShadow uSampler;
layout(location = 0) in vec3 vUV;
layout(location = 0) out float FragColor;
float sample_combined()
{
return texture(uShadow, vec3(vUV.xy, vUV.z));
}
float sample_separate()
{
return texture(sampler2DShadow(uTexture, uSampler), vec3(vUV.xy, vUV.z));
}
void main()
{
FragColor = sample_combined() + sample_separate();
}

View File

@ -0,0 +1,71 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 44
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %vUV %FragColor
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %sample_combined_ "sample_combined("
OpName %sample_separate_ "sample_separate("
OpName %uShadow "uShadow"
OpName %vUV "vUV"
OpName %uTexture "uTexture"
OpName %uSampler "uSampler"
OpName %FragColor "FragColor"
OpDecorate %uShadow DescriptorSet 0
OpDecorate %uShadow Binding 0
OpDecorate %vUV Location 0
OpDecorate %uTexture DescriptorSet 0
OpDecorate %uTexture Binding 1
OpDecorate %uSampler DescriptorSet 0
OpDecorate %uSampler Binding 2
OpDecorate %FragColor Location 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%7 = OpTypeFunction %float
%12 = OpTypeImage %float 2D 2 0 0 1 Unknown
%13 = OpTypeSampledImage %12
%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
%uShadow = OpVariable %_ptr_UniformConstant_13 UniformConstant
%v3float = OpTypeVector %float 3
%_ptr_Input_v3float = OpTypePointer Input %v3float
%vUV = OpVariable %_ptr_Input_v3float Input
%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %12
%uTexture = OpVariable %_ptr_UniformConstant_25 UniformConstant
%29 = OpTypeSampler
%_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
%uSampler = OpVariable %_ptr_UniformConstant_29 UniformConstant
%_ptr_Output_float = OpTypePointer Output %float
%FragColor = OpVariable %_ptr_Output_float Output
%main = OpFunction %void None %3
%5 = OpLabel
%41 = OpFunctionCall %float %sample_combined_
%42 = OpFunctionCall %float %sample_separate_
%43 = OpFAdd %float %41 %42
OpStore %FragColor %43
OpReturn
OpFunctionEnd
%sample_combined_ = OpFunction %float None %7
%9 = OpLabel
%16 = OpLoad %13 %uShadow
%20 = OpLoad %v3float %vUV
%21 = OpCompositeExtract %float %20 2
%22 = OpImageSampleDrefImplicitLod %float %16 %20 %21
OpReturnValue %22
OpFunctionEnd
%sample_separate_ = OpFunction %float None %7
%11 = OpLabel
%28 = OpLoad %12 %uTexture
%32 = OpLoad %29 %uSampler
%33 = OpSampledImage %13 %28 %32
%34 = OpLoad %v3float %vUV
%35 = OpCompositeExtract %float %34 2
%36 = OpImageSampleDrefImplicitLod %float %33 %34 %35
OpReturnValue %36
OpFunctionEnd

View File

@ -0,0 +1,71 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 44
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %vUV %FragColor
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %sample_combined_ "sample_combined("
OpName %sample_separate_ "sample_separate("
OpName %uShadow "uShadow"
OpName %vUV "vUV"
OpName %uTexture "uTexture"
OpName %uSampler "uSampler"
OpName %FragColor "FragColor"
OpDecorate %uShadow DescriptorSet 0
OpDecorate %uShadow Binding 0
OpDecorate %vUV Location 0
OpDecorate %uTexture DescriptorSet 0
OpDecorate %uTexture Binding 1
OpDecorate %uSampler DescriptorSet 0
OpDecorate %uSampler Binding 2
OpDecorate %FragColor Location 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%7 = OpTypeFunction %float
%12 = OpTypeImage %float 2D 2 0 0 1 Unknown
%13 = OpTypeSampledImage %12
%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
%uShadow = OpVariable %_ptr_UniformConstant_13 UniformConstant
%v3float = OpTypeVector %float 3
%_ptr_Input_v3float = OpTypePointer Input %v3float
%vUV = OpVariable %_ptr_Input_v3float Input
%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %12
%uTexture = OpVariable %_ptr_UniformConstant_25 UniformConstant
%29 = OpTypeSampler
%_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
%uSampler = OpVariable %_ptr_UniformConstant_29 UniformConstant
%_ptr_Output_float = OpTypePointer Output %float
%FragColor = OpVariable %_ptr_Output_float Output
%main = OpFunction %void None %3
%5 = OpLabel
%41 = OpFunctionCall %float %sample_combined_
%42 = OpFunctionCall %float %sample_separate_
%43 = OpFAdd %float %41 %42
OpStore %FragColor %43
OpReturn
OpFunctionEnd
%sample_combined_ = OpFunction %float None %7
%9 = OpLabel
%16 = OpLoad %13 %uShadow
%20 = OpLoad %v3float %vUV
%21 = OpCompositeExtract %float %20 2
%22 = OpImageSampleDrefImplicitLod %float %16 %20 %21
OpReturnValue %22
OpFunctionEnd
%sample_separate_ = OpFunction %float None %7
%11 = OpLabel
%28 = OpLoad %12 %uTexture
%32 = OpLoad %29 %uSampler
%33 = OpSampledImage %13 %28 %32
%34 = OpLoad %v3float %vUV
%35 = OpCompositeExtract %float %34 2
%36 = OpImageSampleDrefImplicitLod %float %33 %34 %35
OpReturnValue %36
OpFunctionEnd

View File

@ -0,0 +1,71 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 44
; Schema: 0
OpCapability Shader
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main" %vUV %FragColor
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %sample_combined_ "sample_combined("
OpName %sample_separate_ "sample_separate("
OpName %uShadow "uShadow"
OpName %vUV "vUV"
OpName %uTexture "uTexture"
OpName %uSampler "uSampler"
OpName %FragColor "FragColor"
OpDecorate %uShadow DescriptorSet 0
OpDecorate %uShadow Binding 0
OpDecorate %vUV Location 0
OpDecorate %uTexture DescriptorSet 0
OpDecorate %uTexture Binding 1
OpDecorate %uSampler DescriptorSet 0
OpDecorate %uSampler Binding 2
OpDecorate %FragColor Location 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%float = OpTypeFloat 32
%7 = OpTypeFunction %float
%12 = OpTypeImage %float 2D 2 0 0 1 Unknown
%13 = OpTypeSampledImage %12
%_ptr_UniformConstant_13 = OpTypePointer UniformConstant %13
%uShadow = OpVariable %_ptr_UniformConstant_13 UniformConstant
%v3float = OpTypeVector %float 3
%_ptr_Input_v3float = OpTypePointer Input %v3float
%vUV = OpVariable %_ptr_Input_v3float Input
%_ptr_UniformConstant_25 = OpTypePointer UniformConstant %12
%uTexture = OpVariable %_ptr_UniformConstant_25 UniformConstant
%29 = OpTypeSampler
%_ptr_UniformConstant_29 = OpTypePointer UniformConstant %29
%uSampler = OpVariable %_ptr_UniformConstant_29 UniformConstant
%_ptr_Output_float = OpTypePointer Output %float
%FragColor = OpVariable %_ptr_Output_float Output
%main = OpFunction %void None %3
%5 = OpLabel
%41 = OpFunctionCall %float %sample_combined_
%42 = OpFunctionCall %float %sample_separate_
%43 = OpFAdd %float %41 %42
OpStore %FragColor %43
OpReturn
OpFunctionEnd
%sample_combined_ = OpFunction %float None %7
%9 = OpLabel
%16 = OpLoad %13 %uShadow
%20 = OpLoad %v3float %vUV
%21 = OpCompositeExtract %float %20 2
%22 = OpImageSampleDrefImplicitLod %float %16 %20 %21
OpReturnValue %22
OpFunctionEnd
%sample_separate_ = OpFunction %float None %7
%11 = OpLabel
%28 = OpLoad %12 %uTexture
%32 = OpLoad %29 %uSampler
%33 = OpSampledImage %13 %28 %32
%34 = OpLoad %v3float %vUV
%35 = OpCompositeExtract %float %34 2
%36 = OpImageSampleDrefImplicitLod %float %33 %34 %35
OpReturnValue %36
OpFunctionEnd

View File

@ -4367,11 +4367,43 @@ bool Compiler::has_active_builtin(BuiltIn builtin, StorageClass storage)
void Compiler::analyze_image_and_sampler_usage()
{
CombinedImageSamplerUsageHandler handler(*this);
CombinedImageSamplerDrefHandler dref_handler(*this);
traverse_all_reachable_opcodes(get<SPIRFunction>(entry_point), dref_handler);
CombinedImageSamplerUsageHandler handler(*this, dref_handler.dref_combined_samplers);
traverse_all_reachable_opcodes(get<SPIRFunction>(entry_point), handler);
comparison_samplers = move(handler.comparison_samplers);
comparison_images = move(handler.comparison_images);
comparison_ids = move(handler.comparison_ids);
need_subpass_input = handler.need_subpass_input;
// Forward information from separate images and samplers into combined image samplers.
for (auto &combined : combined_image_samplers)
if (comparison_ids.count(combined.sampler_id))
comparison_ids.insert(combined.combined_id);
}
bool Compiler::CombinedImageSamplerDrefHandler::handle(spv::Op opcode, const uint32_t *args, uint32_t)
{
// Mark all sampled images which are used with Dref.
switch (opcode)
{
case OpImageSampleDrefExplicitLod:
case OpImageSampleDrefImplicitLod:
case OpImageSampleProjDrefExplicitLod:
case OpImageSampleProjDrefImplicitLod:
case OpImageSparseSampleProjDrefImplicitLod:
case OpImageSparseSampleDrefImplicitLod:
case OpImageSparseSampleProjDrefExplicitLod:
case OpImageSparseSampleDrefExplicitLod:
case OpImageDrefGather:
case OpImageSparseDrefGather:
dref_combined_samplers.insert(args[2]);
return true;
default:
break;
}
return true;
}
bool Compiler::CombinedImageSamplerUsageHandler::begin_function_scope(const uint32_t *args, uint32_t length)
@ -4392,20 +4424,12 @@ bool Compiler::CombinedImageSamplerUsageHandler::begin_function_scope(const uint
return true;
}
void Compiler::CombinedImageSamplerUsageHandler::add_hierarchy_to_comparison_images(uint32_t image)
void Compiler::CombinedImageSamplerUsageHandler::add_hierarchy_to_comparison_ids(uint32_t id)
{
// Traverse the variable dependency hierarchy and tag everything in its path with comparison images.
comparison_images.insert(image);
for (auto &img : dependency_hierarchy[image])
add_hierarchy_to_comparison_images(img);
}
void Compiler::CombinedImageSamplerUsageHandler::add_hierarchy_to_comparison_samplers(uint32_t sampler)
{
// Traverse the variable dependency hierarchy and tag everything in its path with comparison samplers.
comparison_samplers.insert(sampler);
for (auto &samp : dependency_hierarchy[sampler])
add_hierarchy_to_comparison_samplers(samp);
// Traverse the variable dependency hierarchy and tag everything in its path with comparison ids.
comparison_ids.insert(id);
for (auto &dep_id : dependency_hierarchy[id])
add_hierarchy_to_comparison_ids(dep_id);
}
bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_t *args, uint32_t length)
@ -4425,6 +4449,10 @@ bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_
auto &type = compiler.get<SPIRType>(args[0]);
if (type.image.dim == DimSubpassData)
need_subpass_input = true;
// If we load a SampledImage and it will be used with Dref, propagate the state up.
if (dref_combined_samplers.count(args[1]) != 0)
add_hierarchy_to_comparison_ids(args[1]);
break;
}
@ -4434,16 +4462,20 @@ bool Compiler::CombinedImageSamplerUsageHandler::handle(Op opcode, const uint32_
return false;
uint32_t result_type = args[0];
uint32_t result_id = args[1];
auto &type = compiler.get<SPIRType>(result_type);
if (type.image.depth)
if (type.image.depth || dref_combined_samplers.count(result_id) != 0)
{
// This image must be a depth image.
uint32_t image = args[2];
add_hierarchy_to_comparison_images(image);
add_hierarchy_to_comparison_ids(image);
// This sampler must be a SamplerComparisionState, and not a regular SamplerState.
// This sampler must be a SamplerComparisonState, and not a regular SamplerState.
uint32_t sampler = args[3];
add_hierarchy_to_comparison_samplers(sampler);
add_hierarchy_to_comparison_ids(sampler);
// Mark the OpSampledImage itself as being comparison state.
comparison_ids.insert(result_id);
}
return true;
}
@ -4654,3 +4686,8 @@ bool Compiler::is_desktop_only_format(spv::ImageFormat format)
return false;
}
bool Compiler::image_is_comparison(const spirv_cross::SPIRType &type, uint32_t id) const
{
return type.image.depth || (comparison_ids.count(id) != 0);
}

View File

@ -826,8 +826,7 @@ protected:
// There might be unrelated IDs found in this set which do not correspond to actual variables.
// This set should only be queried for the existence of samplers which are already known to be variables or parameter IDs.
// Similar is implemented for images, as well as if subpass inputs are needed.
std::unordered_set<uint32_t> comparison_samplers;
std::unordered_set<uint32_t> comparison_images;
std::unordered_set<uint32_t> comparison_ids;
bool need_subpass_input = false;
// In certain backends, we will need to use a dummy sampler to be able to emit code.
@ -836,23 +835,37 @@ protected:
uint32_t dummy_sampler_id = 0;
void analyze_image_and_sampler_usage();
struct CombinedImageSamplerDrefHandler : OpcodeHandler
{
CombinedImageSamplerDrefHandler(Compiler &compiler_)
: compiler(compiler_)
{
}
bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override;
Compiler &compiler;
std::unordered_set<uint32_t> dref_combined_samplers;
};
struct CombinedImageSamplerUsageHandler : OpcodeHandler
{
CombinedImageSamplerUsageHandler(Compiler &compiler_)
CombinedImageSamplerUsageHandler(Compiler &compiler_,
const std::unordered_set<uint32_t> &dref_combined_samplers_)
: compiler(compiler_)
, dref_combined_samplers(dref_combined_samplers_)
{
}
bool begin_function_scope(const uint32_t *args, uint32_t length) override;
bool handle(spv::Op opcode, const uint32_t *args, uint32_t length) override;
Compiler &compiler;
const std::unordered_set<uint32_t> &dref_combined_samplers;
std::unordered_map<uint32_t, std::unordered_set<uint32_t>> dependency_hierarchy;
std::unordered_set<uint32_t> comparison_images;
std::unordered_set<uint32_t> comparison_samplers;
std::unordered_set<uint32_t> comparison_ids;
void add_hierarchy_to_comparison_samplers(uint32_t sampler);
void add_hierarchy_to_comparison_images(uint32_t sampler);
void add_hierarchy_to_comparison_ids(uint32_t ids);
bool need_subpass_input = false;
};
@ -868,6 +881,8 @@ 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;
private:
// Used only to implement the old deprecated get_entry_point() interface.
const SPIREntryPoint &get_first_entry_point(const std::string &name) const;

View File

@ -3460,7 +3460,7 @@ bool CompilerGLSL::check_explicit_lod_allowed(uint32_t lod)
return allowed;
}
string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t lod)
string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t lod, uint32_t tex)
{
const char *type;
switch (imgtype.image.dim)
@ -3512,7 +3512,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
if (imgtype.image.depth && is_legacy_es())
if (image_is_comparison(imgtype, tex) && is_legacy_es())
{
if (op == "texture" || op == "textureProj")
require_extension_internal("GL_EXT_shadow_samplers");
@ -3520,8 +3520,8 @@ string CompilerGLSL::legacy_tex_op(const std::string &op, const SPIRType &imgtyp
SPIRV_CROSS_THROW(join(op, " not allowed on depth samplers in legacy ES"));
}
bool is_es_and_depth = (is_legacy_es() && imgtype.image.depth);
std::string type_prefix = imgtype.image.depth ? "shadow" : "texture";
bool is_es_and_depth = is_legacy_es() && image_is_comparison(imgtype, tex);
std::string type_prefix = image_is_comparison(imgtype, tex) ? "shadow" : "texture";
if (op == "texture")
return is_es_and_depth ? join(type_prefix, type, "EXT") : join(type_prefix, type);
@ -3764,7 +3764,7 @@ void CompilerGLSL::emit_sampled_image_op(uint32_t result_type, uint32_t result_i
if (options.vulkan_semantics && combined_image_samplers.empty())
{
emit_binary_func_op(result_type, result_id, image_id, samp_id,
type_to_glsl(get<SPIRType>(result_type)).c_str());
type_to_glsl(get<SPIRType>(result_type), result_id).c_str());
// Make sure to suppress usage tracking. It is illegal to create temporaries of opaque types.
forwarded_temporaries.erase(result_id);
@ -3930,7 +3930,7 @@ void CompilerGLSL::emit_texture_op(const Instruction &i)
expr += ")";
// texture(samplerXShadow) returns float. shadowX() returns vec4. Swizzle here.
if (is_legacy() && imgtype.image.depth)
if (is_legacy() && image_is_comparison(imgtype, img))
expr += ".r";
emit_op(result_type, id, expr, forward);
@ -3953,8 +3953,9 @@ void CompilerGLSL::emit_texture_op(const Instruction &i)
// Returns the function name for a texture sampling function for the specified image and sampling characteristics.
// For some subclasses, the function is a method on the specified image.
string CompilerGLSL::to_function_name(uint32_t, 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)
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)
{
string fname;
@ -3964,7 +3965,7 @@ string CompilerGLSL::to_function_name(uint32_t, const SPIRType &imgtype, bool is
// 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) &&
imgtype.image.depth && lod)
image_is_comparison(imgtype, tex) && lod)
{
auto *constant_lod = maybe_get<SPIRConstant>(lod);
if (!constant_lod || constant_lod->scalar_f32() != 0.0f)
@ -3994,7 +3995,7 @@ string CompilerGLSL::to_function_name(uint32_t, const SPIRType &imgtype, bool is
if (has_offset)
fname += "Offset";
return is_legacy() ? legacy_tex_op(fname, imgtype, lod) : fname;
return is_legacy() ? legacy_tex_op(fname, imgtype, lod, tex) : fname;
}
std::string CompilerGLSL::convert_separate_image_to_combined(uint32_t id)
@ -4079,7 +4080,7 @@ string CompilerGLSL::to_function_args(uint32_t img, const SPIRType &imgtype, boo
// 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) &&
imgtype.image.depth && lod;
image_is_comparison(imgtype, img) && lod;
if (dref)
{
@ -8418,7 +8419,7 @@ string CompilerGLSL::type_to_array_glsl(const SPIRType &type)
}
}
string CompilerGLSL::image_type_glsl(const SPIRType &type, uint32_t /* id */)
string CompilerGLSL::image_type_glsl(const SPIRType &type, uint32_t id)
{
auto &imagetype = get<SPIRType>(type.image.type);
string res;
@ -8491,8 +8492,11 @@ 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)) && type.image.depth)
if (((type.basetype == SPIRType::SampledImage) || (type.basetype == SPIRType::Sampler)) &&
image_is_comparison(type, id))
{
res += "Shadow";
}
return res;
}
@ -8538,7 +8542,7 @@ string CompilerGLSL::type_to_glsl(const SPIRType &type, uint32_t id)
case SPIRType::Sampler:
// The depth field is set by calling code based on the variable ID of the sampler, effectively reintroducing
// this distinction into the type system.
return comparison_samplers.count(id) ? "samplerShadow" : "sampler";
return comparison_ids.count(id) ? "samplerShadow" : "sampler";
case SPIRType::Void:
return "void";

View File

@ -491,7 +491,7 @@ protected:
void replace_fragment_output(SPIRVariable &var);
void replace_fragment_outputs();
bool check_explicit_lod_allowed(uint32_t lod);
std::string legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t lod);
std::string legacy_tex_op(const std::string &op, const SPIRType &imgtype, uint32_t lod, uint32_t id);
uint32_t indent = 0;

View File

@ -224,7 +224,7 @@ static bool hlsl_opcode_is_sign_invariant(Op opcode)
}
}
string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type)
string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type, uint32_t)
{
auto &imagetype = get<SPIRType>(type.image.type);
const char *dim = nullptr;
@ -275,7 +275,7 @@ string CompilerHLSL::image_type_hlsl_modern(const SPIRType &type)
">");
}
string CompilerHLSL::image_type_hlsl_legacy(const SPIRType &type)
string CompilerHLSL::image_type_hlsl_legacy(const SPIRType &type, uint32_t id)
{
auto &imagetype = get<SPIRType>(type.image.type);
string res;
@ -338,18 +338,18 @@ string CompilerHLSL::image_type_hlsl_legacy(const SPIRType &type)
res += "MS";
if (type.image.arrayed)
res += "Array";
if (type.image.depth)
if (image_is_comparison(type, id))
res += "Shadow";
return res;
}
string CompilerHLSL::image_type_hlsl(const SPIRType &type)
string CompilerHLSL::image_type_hlsl(const SPIRType &type, uint32_t id)
{
if (hlsl_options.shader_model <= 30)
return image_type_hlsl_legacy(type);
return image_type_hlsl_legacy(type, id);
else
return image_type_hlsl_modern(type);
return image_type_hlsl_modern(type, id);
}
// The optional id parameter indicates the object whose type we are trying
@ -370,10 +370,10 @@ string CompilerHLSL::type_to_glsl(const SPIRType &type, uint32_t id)
case SPIRType::Image:
case SPIRType::SampledImage:
return image_type_hlsl(type);
return image_type_hlsl(type, id);
case SPIRType::Sampler:
return comparison_samplers.count(id) ? "SamplerComparisonState" : "SamplerState";
return comparison_ids.count(id) ? "SamplerComparisonState" : "SamplerState";
case SPIRType::Void:
return "void";
@ -2060,7 +2060,7 @@ void CompilerHLSL::emit_function_prototype(SPIRFunction &func, const Bitset &ret
{
// Manufacture automatic sampler arg for SampledImage texture
decl += ", ";
decl += join(arg_type.image.depth ? "SamplerComparisonState " : "SamplerState ",
decl += join(image_is_comparison(arg_type, arg.id) ? "SamplerComparisonState " : "SamplerState ",
to_sampler_expression(arg.id), type_to_array_glsl(arg_type));
}
@ -2575,7 +2575,7 @@ void CompilerHLSL::emit_texture_op(const Instruction &i)
{
texop += img_expr;
if (imgtype.image.depth)
if (image_is_comparison(imgtype, img))
{
if (gather)
{
@ -2927,13 +2927,13 @@ void CompilerHLSL::emit_modern_uniform(const SPIRVariable &var)
if (type.basetype == SPIRType::Image && type.image.sampled == 2)
is_coherent = has_decoration(var.self, DecorationCoherent);
statement(is_coherent ? "globallycoherent " : "", image_type_hlsl_modern(type), " ", to_name(var.self),
type_to_array_glsl(type), to_resource_binding(var), ";");
statement(is_coherent ? "globallycoherent " : "", image_type_hlsl_modern(type, var.self), " ",
to_name(var.self), type_to_array_glsl(type), to_resource_binding(var), ";");
if (type.basetype == SPIRType::SampledImage && type.image.dim != DimBuffer)
{
// For combined image samplers, also emit a combined image sampler.
if (type.image.depth)
if (image_is_comparison(type, var.self))
statement("SamplerComparisonState ", to_sampler_expression(var.self), type_to_array_glsl(type),
to_resource_binding_sampler(var), ";");
else
@ -2944,7 +2944,7 @@ void CompilerHLSL::emit_modern_uniform(const SPIRVariable &var)
}
case SPIRType::Sampler:
if (comparison_samplers.count(var.self))
if (comparison_ids.count(var.self))
statement("SamplerComparisonState ", to_name(var.self), type_to_array_glsl(type), to_resource_binding(var),
";");
else

View File

@ -118,9 +118,9 @@ public:
private:
std::string type_to_glsl(const SPIRType &type, uint32_t id = 0) override;
std::string image_type_hlsl(const SPIRType &type);
std::string image_type_hlsl_modern(const SPIRType &type);
std::string image_type_hlsl_legacy(const SPIRType &type);
std::string image_type_hlsl(const SPIRType &type, uint32_t id);
std::string image_type_hlsl_modern(const SPIRType &type, uint32_t id);
std::string image_type_hlsl_legacy(const SPIRType &type, uint32_t id);
void emit_function_prototype(SPIRFunction &func, const Bitset &return_flags) override;
void emit_hlsl_entry_point();
void emit_header() override;

View File

@ -3633,9 +3633,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;
bool shadow_image = comparison_images.count(id) != 0;
if (img_type.depth || shadow_image)
if (image_is_comparison(type, id))
{
switch (img_type.dim)
{