diff options
author | Hans-Kristian Arntzen <post@arntzen-software.no> | 2019-03-21 15:52:00 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-03-21 15:52:00 +0300 |
commit | 5dacfa9dc20d0380a67cd4f84dd17cfd8f96fd5d (patch) | |
tree | 47d6ff83956eb3abc2f932135a3320162357155e /spirv_glsl.cpp | |
parent | 1b00a6e48a4d9e1bd80bedc0e8243246f0a33a72 (diff) | |
parent | 0b20180537b620e210dc098991168a9b76e428d3 (diff) |
Merge pull request #898 from KhronosGroup/fix-897
GLSL: Fix some complex cases for loading arrays
Diffstat (limited to 'spirv_glsl.cpp')
-rw-r--r-- | spirv_glsl.cpp | 58 |
1 files changed, 58 insertions, 0 deletions
diff --git a/spirv_glsl.cpp b/spirv_glsl.cpp index e8260b1d..d04adae4 100644 --- a/spirv_glsl.cpp +++ b/spirv_glsl.cpp @@ -6909,6 +6909,11 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction) // We might need to bitcast in order to load from a builtin. bitcast_from_builtin_load(ptr, expr, get<SPIRType>(result_type)); + // We might be trying to load a gl_Position[N], where we should be + // doing float4[](gl_in[i].gl_Position, ...) instead. + // Similar workarounds are required for input arrays in tessellation. + unroll_array_from_complex_load(id, ptr, expr); + if (ptr_expression) ptr_expression->need_transpose = old_need_transpose; @@ -11041,6 +11046,59 @@ void CompilerGLSL::emit_array_copy(const string &lhs, uint32_t rhs_id) statement(lhs, " = ", to_expression(rhs_id), ";"); } +void CompilerGLSL::unroll_array_from_complex_load(uint32_t target_id, uint32_t source_id, std::string &expr) +{ + if (!backend.force_gl_in_out_block) + return; + // This path is only relevant for GL backends. + + auto *var = maybe_get<SPIRVariable>(source_id); + if (!var) + return; + + if (var->storage != StorageClassInput) + return; + + auto &type = get_variable_data_type(*var); + if (type.array.empty()) + return; + + auto builtin = BuiltIn(get_decoration(var->self, DecorationBuiltIn)); + bool is_builtin = is_builtin_variable(*var) && (builtin == BuiltInPointSize || builtin == BuiltInPosition); + bool is_tess = is_tessellation_shader(); + + // Tessellation input arrays are special in that they are unsized, so we cannot directly copy from it. + // We must unroll the array load. + // For builtins, we couldn't catch this case normally, + // because this is resolved in the OpAccessChain in most cases. + // If we load the entire array, we have no choice but to unroll here. + if (is_builtin || is_tess) + { + auto new_expr = join("_", target_id, "_unrolled"); + statement(variable_decl(type, new_expr, target_id), ";"); + string array_expr; + if (type.array_size_literal.front()) + { + array_expr = convert_to_string(type.array.front()); + if (type.array.front() == 0) + SPIRV_CROSS_THROW("Cannot unroll an array copy from unsized array."); + } + else + array_expr = to_expression(type.array.front()); + + // The array size might be a specialization constant, so use a for-loop instead. + statement("for (int i = 0; i < int(", array_expr, "); i++)"); + begin_scope(); + if (is_builtin) + statement(new_expr, "[i] = gl_in[i].", expr, ";"); + else + statement(new_expr, "[i] = ", expr, "[i];"); + end_scope(); + + expr = move(new_expr); + } +} + void CompilerGLSL::bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const spirv_cross::SPIRType &expr_type) { |