GLSL: implement transpose() in GLSL 1.10 / ES 1.00

This commit is contained in:
rdb 2020-11-05 17:09:33 +01:00
parent a20c768698
commit bf71994dae
5 changed files with 127 additions and 5 deletions

View File

@ -13,8 +13,17 @@ attribute vec4 Position;
mat4 SPIRV_Cross_workaround_load_row_major(mat4 wrap) { return wrap; }
void main()
mat4 SPIRV_Cross_Transpose(mat4 m)
{
gl_Position = (((SPIRV_Cross_workaround_load_row_major(_13.M) * (Position * _13.MVPRowMajor)) + (SPIRV_Cross_workaround_load_row_major(_13.M) * (SPIRV_Cross_workaround_load_row_major(_13.MVPColMajor) * Position))) + (SPIRV_Cross_workaround_load_row_major(_13.M) * (_13.MVPRowMajor * Position))) + (SPIRV_Cross_workaround_load_row_major(_13.M) * (Position * SPIRV_Cross_workaround_load_row_major(_13.MVPColMajor)));
return mat4(m[0][0], m[1][0], m[2][0], m[3][0], m[0][1], m[1][1], m[2][1], m[3][1], m[0][2], m[1][2], m[2][2], m[3][2], m[0][3], m[1][3], m[2][3], m[3][3]);
}
void main()
{
mat4 _55 = _13.MVPRowMajor;
mat4 _61 = SPIRV_Cross_workaround_load_row_major(_13.MVPColMajor);
mat4 _80 = SPIRV_Cross_Transpose(_13.MVPRowMajor) * 2.0;
mat4 _87 = SPIRV_Cross_Transpose(_61) * 2.0;
gl_Position = (((((((((((SPIRV_Cross_workaround_load_row_major(_13.M) * (Position * _13.MVPRowMajor)) + (SPIRV_Cross_workaround_load_row_major(_13.M) * (SPIRV_Cross_workaround_load_row_major(_13.MVPColMajor) * Position))) + (SPIRV_Cross_workaround_load_row_major(_13.M) * (_13.MVPRowMajor * Position))) + (SPIRV_Cross_workaround_load_row_major(_13.M) * (Position * SPIRV_Cross_workaround_load_row_major(_13.MVPColMajor)))) + (_55 * Position)) + (Position * _61)) + (Position * _55)) + (_61 * Position)) + (_80 * Position)) + (_87 * Position)) + (Position * _80)) + (Position * _87);
}

View File

@ -13,12 +13,25 @@ attribute vec4 Position;
mat4 SPIRV_Cross_workaround_load_row_major(mat4 wrap) { return wrap; }
mat4 SPIRV_Cross_Transpose(mat4 m)
{
return mat4(m[0][0], m[1][0], m[2][0], m[3][0], m[0][1], m[1][1], m[2][1], m[3][1], m[0][2], m[1][2], m[2][2], m[3][2], m[0][3], m[1][3], m[2][3], m[3][3]);
}
void main()
{
vec4 c0 = SPIRV_Cross_workaround_load_row_major(_13.M) * (Position * _13.MVPRowMajor);
vec4 c1 = SPIRV_Cross_workaround_load_row_major(_13.M) * (SPIRV_Cross_workaround_load_row_major(_13.MVPColMajor) * Position);
vec4 c2 = SPIRV_Cross_workaround_load_row_major(_13.M) * (_13.MVPRowMajor * Position);
vec4 c3 = SPIRV_Cross_workaround_load_row_major(_13.M) * (Position * SPIRV_Cross_workaround_load_row_major(_13.MVPColMajor));
gl_Position = ((c0 + c1) + c2) + c3;
vec4 c4 = _13.MVPRowMajor * Position;
vec4 c5 = Position * SPIRV_Cross_workaround_load_row_major(_13.MVPColMajor);
vec4 c6 = Position * _13.MVPRowMajor;
vec4 c7 = SPIRV_Cross_workaround_load_row_major(_13.MVPColMajor) * Position;
vec4 c8 = (SPIRV_Cross_Transpose(_13.MVPRowMajor) * 2.0) * Position;
vec4 c9 = (SPIRV_Cross_Transpose(SPIRV_Cross_workaround_load_row_major(_13.MVPColMajor)) * 2.0) * Position;
vec4 c10 = Position * (SPIRV_Cross_Transpose(_13.MVPRowMajor) * 2.0);
vec4 c11 = Position * (SPIRV_Cross_Transpose(SPIRV_Cross_workaround_load_row_major(_13.MVPColMajor)) * 2.0);
gl_Position = ((((((((((c0 + c1) + c2) + c3) + c4) + c5) + c6) + c7) + c8) + c9) + c10) + c11;
}

View File

@ -15,6 +15,18 @@ void main()
vec4 c1 = M * (MVPColMajor * Position);
vec4 c2 = M * (Position * MVPRowMajor);
vec4 c3 = M * (Position * MVPColMajor);
gl_Position = c0 + c1 + c2 + c3;
vec4 c4 = transpose(MVPRowMajor) * Position;
vec4 c5 = transpose(MVPColMajor) * Position;
vec4 c6 = Position * transpose(MVPRowMajor);
vec4 c7 = Position * transpose(MVPColMajor);
// Multiplying by scalar forces resolution of the transposition
vec4 c8 = (MVPRowMajor * 2.0) * Position;
vec4 c9 = (transpose(MVPColMajor) * 2.0) * Position;
vec4 c10 = Position * (MVPRowMajor * 2.0);
vec4 c11 = Position * (transpose(MVPColMajor) * 2.0);
gl_Position = c0 + c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8 + c9 + c10 + c11;
}

View File

@ -3814,6 +3814,33 @@ void CompilerGLSL::emit_extension_workarounds(spv::ExecutionModel model)
}
statement("");
}
if (requires_transpose_2x2)
{
statement("mat2 SPIRV_Cross_Transpose(mat2 m)");
begin_scope();
statement("return mat2(m[0][0], m[1][0], m[0][1], m[1][1]);");
end_scope();
statement("");
}
if (requires_transpose_3x3)
{
statement("mat3 SPIRV_Cross_Transpose(mat3 m)");
begin_scope();
statement("return mat3(m[0][0], m[1][0], m[2][0], m[0][1], m[1][1], m[2][1], m[0][2], m[1][2], m[2][2]);");
end_scope();
statement("");
}
if (requires_transpose_4x4)
{
statement("mat4 SPIRV_Cross_Transpose(mat4 m)");
begin_scope();
statement("return mat4(m[0][0], m[1][0], m[2][0], m[3][0], m[0][1], m[1][1], m[2][1], m[3][1], m[0][2], m[1][2], m[2][2], m[3][2], m[0][3], m[1][3], m[2][3], m[3][3]);");
end_scope();
statement("");
}
}
// Returns a string representation of the ID, usable as a function arg.
@ -10265,7 +10292,32 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
break;
case OpTranspose:
GLSL_UFOP(transpose);
if (options.version < 120) // Matches GLSL 1.10 / ESSL 1.00
{
// transpose() is not available, so instead, flip need_transpose,
// which can later be turned into an emulated transpose op by
// convert_row_major_matrix(), if necessary.
uint32_t result_type = ops[0];
uint32_t result_id = ops[1];
uint32_t input = ops[2];
// Force need_transpose to false temporarily to prevent
// to_expression() from doing the transpose.
bool need_transpose = false;
auto *input_e = maybe_get<SPIRExpression>(input);
if (input_e)
swap(need_transpose, input_e->need_transpose);
bool forward = should_forward(input);
auto &e = emit_op(result_type, result_id, to_expression(input), forward);
e.need_transpose = !need_transpose;
// Restore the old need_transpose flag.
if (input_e)
input_e->need_transpose = need_transpose;
}
else
GLSL_UFOP(transpose);
break;
case OpSRem:
@ -12140,6 +12192,38 @@ string CompilerGLSL::convert_row_major_matrix(string exp_str, const SPIRType &ex
transposed_expr += ")";
return transposed_expr;
}
else if (options.version < 120)
{
// GLSL 110, ES 100 do not have transpose(), so emulate it. Note that
// these GLSL versions do not support non-square matrices.
if (exp_type.vecsize == 2 && exp_type.columns == 2)
{
if (!requires_transpose_2x2)
{
requires_transpose_2x2 = true;
force_recompile();
}
}
else if (exp_type.vecsize == 3 && exp_type.columns == 3)
{
if (!requires_transpose_3x3)
{
requires_transpose_3x3 = true;
force_recompile();
}
}
else if (exp_type.vecsize == 4 && exp_type.columns == 4)
{
if (!requires_transpose_4x4)
{
requires_transpose_4x4 = true;
force_recompile();
}
}
else
SPIRV_CROSS_THROW("Non-square matrices are not supported in legacy GLSL, cannot transpose.");
return join("SPIRV_Cross_Transpose(", exp_str, ")");
}
else
return join("transpose(", exp_str, ")");
}

View File

@ -806,6 +806,10 @@ protected:
return !options.es && options.version < 130;
}
bool requires_transpose_2x2 = false;
bool requires_transpose_3x3 = false;
bool requires_transpose_4x4 = false;
bool args_will_forward(uint32_t id, const uint32_t *args, uint32_t num_args, bool pure);
void register_call_out_argument(uint32_t id);
void register_impure_function_call();