Implement access chain flattening support for row major matrices

We currently only support access chains that end in a matrix by propagating
"needs transpose" flag upstream which flips the matrix multiplication order.

It's possible to support indexed extraction as well, however it would have to
generate code like this:

    vec4 row = vec4(UBO[0].y, UBO[1].y, UBO[2].y, UBO[3].y);

for a column equivalent of:

    vec4 row = UBO[1];

It is definitely possible to do so but it requires signaling the vector output
that it needs to switch to per-component extraction which is a bit more trouble
than this is worth for now.
This commit is contained in:
Arseny Kapoulkine 2017-01-17 18:10:28 -08:00
Родитель 1ec6c1a029
Коммит 62b27f1d81
4 изменённых файлов: 36 добавлений и 11 удалений

Просмотреть файл

@ -0,0 +1,10 @@
#version 310 es
uniform vec4 UBO[8];
in vec4 aVertex;
void main()
{
gl_Position = (mat4(UBO[0], UBO[1], UBO[2], UBO[3]) * aVertex) + (aVertex * mat4(UBO[4], UBO[5], UBO[6], UBO[7]));
}

Просмотреть файл

@ -0,0 +1,14 @@
#version 310 es
layout(std140) uniform UBO
{
layout(column_major) mat4 uMVPR;
layout(row_major) mat4 uMVPC;
};
in vec4 aVertex;
void main()
{
gl_Position = uMVPR * aVertex + uMVPC * aVertex;
}

Просмотреть файл

@ -3295,7 +3295,7 @@ string CompilerGLSL::access_chain(uint32_t base, const uint32_t *indices, uint32
if (flattened_buffer_blocks.count(base))
{
if (need_transpose)
*need_transpose = false;
flattened_access_chain_offset(base, indices, count, 0, need_transpose);
return flattened_access_chain(base, indices, count, target_type, 0);
}
@ -3393,7 +3393,7 @@ std::string CompilerGLSL::flattened_access_chain_vector_scalar(uint32_t base, co
return expr;
}
std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(uint32_t base, const uint32_t *indices, uint32_t count, uint32_t offset)
std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(uint32_t base, const uint32_t *indices, uint32_t count, uint32_t offset, bool *need_transpose)
{
const auto *type = &expression_type(base);
uint32_t type_size = 0;
@ -3402,6 +3402,7 @@ std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(uin
SPIRType temp;
std::string expr;
bool row_major_matrix_needs_conversion = false;
for (uint32_t i = 0; i < count; i++)
{
@ -3443,11 +3444,15 @@ std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(uin
offset += type_struct_member_offset(*type, index);
type_size = uint32_t(get_declared_struct_member_size(*type, index));
row_major_matrix_needs_conversion = (combined_decoration_for_member(*type, index) & (1ull << DecorationRowMajor)) != 0;
type = &get<SPIRType>(type->member_types[index]);
}
// Matrix -> Vector
else if (type->columns > 1)
{
if (row_major_matrix_needs_conversion)
SPIRV_CROSS_THROW("Matrix indexing is not supported for flattened row major matrices!");
if (ids[index].get_type() != TypeConstant)
SPIRV_CROSS_THROW("Cannot flatten dynamic matrix indexing!");
@ -3481,6 +3486,9 @@ std::pair<std::string, uint32_t> CompilerGLSL::flattened_access_chain_offset(uin
SPIRV_CROSS_THROW("Cannot subdivide a scalar value!");
}
if (need_transpose)
*need_transpose = row_major_matrix_needs_conversion;
return std::make_pair(expr, offset);
}
@ -5642,13 +5650,6 @@ void CompilerGLSL::flatten_buffer_block(uint32_t id)
if (type.member_types.empty())
SPIRV_CROSS_THROW(name + " is an empty struct.");
uint64_t member_flags = 0;
for (uint32_t i = 0; i < type.member_types.size(); i++)
member_flags |= combined_decoration_for_member(type, i);
if (member_flags & (1ull << DecorationRowMajor))
SPIRV_CROSS_THROW(name + " uses row major matrices which is not supported.");
flattened_buffer_blocks.insert(id);
}

Просмотреть файл

@ -315,13 +315,13 @@ protected:
bool suppress_usage_tracking = false);
std::string access_chain(uint32_t base, const uint32_t *indices, uint32_t count, bool index_is_literal,
bool chain_only = false, bool *need_transpose = nullptr);
std::string access_chain(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, bool *need_transpose);
std::string access_chain(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, bool *need_transpose = nullptr);
std::string flattened_access_chain(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset);
std::string flattened_access_chain_struct(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset);
std::string flattened_access_chain_matrix(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset);
std::string flattened_access_chain_vector_scalar(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type, uint32_t offset);
std::pair<std::string, uint32_t> flattened_access_chain_offset(uint32_t base, const uint32_t *indices, uint32_t count, uint32_t offset);
std::pair<std::string, uint32_t> flattened_access_chain_offset(uint32_t base, const uint32_t *indices, uint32_t count, uint32_t offset, bool *need_transpose = nullptr);
const char *index_to_swizzle(uint32_t index);
std::string remap_swizzle(uint32_t result_type, uint32_t input_components, uint32_t expr);