Use GL_EXT_samplerless_texture_functions in Vulkan GLSL.

This commit is contained in:
Hans-Kristian Arntzen 2018-09-27 13:36:38 +02:00
parent 44ed66426b
commit c07c303999
8 changed files with 37 additions and 36 deletions

View File

@ -832,7 +832,8 @@ static int main_inner(int argc, char *argv[])
else
{
combined_image_samplers = !args.vulkan_semantics;
build_dummy_sampler = true;
if (!args.vulkan_semantics)
build_dummy_sampler = true;
compiler = unique_ptr<CompilerGLSL>(new CompilerGLSL(read_spirv_file(args.input)));
}

View File

@ -1,14 +1,14 @@
#version 450
#extension GL_EXT_samplerless_texture_functions : require
layout(set = 0, binding = 0) uniform sampler Sampler;
layout(set = 0, binding = 0) uniform texture2D SampledImage;
layout(set = 0, binding = 0) uniform sampler SPIRV_Cross_DummySampler;
layout(location = 0) out vec4 _entryPointOutput;
void main()
{
ivec2 _152 = ivec3(int(gl_FragCoord.x * 1280.0), int(gl_FragCoord.y * 720.0), 0).xy;
_entryPointOutput = ((texelFetch(sampler2D(SampledImage, SPIRV_Cross_DummySampler), _152, 0) + texelFetch(sampler2D(SampledImage, SPIRV_Cross_DummySampler), _152, 0)) + texture(sampler2D(SampledImage, Sampler), gl_FragCoord.xy)) + texture(sampler2D(SampledImage, Sampler), gl_FragCoord.xy);
_entryPointOutput = ((texelFetch(SampledImage, _152, 0) + texelFetch(SampledImage, _152, 0)) + texture(sampler2D(SampledImage, Sampler), gl_FragCoord.xy)) + texture(sampler2D(SampledImage, Sampler), gl_FragCoord.xy);
}

View File

@ -1,14 +1,14 @@
#version 450
#extension GL_EXT_samplerless_texture_functions : require
layout(set = 0, binding = 0) uniform sampler Sampler;
layout(set = 0, binding = 0) uniform texture2D SampledImage;
layout(set = 0, binding = 0) uniform sampler SPIRV_Cross_DummySampler;
layout(location = 0) out vec4 _entryPointOutput;
vec4 sample_fetch(texture2D tex, ivec3 UV)
{
return texelFetch(sampler2D(tex, SPIRV_Cross_DummySampler), UV.xy, UV.z);
return texelFetch(tex, UV.xy, UV.z);
}
vec4 sample_sampler(texture2D tex, vec2 UV)
@ -21,7 +21,7 @@ vec4 _main(vec4 xIn)
ivec3 coord = ivec3(int(xIn.x * 1280.0), int(xIn.y * 720.0), 0);
ivec3 param = coord;
vec4 value = sample_fetch(SampledImage, param);
value += texelFetch(sampler2D(SampledImage, SPIRV_Cross_DummySampler), coord.xy, coord.z);
value += texelFetch(SampledImage, coord.xy, coord.z);
vec2 param_1 = xIn.xy;
value += sample_sampler(SampledImage, param_1);
value += texture(sampler2D(SampledImage, Sampler), xIn.xy);

View File

@ -1,14 +1,14 @@
#version 450
#extension GL_EXT_samplerless_texture_functions : require
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));
ivec2 b = textureSize(uSampler2D, 0);
ivec2 c = textureSize(uSampler2DMS);
int l1 = textureQueryLevels(uSampler2D);
int s0 = textureSamples(uSampler2DMS);
}

View File

@ -1098,8 +1098,8 @@ const SPIRType &Compiler::get_non_pointer_type(uint32_t type_id) const
bool Compiler::is_sampled_image_type(const SPIRType &type)
{
return (type.basetype == SPIRType::Image || type.basetype == SPIRType::SampledImage) &&
type.image.sampled == 1 && type.image.dim != DimBuffer;
return (type.basetype == SPIRType::Image || type.basetype == SPIRType::SampledImage) && type.image.sampled == 1 &&
type.image.dim != DimBuffer;
}
void Compiler::set_member_decoration_string(uint32_t id, uint32_t index, spv::Decoration decoration,

View File

@ -4083,30 +4083,32 @@ string CompilerGLSL::to_function_name(uint32_t tex, const SPIRType &imgtype, boo
return is_legacy() ? legacy_tex_op(fname, imgtype, lod, tex) : fname;
}
std::string CompilerGLSL::convert_separate_image_to_combined(uint32_t id)
std::string CompilerGLSL::convert_separate_image_to_expression(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 we are fetching from a plain OpTypeImage, we must combine with a dummy sampler in GLSL.
// In Vulkan GLSL, we can make use of the newer GL_EXT_samplerless_texture_functions.
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),
")");
// Newer glslang supports this extension to deal with texture2D as argument to texture functions.
if (dummy_sampler_id)
SPIRV_CROSS_THROW("Vulkan GLSL should not have a dummy sampler for combining.");
require_extension_internal("GL_EXT_samplerless_texture_functions");
}
else
{
if (!dummy_sampler_id)
SPIRV_CROSS_THROW(
"Cannot find dummy sampler ID. Was build_dummy_sampler_for_combined_images() called?");
return to_combined_image_sampler(id, dummy_sampler_id);
}
}
}
@ -4121,7 +4123,7 @@ string CompilerGLSL::to_function_args(uint32_t img, const SPIRType &imgtype, boo
{
string farg_str;
if (is_fetch)
farg_str = convert_separate_image_to_combined(img);
farg_str = convert_separate_image_to_expression(img);
else
farg_str = to_expression(img);
@ -7526,7 +7528,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
if (options.es)
SPIRV_CROSS_THROW("textureQueryLevels not supported in ES profile.");
auto expr = join("textureQueryLevels(", convert_separate_image_to_combined(ops[2]), ")");
auto expr = join("textureQueryLevels(", convert_separate_image_to_expression(ops[2]), ")");
auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::Int, expr);
emit_op(result_type, id, expr, true);
@ -7543,7 +7545,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
if (type.image.sampled == 2)
expr = join("imageSamples(", to_expression(ops[2]), ")");
else
expr = join("textureSamples(", convert_separate_image_to_combined(ops[2]), ")");
expr = join("textureSamples(", convert_separate_image_to_expression(ops[2]), ")");
auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::Int, expr);
@ -7564,7 +7566,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
uint32_t result_type = ops[0];
uint32_t id = ops[1];
auto expr = join("textureSize(", convert_separate_image_to_combined(ops[2]), ", ",
auto expr = join("textureSize(", convert_separate_image_to_expression(ops[2]), ", ",
bitcast_expression(SPIRType::Int, ops[3]), ")");
auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::Int, expr);
@ -7783,7 +7785,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(", convert_separate_image_to_combined(ops[2]), ")");
expr = join("textureSize(", convert_separate_image_to_expression(ops[2]), ")");
}
auto &restype = get<SPIRType>(ops[0]);
@ -9282,8 +9284,7 @@ void CompilerGLSL::branch(uint32_t from, uint32_t to)
// Only sensible solution is to make a ladder variable, which we declare at the top of the switch block,
// write to the ladder here, and defer the break.
// The loop we're breaking out of must dominate the switch block, or there is no ladder breaking case.
if (current_emitting_switch && is_loop_break(to) &&
current_emitting_switch->loop_dominator != -1u &&
if (current_emitting_switch && is_loop_break(to) && current_emitting_switch->loop_dominator != -1u &&
get<SPIRBlock>(current_emitting_switch->loop_dominator).merge_block == to)
{
if (!current_emitting_switch->need_ladder_break)

View File

@ -574,7 +574,7 @@ 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);
std::string convert_separate_image_to_expression(uint32_t id);
// Builtins in GLSL are always specific signedness, but the SPIR-V can declare them
// as either unsigned or signed.

View File

@ -3161,8 +3161,7 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
farg_str += to_expression(sample);
}
if (msl_options.swizzle_texture_samples && is_sampled_image_type(imgtype) &&
(!is_gather || !imgtype.image.depth))
if (msl_options.swizzle_texture_samples && is_sampled_image_type(imgtype) && (!is_gather || !imgtype.image.depth))
{
// Add the swizzle constant from the swizzle buffer.
if (!is_gather)
@ -4687,8 +4686,8 @@ bool CompilerMSL::SampledImageScanner::handle(spv::Op opcode, const uint32_t *ar
case OpImageSampleProjDrefImplicitLod:
case OpImageFetch:
case OpImageGather:
compiler.has_sampled_images = compiler.has_sampled_images ||
compiler.is_sampled_image_type(compiler.expression_type(args[2]));
compiler.has_sampled_images =
compiler.has_sampled_images || compiler.is_sampled_image_type(compiler.expression_type(args[2]));
break;
default:
break;