This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/gpu/shaders/common/gpu_shader_test_lib.glsl
Clément Foucault 125b283589 GPU: Add Math libraries to GPU shaders code
This implement most of the functions provided by the BLI math library.
This is part of the effort to unify GLSL and C++ syntax. Ref T103026.

This also adds some infrastructure to make it possible to run GLSL shader unit
test.

Some code already present in other libs is being copied to the new libs.
This patch does not make use of the new libs outside of the tests.

Note that the test is still crashing when using metal.
2023-01-06 22:33:23 +01:00

215 lines
8.1 KiB
GLSL

// clang-format off
#ifndef GPU_METAL
bool is_integer(bool v) { return true; }
#endif
bool is_integer(uint v) { return true; }
bool is_integer(int v) { return true; }
bool is_integer(float v) { return false; }
bool is_integer(ivec2 v) { return true; }
bool is_integer(ivec3 v) { return true; }
bool is_integer(ivec4 v) { return true; }
bool is_integer(uvec2 v) { return true; }
bool is_integer(uvec3 v) { return true; }
bool is_integer(uvec4 v) { return true; }
bool is_integer(vec2 v) { return false; }
bool is_integer(vec3 v) { return false; }
bool is_integer(vec4 v) { return false; }
bool is_integer(mat2x2 v) { return false; }
bool is_integer(mat2x3 v) { return false; }
bool is_integer(mat2x4 v) { return false; }
bool is_integer(mat3x2 v) { return false; }
bool is_integer(mat3x3 v) { return false; }
bool is_integer(mat3x4 v) { return false; }
bool is_integer(mat4x2 v) { return false; }
bool is_integer(mat4x3 v) { return false; }
bool is_integer(mat4x4 v) { return false; }
int mat_row_len(mat2x2 v) { return 2; }
int mat_row_len(mat2x3 v) { return 3; }
int mat_row_len(mat2x4 v) { return 4; }
int mat_row_len(mat3x2 v) { return 2; }
int mat_row_len(mat3x3 v) { return 3; }
int mat_row_len(mat3x4 v) { return 4; }
int mat_row_len(mat4x2 v) { return 2; }
int mat_row_len(mat4x3 v) { return 3; }
int mat_row_len(mat4x4 v) { return 4; }
int mat_col_len(mat2x2 v) { return 2; }
int mat_col_len(mat2x3 v) { return 2; }
int mat_col_len(mat2x4 v) { return 2; }
int mat_col_len(mat3x2 v) { return 3; }
int mat_col_len(mat3x3 v) { return 3; }
int mat_col_len(mat3x4 v) { return 3; }
int mat_col_len(mat4x2 v) { return 4; }
int mat_col_len(mat4x3 v) { return 4; }
int mat_col_len(mat4x4 v) { return 4; }
int mat_col_len(ivec2 v) { return 2; }
int mat_col_len(ivec3 v) { return 3; }
int mat_col_len(ivec4 v) { return 4; }
int mat_col_len(uvec2 v) { return 2; }
int mat_col_len(uvec3 v) { return 3; }
int mat_col_len(uvec4 v) { return 4; }
int mat_col_len(vec2 v) { return 2; }
int mat_col_len(vec3 v) { return 3; }
int mat_col_len(vec4 v) { return 4; }
#ifndef GPU_METAL
uint to_type(bool v) { return TEST_TYPE_BOOL; }
#endif
uint to_type(uint v) { return TEST_TYPE_UINT; }
uint to_type(int v) { return TEST_TYPE_INT; }
uint to_type(float v) { return TEST_TYPE_FLOAT; }
uint to_type(ivec2 v) { return TEST_TYPE_IVEC2; }
uint to_type(ivec3 v) { return TEST_TYPE_IVEC3; }
uint to_type(ivec4 v) { return TEST_TYPE_IVEC4; }
uint to_type(uvec2 v) { return TEST_TYPE_UVEC2; }
uint to_type(uvec3 v) { return TEST_TYPE_UVEC3; }
uint to_type(uvec4 v) { return TEST_TYPE_UVEC4; }
uint to_type(vec2 v) { return TEST_TYPE_VEC2; }
uint to_type(vec3 v) { return TEST_TYPE_VEC3; }
uint to_type(vec4 v) { return TEST_TYPE_VEC4; }
uint to_type(mat2x2 v) { return TEST_TYPE_MAT2X2; }
uint to_type(mat2x3 v) { return TEST_TYPE_MAT2X3; }
uint to_type(mat2x4 v) { return TEST_TYPE_MAT2X4; }
uint to_type(mat3x2 v) { return TEST_TYPE_MAT3X2; }
uint to_type(mat3x3 v) { return TEST_TYPE_MAT3X3; }
uint to_type(mat3x4 v) { return TEST_TYPE_MAT3X4; }
uint to_type(mat4x2 v) { return TEST_TYPE_MAT4X2; }
uint to_type(mat4x3 v) { return TEST_TYPE_MAT4X3; }
uint to_type(mat4x4 v) { return TEST_TYPE_MAT4X4; }
// clang-format on
#define WRITE_MATRIX(v) \
TestOutputRawData raw; \
for (int c = 0; c < mat_col_len(v); c++) { \
for (int r = 0; r < mat_row_len(v); r++) { \
raw.data[c * mat_row_len(v) + r] = floatBitsToUint(v[c][r]); \
} \
} \
return raw;
#define WRITE_FLOAT_VECTOR(v) \
TestOutputRawData raw; \
for (int c = 0; c < mat_col_len(v); c++) { \
raw.data[c] = floatBitsToUint(v[c]); \
} \
return raw;
#define WRITE_INT_VECTOR(v) \
TestOutputRawData raw; \
for (int c = 0; c < mat_col_len(v); c++) { \
raw.data[c] = uint(v[c]); \
} \
return raw;
#define WRITE_FLOAT_SCALAR(v) \
TestOutputRawData raw; \
raw.data[0] = floatBitsToUint(v); \
return raw;
#define WRITE_INT_SCALAR(v) \
TestOutputRawData raw; \
raw.data[0] = uint(v); \
return raw;
// clang-format off
#ifndef GPU_METAL
TestOutputRawData as_raw_data(bool v) { WRITE_INT_SCALAR(v); }
#endif
TestOutputRawData as_raw_data(uint v) { WRITE_INT_SCALAR(v); }
TestOutputRawData as_raw_data(int v) { WRITE_INT_SCALAR(v); }
TestOutputRawData as_raw_data(float v) { WRITE_FLOAT_SCALAR(v); }
TestOutputRawData as_raw_data(ivec2 v) { WRITE_INT_VECTOR(v); }
TestOutputRawData as_raw_data(ivec3 v) { WRITE_INT_VECTOR(v); }
TestOutputRawData as_raw_data(ivec4 v) { WRITE_INT_VECTOR(v); }
TestOutputRawData as_raw_data(uvec2 v) { WRITE_INT_VECTOR(v); }
TestOutputRawData as_raw_data(uvec3 v) { WRITE_INT_VECTOR(v); }
TestOutputRawData as_raw_data(uvec4 v) { WRITE_INT_VECTOR(v); }
TestOutputRawData as_raw_data(vec2 v) { WRITE_FLOAT_VECTOR(v); }
TestOutputRawData as_raw_data(vec3 v) { WRITE_FLOAT_VECTOR(v); }
TestOutputRawData as_raw_data(vec4 v) { WRITE_FLOAT_VECTOR(v); }
TestOutputRawData as_raw_data(mat2x2 v) { WRITE_MATRIX(v); }
TestOutputRawData as_raw_data(mat2x3 v) { WRITE_MATRIX(v); }
TestOutputRawData as_raw_data(mat2x4 v) { WRITE_MATRIX(v); }
TestOutputRawData as_raw_data(mat3x2 v) { WRITE_MATRIX(v); }
TestOutputRawData as_raw_data(mat3x3 v) { WRITE_MATRIX(v); }
TestOutputRawData as_raw_data(mat3x4 v) { WRITE_MATRIX(v); }
TestOutputRawData as_raw_data(mat4x2 v) { WRITE_MATRIX(v); }
TestOutputRawData as_raw_data(mat4x3 v) { WRITE_MATRIX(v); }
TestOutputRawData as_raw_data(mat4x4 v) { WRITE_MATRIX(v); }
// clang-format on
int g_test_id = 0;
#ifdef GPU_COMPUTE_SHADER
# define EXPECT_OP(OP, val1, val2) \
out_test[g_test_id++] = test_output( \
as_raw_data(val1), as_raw_data(val2), bool(OP), int(__LINE__), to_type(val1))
#else
/** WORKAROUND: Fragment shader variant for older platform. */
# define EXPECT_OP(OP, val1, val2) \
g_test_id += 1; \
if (g_test_id == 1) { \
/* Avoid pixels with undefined values. */ \
out_test = uvec4(0); \
} \
if (int(gl_FragCoord.y) == g_test_id - 1) { \
TestOutput to = test_output( \
as_raw_data(val1), as_raw_data(val2), bool(OP), int(__LINE__), to_type(val1)); \
switch (int(gl_FragCoord.x)) { \
case 0: \
out_test = uvec4( \
to.expect.data[0], to.expect.data[1], to.expect.data[2], to.expect.data[3]); \
break; \
case 1: \
out_test = uvec4( \
to.expect.data[4], to.expect.data[5], to.expect.data[6], to.expect.data[7]); \
break; \
case 2: \
out_test = uvec4( \
to.expect.data[8], to.expect.data[9], to.expect.data[10], to.expect.data[11]); \
break; \
case 3: \
out_test = uvec4( \
to.expect.data[12], to.expect.data[13], to.expect.data[14], to.expect.data[15]); \
break; \
case 4: \
out_test = uvec4( \
to.result.data[0], to.result.data[1], to.result.data[2], to.result.data[3]); \
break; \
case 5: \
out_test = uvec4( \
to.result.data[4], to.result.data[5], to.result.data[6], to.result.data[7]); \
break; \
case 6: \
out_test = uvec4( \
to.result.data[8], to.result.data[9], to.result.data[10], to.result.data[11]); \
break; \
case 7: \
out_test = uvec4( \
to.result.data[12], to.result.data[13], to.result.data[14], to.result.data[15]); \
break; \
case 8: \
out_test = uvec4(to.status, to.line, to.type, 0); \
break; \
} \
}
#endif
#define EXPECT_EQ(result, expect) EXPECT_OP((result) == (expect), result, expect)
#define EXPECT_NE(result, expect) EXPECT_OP((result) != (expect), result, expect)
#define EXPECT_LE(result, expect) EXPECT_OP((result) <= (expect), result, expect)
#define EXPECT_LT(result, expect) EXPECT_OP((result) < (expect), result, expect)
#define EXPECT_GE(result, expect) EXPECT_OP((result) >= (expect), result, expect)
#define EXPECT_GT(result, expect) EXPECT_OP((result) > (expect), result, expect)
#define EXPECT_TRUE(result) EXPECT_OP(result, result, true)
#define EXPECT_FALSE(result) EXPECT_OP(!result, result, false)
#define EXPECT_NEAR(result, expect, threshold) \
EXPECT_OP(is_equal(result, expect, threshold), result, expect)