Blender V4.3
push_constants_test.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2023 Blender Authors
2 *
3 * SPDX-License-Identifier: Apache-2.0 */
4
5#include "testing/testing.h"
6
7#include "GPU_capabilities.hh"
8#include "GPU_compute.hh"
9#include "GPU_shader.hh"
10#include "GPU_storage_buffer.hh"
11
12#include "BLI_math_vector.hh"
13#include "BLI_utility_mixins.hh"
14#include "BLI_vector.hh"
15
16#include "gpu_testing.hh"
17
18namespace blender::gpu::tests {
19struct CallData {
20 GPUStorageBuf *ssbo = nullptr;
22
23 float float_in;
27
28 void init_ssbo(size_t num_floats)
29 {
30 if (ssbo == nullptr) {
32 num_floats * sizeof(float), nullptr, GPU_USAGE_DEVICE_ONLY, __func__);
33 data.resize(num_floats);
34 }
35 }
36
38 {
39 if (ssbo != nullptr) {
41 ssbo = nullptr;
42 }
43 }
44
45 void generate_test_data(const float vector_mul, const float scalar_mul)
46 {
47 float_in = vector_mul;
48 vec2_in = float2(vector_mul * 2.0, vector_mul * 2.0 + scalar_mul);
50 vector_mul * 3.0, vector_mul * 3.0 + scalar_mul, vector_mul * 3.0 + scalar_mul * 2.0);
51 vec4_in = float4(vector_mul * 4.0,
52 vector_mul * 4.0 + scalar_mul,
53 vector_mul * 4.0 + scalar_mul * 2.0,
54 vector_mul * 4.0 + scalar_mul * 3.0);
55 }
56
62
63 void validate()
64 {
65 /* Check the results. */
66 EXPECT_EQ(float_in, data[0]);
67 EXPECT_EQ(vec2_in.x, data[1]);
68 EXPECT_EQ(vec2_in.y, data[2]);
69 EXPECT_EQ(vec3_in.x, data[3]);
70 EXPECT_EQ(vec3_in.y, data[4]);
71 EXPECT_EQ(vec3_in.z, data[5]);
72 EXPECT_EQ(vec4_in.x, data[6]);
73 EXPECT_EQ(vec4_in.y, data[7]);
74 EXPECT_EQ(vec4_in.z, data[8]);
75 EXPECT_EQ(vec4_in.w, data[9]);
76 }
77};
78
79struct Shader {
80 GPUShader *shader = nullptr;
82
84 {
85 call_datas.reserve(10);
86 }
87
89 {
90 if (shader != nullptr) {
92 GPU_shader_free(shader);
93 }
94 }
95
96 void init_shader(const char *info_name)
97 {
98 if (shader == nullptr) {
99 shader = GPU_shader_create_from_info_name(info_name);
100 EXPECT_NE(shader, nullptr);
101 GPU_shader_bind(shader);
102 }
103 }
104
106 {
107 CallData call_data;
108 call_datas.append(call_data);
109 return call_datas.last();
110 }
111
112 void bind(CallData &call_data)
113 {
114 GPU_storagebuf_bind(call_data.ssbo, GPU_shader_get_ssbo_binding(shader, "data_out"));
115 }
116
117 void update_push_constants(const CallData &call_data)
118 {
119 GPU_shader_uniform_1f(shader, "float_in", call_data.float_in);
120 GPU_shader_uniform_2fv(shader, "vec2_in", call_data.vec2_in);
121 GPU_shader_uniform_3fv(shader, "vec3_in", call_data.vec3_in);
122 GPU_shader_uniform_4fv(shader, "vec4_in", call_data.vec4_in);
123 }
124
125 void dispatch()
126 {
127 /* Dispatching 1000000 times to add some stress to the GPU. Without it tests may succeed when
128 * using too simple shaders. */
129 GPU_compute_dispatch(shader, 1000, 1000, 1);
130 }
131};
132
134static void do_push_constants_test(const char *info_name, const int num_calls_simultaneously = 1)
135{
136 static constexpr uint SIZE = 16;
137
138 Shader shader;
139 shader.init_shader(info_name);
140
141 for (const int call_index : IndexRange(num_calls_simultaneously)) {
142 CallData &call_data = shader.new_call();
143 call_data.generate_test_data(call_index * 10.0, (call_index + 1) * 1.0);
144 call_data.init_ssbo(SIZE);
145 shader.bind(call_data);
146 shader.update_push_constants(call_data);
147 shader.dispatch();
148 }
149 /* All calls will be "simultaneously" in flight. First read-back will wait until the dispatches
150 * have finished execution. */
151 for (const int call_index : IndexRange(num_calls_simultaneously)) {
152 CallData &call_data = shader.call_datas[call_index];
153 call_data.read_back();
154 call_data.validate();
155 }
156}
157
158/* Test case with single call as sanity check, before we make it more interesting. */
160{
161 do_push_constants_test("gpu_push_constants_test");
162}
163GPU_TEST(push_constants)
164
166{
167 do_push_constants_test("gpu_push_constants_128bytes_test");
168}
169GPU_TEST(push_constants_128bytes)
170
172{
173 do_push_constants_test("gpu_push_constants_256bytes_test");
174}
175GPU_TEST(push_constants_256bytes)
176
178{
179 do_push_constants_test("gpu_push_constants_512bytes_test");
180}
181GPU_TEST(push_constants_512bytes)
182
184{
185 do_push_constants_test("gpu_push_constants_8192bytes_test");
186}
187GPU_TEST(push_constants_8192bytes)
188
189/* Schedule multiple simultaneously. */
191{
192 do_push_constants_test("gpu_push_constants_test", 10);
193}
194GPU_TEST(push_constants_multiple)
195
197{
198 do_push_constants_test("gpu_push_constants_128bytes_test", 10);
199}
200GPU_TEST(push_constants_multiple_128bytes)
201
203{
204 do_push_constants_test("gpu_push_constants_256bytes_test", 10);
205}
206GPU_TEST(push_constants_multiple_256bytes)
207
209{
210 do_push_constants_test("gpu_push_constants_512bytes_test", 10);
211}
212GPU_TEST(push_constants_multiple_512bytes)
213
215{
216 do_push_constants_test("gpu_push_constants_8192bytes_test", 10);
217}
218GPU_TEST(push_constants_multiple_8192bytes)
219
220} // namespace blender::gpu::tests
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
unsigned int uint
void GPU_compute_dispatch(GPUShader *shader, uint groups_x_len, uint groups_y_len, uint groups_z_len)
void GPU_shader_uniform_2fv(GPUShader *sh, const char *name, const float data[2])
GPUShader * GPU_shader_create_from_info_name(const char *info_name)
void GPU_shader_uniform_1f(GPUShader *sh, const char *name, float value)
void GPU_shader_uniform_3fv(GPUShader *sh, const char *name, const float data[3])
int GPU_shader_get_ssbo_binding(GPUShader *shader, const char *name)
void GPU_shader_bind(GPUShader *shader)
void GPU_shader_uniform_4fv(GPUShader *sh, const char *name, const float data[4])
void GPU_shader_free(GPUShader *shader)
void GPU_shader_unbind()
void GPU_memory_barrier(eGPUBarrier barrier)
Definition gpu_state.cc:374
@ GPU_BARRIER_SHADER_STORAGE
Definition GPU_state.hh:48
void GPU_storagebuf_bind(GPUStorageBuf *ssbo, int slot)
GPUStorageBuf * GPU_storagebuf_create_ex(size_t size, const void *data, GPUUsageType usage, const char *name)
void GPU_storagebuf_free(GPUStorageBuf *ssbo)
void GPU_storagebuf_read(GPUStorageBuf *ssbo, void *data)
@ GPU_USAGE_DEVICE_ONLY
struct GPUShader GPUShader
#define GPU_TEST(test_name)
static void test_push_constants_8192bytes()
static void test_push_constants_128bytes()
static void test_push_constants_multiple_8192bytes()
static void test_push_constants_multiple()
static void test_push_constants()
static void test_push_constants_256bytes()
static void test_push_constants_multiple_128bytes()
static void test_push_constants_multiple_256bytes()
static void test_push_constants_multiple_512bytes()
static void do_push_constants_test(const char *info_name, const int num_calls_simultaneously=1)
static void test_push_constants_512bytes()
VecBase< float, 4 > float4
VecBase< float, 2 > float2
VecBase< float, 3 > float3
void generate_test_data(const float vector_mul, const float scalar_mul)
void init_ssbo(size_t num_floats)
void update_push_constants(const CallData &call_data)
void bind(CallData &call_data)
void init_shader(const char *info_name)