Merge pull request #715 from KhronosGroup/fix-709

Use GL_EXT_samplerless_texture_functions in Vulkan GLSL.
This commit is contained in:
Hans-Kristian Arntzen 2018-09-27 14:05:55 +02:00 committed by GitHub
commit e0fb64bfe7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 37 additions and 36 deletions

View File

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

View File

@ -1,14 +1,14 @@
#version 450 #version 450
#extension GL_EXT_samplerless_texture_functions : require
layout(set = 0, binding = 0) uniform sampler Sampler; layout(set = 0, binding = 0) uniform sampler Sampler;
layout(set = 0, binding = 0) uniform texture2D SampledImage; layout(set = 0, binding = 0) uniform texture2D SampledImage;
layout(set = 0, binding = 0) uniform sampler SPIRV_Cross_DummySampler;
layout(location = 0) out vec4 _entryPointOutput; layout(location = 0) out vec4 _entryPointOutput;
void main() void main()
{ {
ivec2 _152 = ivec3(int(gl_FragCoord.x * 1280.0), int(gl_FragCoord.y * 720.0), 0).xy; 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 #version 450
#extension GL_EXT_samplerless_texture_functions : require
layout(set = 0, binding = 0) uniform sampler Sampler; layout(set = 0, binding = 0) uniform sampler Sampler;
layout(set = 0, binding = 0) uniform texture2D SampledImage; layout(set = 0, binding = 0) uniform texture2D SampledImage;
layout(set = 0, binding = 0) uniform sampler SPIRV_Cross_DummySampler;
layout(location = 0) out vec4 _entryPointOutput; layout(location = 0) out vec4 _entryPointOutput;
vec4 sample_fetch(texture2D tex, ivec3 UV) 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) 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 coord = ivec3(int(xIn.x * 1280.0), int(xIn.y * 720.0), 0);
ivec3 param = coord; ivec3 param = coord;
vec4 value = sample_fetch(SampledImage, param); 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; vec2 param_1 = xIn.xy;
value += sample_sampler(SampledImage, param_1); value += sample_sampler(SampledImage, param_1);
value += texture(sampler2D(SampledImage, Sampler), xIn.xy); value += texture(sampler2D(SampledImage, Sampler), xIn.xy);

View File

@ -1,14 +1,14 @@
#version 450 #version 450
#extension GL_EXT_samplerless_texture_functions : require
layout(set = 0, binding = 0) uniform texture2D uSampler2D; layout(set = 0, binding = 0) uniform texture2D uSampler2D;
layout(set = 0, binding = 0) uniform texture2DMS uSampler2DMS; layout(set = 0, binding = 0) uniform texture2DMS uSampler2DMS;
layout(set = 0, binding = 0) uniform sampler SPIRV_Cross_DummySampler;
void main() void main()
{ {
ivec2 b = textureSize(sampler2D(uSampler2D, SPIRV_Cross_DummySampler), 0); ivec2 b = textureSize(uSampler2D, 0);
ivec2 c = textureSize(sampler2DMS(uSampler2DMS, SPIRV_Cross_DummySampler)); ivec2 c = textureSize(uSampler2DMS);
int l1 = textureQueryLevels(sampler2D(uSampler2D, SPIRV_Cross_DummySampler)); int l1 = textureQueryLevels(uSampler2D);
int s0 = textureSamples(sampler2DMS(uSampler2DMS, SPIRV_Cross_DummySampler)); 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) bool Compiler::is_sampled_image_type(const SPIRType &type)
{ {
return (type.basetype == SPIRType::Image || type.basetype == SPIRType::SampledImage) && return (type.basetype == SPIRType::Image || type.basetype == SPIRType::SampledImage) && type.image.sampled == 1 &&
type.image.sampled == 1 && type.image.dim != DimBuffer; type.image.dim != DimBuffer;
} }
void Compiler::set_member_decoration_string(uint32_t id, uint32_t index, spv::Decoration decoration, 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; 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); 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) if (var)
{ {
auto &type = get<SPIRType>(var->basetype); auto &type = get<SPIRType>(var->basetype);
if (type.basetype == SPIRType::Image && type.image.sampled == 1 && type.image.dim != DimBuffer) 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) if (options.vulkan_semantics)
{ {
auto sampled_type = imgtype; // Newer glslang supports this extension to deal with texture2D as argument to texture functions.
sampled_type.basetype = SPIRType::SampledImage; if (dummy_sampler_id)
return join(type_to_glsl(sampled_type), "(", to_expression(id), ", ", to_expression(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 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); 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; string farg_str;
if (is_fetch) if (is_fetch)
farg_str = convert_separate_image_to_combined(img); farg_str = convert_separate_image_to_expression(img);
else else
farg_str = to_expression(img); farg_str = to_expression(img);
@ -7526,7 +7528,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
if (options.es) if (options.es)
SPIRV_CROSS_THROW("textureQueryLevels not supported in ES profile."); 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]); auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::Int, expr); expr = bitcast_expression(restype, SPIRType::Int, expr);
emit_op(result_type, id, expr, true); emit_op(result_type, id, expr, true);
@ -7543,7 +7545,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
if (type.image.sampled == 2) if (type.image.sampled == 2)
expr = join("imageSamples(", to_expression(ops[2]), ")"); expr = join("imageSamples(", to_expression(ops[2]), ")");
else 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]); auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::Int, expr); 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 result_type = ops[0];
uint32_t id = ops[1]; 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]), ")"); bitcast_expression(SPIRType::Int, ops[3]), ")");
auto &restype = get<SPIRType>(ops[0]); auto &restype = get<SPIRType>(ops[0]);
expr = bitcast_expression(restype, SPIRType::Int, expr); expr = bitcast_expression(restype, SPIRType::Int, expr);
@ -7783,7 +7785,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
else else
{ {
// This path is hit for samplerBuffers and multisampled images which do not have LOD. // 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]); 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, // 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. // 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. // 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) && if (current_emitting_switch && is_loop_break(to) && current_emitting_switch->loop_dominator != -1u &&
current_emitting_switch->loop_dominator != -1u &&
get<SPIRBlock>(current_emitting_switch->loop_dominator).merge_block == to) get<SPIRBlock>(current_emitting_switch->loop_dominator).merge_block == to)
{ {
if (!current_emitting_switch->need_ladder_break) 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_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_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 // Builtins in GLSL are always specific signedness, but the SPIR-V can declare them
// as either unsigned or signed. // 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); farg_str += to_expression(sample);
} }
if (msl_options.swizzle_texture_samples && is_sampled_image_type(imgtype) && if (msl_options.swizzle_texture_samples && is_sampled_image_type(imgtype) && (!is_gather || !imgtype.image.depth))
(!is_gather || !imgtype.image.depth))
{ {
// Add the swizzle constant from the swizzle buffer. // Add the swizzle constant from the swizzle buffer.
if (!is_gather) if (!is_gather)
@ -4687,8 +4686,8 @@ bool CompilerMSL::SampledImageScanner::handle(spv::Op opcode, const uint32_t *ar
case OpImageSampleProjDrefImplicitLod: case OpImageSampleProjDrefImplicitLod:
case OpImageFetch: case OpImageFetch:
case OpImageGather: case OpImageGather:
compiler.has_sampled_images = compiler.has_sampled_images || compiler.has_sampled_images =
compiler.is_sampled_image_type(compiler.expression_type(args[2])); compiler.has_sampled_images || compiler.is_sampled_image_type(compiler.expression_type(args[2]));
break; break;
default: default:
break; break;