Build combined dummy samplers for Query functions without sampler as well.

Deal with various query functions which require dummy sampler.
In SPIR-V, separate images are used, but GLSL (even Vulkan GLSL)
requires combined sampler images ...
This commit is contained in:
Hans-Kristian Arntzen 2018-04-30 11:18:18 +02:00
Родитель d93807a625
Коммит 40bbf6be7a
8 изменённых файлов: 154 добавлений и 36 удалений

Просмотреть файл

@ -0,0 +1,9 @@
#version 450
uniform sampler2D SPIRV_Cross_CombineduSampler2DSPIRV_Cross_DummySampler;
uniform sampler2DMS SPIRV_Cross_CombineduSampler2DMSSPIRV_Cross_DummySampler;
void main()
{
}

Просмотреть файл

@ -0,0 +1,10 @@
#version 450
layout(set = 0, binding = 0) uniform texture2D uSampler2D;
layout(set = 0, binding = 0) uniform texture2DMS uSampler2DMS;
layout(set = 0, binding = 0) uniform sampler SPIRV_Cross_DummySampler;
void main()
{
}

Просмотреть файл

@ -0,0 +1,13 @@
#version 450
uniform sampler2D SPIRV_Cross_CombineduSampler2DSPIRV_Cross_DummySampler;
uniform sampler2DMS SPIRV_Cross_CombineduSampler2DMSSPIRV_Cross_DummySampler;
void main()
{
ivec2 b = textureSize(SPIRV_Cross_CombineduSampler2DSPIRV_Cross_DummySampler, 0);
ivec2 c = textureSize(SPIRV_Cross_CombineduSampler2DMSSPIRV_Cross_DummySampler);
int l1 = textureQueryLevels(SPIRV_Cross_CombineduSampler2DSPIRV_Cross_DummySampler);
int s0 = textureSamples(SPIRV_Cross_CombineduSampler2DMSSPIRV_Cross_DummySampler);
}

Просмотреть файл

@ -0,0 +1,14 @@
#version 450
layout(set = 0, binding = 0) uniform texture2D uSampler2D;
layout(set = 0, binding = 0) uniform texture2DMS uSampler2DMS;
layout(set = 0, binding = 0) uniform sampler SPIRV_Cross_DummySampler;
void main()
{
ivec2 b = textureSize(sampler2D(uSampler2D, SPIRV_Cross_DummySampler), 0);
ivec2 c = textureSize(sampler2DMS(uSampler2DMS, SPIRV_Cross_DummySampler));
int l1 = textureQueryLevels(sampler2D(uSampler2D, SPIRV_Cross_DummySampler));
int s0 = textureSamples(sampler2DMS(uSampler2DMS, SPIRV_Cross_DummySampler));
}

Просмотреть файл

@ -0,0 +1,57 @@
; SPIR-V
; Version: 1.0
; Generator: Khronos Glslang Reference Front End; 6
; Bound: 36
; Schema: 0
OpCapability Shader
OpCapability ImageQuery
%1 = OpExtInstImport "GLSL.std.450"
OpMemoryModel Logical GLSL450
OpEntryPoint Fragment %main "main"
OpExecutionMode %main OriginUpperLeft
OpSource GLSL 450
OpName %main "main"
OpName %b "b"
OpName %uSampler2D "uSampler2D"
OpName %c "c"
OpName %uSampler2DMS "uSampler2DMS"
OpName %l1 "l1"
OpName %s0 "s0"
OpDecorate %uSampler2D DescriptorSet 0
OpDecorate %uSampler2D Binding 0
OpDecorate %uSampler2DMS DescriptorSet 0
OpDecorate %uSampler2DMS Binding 0
%void = OpTypeVoid
%3 = OpTypeFunction %void
%int = OpTypeInt 32 1
%v2int = OpTypeVector %int 2
%_ptr_Function_v2int = OpTypePointer Function %v2int
%float = OpTypeFloat 32
%11 = OpTypeImage %float 2D 0 0 0 1 Unknown
%_ptr_UniformConstant_12 = OpTypePointer UniformConstant %11
%uSampler2D = OpVariable %_ptr_UniformConstant_12 UniformConstant
%int_0 = OpConstant %int 0
%20 = OpTypeImage %float 2D 0 0 1 1 Unknown
%_ptr_UniformConstant_21 = OpTypePointer UniformConstant %20
%uSampler2DMS = OpVariable %_ptr_UniformConstant_21 UniformConstant
%_ptr_Function_int = OpTypePointer Function %int
%main = OpFunction %void None %3
%5 = OpLabel
%b = OpVariable %_ptr_Function_v2int Function
%c = OpVariable %_ptr_Function_v2int Function
%l1 = OpVariable %_ptr_Function_int Function
%s0 = OpVariable %_ptr_Function_int Function
%15 = OpLoad %11 %uSampler2D
%18 = OpImageQuerySizeLod %v2int %15 %int_0
OpStore %b %18
%24 = OpLoad %20 %uSampler2DMS
%26 = OpImageQuerySize %v2int %24
OpStore %c %26
%29 = OpLoad %11 %uSampler2D
%31 = OpImageQueryLevels %int %29
OpStore %l1 %31
%33 = OpLoad %20 %uSampler2DMS
%35 = OpImageQuerySamples %int %33
OpStore %s0 %35
OpReturn
OpFunctionEnd

Просмотреть файл

@ -3157,8 +3157,12 @@ bool Compiler::DummySamplerForCombinedImageHandler::handle(Op opcode, const uint
}
case OpImageFetch:
case OpImageQuerySizeLod:
case OpImageQuerySize:
case OpImageQueryLevels:
case OpImageQuerySamples:
{
// If we are fetching from a plain OpTypeImage, we must pre-combine with our dummy sampler.
// If we are fetching or querying LOD from a plain OpTypeImage, we must pre-combine with our dummy sampler.
auto *var = compiler.maybe_get_backing_variable(args[2]);
if (var)
{
@ -3259,8 +3263,12 @@ bool Compiler::CombinedImageSamplerHandler::handle(Op opcode, const uint32_t *ar
}
case OpImageFetch:
case OpImageQuerySizeLod:
case OpImageQuerySize:
case OpImageQueryLevels:
case OpImageQuerySamples:
{
// If we are fetching from a plain OpTypeImage, we must pre-combine with our dummy sampler.
// If we are fetching from a plain OpTypeImage or querying LOD, we must pre-combine with our dummy sampler.
auto *var = compiler.maybe_get_backing_variable(args[2]);
if (!var)
return true;
@ -3288,9 +3296,6 @@ bool Compiler::CombinedImageSamplerHandler::handle(Op opcode, const uint32_t *ar
return true;
}
if (length < 4)
return false;
// Registers sampler2D calls used in case they are parameters so
// that their callees know which combined image samplers to propagate down the call stack.
if (!functions.empty())
@ -3337,6 +3342,7 @@ bool Compiler::CombinedImageSamplerHandler::handle(Op opcode, const uint32_t *ar
type = compiler.expression_type(args[2]);
type.self = sampled_type;
type.basetype = SPIRType::SampledImage;
type.image.depth = false;
}
else
{

Просмотреть файл

@ -3909,40 +3909,47 @@ string CompilerGLSL::to_function_name(uint32_t, const SPIRType &imgtype, bool is
return is_legacy() ? legacy_tex_op(fname, imgtype, lod) : fname;
}
std::string CompilerGLSL::convert_separate_image_to_combined(uint32_t id)
{
auto &imgtype = expression_type(id);
auto *var = maybe_get_backing_variable(id);
// If we are fetching from a plain OpTypeImage, we must combine with a dummy sampler.
if (var)
{
auto &type = get<SPIRType>(var->basetype);
if (type.basetype == SPIRType::Image && type.image.sampled == 1 && type.image.dim != DimBuffer)
{
if (!dummy_sampler_id)
SPIRV_CROSS_THROW(
"Cannot find dummy sampler ID. Was build_dummy_sampler_for_combined_images() called?");
if (options.vulkan_semantics)
{
auto sampled_type = imgtype;
sampled_type.basetype = SPIRType::SampledImage;
return join(type_to_glsl(sampled_type), "(", to_expression(id), ", ",
to_expression(dummy_sampler_id), ")");
}
else
return to_combined_image_sampler(id, dummy_sampler_id);
}
}
return to_expression(id);
}
// Returns the function args for a texture sampling function for the specified image and sampling characteristics.
string CompilerGLSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool is_fetch, bool, bool is_proj,
uint32_t coord, uint32_t coord_components, uint32_t dref, uint32_t grad_x,
uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias,
uint32_t comp, uint32_t sample, bool *p_forward)
{
string farg_str = to_expression(img);
string farg_str;
if (is_fetch)
{
auto *var = maybe_get_backing_variable(img);
// If we are fetching from a plain OpTypeImage, we must combine with a dummy sampler.
if (var)
{
auto &type = get<SPIRType>(var->basetype);
if (type.basetype == SPIRType::Image && type.image.sampled == 1 && type.image.dim != DimBuffer)
{
if (!dummy_sampler_id)
SPIRV_CROSS_THROW(
"Cannot find dummy sampler ID. Was build_dummy_sampler_for_combined_images() called?");
if (options.vulkan_semantics)
{
auto sampled_type = imgtype;
sampled_type.basetype = SPIRType::SampledImage;
farg_str = join(type_to_glsl(sampled_type), "(", to_expression(img), ", ",
to_expression(dummy_sampler_id), ")");
}
else
farg_str = to_combined_image_sampler(img, dummy_sampler_id);
}
}
}
farg_str = convert_separate_image_to_combined(img);
else
farg_str = to_expression(img);
bool swizz_func = backend.swizzle_is_function;
auto swizzle = [swizz_func](uint32_t comps, uint32_t in_comps) -> const char * {
@ -7234,7 +7241,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
if (options.es)
SPIRV_CROSS_THROW("textureQueryLevels not supported in ES profile.");
auto expr = join("textureQueryLevels(", to_expression(ops[2]), ")");
auto expr = join("textureQueryLevels(", convert_separate_image_to_combined(ops[2]), ")");
auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::Int, expr);
emit_op(result_type, id, expr, true);
@ -7251,7 +7258,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
if (type.image.sampled == 2)
expr = join("imageSamples(", to_expression(ops[2]), ")");
else
expr = join("textureSamples(", to_expression(ops[2]), ")");
expr = join("textureSamples(", convert_separate_image_to_combined(ops[2]), ")");
auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::Int, expr);
@ -7272,7 +7279,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
uint32_t result_type = ops[0];
uint32_t id = ops[1];
auto expr = join("textureSize(", to_expression(ops[2]), ", ", bitcast_expression(SPIRType::Int, ops[3]), ")");
auto expr = join("textureSize(", convert_separate_image_to_combined(ops[2]), ", ", bitcast_expression(SPIRType::Int, ops[3]), ")");
auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::Int, expr);
emit_op(result_type, id, expr, true);
@ -7490,7 +7497,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
else
{
// This path is hit for samplerBuffers and multisampled images which do not have LOD.
expr = join("textureSize(", to_expression(ops[2]), ")");
expr = join("textureSize(", convert_separate_image_to_combined(ops[2]), ")");
}
auto &restype = get<SPIRType>(ops[0]);

Просмотреть файл

@ -556,6 +556,8 @@ protected:
std::string convert_float_to_string(const SPIRConstant &value, uint32_t col, uint32_t row);
std::string convert_double_to_string(const SPIRConstant &value, uint32_t col, uint32_t row);
std::string convert_separate_image_to_combined(uint32_t id);
private:
void init()
{