mirror of
https://github.com/baldurk/renderdoc.git
synced 2026-10-16 00:59:22 +00:00
Add support for matrix operations (transpose/determinant/inverse)
This commit is contained in:
5 files changed
+301
-6
No files matched your search
@@ -1455,6 +1455,21 @@ void ThreadState::StepNext(ShaderDebugState *state, const rdcarray<ThreadState>
|
||||
SetDst(state, mul.result, var);
|
||||
break;
|
||||
}
|
||||
case Op::Transpose:
|
||||
{
|
||||
OpTranspose transpose(it);
|
||||
|
||||
ShaderVariable matrix = GetSrc(transpose.matrix);
|
||||
ShaderVariable var = matrix;
|
||||
std::swap(var.rows, var.columns);
|
||||
|
||||
for(uint8_t r = 0; r < var.rows; r++)
|
||||
for(uint8_t c = 0; c < var.columns; c++)
|
||||
var.value.fv[r * var.columns + c] = matrix.value.fv[c * matrix.columns + r];
|
||||
|
||||
SetDst(state, transpose.result, var);
|
||||
break;
|
||||
}
|
||||
case Op::MatrixTimesVector:
|
||||
{
|
||||
OpMatrixTimesVector mul(it);
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
|
||||
#include "spirv_debug.h"
|
||||
#include <math.h>
|
||||
#include "maths/matrix.h"
|
||||
|
||||
namespace rdcspv
|
||||
{
|
||||
@@ -179,6 +180,67 @@ ShaderVariable Pow(ThreadState &state, const rdcarray<Id> ¶ms)
|
||||
return var;
|
||||
}
|
||||
|
||||
ShaderVariable Determinant(ThreadState &state, const rdcarray<Id> ¶ms)
|
||||
{
|
||||
CHECK_PARAMS(1);
|
||||
|
||||
ShaderVariable m = state.GetSrc(params[0]);
|
||||
|
||||
RDCASSERTEQUAL(m.rows, m.columns);
|
||||
|
||||
if(m.rows == 4)
|
||||
{
|
||||
Matrix4f mat;
|
||||
mat.SetFrom(m.value.fv);
|
||||
m.value.f.x = mat.Determinant();
|
||||
}
|
||||
else if(m.rows == 3)
|
||||
{
|
||||
Matrix3f mat;
|
||||
mat.SetFrom(m.value.fv);
|
||||
m.value.f.x = mat.Determinant();
|
||||
}
|
||||
else if(m.rows == 2)
|
||||
{
|
||||
Matrix2f mat;
|
||||
mat.SetFrom(m.value.fv);
|
||||
m.value.f.x = mat.Determinant();
|
||||
}
|
||||
m.rows = m.columns = 1;
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
ShaderVariable MatrixInverse(ThreadState &state, const rdcarray<Id> ¶ms)
|
||||
{
|
||||
CHECK_PARAMS(1);
|
||||
|
||||
ShaderVariable m = state.GetSrc(params[0]);
|
||||
|
||||
RDCASSERTEQUAL(m.rows, m.columns);
|
||||
|
||||
if(m.rows == 4)
|
||||
{
|
||||
Matrix4f mat;
|
||||
mat.SetFrom(m.value.fv);
|
||||
memcpy(m.value.fv, mat.Inverse().Data(), sizeof(mat));
|
||||
}
|
||||
else if(m.rows == 3)
|
||||
{
|
||||
Matrix3f mat;
|
||||
mat.SetFrom(m.value.fv);
|
||||
memcpy(m.value.fv, mat.Inverse().Data(), sizeof(mat));
|
||||
}
|
||||
else if(m.rows == 2)
|
||||
{
|
||||
Matrix2f mat;
|
||||
mat.SetFrom(m.value.fv);
|
||||
memcpy(m.value.fv, mat.Inverse().Data(), sizeof(mat));
|
||||
}
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static T GLSLMax(T x, T y)
|
||||
{
|
||||
@@ -457,6 +519,8 @@ void ConfigureGLSLStd450(ExtInstDispatcher &extinst)
|
||||
EXT(Ceil);
|
||||
EXT(Fract);
|
||||
EXT(Pow);
|
||||
EXT(Determinant);
|
||||
EXT(MatrixInverse);
|
||||
EXT(FMin);
|
||||
EXT(UMin);
|
||||
EXT(SMin);
|
||||
|
||||
@@ -31,11 +31,6 @@
|
||||
#include "quat.h"
|
||||
#include "vec.h"
|
||||
|
||||
static inline size_t matIdx(const size_t x, const size_t y)
|
||||
{
|
||||
return x + y * 4;
|
||||
}
|
||||
|
||||
Matrix4f Matrix4f::Mul(const Matrix4f &o) const
|
||||
{
|
||||
Matrix4f m;
|
||||
@@ -62,6 +57,24 @@ Matrix4f Matrix4f::Transpose() const
|
||||
return m;
|
||||
}
|
||||
|
||||
float Matrix4f::Determinant() const
|
||||
{
|
||||
float a0 = (*this)[0] * (*this)[5] - (*this)[1] * (*this)[4];
|
||||
float a1 = (*this)[0] * (*this)[6] - (*this)[2] * (*this)[4];
|
||||
float a2 = (*this)[0] * (*this)[7] - (*this)[3] * (*this)[4];
|
||||
float a3 = (*this)[1] * (*this)[6] - (*this)[2] * (*this)[5];
|
||||
float a4 = (*this)[1] * (*this)[7] - (*this)[3] * (*this)[5];
|
||||
float a5 = (*this)[2] * (*this)[7] - (*this)[3] * (*this)[6];
|
||||
float b0 = (*this)[8] * (*this)[13] - (*this)[9] * (*this)[12];
|
||||
float b1 = (*this)[8] * (*this)[14] - (*this)[10] * (*this)[12];
|
||||
float b2 = (*this)[8] * (*this)[15] - (*this)[11] * (*this)[12];
|
||||
float b3 = (*this)[9] * (*this)[14] - (*this)[10] * (*this)[13];
|
||||
float b4 = (*this)[9] * (*this)[15] - (*this)[11] * (*this)[13];
|
||||
float b5 = (*this)[10] * (*this)[15] - (*this)[11] * (*this)[14];
|
||||
|
||||
return a0 * b5 - a1 * b4 + a2 * b3 + a3 * b2 - a4 * b1 + a5 * b0;
|
||||
}
|
||||
|
||||
Matrix4f Matrix4f::Inverse() const
|
||||
{
|
||||
float a0 = (*this)[0] * (*this)[5] - (*this)[1] * (*this)[4];
|
||||
@@ -120,7 +133,7 @@ Matrix4f Matrix4f::Inverse() const
|
||||
}
|
||||
|
||||
// no inverse
|
||||
return Matrix4f::Identity();
|
||||
return Matrix4f::Zero();
|
||||
}
|
||||
|
||||
Vec3f Matrix4f::Transform(const Vec3f &v, const float w) const
|
||||
@@ -274,3 +287,77 @@ Matrix4f Matrix4f::ReversePerspective(const float degfov, const float N, const f
|
||||
|
||||
return Matrix4f(persp);
|
||||
}
|
||||
|
||||
Matrix3f Matrix3f::Transpose() const
|
||||
{
|
||||
Matrix3f m;
|
||||
for(size_t x = 0; x < 3; x++)
|
||||
for(size_t y = 0; y < 3; y++)
|
||||
m[matIdx(x, y)] = (*this)[matIdx(y, x)];
|
||||
|
||||
return m;
|
||||
}
|
||||
|
||||
float Matrix3f::Determinant() const
|
||||
{
|
||||
return f[0] * (f[4] * f[8] - f[5] * f[7]) - f[1] * (f[3] * f[8] - f[5] * f[6]) +
|
||||
f[2] * (f[3] * f[7] - f[4] * f[6]);
|
||||
}
|
||||
|
||||
Matrix3f Matrix3f::Inverse() const
|
||||
{
|
||||
float det = Determinant();
|
||||
Matrix3f m = {};
|
||||
if(fabsf(det) > FLT_EPSILON)
|
||||
{
|
||||
m[0] = Matrix2f(f[matIdx(1, 1)], f[matIdx(2, 1)], f[matIdx(1, 2)], f[matIdx(2, 2)]).Determinant();
|
||||
m[1] = Matrix2f(f[matIdx(1, 0)], f[matIdx(2, 0)], f[matIdx(1, 2)], f[matIdx(2, 2)]).Determinant();
|
||||
m[2] = Matrix2f(f[matIdx(1, 0)], f[matIdx(2, 0)], f[matIdx(1, 1)], f[matIdx(2, 1)]).Determinant();
|
||||
|
||||
m[3] = Matrix2f(f[matIdx(0, 1)], f[matIdx(2, 1)], f[matIdx(0, 2)], f[matIdx(2, 2)]).Determinant();
|
||||
m[4] = Matrix2f(f[matIdx(0, 0)], f[matIdx(2, 0)], f[matIdx(0, 2)], f[matIdx(2, 2)]).Determinant();
|
||||
m[5] = Matrix2f(f[matIdx(0, 0)], f[matIdx(2, 0)], f[matIdx(0, 1)], f[matIdx(2, 1)]).Determinant();
|
||||
|
||||
m[6] = Matrix2f(f[matIdx(0, 1)], f[matIdx(1, 1)], f[matIdx(0, 2)], f[matIdx(1, 2)]).Determinant();
|
||||
m[7] = Matrix2f(f[matIdx(0, 0)], f[matIdx(1, 0)], f[matIdx(0, 2)], f[matIdx(1, 2)]).Determinant();
|
||||
m[8] = Matrix2f(f[matIdx(0, 0)], f[matIdx(1, 0)], f[matIdx(0, 1)], f[matIdx(1, 1)]).Determinant();
|
||||
|
||||
float invdet = 1.0f / Determinant();
|
||||
|
||||
for(size_t i = 0; i < 9; i++)
|
||||
{
|
||||
m[i] *= invdet;
|
||||
if(i & 1)
|
||||
m[i] *= -1.0f;
|
||||
}
|
||||
}
|
||||
return m;
|
||||
}
|
||||
|
||||
Matrix2f Matrix2f::Transpose() const
|
||||
{
|
||||
Matrix2f m = *this;
|
||||
m[1] = f[2];
|
||||
m[2] = f[1];
|
||||
return m;
|
||||
}
|
||||
|
||||
float Matrix2f::Determinant() const
|
||||
{
|
||||
return f[0] * f[3] - f[1] * f[2];
|
||||
}
|
||||
|
||||
Matrix2f Matrix2f::Inverse() const
|
||||
{
|
||||
float det = Determinant();
|
||||
Matrix2f m = {};
|
||||
if(fabsf(det) > FLT_EPSILON)
|
||||
{
|
||||
float invdet = 1.0f / Determinant();
|
||||
m[0] = invdet * f[3];
|
||||
m[1] = invdet * -f[1];
|
||||
m[2] = invdet * -f[2];
|
||||
m[3] = invdet * f[0];
|
||||
}
|
||||
return m;
|
||||
}
|
||||
@@ -65,12 +65,14 @@ public:
|
||||
inline float operator[](const size_t i) const { return f[i]; }
|
||||
inline float &operator[](const size_t i) { return f[i]; }
|
||||
Matrix4f Transpose() const;
|
||||
float Determinant() const;
|
||||
Matrix4f Inverse() const;
|
||||
Matrix4f Mul(const Matrix4f &o) const;
|
||||
|
||||
Vec3f Transform(const Vec3f &v, const float w = 1.0f) const;
|
||||
|
||||
const float *Data() const { return &f[0]; }
|
||||
void SetFrom(float data[16]) { memcpy(f, data, sizeof(Matrix4f)); }
|
||||
const Vec3f GetPosition() const;
|
||||
const Vec3f GetForward() const;
|
||||
const Vec3f GetRight() const;
|
||||
@@ -80,5 +82,47 @@ private:
|
||||
Matrix4f(const float *d) { memcpy(f, d, sizeof(Matrix4f)); }
|
||||
friend class Quatf;
|
||||
|
||||
constexpr inline size_t matIdx(const size_t x, const size_t y) const { return x + y * 4; }
|
||||
float f[16];
|
||||
};
|
||||
|
||||
class Matrix3f
|
||||
{
|
||||
public:
|
||||
Matrix3f() {}
|
||||
inline float operator[](const size_t i) const { return f[i]; }
|
||||
inline float &operator[](const size_t i) { return f[i]; }
|
||||
Matrix3f Transpose() const;
|
||||
float Determinant() const;
|
||||
Matrix3f Inverse() const;
|
||||
|
||||
const float *Data() const { return &f[0]; }
|
||||
void SetFrom(float data[9]) { memcpy(f, data, sizeof(Matrix3f)); }
|
||||
private:
|
||||
constexpr inline size_t matIdx(const size_t x, const size_t y) const { return x + y * 3; }
|
||||
float f[9];
|
||||
};
|
||||
|
||||
class Matrix2f
|
||||
{
|
||||
public:
|
||||
Matrix2f() {}
|
||||
Matrix2f(float a, float b, float c, float d)
|
||||
{
|
||||
f[0] = a;
|
||||
f[1] = b;
|
||||
f[2] = c;
|
||||
f[3] = d;
|
||||
}
|
||||
inline float operator[](const size_t i) const { return f[i]; }
|
||||
inline float &operator[](const size_t i) { return f[i]; }
|
||||
Matrix2f Transpose() const;
|
||||
float Determinant() const;
|
||||
Matrix2f Inverse() const;
|
||||
|
||||
const float *Data() const { return &f[0]; }
|
||||
void SetFrom(float data[4]) { memcpy(f, data, sizeof(Matrix2f)); }
|
||||
private:
|
||||
constexpr inline size_t matIdx(const size_t x, const size_t y) const { return x + y * 2; }
|
||||
float f[4];
|
||||
};
|
||||
@@ -953,6 +953,23 @@ void main()
|
||||
|
||||
%_vec = OpCompositeConstruct %float4 %randf_16 %randf_17 %randf_18 %randf_19
|
||||
|
||||
%_out_float4 = OpMatrixTimesVector %float4 %_mat %_vec
|
||||
)EOTEST",
|
||||
R"EOTEST(
|
||||
%_cola = OpCompositeConstruct %float4 %randf_0 %randf_1 %randf_2 %randf_3
|
||||
%_colb = OpCompositeConstruct %float4 %randf_4 %randf_5 %randf_6 %randf_7
|
||||
%_mat1 = OpCompositeConstruct %float4x2 %_cola %_colb
|
||||
|
||||
%_colc = OpCompositeConstruct %float4 %randf_8 %randf_9 %randf_10 %randf_11
|
||||
%_cold = OpCompositeConstruct %float4 %randf_12 %randf_13 %randf_14 %randf_15
|
||||
%_mat2 = OpCompositeConstruct %float4x2 %_colc %_cold
|
||||
|
||||
%_mat2t = OpTranspose %float2x4 %_mat2
|
||||
|
||||
%_mat = OpMatrixTimesMatrix %float4x4 %_mat1 %_mat2t
|
||||
|
||||
%_vec = OpCompositeConstruct %float4 %randf_16 %randf_17 %randf_18 %randf_19
|
||||
|
||||
%_out_float4 = OpMatrixTimesVector %float4 %_mat %_vec
|
||||
)EOTEST",
|
||||
R"EOTEST(
|
||||
@@ -968,9 +985,76 @@ void main()
|
||||
R"EOTEST(
|
||||
%_vec = OpCompositeConstruct %float4 %randf_0 %randf_1 %randf_2 %randf_3
|
||||
%_out_float4 = OpVectorTimesScalar %float4 %_vec %randf_4
|
||||
)EOTEST",
|
||||
R"EOTEST(
|
||||
%_cola = OpCompositeConstruct %float2 %randf_0 %randf_1
|
||||
%_colb = OpCompositeConstruct %float2 %randf_4 %randf_5
|
||||
%_colc = OpCompositeConstruct %float2 %randf_8 %randf_9
|
||||
%_cold = OpCompositeConstruct %float2 %randf_12 %randf_13
|
||||
%_mat1 = OpCompositeConstruct %float2x2 %_cola %_colb
|
||||
|
||||
%_out_float = OpExtInst %float %glsl450 Determinant %_mat1
|
||||
)EOTEST",
|
||||
R"EOTEST(
|
||||
%_cola = OpCompositeConstruct %float3 %randf_0 %randf_1 %randf_2
|
||||
%_colb = OpCompositeConstruct %float3 %randf_4 %randf_5 %randf_6
|
||||
%_colc = OpCompositeConstruct %float3 %randf_8 %randf_9 %randf_10
|
||||
%_mat1 = OpCompositeConstruct %float3x3 %_cola %_colb %_colc
|
||||
|
||||
%_out_float = OpExtInst %float %glsl450 Determinant %_mat1
|
||||
)EOTEST",
|
||||
R"EOTEST(
|
||||
%_cola = OpCompositeConstruct %float4 %randf_0 %randf_1 %randf_2 %randf_3
|
||||
%_colb = OpCompositeConstruct %float4 %randf_4 %randf_5 %randf_6 %randf_7
|
||||
%_colc = OpCompositeConstruct %float4 %randf_8 %randf_9 %randf_10 %randf_11
|
||||
%_cold = OpCompositeConstruct %float4 %randf_12 %randf_13 %randf_14 %randf_15
|
||||
%_mat1 = OpCompositeConstruct %float4x4 %_cola %_colb %_colc %_cold
|
||||
|
||||
%_out_float = OpExtInst %float %glsl450 Determinant %_mat1
|
||||
)EOTEST",
|
||||
});
|
||||
|
||||
// test matrix inverse, but round the result to avoid needing to lower our global precision
|
||||
// epsilon
|
||||
for(int dim = 2; dim <= 4; dim++)
|
||||
{
|
||||
std::string test = fmt::format(R"EOTEST(
|
||||
%_cola = OpCompositeConstruct %float{0} %randf_0 %randf_1 {1} %randf_2 {2} %randf_3
|
||||
%_colb = OpCompositeConstruct %float{0} %randf_4 %randf_5 {1} %randf_6 {2} %randf_7
|
||||
%_colc = OpCompositeConstruct %float{0} %randf_8 %randf_9 {1} %randf_10 {2} %randf_11
|
||||
%_cold = OpCompositeConstruct %float{0} %randf_12 %randf_13 {1} %randf_14 {2} %randf_15
|
||||
|
||||
%_mat = OpCompositeConstruct %float{0}x{0} %_cola %_colb {1} %_colc {2} %_cold
|
||||
|
||||
%_vec = OpCompositeConstruct %float{0} %randf_16 %randf_17 {1} %randf_18 {2} %randf_19
|
||||
|
||||
%_mat0 = OpExtInst %float{0}x{0} %glsl450 MatrixInverse %_mat
|
||||
)EOTEST",
|
||||
dim, dim < 3 ? ";" : "", dim < 4 ? ";" : "");
|
||||
|
||||
int i = 0;
|
||||
for(int col = 0; col < dim; col++)
|
||||
{
|
||||
for(int row = 0; row < dim; row++)
|
||||
{
|
||||
test += fmt::format(R"EOTEST(
|
||||
%_mat{0}{1}a = OpCompositeExtract %float %_mat{2} {0} {1}
|
||||
%_mat{0}{1}b = OpFMul %float %_mat{0}{1}a %float_500_0
|
||||
%_mat{0}{1}c = OpExtInst %float %glsl450 RoundEven %_mat{0}{1}b
|
||||
%_mat{0}{1}d = OpFDiv %float %_mat{0}{1}c %float_500_0
|
||||
|
||||
%_mat{3} = OpCompositeInsert %float{4}x{4} %_mat{0}{1}d %_mat{2} {0} {1}
|
||||
)EOTEST",
|
||||
col, row, i, i + 1, dim);
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
test += fmt::format("%_out_float{0} = OpMatrixTimesVector %float{0} %_mat{1} %_vec\n", dim, i);
|
||||
|
||||
asm_tests.push_back(test);
|
||||
}
|
||||
|
||||
// test OpVectorShuffle
|
||||
append_tests({
|
||||
"%_out_float4 = OpVectorShuffle %float4 %float4_0000 %float4_1234 7 6 0 1",
|
||||
@@ -1347,6 +1431,7 @@ void main()
|
||||
%uint4 = OpTypeVector %uint 4
|
||||
|
||||
%float2x2 = OpTypeMatrix %float2 2
|
||||
%float3x3 = OpTypeMatrix %float3 3
|
||||
%float2x4 = OpTypeMatrix %float2 4
|
||||
%float4x2 = OpTypeMatrix %float4 2
|
||||
%float4x4 = OpTypeMatrix %float4 4
|
||||
|
||||
Reference in new issue
Block a user