GLSL: Implement noncoherent framebuffer fetch.
This commit is contained in:
parent
418542eaef
commit
26a4986009
7
main.cpp
7
main.cpp
@ -662,6 +662,7 @@ struct CLIArguments
|
||||
bool glsl_emit_ubo_as_plain_uniforms = false;
|
||||
bool glsl_force_flattened_io_blocks = false;
|
||||
SmallVector<pair<uint32_t, uint32_t>> glsl_ext_framebuffer_fetch;
|
||||
bool glsl_ext_framebuffer_fetch_noncoherent = false;
|
||||
bool vulkan_glsl_disable_ext_samplerless_texture_functions = false;
|
||||
bool emit_line_directives = false;
|
||||
bool enable_storage_image_qualifier_deduction = true;
|
||||
@ -754,6 +755,7 @@ static void print_help_glsl()
|
||||
"\t[--glsl-emit-ubo-as-plain-uniforms]:\n\t\tInstead of emitting UBOs, emit them as plain uniform structs.\n"
|
||||
"\t[--glsl-remap-ext-framebuffer-fetch input-attachment color-location]:\n\t\tRemaps an input attachment to use GL_EXT_shader_framebuffer_fetch.\n"
|
||||
"\t\tgl_LastFragData[location] is read from. The attachment to read from must be declared as an output in the shader.\n"
|
||||
"\t[--glsl-ext-framebuffer-fetch-noncoherent]:\n\t\tUses noncoherent qualifier for framebuffer fetch.\n"
|
||||
"\t[--vulkan-glsl-disable-ext-samplerless-texture-functions]:\n\t\tDo not allow use of GL_EXT_samperless_texture_functions, even in Vulkan GLSL.\n"
|
||||
"\t\tUse of texelFetch and similar might have to create dummy samplers to work around it.\n"
|
||||
"\t[--combined-samplers-inherit-bindings]:\n\t\tInherit binding information from the textures when building combined image samplers from separate textures and samplers.\n"
|
||||
@ -1279,7 +1281,7 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
|
||||
compiler->set_common_options(opts);
|
||||
|
||||
for (auto &fetch : args.glsl_ext_framebuffer_fetch)
|
||||
compiler->remap_ext_framebuffer_fetch(fetch.first, fetch.second);
|
||||
compiler->remap_ext_framebuffer_fetch(fetch.first, fetch.second, !args.glsl_ext_framebuffer_fetch_noncoherent);
|
||||
|
||||
// Set HLSL specific options.
|
||||
if (args.hlsl)
|
||||
@ -1469,6 +1471,9 @@ static int main_inner(int argc, char *argv[])
|
||||
uint32_t color_attachment = parser.next_uint();
|
||||
args.glsl_ext_framebuffer_fetch.push_back({ input_index, color_attachment });
|
||||
});
|
||||
cbs.add("--glsl-ext-framebuffer-fetch-noncoherent", [&args](CLIParser &) {
|
||||
args.glsl_ext_framebuffer_fetch_noncoherent = true;
|
||||
});
|
||||
cbs.add("--vulkan-glsl-disable-ext-samplerless-texture-functions",
|
||||
[&args](CLIParser &) { args.vulkan_glsl_disable_ext_samplerless_texture_functions = true; });
|
||||
cbs.add("--disable-storage-image-qualifier-deduction",
|
||||
|
@ -0,0 +1,18 @@
|
||||
#version 310 es
|
||||
#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require
|
||||
precision mediump float;
|
||||
precision highp int;
|
||||
|
||||
mediump vec4 uSubpass0;
|
||||
mediump vec4 uSubpass1;
|
||||
|
||||
layout(location = 0, noncoherent) inout vec3 FragColor;
|
||||
layout(location = 1, noncoherent) inout vec4 FragColor2;
|
||||
|
||||
void main()
|
||||
{
|
||||
uSubpass0.xyz = FragColor;
|
||||
uSubpass1 = FragColor2;
|
||||
FragColor = uSubpass0.xyz + uSubpass1.xyz;
|
||||
}
|
||||
|
@ -0,0 +1,16 @@
|
||||
#version 100
|
||||
#extension GL_EXT_shader_framebuffer_fetch_non_coherent : require
|
||||
#extension GL_EXT_draw_buffers : require
|
||||
precision mediump float;
|
||||
precision highp int;
|
||||
|
||||
mediump vec4 uSubpass0;
|
||||
mediump vec4 uSubpass1;
|
||||
|
||||
void main()
|
||||
{
|
||||
uSubpass0 = gl_LastFragData[0];
|
||||
uSubpass1 = gl_LastFragData[1];
|
||||
gl_FragData[0] = uSubpass0.xyz + uSubpass1.xyz;
|
||||
}
|
||||
|
@ -0,0 +1,12 @@
|
||||
#version 310 es
|
||||
precision mediump float;
|
||||
|
||||
layout(input_attachment_index = 0, set = 0, binding = 0) uniform mediump subpassInput uSubpass0;
|
||||
layout(input_attachment_index = 1, set = 0, binding = 1) uniform mediump subpassInput uSubpass1;
|
||||
layout(location = 0) out vec3 FragColor;
|
||||
layout(location = 1) out vec4 FragColor2;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor.rgb = subpassLoad(uSubpass0).rgb + subpassLoad(uSubpass1).rgb;
|
||||
}
|
@ -0,0 +1,12 @@
|
||||
#version 310 es
|
||||
precision mediump float;
|
||||
|
||||
layout(input_attachment_index = 0, set = 0, binding = 0) uniform mediump subpassInput uSubpass0;
|
||||
layout(input_attachment_index = 1, set = 0, binding = 1) uniform mediump subpassInput uSubpass1;
|
||||
layout(location = 0) out vec3 FragColor;
|
||||
layout(location = 1) out vec4 FragColor2;
|
||||
|
||||
void main()
|
||||
{
|
||||
FragColor.rgb = subpassLoad(uSubpass0).rgb + subpassLoad(uSubpass1).rgb;
|
||||
}
|
@ -359,10 +359,26 @@ void CompilerGLSL::remap_pls_variables()
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerGLSL::remap_ext_framebuffer_fetch(uint32_t input_attachment_index, uint32_t color_location)
|
||||
void CompilerGLSL::remap_ext_framebuffer_fetch(uint32_t input_attachment_index, uint32_t color_location, bool coherent)
|
||||
{
|
||||
subpass_to_framebuffer_fetch_attachment.push_back({ input_attachment_index, color_location });
|
||||
inout_color_attachments.insert(color_location);
|
||||
inout_color_attachments.push_back({ color_location, coherent });
|
||||
}
|
||||
|
||||
bool CompilerGLSL::location_is_framebuffer_fetch(uint32_t location) const
|
||||
{
|
||||
return std::find_if(begin(inout_color_attachments), end(inout_color_attachments),
|
||||
[&](const std::pair<uint32_t, bool> &elem) {
|
||||
return elem.first == location;
|
||||
}) != end(inout_color_attachments);
|
||||
}
|
||||
|
||||
bool CompilerGLSL::location_is_non_coherent_framebuffer_fetch(uint32_t location) const
|
||||
{
|
||||
return std::find_if(begin(inout_color_attachments), end(inout_color_attachments),
|
||||
[&](const std::pair<uint32_t, bool> &elem) {
|
||||
return elem.first == location && !elem.second;
|
||||
}) != end(inout_color_attachments);
|
||||
}
|
||||
|
||||
void CompilerGLSL::find_static_extensions()
|
||||
@ -484,7 +500,22 @@ void CompilerGLSL::find_static_extensions()
|
||||
SPIRV_CROSS_THROW("Can only use GL_EXT_shader_framebuffer_fetch in fragment shaders.");
|
||||
if (options.vulkan_semantics)
|
||||
SPIRV_CROSS_THROW("Cannot use EXT_shader_framebuffer_fetch in Vulkan GLSL.");
|
||||
require_extension_internal("GL_EXT_shader_framebuffer_fetch");
|
||||
|
||||
bool has_coherent = false;
|
||||
bool has_incoherent = false;
|
||||
|
||||
for (auto &att : inout_color_attachments)
|
||||
{
|
||||
if (att.second)
|
||||
has_coherent = true;
|
||||
else
|
||||
has_incoherent = true;
|
||||
}
|
||||
|
||||
if (has_coherent)
|
||||
require_extension_internal("GL_EXT_shader_framebuffer_fetch");
|
||||
if (has_incoherent)
|
||||
require_extension_internal("GL_EXT_shader_framebuffer_fetch_non_coherent");
|
||||
}
|
||||
|
||||
if (options.separate_shader_objects && !options.es && options.version < 410)
|
||||
@ -1693,6 +1724,12 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var)
|
||||
attr.push_back(join("location = ", get_decoration(var.self, DecorationLocation)));
|
||||
}
|
||||
|
||||
if (get_execution_model() == ExecutionModelFragment && var.storage == StorageClassOutput &&
|
||||
location_is_non_coherent_framebuffer_fetch(get_decoration(var.self, DecorationLocation)))
|
||||
{
|
||||
attr.push_back("noncoherent");
|
||||
}
|
||||
|
||||
// Transform feedback
|
||||
bool uses_enhanced_layouts = false;
|
||||
if (is_block && var.storage == StorageClassOutput)
|
||||
@ -2234,7 +2271,9 @@ const char *CompilerGLSL::to_storage_qualifiers_glsl(const SPIRVariable &var)
|
||||
return "varying "; // Fragment outputs are renamed so they never hit this case.
|
||||
else if (execution.model == ExecutionModelFragment && var.storage == StorageClassOutput)
|
||||
{
|
||||
if (inout_color_attachments.count(get_decoration(var.self, DecorationLocation)) != 0)
|
||||
uint32_t loc = get_decoration(var.self, DecorationLocation);
|
||||
bool is_inout = location_is_framebuffer_fetch(loc);
|
||||
if (is_inout)
|
||||
return "inout ";
|
||||
else
|
||||
return "out ";
|
||||
@ -3405,7 +3444,7 @@ void CompilerGLSL::emit_resources()
|
||||
|
||||
// Unused output I/O variables might still be required to implement framebuffer fetch.
|
||||
if (var.storage == StorageClassOutput && !is_legacy() &&
|
||||
inout_color_attachments.count(get_decoration(var.self, DecorationLocation)) != 0)
|
||||
location_is_framebuffer_fetch(get_decoration(var.self, DecorationLocation)) != 0)
|
||||
{
|
||||
is_hidden = false;
|
||||
}
|
||||
|
@ -178,7 +178,8 @@ public:
|
||||
|
||||
// Redirect a subpassInput reading from input_attachment_index to instead load its value from
|
||||
// the color attachment at location = color_location. Requires ESSL.
|
||||
void remap_ext_framebuffer_fetch(uint32_t input_attachment_index, uint32_t color_location);
|
||||
// If coherent, uses GL_EXT_shader_framebuffer_fetch, if not, uses noncoherent variant.
|
||||
void remap_ext_framebuffer_fetch(uint32_t input_attachment_index, uint32_t color_location, bool coherent);
|
||||
|
||||
explicit CompilerGLSL(std::vector<uint32_t> spirv_)
|
||||
: Compiler(std::move(spirv_))
|
||||
@ -858,7 +859,9 @@ protected:
|
||||
|
||||
// GL_EXT_shader_framebuffer_fetch support.
|
||||
std::vector<std::pair<uint32_t, uint32_t>> subpass_to_framebuffer_fetch_attachment;
|
||||
std::unordered_set<uint32_t> inout_color_attachments;
|
||||
std::vector<std::pair<uint32_t, bool>> inout_color_attachments;
|
||||
bool location_is_framebuffer_fetch(uint32_t location) const;
|
||||
bool location_is_non_coherent_framebuffer_fetch(uint32_t location) const;
|
||||
bool subpass_input_is_framebuffer_fetch(uint32_t id) const;
|
||||
void emit_inout_fragment_outputs_copy_to_subpass_inputs();
|
||||
const SPIRVariable *find_subpass_input_by_attachment_index(uint32_t index) const;
|
||||
|
@ -551,6 +551,8 @@ def cross_compile(shader, vulkan, spirv, invalid_spirv, eliminate, is_legacy, fl
|
||||
extra_args += ['--glsl-remap-ext-framebuffer-fetch', '1', '1']
|
||||
extra_args += ['--glsl-remap-ext-framebuffer-fetch', '2', '2']
|
||||
extra_args += ['--glsl-remap-ext-framebuffer-fetch', '3', '3']
|
||||
if '.framebuffer-fetch-noncoherent.' in shader:
|
||||
extra_args += ['--glsl-ext-framebuffer-fetch-noncoherent']
|
||||
if '.zero-initialize.' in shader:
|
||||
extra_args += ['--force-zero-initialized-variables']
|
||||
if '.force-flattened-io.' in shader:
|
||||
|
Loading…
Reference in New Issue
Block a user