Blender  V3.3
gpu_shader_test.cc
Go to the documentation of this file.
1 /* SPDX-License-Identifier: Apache-2.0 */
2 
3 #include "testing/testing.h"
4 
5 #include "GPU_capabilities.h"
6 #include "GPU_compute.h"
7 #include "GPU_index_buffer.h"
8 #include "GPU_shader.h"
9 #include "GPU_texture.h"
10 #include "GPU_vertex_buffer.h"
11 #include "GPU_vertex_format.h"
12 
13 #include "MEM_guardedalloc.h"
14 
15 #include "gpu_testing.hh"
16 
17 #include "GPU_glew.h"
18 
19 namespace blender::gpu::tests {
20 
22 {
23 
25  /* We can't test as a the platform does not support compute shaders. */
26  std::cout << "Skipping compute shader test: platform not supported";
27  return;
28  }
29 
30  static constexpr uint SIZE = 512;
31 
32  /* Build compute shader. */
33  const char *compute_glsl = R"(
34 
35 layout(local_size_x = 1, local_size_y = 1) in;
36 layout(rgba32f, binding = 0) uniform image2D img_output;
37 
38 void main() {
39  vec4 pixel = vec4(1.0, 0.5, 0.2, 1.0);
40  imageStore(img_output, ivec2(gl_GlobalInvocationID.xy), pixel);
41 }
42 
43 )";
44 
46  compute_glsl, nullptr, nullptr, "gpu_shader_compute_2d");
47  EXPECT_NE(shader, nullptr);
48 
49  /* Create texture to store result and attach to shader. */
51  "gpu_shader_compute_2d", SIZE, SIZE, 1, GPU_RGBA32F, nullptr);
52  EXPECT_NE(texture, nullptr);
53 
54  GPU_shader_bind(shader);
55  GPU_texture_image_bind(texture, GPU_shader_get_texture_binding(shader, "img_output"));
56 
57  /* Dispatch compute task. */
58  GPU_compute_dispatch(shader, SIZE, SIZE, 1);
59 
60  /* Check if compute has been done. */
62  float *data = static_cast<float *>(GPU_texture_read(texture, GPU_DATA_FLOAT, 0));
63  EXPECT_NE(data, nullptr);
64  for (int index = 0; index < SIZE * SIZE; index++) {
65  EXPECT_FLOAT_EQ(data[index * 4 + 0], 1.0f);
66  EXPECT_FLOAT_EQ(data[index * 4 + 1], 0.5f);
67  EXPECT_FLOAT_EQ(data[index * 4 + 2], 0.2f);
68  EXPECT_FLOAT_EQ(data[index * 4 + 3], 1.0f);
69  }
70  MEM_freeN(data);
71 
72  /* Cleanup. */
74  GPU_texture_unbind(texture);
75  GPU_texture_free(texture);
76  GPU_shader_free(shader);
77 }
78 GPU_TEST(gpu_shader_compute_2d)
79 
81 {
82 
84  /* We can't test as a the platform does not support compute shaders. */
85  std::cout << "Skipping compute shader test: platform not supported";
86  return;
87  }
88 
89  static constexpr uint SIZE = 10;
90 
91  /* Build compute shader. */
92  const char *compute_glsl = R"(
93 
94 layout(local_size_x = 1) in;
95 
96 layout(rgba32f, binding = 1) uniform image1D outputVboData;
97 
98 void main() {
99  int index = int(gl_GlobalInvocationID.x);
100  vec4 pos = vec4(gl_GlobalInvocationID.x);
101  imageStore(outputVboData, index, pos);
102 }
103 
104 )";
105 
107  compute_glsl, nullptr, nullptr, "gpu_shader_compute_1d");
108  EXPECT_NE(shader, nullptr);
109 
110  /* Construct Texture. */
112  "gpu_shader_compute_1d", SIZE, 1, GPU_RGBA32F, nullptr);
113  EXPECT_NE(texture, nullptr);
114 
115  GPU_shader_bind(shader);
116  GPU_texture_image_bind(texture, GPU_shader_get_texture_binding(shader, "outputVboData"));
117 
118  /* Dispatch compute task. */
119  GPU_compute_dispatch(shader, SIZE, 1, 1);
120 
121  /* Check if compute has been done. */
123 
124  /* Create texture to load back result. */
125  float *data = static_cast<float *>(GPU_texture_read(texture, GPU_DATA_FLOAT, 0));
126  EXPECT_NE(data, nullptr);
127  for (int index = 0; index < SIZE; index++) {
128  float expected_value = index;
129  EXPECT_FLOAT_EQ(data[index * 4 + 0], expected_value);
130  EXPECT_FLOAT_EQ(data[index * 4 + 1], expected_value);
131  EXPECT_FLOAT_EQ(data[index * 4 + 2], expected_value);
132  EXPECT_FLOAT_EQ(data[index * 4 + 3], expected_value);
133  }
134  MEM_freeN(data);
135 
136  /* Cleanup. */
138  GPU_texture_unbind(texture);
139  GPU_texture_free(texture);
140  GPU_shader_free(shader);
141 }
142 GPU_TEST(gpu_shader_compute_1d)
143 
145 {
146 
148  /* We can't test as a the platform does not support compute shaders. */
149  std::cout << "Skipping compute shader test: platform not supported";
150  return;
151  }
152 
153  static constexpr uint SIZE = 128;
154 
155  /* Build compute shader. */
156  const char *compute_glsl = R"(
157 
158 layout(local_size_x = 1) in;
159 
160 layout(std430, binding = 0) writeonly buffer outputVboData
161 {
162  vec4 out_positions[];
163 };
164 
165 void main() {
166  uint index = gl_GlobalInvocationID.x;
167  vec4 pos = vec4(gl_GlobalInvocationID.x);
168  out_positions[index] = pos;
169 }
170 
171 )";
172 
174  compute_glsl, nullptr, nullptr, "gpu_shader_compute_vbo");
175  EXPECT_NE(shader, nullptr);
176  GPU_shader_bind(shader);
177 
178  /* Construct VBO. */
179  static GPUVertFormat format = {0};
183  GPU_vertbuf_bind_as_ssbo(vbo, GPU_shader_get_ssbo(shader, "outputVboData"));
184 
185  /* Dispatch compute task. */
186  GPU_compute_dispatch(shader, SIZE, 1, 1);
187 
188  /* Check if compute has been done. */
190 
191  /* Download the vertex buffer. */
192  const float *data = static_cast<const float *>(GPU_vertbuf_read(vbo));
193  ASSERT_NE(data, nullptr);
194  for (int index = 0; index < SIZE; index++) {
195  float expected_value = index;
196  EXPECT_FLOAT_EQ(data[index * 4 + 0], expected_value);
197  EXPECT_FLOAT_EQ(data[index * 4 + 1], expected_value);
198  EXPECT_FLOAT_EQ(data[index * 4 + 2], expected_value);
199  EXPECT_FLOAT_EQ(data[index * 4 + 3], expected_value);
200  }
201 
202  /* Cleanup. */
204  GPU_vertbuf_discard(vbo);
205  GPU_shader_free(shader);
206 }
207 GPU_TEST(gpu_shader_compute_vbo)
208 
210 {
211 
213  /* We can't test as a the platform does not support compute shaders. */
214  std::cout << "Skipping compute shader test: platform not supported";
215  return;
216  }
217 
218  static constexpr uint SIZE = 128;
219 
220  /* Build compute shader. */
221  const char *compute_glsl = R"(
222 
223 layout(local_size_x = 1) in;
224 
225 layout(std430, binding = 1) writeonly buffer outputIboData
226 {
227  uint out_indexes[];
228 };
229 
230 void main() {
231  uint store_index = int(gl_GlobalInvocationID.x);
232  out_indexes[store_index] = store_index;
233 }
234 
235 )";
236 
238  compute_glsl, nullptr, nullptr, "gpu_shader_compute_vbo");
239  EXPECT_NE(shader, nullptr);
240  GPU_shader_bind(shader);
241 
242  /* Construct IBO. */
244  GPU_indexbuf_bind_as_ssbo(ibo, GPU_shader_get_ssbo(shader, "outputIboData"));
245 
246  /* Dispatch compute task. */
247  GPU_compute_dispatch(shader, SIZE, 1, 1);
248 
249  /* Check if compute has been done. */
251 
252  /* Download the index buffer. */
253  const uint32_t *data = GPU_indexbuf_read(ibo);
254  ASSERT_NE(data, nullptr);
255  for (int index = 0; index < SIZE; index++) {
256  uint32_t expected = index;
257  EXPECT_EQ(data[index], expected);
258  }
259 
260  /* Cleanup. */
263  GPU_shader_free(shader);
264 }
265 GPU_TEST(gpu_shader_compute_ibo)
266 
268 {
270  /* We can't test as a the platform does not support compute shaders. */
271  std::cout << "Skipping compute shader test: platform not supported";
272  return;
273  }
274 
275  /* Build compute shader. */
276  const char *compute_glsl = R"(
277 
278 layout(local_size_x = 1) in;
279 
280 layout(std430, binding = 0) buffer ssboBinding0
281 {
282  int data0[];
283 };
284 layout(std430, binding = 1) buffer ssboBinding1
285 {
286  int data1[];
287 };
288 
289 void main() {
290 }
291 
292 )";
293 
294  GPUShader *shader = GPU_shader_create_compute(compute_glsl, nullptr, nullptr, "gpu_shader_ssbo");
295  EXPECT_NE(shader, nullptr);
296  GPU_shader_bind(shader);
297 
298  EXPECT_EQ(0, GPU_shader_get_ssbo(shader, "ssboBinding0"));
299  EXPECT_EQ(1, GPU_shader_get_ssbo(shader, "ssboBinding1"));
300 
301  /* Cleanup. */
303  GPU_shader_free(shader);
304 }
305 GPU_TEST(gpu_shader_ssbo_binding)
306 
307 } // namespace blender::gpu::tests
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
#define SIZE
unsigned int uint
Definition: BLI_sys_types.h:67
bool GPU_compute_shader_support(void)
void GPU_compute_dispatch(GPUShader *shader, uint groups_x_len, uint groups_y_len, uint groups_z_len)
Definition: gpu_compute.cc:11
struct GPUIndexBuf GPUIndexBuf
GPUIndexBuf * GPU_indexbuf_build_on_device(uint index_len)
void GPU_indexbuf_bind_as_ssbo(GPUIndexBuf *elem, int binding)
const uint32_t * GPU_indexbuf_read(GPUIndexBuf *elem)
void GPU_indexbuf_discard(GPUIndexBuf *elem)
void GPU_shader_unbind(void)
Definition: gpu_shader.cc:513
struct GPUShader GPUShader
Definition: GPU_shader.h:20
void GPU_shader_bind(GPUShader *shader)
Definition: gpu_shader.cc:491
GPUShader * GPU_shader_create_compute(const char *computecode, const char *libcode, const char *defines, const char *shname)
Definition: gpu_shader.cc:230
int GPU_shader_get_texture_binding(GPUShader *shader, const char *name)
Definition: gpu_shader.cc:599
void GPU_shader_free(GPUShader *shader)
Definition: gpu_shader.cc:200
int GPU_shader_get_ssbo(GPUShader *shader, const char *name)
Definition: gpu_shader.cc:578
void GPU_memory_barrier(eGPUBarrier barrier)
Definition: gpu_state.cc:371
@ GPU_BARRIER_SHADER_STORAGE
Definition: GPU_state.h:29
@ GPU_BARRIER_TEXTURE_FETCH
Definition: GPU_state.h:30
void GPU_texture_image_bind(GPUTexture *tex, int unit)
Definition: gpu_texture.cc:483
GPUTexture * GPU_texture_create_1d(const char *name, int w, int mip_len, eGPUTextureFormat format, const float *data)
Definition: gpu_texture.cc:278
struct GPUTexture GPUTexture
Definition: GPU_texture.h:17
void * GPU_texture_read(GPUTexture *tex, eGPUDataFormat data_format, int miplvl)
Definition: gpu_texture.cc:432
@ GPU_DATA_FLOAT
Definition: GPU_texture.h:171
void GPU_texture_free(GPUTexture *tex)
Definition: gpu_texture.cc:564
void GPU_texture_unbind(GPUTexture *tex)
Definition: gpu_texture.cc:472
GPUTexture * GPU_texture_create_2d(const char *name, int w, int h, int mip_len, eGPUTextureFormat format, const float *data)
Definition: gpu_texture.cc:291
@ GPU_RGBA32F
Definition: GPU_texture.h:90
void GPU_vertbuf_discard(GPUVertBuf *)
struct GPUVertBuf GPUVertBuf
void GPU_vertbuf_data_alloc(GPUVertBuf *, uint v_len)
void GPU_vertbuf_bind_as_ssbo(struct GPUVertBuf *verts, int binding)
const void * GPU_vertbuf_read(GPUVertBuf *verts)
GPUVertBuf * GPU_vertbuf_create_with_format_ex(const GPUVertFormat *, GPUUsageType)
@ GPU_USAGE_DEVICE_ONLY
@ GPU_FETCH_FLOAT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_F32
Read Guarded memory(de)allocation.
#define GPU_TEST(test_name)
Definition: gpu_testing.hh:41
format
Definition: logImageCore.h:38
void(* MEM_freeN)(void *vmemh)
Definition: mallocn.c:27
static void test_gpu_shader_compute_vbo()
static void test_gpu_shader_ssbo_binding()
static void test_gpu_shader_compute_2d()
static void test_gpu_shader_compute_1d()
static void test_gpu_shader_compute_ibo()
unsigned int uint32_t
Definition: stdint.h:80