Implement MatrixInverse on HLSL.
Copy-paste implementation from MSL. I assume it's correct.
This commit is contained in:
parent
6066fe486e
commit
b380a2113a
122
reference/opt/shaders-hlsl/comp/inverse.comp
Normal file
122
reference/opt/shaders-hlsl/comp/inverse.comp
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
RWByteAddressBuffer _15 : register(u0);
|
||||||
|
ByteAddressBuffer _20 : register(t1);
|
||||||
|
|
||||||
|
// Returns the inverse of a matrix, by using the algorithm of calculating the classical
|
||||||
|
// adjoint and dividing by the determinant. The contents of the matrix are changed.
|
||||||
|
float2x2 SPIRV_Cross_Inverse(float2x2 m)
|
||||||
|
{
|
||||||
|
float2x2 adj; // The adjoint matrix (inverse after dividing by determinant)
|
||||||
|
|
||||||
|
// Create the transpose of the cofactors, as the classical adjoint of the matrix.
|
||||||
|
adj[0][0] = m[1][1];
|
||||||
|
adj[0][1] = -m[0][1];
|
||||||
|
|
||||||
|
adj[1][0] = -m[1][0];
|
||||||
|
adj[1][1] = m[0][0];
|
||||||
|
|
||||||
|
// Calculate the determinant as a combination of the cofactors of the first row.
|
||||||
|
float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]);
|
||||||
|
|
||||||
|
// Divide the classical adjoint matrix by the determinant.
|
||||||
|
// If determinant is zero, matrix is not invertable, so leave it unchanged.
|
||||||
|
return (det != 0.0f) ? (adj * (1.0f / det)) : m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the determinant of a 2x2 matrix.
|
||||||
|
float SPIRV_Cross_Det2x2(float a1, float a2, float b1, float b2)
|
||||||
|
{
|
||||||
|
return a1 * b2 - b1 * a2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the inverse of a matrix, by using the algorithm of calculating the classical
|
||||||
|
// adjoint and dividing by the determinant. The contents of the matrix are changed.
|
||||||
|
float3x3 SPIRV_Cross_Inverse(float3x3 m)
|
||||||
|
{
|
||||||
|
float3x3 adj; // The adjoint matrix (inverse after dividing by determinant)
|
||||||
|
|
||||||
|
// Create the transpose of the cofactors, as the classical adjoint of the matrix.
|
||||||
|
adj[0][0] = SPIRV_Cross_Det2x2(m[1][1], m[1][2], m[2][1], m[2][2]);
|
||||||
|
adj[0][1] = -SPIRV_Cross_Det2x2(m[0][1], m[0][2], m[2][1], m[2][2]);
|
||||||
|
adj[0][2] = SPIRV_Cross_Det2x2(m[0][1], m[0][2], m[1][1], m[1][2]);
|
||||||
|
|
||||||
|
adj[1][0] = -SPIRV_Cross_Det2x2(m[1][0], m[1][2], m[2][0], m[2][2]);
|
||||||
|
adj[1][1] = SPIRV_Cross_Det2x2(m[0][0], m[0][2], m[2][0], m[2][2]);
|
||||||
|
adj[1][2] = -SPIRV_Cross_Det2x2(m[0][0], m[0][2], m[1][0], m[1][2]);
|
||||||
|
|
||||||
|
adj[2][0] = SPIRV_Cross_Det2x2(m[1][0], m[1][1], m[2][0], m[2][1]);
|
||||||
|
adj[2][1] = -SPIRV_Cross_Det2x2(m[0][0], m[0][1], m[2][0], m[2][1]);
|
||||||
|
adj[2][2] = SPIRV_Cross_Det2x2(m[0][0], m[0][1], m[1][0], m[1][1]);
|
||||||
|
|
||||||
|
// Calculate the determinant as a combination of the cofactors of the first row.
|
||||||
|
float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]);
|
||||||
|
|
||||||
|
// Divide the classical adjoint matrix by the determinant.
|
||||||
|
// If determinant is zero, matrix is not invertable, so leave it unchanged.
|
||||||
|
return (det != 0.0f) ? (adj * (1.0f / det)) : m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the determinant of a 3x3 matrix.
|
||||||
|
float SPIRV_Cross_Det3x3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3)
|
||||||
|
{
|
||||||
|
return a1 * SPIRV_Cross_Det2x2(b2, b3, c2, c3) - b1 * SPIRV_Cross_Det2x2(a2, a3, c2, c3) + c1 * SPIRV_Cross_Det2x2(a2, a3, b2, b3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the inverse of a matrix, by using the algorithm of calculating the classical
|
||||||
|
// adjoint and dividing by the determinant. The contents of the matrix are changed.
|
||||||
|
float4x4 SPIRV_Cross_Inverse(float4x4 m)
|
||||||
|
{
|
||||||
|
float4x4 adj; // The adjoint matrix (inverse after dividing by determinant)
|
||||||
|
|
||||||
|
// Create the transpose of the cofactors, as the classical adjoint of the matrix.
|
||||||
|
adj[0][0] = SPIRV_Cross_Det3x3(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]);
|
||||||
|
adj[0][1] = -SPIRV_Cross_Det3x3(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]);
|
||||||
|
adj[0][2] = SPIRV_Cross_Det3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[3][1], m[3][2], m[3][3]);
|
||||||
|
adj[0][3] = -SPIRV_Cross_Det3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3]);
|
||||||
|
|
||||||
|
adj[1][0] = -SPIRV_Cross_Det3x3(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]);
|
||||||
|
adj[1][1] = SPIRV_Cross_Det3x3(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]);
|
||||||
|
adj[1][2] = -SPIRV_Cross_Det3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[3][0], m[3][2], m[3][3]);
|
||||||
|
adj[1][3] = SPIRV_Cross_Det3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3]);
|
||||||
|
|
||||||
|
adj[2][0] = SPIRV_Cross_Det3x3(m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]);
|
||||||
|
adj[2][1] = -SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]);
|
||||||
|
adj[2][2] = SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[3][0], m[3][1], m[3][3]);
|
||||||
|
adj[2][3] = -SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3]);
|
||||||
|
|
||||||
|
adj[3][0] = -SPIRV_Cross_Det3x3(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]);
|
||||||
|
adj[3][1] = SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]);
|
||||||
|
adj[3][2] = -SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[3][0], m[3][1], m[3][2]);
|
||||||
|
adj[3][3] = SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2]);
|
||||||
|
|
||||||
|
// Calculate the determinant as a combination of the cofactors of the first row.
|
||||||
|
float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]) + (adj[0][3] * m[3][0]);
|
||||||
|
|
||||||
|
// Divide the classical adjoint matrix by the determinant.
|
||||||
|
// If determinant is zero, matrix is not invertable, so leave it unchanged.
|
||||||
|
return (det != 0.0f) ? (adj * (1.0f / det)) : m;
|
||||||
|
}
|
||||||
|
|
||||||
|
void comp_main()
|
||||||
|
{
|
||||||
|
float2x2 _23 = asfloat(uint2x2(_20.Load2(0), _20.Load2(8)));
|
||||||
|
float2x2 _24 = SPIRV_Cross_Inverse(_23);
|
||||||
|
_15.Store2(0, asuint(_24[0]));
|
||||||
|
_15.Store2(8, asuint(_24[1]));
|
||||||
|
float3x3 _29 = asfloat(uint3x3(_20.Load3(16), _20.Load3(32), _20.Load3(48)));
|
||||||
|
float3x3 _30 = SPIRV_Cross_Inverse(_29);
|
||||||
|
_15.Store3(16, asuint(_30[0]));
|
||||||
|
_15.Store3(32, asuint(_30[1]));
|
||||||
|
_15.Store3(48, asuint(_30[2]));
|
||||||
|
float4x4 _35 = asfloat(uint4x4(_20.Load4(64), _20.Load4(80), _20.Load4(96), _20.Load4(112)));
|
||||||
|
float4x4 _36 = SPIRV_Cross_Inverse(_35);
|
||||||
|
_15.Store4(64, asuint(_36[0]));
|
||||||
|
_15.Store4(80, asuint(_36[1]));
|
||||||
|
_15.Store4(96, asuint(_36[2]));
|
||||||
|
_15.Store4(112, asuint(_36[3]));
|
||||||
|
}
|
||||||
|
|
||||||
|
[numthreads(1, 1, 1)]
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
comp_main();
|
||||||
|
}
|
122
reference/shaders-hlsl/comp/inverse.comp
Normal file
122
reference/shaders-hlsl/comp/inverse.comp
Normal file
@ -0,0 +1,122 @@
|
|||||||
|
RWByteAddressBuffer _15 : register(u0);
|
||||||
|
ByteAddressBuffer _20 : register(t1);
|
||||||
|
|
||||||
|
// Returns the inverse of a matrix, by using the algorithm of calculating the classical
|
||||||
|
// adjoint and dividing by the determinant. The contents of the matrix are changed.
|
||||||
|
float2x2 SPIRV_Cross_Inverse(float2x2 m)
|
||||||
|
{
|
||||||
|
float2x2 adj; // The adjoint matrix (inverse after dividing by determinant)
|
||||||
|
|
||||||
|
// Create the transpose of the cofactors, as the classical adjoint of the matrix.
|
||||||
|
adj[0][0] = m[1][1];
|
||||||
|
adj[0][1] = -m[0][1];
|
||||||
|
|
||||||
|
adj[1][0] = -m[1][0];
|
||||||
|
adj[1][1] = m[0][0];
|
||||||
|
|
||||||
|
// Calculate the determinant as a combination of the cofactors of the first row.
|
||||||
|
float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]);
|
||||||
|
|
||||||
|
// Divide the classical adjoint matrix by the determinant.
|
||||||
|
// If determinant is zero, matrix is not invertable, so leave it unchanged.
|
||||||
|
return (det != 0.0f) ? (adj * (1.0f / det)) : m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the determinant of a 2x2 matrix.
|
||||||
|
float SPIRV_Cross_Det2x2(float a1, float a2, float b1, float b2)
|
||||||
|
{
|
||||||
|
return a1 * b2 - b1 * a2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the inverse of a matrix, by using the algorithm of calculating the classical
|
||||||
|
// adjoint and dividing by the determinant. The contents of the matrix are changed.
|
||||||
|
float3x3 SPIRV_Cross_Inverse(float3x3 m)
|
||||||
|
{
|
||||||
|
float3x3 adj; // The adjoint matrix (inverse after dividing by determinant)
|
||||||
|
|
||||||
|
// Create the transpose of the cofactors, as the classical adjoint of the matrix.
|
||||||
|
adj[0][0] = SPIRV_Cross_Det2x2(m[1][1], m[1][2], m[2][1], m[2][2]);
|
||||||
|
adj[0][1] = -SPIRV_Cross_Det2x2(m[0][1], m[0][2], m[2][1], m[2][2]);
|
||||||
|
adj[0][2] = SPIRV_Cross_Det2x2(m[0][1], m[0][2], m[1][1], m[1][2]);
|
||||||
|
|
||||||
|
adj[1][0] = -SPIRV_Cross_Det2x2(m[1][0], m[1][2], m[2][0], m[2][2]);
|
||||||
|
adj[1][1] = SPIRV_Cross_Det2x2(m[0][0], m[0][2], m[2][0], m[2][2]);
|
||||||
|
adj[1][2] = -SPIRV_Cross_Det2x2(m[0][0], m[0][2], m[1][0], m[1][2]);
|
||||||
|
|
||||||
|
adj[2][0] = SPIRV_Cross_Det2x2(m[1][0], m[1][1], m[2][0], m[2][1]);
|
||||||
|
adj[2][1] = -SPIRV_Cross_Det2x2(m[0][0], m[0][1], m[2][0], m[2][1]);
|
||||||
|
adj[2][2] = SPIRV_Cross_Det2x2(m[0][0], m[0][1], m[1][0], m[1][1]);
|
||||||
|
|
||||||
|
// Calculate the determinant as a combination of the cofactors of the first row.
|
||||||
|
float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]);
|
||||||
|
|
||||||
|
// Divide the classical adjoint matrix by the determinant.
|
||||||
|
// If determinant is zero, matrix is not invertable, so leave it unchanged.
|
||||||
|
return (det != 0.0f) ? (adj * (1.0f / det)) : m;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the determinant of a 3x3 matrix.
|
||||||
|
float SPIRV_Cross_Det3x3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, float c2, float c3)
|
||||||
|
{
|
||||||
|
return a1 * SPIRV_Cross_Det2x2(b2, b3, c2, c3) - b1 * SPIRV_Cross_Det2x2(a2, a3, c2, c3) + c1 * SPIRV_Cross_Det2x2(a2, a3, b2, b3);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the inverse of a matrix, by using the algorithm of calculating the classical
|
||||||
|
// adjoint and dividing by the determinant. The contents of the matrix are changed.
|
||||||
|
float4x4 SPIRV_Cross_Inverse(float4x4 m)
|
||||||
|
{
|
||||||
|
float4x4 adj; // The adjoint matrix (inverse after dividing by determinant)
|
||||||
|
|
||||||
|
// Create the transpose of the cofactors, as the classical adjoint of the matrix.
|
||||||
|
adj[0][0] = SPIRV_Cross_Det3x3(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]);
|
||||||
|
adj[0][1] = -SPIRV_Cross_Det3x3(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], m[3][3]);
|
||||||
|
adj[0][2] = SPIRV_Cross_Det3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[3][1], m[3][2], m[3][3]);
|
||||||
|
adj[0][3] = -SPIRV_Cross_Det3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3]);
|
||||||
|
|
||||||
|
adj[1][0] = -SPIRV_Cross_Det3x3(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]);
|
||||||
|
adj[1][1] = SPIRV_Cross_Det3x3(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], m[3][3]);
|
||||||
|
adj[1][2] = -SPIRV_Cross_Det3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[3][0], m[3][2], m[3][3]);
|
||||||
|
adj[1][3] = SPIRV_Cross_Det3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3]);
|
||||||
|
|
||||||
|
adj[2][0] = SPIRV_Cross_Det3x3(m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]);
|
||||||
|
adj[2][1] = -SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], m[3][3]);
|
||||||
|
adj[2][2] = SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[3][0], m[3][1], m[3][3]);
|
||||||
|
adj[2][3] = -SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3]);
|
||||||
|
|
||||||
|
adj[3][0] = -SPIRV_Cross_Det3x3(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]);
|
||||||
|
adj[3][1] = SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], m[3][2]);
|
||||||
|
adj[3][2] = -SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[3][0], m[3][1], m[3][2]);
|
||||||
|
adj[3][3] = SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2]);
|
||||||
|
|
||||||
|
// Calculate the determinant as a combination of the cofactors of the first row.
|
||||||
|
float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]) + (adj[0][3] * m[3][0]);
|
||||||
|
|
||||||
|
// Divide the classical adjoint matrix by the determinant.
|
||||||
|
// If determinant is zero, matrix is not invertable, so leave it unchanged.
|
||||||
|
return (det != 0.0f) ? (adj * (1.0f / det)) : m;
|
||||||
|
}
|
||||||
|
|
||||||
|
void comp_main()
|
||||||
|
{
|
||||||
|
float2x2 _23 = asfloat(uint2x2(_20.Load2(0), _20.Load2(8)));
|
||||||
|
float2x2 _24 = SPIRV_Cross_Inverse(_23);
|
||||||
|
_15.Store2(0, asuint(_24[0]));
|
||||||
|
_15.Store2(8, asuint(_24[1]));
|
||||||
|
float3x3 _29 = asfloat(uint3x3(_20.Load3(16), _20.Load3(32), _20.Load3(48)));
|
||||||
|
float3x3 _30 = SPIRV_Cross_Inverse(_29);
|
||||||
|
_15.Store3(16, asuint(_30[0]));
|
||||||
|
_15.Store3(32, asuint(_30[1]));
|
||||||
|
_15.Store3(48, asuint(_30[2]));
|
||||||
|
float4x4 _35 = asfloat(uint4x4(_20.Load4(64), _20.Load4(80), _20.Load4(96), _20.Load4(112)));
|
||||||
|
float4x4 _36 = SPIRV_Cross_Inverse(_35);
|
||||||
|
_15.Store4(64, asuint(_36[0]));
|
||||||
|
_15.Store4(80, asuint(_36[1]));
|
||||||
|
_15.Store4(96, asuint(_36[2]));
|
||||||
|
_15.Store4(112, asuint(_36[3]));
|
||||||
|
}
|
||||||
|
|
||||||
|
[numthreads(1, 1, 1)]
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
comp_main();
|
||||||
|
}
|
23
shaders-hlsl/comp/inverse.comp
Normal file
23
shaders-hlsl/comp/inverse.comp
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#version 450
|
||||||
|
layout(local_size_x = 1) in;
|
||||||
|
|
||||||
|
layout(std430, binding = 0) writeonly buffer MatrixOut
|
||||||
|
{
|
||||||
|
mat2 m2out;
|
||||||
|
mat3 m3out;
|
||||||
|
mat4 m4out;
|
||||||
|
};
|
||||||
|
|
||||||
|
layout(std430, binding = 1) readonly buffer MatrixIn
|
||||||
|
{
|
||||||
|
mat2 m2in;
|
||||||
|
mat3 m3in;
|
||||||
|
mat4 m4in;
|
||||||
|
};
|
||||||
|
|
||||||
|
void main()
|
||||||
|
{
|
||||||
|
m2out = inverse(m2in);
|
||||||
|
m3out = inverse(m3in);
|
||||||
|
m4out = inverse(m4in);
|
||||||
|
}
|
187
spirv_hlsl.cpp
187
spirv_hlsl.cpp
@ -1225,8 +1225,7 @@ void CompilerHLSL::emit_resources()
|
|||||||
return name1.compare(name2) < 0;
|
return name1.compare(name2) < 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
static const uint64_t implicit_builtins = (1ull << BuiltInNumWorkgroups) |
|
static const uint64_t implicit_builtins = (1ull << BuiltInNumWorkgroups) | (1ull << BuiltInPointCoord);
|
||||||
(1ull << BuiltInPointCoord);
|
|
||||||
if (!input_variables.empty() || (active_input_builtins & ~implicit_builtins))
|
if (!input_variables.empty() || (active_input_builtins & ~implicit_builtins))
|
||||||
{
|
{
|
||||||
require_input = true;
|
require_input = true;
|
||||||
@ -1540,6 +1539,159 @@ void CompilerHLSL::emit_resources()
|
|||||||
statement("");
|
statement("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (requires_inverse_2x2)
|
||||||
|
{
|
||||||
|
statement("// Returns the inverse of a matrix, by using the algorithm of calculating the classical");
|
||||||
|
statement("// adjoint and dividing by the determinant. The contents of the matrix are changed.");
|
||||||
|
statement("float2x2 SPIRV_Cross_Inverse(float2x2 m)");
|
||||||
|
begin_scope();
|
||||||
|
statement("float2x2 adj; // The adjoint matrix (inverse after dividing by determinant)");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement("// Create the transpose of the cofactors, as the classical adjoint of the matrix.");
|
||||||
|
statement("adj[0][0] = m[1][1];");
|
||||||
|
statement("adj[0][1] = -m[0][1];");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement("adj[1][0] = -m[1][0];");
|
||||||
|
statement("adj[1][1] = m[0][0];");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement("// Calculate the determinant as a combination of the cofactors of the first row.");
|
||||||
|
statement("float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]);");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement("// Divide the classical adjoint matrix by the determinant.");
|
||||||
|
statement("// If determinant is zero, matrix is not invertable, so leave it unchanged.");
|
||||||
|
statement("return (det != 0.0f) ? (adj * (1.0f / det)) : m;");
|
||||||
|
end_scope();
|
||||||
|
statement("");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requires_inverse_3x3)
|
||||||
|
{
|
||||||
|
statement("// Returns the determinant of a 2x2 matrix.");
|
||||||
|
statement("float SPIRV_Cross_Det2x2(float a1, float a2, float b1, float b2)");
|
||||||
|
begin_scope();
|
||||||
|
statement("return a1 * b2 - b1 * a2;");
|
||||||
|
end_scope();
|
||||||
|
statement_no_indent("");
|
||||||
|
statement("// Returns the inverse of a matrix, by using the algorithm of calculating the classical");
|
||||||
|
statement("// adjoint and dividing by the determinant. The contents of the matrix are changed.");
|
||||||
|
statement("float3x3 SPIRV_Cross_Inverse(float3x3 m)");
|
||||||
|
begin_scope();
|
||||||
|
statement("float3x3 adj; // The adjoint matrix (inverse after dividing by determinant)");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement("// Create the transpose of the cofactors, as the classical adjoint of the matrix.");
|
||||||
|
statement("adj[0][0] = SPIRV_Cross_Det2x2(m[1][1], m[1][2], m[2][1], m[2][2]);");
|
||||||
|
statement("adj[0][1] = -SPIRV_Cross_Det2x2(m[0][1], m[0][2], m[2][1], m[2][2]);");
|
||||||
|
statement("adj[0][2] = SPIRV_Cross_Det2x2(m[0][1], m[0][2], m[1][1], m[1][2]);");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement("adj[1][0] = -SPIRV_Cross_Det2x2(m[1][0], m[1][2], m[2][0], m[2][2]);");
|
||||||
|
statement("adj[1][1] = SPIRV_Cross_Det2x2(m[0][0], m[0][2], m[2][0], m[2][2]);");
|
||||||
|
statement("adj[1][2] = -SPIRV_Cross_Det2x2(m[0][0], m[0][2], m[1][0], m[1][2]);");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement("adj[2][0] = SPIRV_Cross_Det2x2(m[1][0], m[1][1], m[2][0], m[2][1]);");
|
||||||
|
statement("adj[2][1] = -SPIRV_Cross_Det2x2(m[0][0], m[0][1], m[2][0], m[2][1]);");
|
||||||
|
statement("adj[2][2] = SPIRV_Cross_Det2x2(m[0][0], m[0][1], m[1][0], m[1][1]);");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement("// Calculate the determinant as a combination of the cofactors of the first row.");
|
||||||
|
statement("float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]);");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement("// Divide the classical adjoint matrix by the determinant.");
|
||||||
|
statement("// If determinant is zero, matrix is not invertable, so leave it unchanged.");
|
||||||
|
statement("return (det != 0.0f) ? (adj * (1.0f / det)) : m;");
|
||||||
|
end_scope();
|
||||||
|
statement("");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (requires_inverse_4x4)
|
||||||
|
{
|
||||||
|
if (!requires_inverse_3x3)
|
||||||
|
{
|
||||||
|
statement("// Returns the determinant of a 2x2 matrix.");
|
||||||
|
statement("float SPIRV_Cross_Det2x2(float a1, float a2, float b1, float b2)");
|
||||||
|
begin_scope();
|
||||||
|
statement("return a1 * b2 - b1 * a2;");
|
||||||
|
end_scope();
|
||||||
|
statement("");
|
||||||
|
}
|
||||||
|
|
||||||
|
statement("// Returns the determinant of a 3x3 matrix.");
|
||||||
|
statement("float SPIRV_Cross_Det3x3(float a1, float a2, float a3, float b1, float b2, float b3, float c1, "
|
||||||
|
"float c2, float c3)");
|
||||||
|
begin_scope();
|
||||||
|
statement("return a1 * SPIRV_Cross_Det2x2(b2, b3, c2, c3) - b1 * SPIRV_Cross_Det2x2(a2, a3, c2, c3) + c1 * "
|
||||||
|
"SPIRV_Cross_Det2x2(a2, a3, "
|
||||||
|
"b2, b3);");
|
||||||
|
end_scope();
|
||||||
|
statement_no_indent("");
|
||||||
|
statement("// Returns the inverse of a matrix, by using the algorithm of calculating the classical");
|
||||||
|
statement("// adjoint and dividing by the determinant. The contents of the matrix are changed.");
|
||||||
|
statement("float4x4 SPIRV_Cross_Inverse(float4x4 m)");
|
||||||
|
begin_scope();
|
||||||
|
statement("float4x4 adj; // The adjoint matrix (inverse after dividing by determinant)");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement("// Create the transpose of the cofactors, as the classical adjoint of the matrix.");
|
||||||
|
statement(
|
||||||
|
"adj[0][0] = SPIRV_Cross_Det3x3(m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], "
|
||||||
|
"m[3][3]);");
|
||||||
|
statement(
|
||||||
|
"adj[0][1] = -SPIRV_Cross_Det3x3(m[0][1], m[0][2], m[0][3], m[2][1], m[2][2], m[2][3], m[3][1], m[3][2], "
|
||||||
|
"m[3][3]);");
|
||||||
|
statement(
|
||||||
|
"adj[0][2] = SPIRV_Cross_Det3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[3][1], m[3][2], "
|
||||||
|
"m[3][3]);");
|
||||||
|
statement(
|
||||||
|
"adj[0][3] = -SPIRV_Cross_Det3x3(m[0][1], m[0][2], m[0][3], m[1][1], m[1][2], m[1][3], m[2][1], m[2][2], "
|
||||||
|
"m[2][3]);");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement(
|
||||||
|
"adj[1][0] = -SPIRV_Cross_Det3x3(m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], "
|
||||||
|
"m[3][3]);");
|
||||||
|
statement(
|
||||||
|
"adj[1][1] = SPIRV_Cross_Det3x3(m[0][0], m[0][2], m[0][3], m[2][0], m[2][2], m[2][3], m[3][0], m[3][2], "
|
||||||
|
"m[3][3]);");
|
||||||
|
statement(
|
||||||
|
"adj[1][2] = -SPIRV_Cross_Det3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[3][0], m[3][2], "
|
||||||
|
"m[3][3]);");
|
||||||
|
statement(
|
||||||
|
"adj[1][3] = SPIRV_Cross_Det3x3(m[0][0], m[0][2], m[0][3], m[1][0], m[1][2], m[1][3], m[2][0], m[2][2], "
|
||||||
|
"m[2][3]);");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement(
|
||||||
|
"adj[2][0] = SPIRV_Cross_Det3x3(m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], "
|
||||||
|
"m[3][3]);");
|
||||||
|
statement(
|
||||||
|
"adj[2][1] = -SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][3], m[2][0], m[2][1], m[2][3], m[3][0], m[3][1], "
|
||||||
|
"m[3][3]);");
|
||||||
|
statement(
|
||||||
|
"adj[2][2] = SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[3][0], m[3][1], "
|
||||||
|
"m[3][3]);");
|
||||||
|
statement(
|
||||||
|
"adj[2][3] = -SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][3], m[1][0], m[1][1], m[1][3], m[2][0], m[2][1], "
|
||||||
|
"m[2][3]);");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement(
|
||||||
|
"adj[3][0] = -SPIRV_Cross_Det3x3(m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], "
|
||||||
|
"m[3][2]);");
|
||||||
|
statement(
|
||||||
|
"adj[3][1] = SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][2], m[2][0], m[2][1], m[2][2], m[3][0], m[3][1], "
|
||||||
|
"m[3][2]);");
|
||||||
|
statement(
|
||||||
|
"adj[3][2] = -SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[3][0], m[3][1], "
|
||||||
|
"m[3][2]);");
|
||||||
|
statement(
|
||||||
|
"adj[3][3] = SPIRV_Cross_Det3x3(m[0][0], m[0][1], m[0][2], m[1][0], m[1][1], m[1][2], m[2][0], m[2][1], "
|
||||||
|
"m[2][2]);");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement("// Calculate the determinant as a combination of the cofactors of the first row.");
|
||||||
|
statement("float det = (adj[0][0] * m[0][0]) + (adj[0][1] * m[1][0]) + (adj[0][2] * m[2][0]) + (adj[0][3] "
|
||||||
|
"* m[3][0]);");
|
||||||
|
statement_no_indent("");
|
||||||
|
statement("// Divide the classical adjoint matrix by the determinant.");
|
||||||
|
statement("// If determinant is zero, matrix is not invertable, so leave it unchanged.");
|
||||||
|
statement("return (det != 0.0f) ? (adj * (1.0f / det)) : m;");
|
||||||
|
end_scope();
|
||||||
|
statement("");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
string CompilerHLSL::layout_for_member(const SPIRType &type, uint32_t index)
|
string CompilerHLSL::layout_for_member(const SPIRType &type, uint32_t index)
|
||||||
@ -2830,6 +2982,37 @@ void CompilerHLSL::emit_glsl_op(uint32_t result_type, uint32_t id, uint32_t eop,
|
|||||||
emit_unary_func_op(result_type, id, args[0], "firstbithigh");
|
emit_unary_func_op(result_type, id, args[0], "firstbithigh");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case GLSLstd450MatrixInverse:
|
||||||
|
{
|
||||||
|
auto &type = get<SPIRType>(result_type);
|
||||||
|
if (type.vecsize == 2 && type.columns == 2)
|
||||||
|
{
|
||||||
|
if (!requires_inverse_2x2)
|
||||||
|
{
|
||||||
|
requires_inverse_2x2 = true;
|
||||||
|
force_recompile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type.vecsize == 3 && type.columns == 3)
|
||||||
|
{
|
||||||
|
if (!requires_inverse_3x3)
|
||||||
|
{
|
||||||
|
requires_inverse_3x3 = true;
|
||||||
|
force_recompile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (type.vecsize == 4 && type.columns == 4)
|
||||||
|
{
|
||||||
|
if (!requires_inverse_4x4)
|
||||||
|
{
|
||||||
|
requires_inverse_4x4 = true;
|
||||||
|
force_recompile = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
emit_unary_func_op(result_type, id, args[0], "SPIRV_Cross_Inverse");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count);
|
CompilerGLSL::emit_glsl_op(result_type, id, eop, args, count);
|
||||||
break;
|
break;
|
||||||
|
@ -161,6 +161,9 @@ private:
|
|||||||
bool requires_snorm16_packing = false;
|
bool requires_snorm16_packing = false;
|
||||||
bool requires_bitfield_insert = false;
|
bool requires_bitfield_insert = false;
|
||||||
bool requires_bitfield_extract = false;
|
bool requires_bitfield_extract = false;
|
||||||
|
bool requires_inverse_2x2 = false;
|
||||||
|
bool requires_inverse_3x3 = false;
|
||||||
|
bool requires_inverse_4x4 = false;
|
||||||
uint64_t required_textureSizeVariants = 0;
|
uint64_t required_textureSizeVariants = 0;
|
||||||
void require_texture_query_variant(const SPIRType &type);
|
void require_texture_query_variant(const SPIRType &type);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user