Support OpTypeImage with depth == 2 (unknown) properly.
Track which OpSampledImages are ever used with Dref opcodes.
This commit is contained in:
parent
a6814a405a
commit
e044732896
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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));
|
||||
}
|
||||
|
41
reference/shaders-hlsl/asm/frag/unknown-depth-state.asm.frag
Normal file
41
reference/shaders-hlsl/asm/frag/unknown-depth-state.asm.frag
Normal 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;
|
||||
}
|
34
reference/shaders-msl/asm/frag/unknown-depth-state.asm.frag
Normal file
34
reference/shaders-msl/asm/frag/unknown-depth-state.asm.frag
Normal 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;
|
||||
}
|
||||
|
23
reference/shaders/asm/frag/unknown-depth-state.asm.vk.frag
Normal file
23
reference/shaders/asm/frag/unknown-depth-state.asm.vk.frag
Normal 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();
|
||||
}
|
||||
|
@ -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();
|
||||
}
|
||||
|
71
shaders-hlsl/asm/frag/unknown-depth-state.asm.frag
Normal file
71
shaders-hlsl/asm/frag/unknown-depth-state.asm.frag
Normal 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
|
71
shaders-msl/asm/frag/unknown-depth-state.asm.frag
Normal file
71
shaders-msl/asm/frag/unknown-depth-state.asm.frag
Normal 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
|
71
shaders/asm/frag/unknown-depth-state.asm.vk.frag
Normal file
71
shaders/asm/frag/unknown-depth-state.asm.vk.frag
Normal 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
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user