diff options
author | Hans-Kristian Arntzen <post@arntzen-software.no> | 2021-05-07 13:28:08 +0300 |
---|---|---|
committer | Hans-Kristian Arntzen <post@arntzen-software.no> | 2021-05-07 13:59:47 +0300 |
commit | e47a30e807990c6fe1998c9c4f291d825f043557 (patch) | |
tree | d795231de807b3489b3b70dde421f9d3689ceb97 /spirv_glsl.cpp | |
parent | 0eeaffe048b91af45eb289b6934e222bf8ab8ae0 (diff) |
Honor NoContraction qualifier.
We'll need to force a temporary and mark it as precise.
MSL is a little weird here, but we can piggyback on top of the invariant
float math option here to force fma() operations everywhere.
Diffstat (limited to 'spirv_glsl.cpp')
-rw-r--r-- | spirv_glsl.cpp | 37 |
1 files changed, 23 insertions, 14 deletions
diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index f69034c9..a8d0925f 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -559,18 +559,19 @@ string CompilerGLSL::compile() { ir.fixup_reserved_names(); - if (options.vulkan_semantics) - backend.allow_precision_qualifiers = true; - else + if (!options.vulkan_semantics) { // only NV_gpu_shader5 supports divergent indexing on OpenGL, and it does so without extra qualifiers backend.nonuniform_qualifier = ""; backend.needs_row_major_load_workaround = true; } + backend.allow_precision_qualifiers = options.vulkan_semantics || options.es; backend.force_gl_in_out_block = true; backend.supports_extensions = true; backend.use_array_constructor = true; + backend.support_precise_qualifier = (!options.es && options.version >= 400) || (options.es && options.version >= 320); + if (is_legacy_es()) backend.support_case_fallthrough = false; @@ -5545,7 +5546,12 @@ void CompilerGLSL::emit_unary_op(uint32_t result_type, uint32_t result_id, uint3 void CompilerGLSL::emit_binary_op(uint32_t result_type, uint32_t result_id, uint32_t op0, uint32_t op1, const char *op) { - bool forward = should_forward(op0) && should_forward(op1); + // Various FP arithmetic opcodes such as add, sub, mul will hit this. + bool force_temporary_precise = backend.support_precise_qualifier && + has_decoration(result_id, DecorationNoContraction) && + type_is_floating_point(get<SPIRType>(result_type)); + bool forward = should_forward(op0) && should_forward(op1) && !force_temporary_precise; + emit_op(result_type, result_id, join(to_enclosed_unpacked_expression(op0), " ", op, " ", to_enclosed_unpacked_expression(op1)), forward); @@ -12728,7 +12734,7 @@ void CompilerGLSL::emit_struct_padding_target(const SPIRType &) { } -const char *CompilerGLSL::flags_to_qualifiers_glsl(const SPIRType &type, const Bitset &flags) +string CompilerGLSL::flags_to_qualifiers_glsl(const SPIRType &type, const Bitset &flags) { // GL_EXT_buffer_reference variables can be marked as restrict. if (flags.get(DecorationRestrictPointerEXT)) @@ -12740,6 +12746,11 @@ const char *CompilerGLSL::flags_to_qualifiers_glsl(const SPIRType &type, const B type.basetype != SPIRType::Sampler) return ""; + string qual; + + if (flags.get(DecorationNoContraction) && backend.support_precise_qualifier) + qual = "precise "; + if (options.es) { auto &execution = get_entry_point(); @@ -12754,7 +12765,7 @@ const char *CompilerGLSL::flags_to_qualifiers_glsl(const SPIRType &type, const B options.fragment.default_int_precision == Options::Mediump && execution.model == ExecutionModelFragment; - return implied_fmediump || implied_imediump ? "" : "mediump "; + qual += (implied_fmediump || implied_imediump) ? "" : "mediump "; } else { @@ -12768,7 +12779,7 @@ const char *CompilerGLSL::flags_to_qualifiers_glsl(const SPIRType &type, const B execution.model == ExecutionModelFragment) || (execution.model != ExecutionModelFragment)); - return implied_fhighp || implied_ihighp ? "" : "highp "; + qual += (implied_fhighp || implied_ihighp) ? "" : "highp "; } } else if (backend.allow_precision_qualifiers) @@ -12776,18 +12787,16 @@ const char *CompilerGLSL::flags_to_qualifiers_glsl(const SPIRType &type, const B // Vulkan GLSL supports precision qualifiers, even in desktop profiles, which is convenient. // The default is highp however, so only emit mediump in the rare case that a shader has these. if (flags.get(DecorationRelaxedPrecision)) - return "mediump "; - else - return ""; + qual += "mediump "; } - else - return ""; + + return qual; } -const char *CompilerGLSL::to_precision_qualifiers_glsl(uint32_t id) +string CompilerGLSL::to_precision_qualifiers_glsl(uint32_t id) { auto &type = expression_type(id); - bool use_precision_qualifiers = backend.allow_precision_qualifiers || options.es; + bool use_precision_qualifiers = backend.allow_precision_qualifiers; if (use_precision_qualifiers && (type.basetype == SPIRType::Image || type.basetype == SPIRType::SampledImage)) { // Force mediump for the sampler type. We cannot declare 16-bit or smaller image types. |