Blender V5.0
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_state.hh"
11#include "GPU_storage_buffer.hh"
12
13#include "BLI_math_vector.hh"
14#include "BLI_utility_mixins.hh"
15#include "BLI_vector.hh"
16
17#include "gpu_testing.hh"
18
19namespace blender::gpu::tests {
20struct CallData {
21 StorageBuf *ssbo = nullptr;
23
24 float float_in;
28
29 void init_ssbo(size_t num_floats)
30 {
31 if (ssbo == nullptr) {
33 num_floats * sizeof(float), nullptr, GPU_USAGE_DEVICE_ONLY, __func__);
34 data.resize(num_floats);
35 }
36 }
37
39 {
40 if (ssbo != nullptr) {
42 ssbo = nullptr;
43 }
44 }
45
46 void generate_test_data(const float vector_mul, const float scalar_mul)
47 {
48 float_in = vector_mul;
49 vec2_in = float2(vector_mul * 2.0, vector_mul * 2.0 + scalar_mul);
51 vector_mul * 3.0, vector_mul * 3.0 + scalar_mul, vector_mul * 3.0 + scalar_mul * 2.0);
52 vec4_in = float4(vector_mul * 4.0,
53 vector_mul * 4.0 + scalar_mul,
54 vector_mul * 4.0 + scalar_mul * 2.0,
55 vector_mul * 4.0 + scalar_mul * 3.0);
56 }
57
63
64 void validate()
65 {
66 /* Check the results. */
68 EXPECT_EQ(vec2_in.x, data[1]);
69 EXPECT_EQ(vec2_in.y, data[2]);
70 EXPECT_EQ(vec3_in.x, data[3]);
71 EXPECT_EQ(vec3_in.y, data[4]);
72 EXPECT_EQ(vec3_in.z, data[5]);
73 EXPECT_EQ(vec4_in.x, data[6]);
74 EXPECT_EQ(vec4_in.y, data[7]);
75 EXPECT_EQ(vec4_in.z, data[8]);
76 EXPECT_EQ(vec4_in.w, data[9]);
77 }
78};
79
80struct Shader {
81 gpu::Shader *shader = nullptr;
83
85 {
86 call_datas.reserve(10);
87 }
88
90 {
91 if (shader != nullptr) {
94 }
95 }
96
97 void init_shader(const char *info_name)
98 {
99 if (shader == nullptr) {
101 EXPECT_NE(shader, nullptr);
103 }
104 }
105
107 {
108 CallData call_data;
109 call_datas.append(call_data);
110 return call_datas.last();
111 }
112
113 void bind(CallData &call_data)
114 {
116 }
117
118 void update_push_constants(const CallData &call_data)
119 {
120 GPU_shader_uniform_1f(shader, "float_in", call_data.float_in);
121 GPU_shader_uniform_2fv(shader, "vec2_in", call_data.vec2_in);
122 GPU_shader_uniform_3fv(shader, "vec3_in", call_data.vec3_in);
123 GPU_shader_uniform_4fv(shader, "vec4_in", call_data.vec4_in);
124 }
125
126 void dispatch()
127 {
128 /* Dispatching 1000000 times to add some stress to the GPU. Without it tests may succeed when
129 * using too simple shaders. */
130 GPU_compute_dispatch(shader, 1000, 1000, 1);
131 }
132};
133
135static void do_push_constants_test(const char *info_name, const int num_calls_simultaneously = 1)
136{
137 static constexpr uint SIZE = 16;
138
140 shader.init_shader(info_name);
141
142 for (const int call_index : IndexRange(num_calls_simultaneously)) {
143 CallData &call_data = shader.new_call();
144 call_data.generate_test_data(call_index * 10.0, (call_index + 1) * 1.0);
145 call_data.init_ssbo(SIZE);
146 shader.bind(call_data);
147 shader.update_push_constants(call_data);
148 shader.dispatch();
149 }
150 /* All calls will be "simultaneously" in flight. First read-back will wait until the dispatches
151 * have finished execution. */
152 for (const int call_index : IndexRange(num_calls_simultaneously)) {
153 CallData &call_data = shader.call_datas[call_index];
154 call_data.read_back();
155 call_data.validate();
156 }
157}
158
159/* Test case with single call as sanity check, before we make it more interesting. */
161{
162 do_push_constants_test("gpu_push_constants_test");
163}
164GPU_TEST(push_constants)
165
167{
168 do_push_constants_test("gpu_push_constants_128bytes_test");
169}
170GPU_TEST(push_constants_128bytes)
171
173{
174 do_push_constants_test("gpu_push_constants_256bytes_test");
175}
176GPU_TEST(push_constants_256bytes)
177
179{
180 do_push_constants_test("gpu_push_constants_512bytes_test");
181}
182GPU_TEST(push_constants_512bytes)
183
185{
186 do_push_constants_test("gpu_push_constants_8192bytes_test");
187}
188GPU_TEST(push_constants_8192bytes)
189
190/* Schedule multiple simultaneously. */
192{
193 do_push_constants_test("gpu_push_constants_test", 10);
194}
195GPU_TEST(push_constants_multiple)
196
198{
199 do_push_constants_test("gpu_push_constants_128bytes_test", 10);
200}
201GPU_TEST(push_constants_multiple_128bytes)
202
204{
205 do_push_constants_test("gpu_push_constants_256bytes_test", 10);
206}
207GPU_TEST(push_constants_multiple_256bytes)
208
210{
211 do_push_constants_test("gpu_push_constants_512bytes_test", 10);
212}
213GPU_TEST(push_constants_multiple_512bytes)
214
216{
217 do_push_constants_test("gpu_push_constants_8192bytes_test", 10);
218}
219GPU_TEST(push_constants_multiple_8192bytes)
220
221} // namespace blender::gpu::tests
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
unsigned int uint
void GPU_compute_dispatch(blender::gpu::Shader *shader, uint groups_x_len, uint groups_y_len, uint groups_z_len, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
void GPU_shader_uniform_1f(blender::gpu::Shader *sh, const char *name, float value)
void GPU_shader_free(blender::gpu::Shader *shader)
void GPU_shader_uniform_4fv(blender::gpu::Shader *sh, const char *name, const float data[4])
void GPU_shader_uniform_3fv(blender::gpu::Shader *sh, const char *name, const float data[3])
void GPU_shader_bind(blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
int GPU_shader_get_ssbo_binding(blender::gpu::Shader *shader, const char *name)
blender::gpu::Shader * GPU_shader_create_from_info_name(const char *info_name)
void GPU_shader_uniform_2fv(blender::gpu::Shader *sh, const char *name, const float data[2])
void GPU_shader_unbind()
@ GPU_BARRIER_SHADER_STORAGE
Definition GPU_state.hh:48
void GPU_memory_barrier(GPUBarrier barrier)
Definition gpu_state.cc:326
void GPU_storagebuf_free(blender::gpu::StorageBuf *ssbo)
blender::gpu::StorageBuf * GPU_storagebuf_create_ex(size_t size, const void *data, GPUUsageType usage, const char *name)
void GPU_storagebuf_bind(blender::gpu::StorageBuf *ssbo, int slot)
void GPU_storagebuf_read(blender::gpu::StorageBuf *ssbo, void *data)
@ GPU_USAGE_DEVICE_ONLY
#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)