Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/KhronosGroup/SPIRV-Cross.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans-Kristian Arntzen <post@arntzen-software.no>2019-03-21 15:52:00 +0300
committerGitHub <noreply@github.com>2019-03-21 15:52:00 +0300
commit5dacfa9dc20d0380a67cd4f84dd17cfd8f96fd5d (patch)
tree47d6ff83956eb3abc2f932135a3320162357155e /spirv_glsl.cpp
parent1b00a6e48a4d9e1bd80bedc0e8243246f0a33a72 (diff)
parent0b20180537b620e210dc098991168a9b76e428d3 (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.cpp58
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)
{