GLSL: implement transpose() in GLSL 1.10 / ES 1.00
This commit is contained in:
parent
a20c768698
commit
bf71994dae
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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, ")");
|
||||
}
|
||||
|
@ -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();
|
||||
|
Loading…
Reference in New Issue
Block a user