MSL: Support more usecases for unpacked vectors.

Additional usecases include array and vector indexing, variable declarations,
loop initializers, function return values, switch statement evaluations,
and various specialized MSL operations.

Ultimately, we might consider refactoring CompilerMSL::to_expression()
to always take into consideration possible unpacking behavior.

Refactor CompilerGLSL::to_enclosed_unpacked_expression()
for conciseness and consistency with similar functionality.
This commit is contained in:
Bill Hollings 2021-10-21 16:11:33 -04:00
parent 345a7d171c
commit 974a0818b8
2 changed files with 24 additions and 38 deletions

View File

@ -4375,19 +4375,7 @@ string CompilerGLSL::to_unpacked_expression(uint32_t id, bool register_expressio
string CompilerGLSL::to_enclosed_unpacked_expression(uint32_t id, bool register_expression_read)
{
// If we need to transpose, it will also take care of unpacking rules.
auto *e = maybe_get<SPIRExpression>(id);
bool need_transpose = e && e->need_transpose;
bool is_remapped = has_extended_decoration(id, SPIRVCrossDecorationPhysicalTypeID);
bool is_packed = has_extended_decoration(id, SPIRVCrossDecorationPhysicalTypePacked);
if (!need_transpose && (is_remapped || is_packed))
{
return unpack_expression_type(to_expression(id, register_expression_read), expression_type(id),
get_extended_decoration(id, SPIRVCrossDecorationPhysicalTypeID),
has_extended_decoration(id, SPIRVCrossDecorationPhysicalTypePacked), false);
}
else
return to_enclosed_expression(id, register_expression_read);
return enclose_expression(to_unpacked_expression(id, register_expression_read));
}
string CompilerGLSL::to_dereferenced_expression(uint32_t id, bool register_expression_read)
@ -8541,7 +8529,7 @@ void CompilerGLSL::access_chain_internal_append_index(std::string &expr, uint32_
if (index_is_literal)
expr += convert_to_string(index);
else
expr += to_expression(index, register_expression_read);
expr += to_unpacked_expression(index, register_expression_read);
expr += "]";
}
@ -8805,7 +8793,7 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice
if (is_literal)
expr += convert_to_string(index);
else
expr += to_expression(index, register_expression_read);
expr += to_unpacked_expression(index, register_expression_read);
expr += "]";
type_id = type->parent_type;
@ -8887,7 +8875,7 @@ string CompilerGLSL::access_chain_internal(uint32_t base, const uint32_t *indice
else
{
expr += "[";
expr += to_expression(index, register_expression_read);
expr += to_unpacked_expression(index, register_expression_read);
expr += "]";
}
@ -13098,7 +13086,7 @@ string CompilerGLSL::argument_decl(const SPIRFunction::Parameter &arg)
string CompilerGLSL::to_initializer_expression(const SPIRVariable &var)
{
return to_expression(var.initializer);
return to_unpacked_expression(var.initializer);
}
string CompilerGLSL::to_zero_initialized_expression(uint32_t type_id)
@ -13146,7 +13134,7 @@ string CompilerGLSL::variable_decl(const SPIRVariable &variable)
{
uint32_t expr = variable.static_expression;
if (ir.ids[expr].get_type() != TypeUndef)
res += join(" = ", to_expression(variable.static_expression));
res += join(" = ", to_unpacked_expression(variable.static_expression));
else if (options.force_zero_initialized_variables && type_can_zero_initialize(type))
res += join(" = ", to_zero_initialized_expression(get_variable_data_type_id(variable)));
}
@ -14931,7 +14919,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
else
{
emit_block_hints(block);
statement("switch (", to_expression(block.condition), ")");
statement("switch (", to_unpacked_expression(block.condition), ")");
}
begin_scope();
@ -15067,7 +15055,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
{
// OpReturnValue can return Undef, so don't emit anything for this case.
if (ir.ids[block.return_value].get_type() != TypeUndef)
statement("return ", to_expression(block.return_value), ";");
statement("return ", to_unpacked_expression(block.return_value), ";");
}
}
else if (!cfg.node_terminates_control_flow_in_sub_graph(current_function->entry_block, block.self) ||
@ -15086,7 +15074,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block)
case SPIRBlock::Kill:
statement(backend.discard_literal, ";");
if (block.return_value)
statement("return ", to_expression(block.return_value), ";");
statement("return ", to_unpacked_expression(block.return_value), ";");
break;
case SPIRBlock::Unreachable:

View File

@ -8150,7 +8150,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
expr += "(";
for (uint32_t col = 0; col < type.columns; col++)
{
expr += to_enclosed_expression(a);
expr += to_enclosed_unpacked_expression(a);
expr += " * ";
expr += to_extract_component_expression(b, col);
if (col + 1 < type.columns)
@ -8255,19 +8255,19 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
auto &res_type = get<SPIRType>(type.member_types[1]);
if (opcode == OpIAddCarry)
{
statement(to_expression(result_id), ".", to_member_name(type, 0), " = ", to_enclosed_expression(op0), " + ",
to_enclosed_expression(op1), ";");
statement(to_expression(result_id), ".", to_member_name(type, 0), " = ",
to_enclosed_unpacked_expression(op0), " + ", to_enclosed_unpacked_expression(op1), ";");
statement(to_expression(result_id), ".", to_member_name(type, 1), " = select(", type_to_glsl(res_type),
"(1), ", type_to_glsl(res_type), "(0), ", to_expression(result_id), ".", to_member_name(type, 0),
" >= max(", to_expression(op0), ", ", to_expression(op1), "));");
"(1), ", type_to_glsl(res_type), "(0), ", to_unpacked_expression(result_id), ".", to_member_name(type, 0),
" >= max(", to_unpacked_expression(op0), ", ", to_unpacked_expression(op1), "));");
}
else
{
statement(to_expression(result_id), ".", to_member_name(type, 0), " = ", to_enclosed_expression(op0), " - ",
to_enclosed_expression(op1), ";");
statement(to_expression(result_id), ".", to_member_name(type, 0), " = ", to_enclosed_unpacked_expression(op0), " - ",
to_enclosed_unpacked_expression(op1), ";");
statement(to_expression(result_id), ".", to_member_name(type, 1), " = select(", type_to_glsl(res_type),
"(1), ", type_to_glsl(res_type), "(0), ", to_enclosed_expression(op0),
" >= ", to_enclosed_expression(op1), ");");
"(1), ", type_to_glsl(res_type), "(0), ", to_enclosed_unpacked_expression(op0),
" >= ", to_enclosed_unpacked_expression(op1), ");");
}
break;
}
@ -8282,10 +8282,10 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
auto &type = get<SPIRType>(result_type);
emit_uninitialized_temporary_expression(result_type, result_id);
statement(to_expression(result_id), ".", to_member_name(type, 0), " = ", to_enclosed_expression(op0), " * ",
to_enclosed_expression(op1), ";");
statement(to_expression(result_id), ".", to_member_name(type, 1), " = mulhi(", to_expression(op0), ", ",
to_expression(op1), ");");
statement(to_expression(result_id), ".", to_member_name(type, 0), " = ",
to_enclosed_unpacked_expression(op0), " * ", to_enclosed_unpacked_expression(op1), ";");
statement(to_expression(result_id), ".", to_member_name(type, 1), " = mulhi(",
to_unpacked_expression(op0), ", ", to_unpacked_expression(op1), ");");
break;
}
@ -8340,8 +8340,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
uint32_t id = ops[1];
uint32_t a = ops[2], b = ops[3];
bool forward = should_forward(a) && should_forward(b);
emit_op(result_type, id, join("int(short(", to_expression(a), ")) * int(short(", to_expression(b), "))"),
forward);
emit_op(result_type, id, join("int(short(", to_unpacked_expression(a), ")) * int(short(", to_unpacked_expression(b), "))"), forward);
inherit_expression_dependencies(id, a);
inherit_expression_dependencies(id, b);
break;
@ -8353,8 +8352,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
uint32_t id = ops[1];
uint32_t a = ops[2], b = ops[3];
bool forward = should_forward(a) && should_forward(b);
emit_op(result_type, id, join("uint(ushort(", to_expression(a), ")) * uint(ushort(", to_expression(b), "))"),
forward);
emit_op(result_type, id, join("uint(ushort(", to_unpacked_expression(a), ")) * uint(ushort(", to_unpacked_expression(b), "))"), forward);
inherit_expression_dependencies(id, a);
inherit_expression_dependencies(id, b);
break;