@@ -5054,10 +5054,10 @@ void CompilerGLSL::emit_polyfills(uint32_t polyfills, bool relaxed)
50545054// Returns a string representation of the ID, usable as a function arg.
50555055// Default is to simply return the expression representation fo the arg ID.
50565056// Subclasses may override to modify the return value.
5057- string CompilerGLSL::to_func_call_arg(const SPIRFunction::Parameter &, uint32_t id)
5057+ string CompilerGLSL::to_func_call_arg(const SPIRFunction::Parameter &arg , uint32_t id)
50585058{
50595059 // BDA expects pointers through function interface.
5060- if (is_physical_pointer (expression_type(id)))
5060+ if (!arg.alias_global_variable && is_physical_or_buffer_pointer (expression_type(id)))
50615061 return to_pointer_expression(id);
50625062
50635063 // Make sure that we use the name of the original variable, and not the parameter alias.
@@ -6899,6 +6899,16 @@ void CompilerGLSL::emit_uninitialized_temporary(uint32_t result_type, uint32_t r
68996899 }
69006900}
69016901
6902+ bool CompilerGLSL::can_declare_inline_temporary(uint32_t id) const
6903+ {
6904+ if (!block_temporary_hoisting && current_continue_block && !hoisted_temporaries.count(id))
6905+ return false;
6906+ if (hoisted_temporaries.count(id))
6907+ return false;
6908+
6909+ return true;
6910+ }
6911+
69026912string CompilerGLSL::declare_temporary(uint32_t result_type, uint32_t result_id)
69036913{
69046914 auto &type = get<SPIRType>(result_type);
@@ -6976,6 +6986,42 @@ SPIRExpression &CompilerGLSL::emit_op(uint32_t result_type, uint32_t result_id,
69766986 }
69776987}
69786988
6989+ void CompilerGLSL::emit_transposed_op(uint32_t result_type, uint32_t result_id, const string &rhs, bool forwarding)
6990+ {
6991+ if (forwarding && (forced_temporaries.find(result_id) == end(forced_temporaries)))
6992+ {
6993+ // Just forward it without temporary.
6994+ // If the forward is trivial, we do not force flushing to temporary for this expression.
6995+ forwarded_temporaries.insert(result_id);
6996+ auto &e = set<SPIRExpression>(result_id, rhs, result_type, true);
6997+ e.need_transpose = true;
6998+ }
6999+ else if (can_declare_inline_temporary(result_id))
7000+ {
7001+ // If expression isn't immutable, bind it to a temporary and make the new temporary immutable (they always are).
7002+ // Since the expression is transposed, we have to ensure the temporary is the transposed type.
7003+
7004+ auto &transposed_type_id = extra_sub_expressions[result_id];
7005+ if (!transposed_type_id)
7006+ {
7007+ auto dummy_type = get<SPIRType>(result_type);
7008+ std::swap(dummy_type.columns, dummy_type.vecsize);
7009+ transposed_type_id = ir.increase_bound_by(1);
7010+ set<SPIRType>(transposed_type_id, dummy_type);
7011+ }
7012+
7013+ statement(declare_temporary(transposed_type_id, result_id), rhs, ";");
7014+ auto &e = set<SPIRExpression>(result_id, to_name(result_id), result_type, true);
7015+ e.need_transpose = true;
7016+ }
7017+ else
7018+ {
7019+ // If we cannot declare the temporary because it's already been hoisted, we don't have the
7020+ // chance to override the temporary type ourselves. Just transpose() the expression.
7021+ emit_op(result_type, result_id, join("transpose(", rhs, ")"), forwarding);
7022+ }
7023+ }
7024+
69797025void CompilerGLSL::emit_unary_op(uint32_t result_type, uint32_t result_id, uint32_t op0, const char *op)
69807026{
69817027 bool forward = should_forward(op0);
@@ -11586,7 +11632,7 @@ bool CompilerGLSL::should_dereference(uint32_t id)
1158611632 // If id is a variable but not a phi variable, we should not dereference it.
1158711633 // BDA passed around as parameters are always pointers.
1158811634 if (auto *var = maybe_get<SPIRVariable>(id))
11589- return (var->parameter && is_physical_pointer (type)) || var->phi_variable;
11635+ return (var->parameter && is_physical_or_buffer_pointer (type)) || var->phi_variable;
1159011636
1159111637 if (auto *expr = maybe_get<SPIRExpression>(id))
1159211638 {
@@ -11622,8 +11668,8 @@ bool CompilerGLSL::should_dereference(uint32_t id)
1162211668bool CompilerGLSL::should_dereference_caller_param(uint32_t id)
1162311669{
1162411670 const auto &type = expression_type(id);
11625- // BDA is always passed around as pointers.
11626- if (is_physical_pointer (type))
11671+ // BDA is always passed around as pointers. Similarly, we need to pass variable buffer pointers as pointers.
11672+ if (is_physical_or_buffer_pointer (type))
1162711673 return false;
1162811674
1162911675 return should_dereference(id);
@@ -13512,8 +13558,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
1351213558 auto expr = join(enclose_expression(to_unpacked_row_major_matrix_expression(ops[3])), " * ",
1351313559 enclose_expression(to_unpacked_row_major_matrix_expression(ops[2])));
1351413560 bool forward = should_forward(ops[2]) && should_forward(ops[3]);
13515- auto &e = emit_op(ops[0], ops[1], expr, forward);
13516- e.need_transpose = true;
13561+ emit_transposed_op(ops[0], ops[1], expr, forward);
1351713562 a->need_transpose = true;
1351813563 b->need_transpose = true;
1351913564 inherit_expression_dependencies(ops[1], ops[2]);
@@ -13536,8 +13581,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
1353613581 auto expr = join(enclose_expression(to_unpacked_row_major_matrix_expression(ops[2])), " * ",
1353713582 to_enclosed_unpacked_expression(ops[3]));
1353813583 bool forward = should_forward(ops[2]) && should_forward(ops[3]);
13539- auto &e = emit_op(ops[0], ops[1], expr, forward);
13540- e.need_transpose = true;
13584+ emit_transposed_op(ops[0], ops[1], expr, forward);
1354113585 a->need_transpose = true;
1354213586 inherit_expression_dependencies(ops[1], ops[2]);
1354313587 inherit_expression_dependencies(ops[1], ops[3]);
0 commit comments