This changes the include directive to use the standard C preprocessor `#include` directive. The regex to applied to all glsl sources is: `pragma BLENDER_REQUIRE\((\w+\.glsl)\)` `include "$1"` This allow C++ linter to parse the code and allow easier codebase traversal. However there is a small catch. While it does work like a standard include directive when the code is treated as C++, it doesn't when compiled by our shader backends. In this case, we still use our dependency concatenation approach instead of file injection. This means that included files will always be prepended when compiled to GLSL and a file cannot be appended more than once. This is why all GLSL lib file should have the `#pragma once` directive and always be included at the start of the file. These requirements are actually already enforced by our code-style in practice. On the implementation, the source needed to be mutated to comment the `#pragma once` and `#include`. This is needed to avoid GLSL compiler error out as this is an extension that not all vendor supports. Rel #127983 Pull Request: https://projects.blender.org/blender/blender/pulls/128076
227 lines
8.4 KiB
GLSL
227 lines
8.4 KiB
GLSL
/* SPDX-FileCopyrightText: 2023 Blender Authors
|
|
*
|
|
* SPDX-License-Identifier: GPL-2.0-or-later */
|
|
|
|
#pragma once
|
|
|
|
/* 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_METAL
|
|
/* Vector comparison in MSL return a `bvec`. Collapse it like in GLSL. */
|
|
# define COLLAPSE_BOOL(OP) bool(all(OP))
|
|
#else
|
|
# define COLLAPSE_BOOL(OP) (OP)
|
|
#endif
|
|
|
|
#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), COLLAPSE_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), COLLAPSE_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)
|