Blender V4.3
framebuffer_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_context.hh"
8#include "GPU_framebuffer.hh"
9#include "GPU_shader.hh"
10#include "gpu_testing.hh"
11
12#include "BLI_math_vector.hh"
13
15
16namespace blender::gpu::tests {
17
19{
20 const int2 size(10, 10);
22 GPUTexture *texture = GPU_texture_create_2d(
23 __func__, UNPACK2(size), 1, GPU_RGBA32F, usage, nullptr);
24
25 GPUFrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
28 GPU_framebuffer_bind(framebuffer);
29
30 const float4 clear_color(0.1f, 0.2f, 0.5f, 1.0f);
31 GPU_framebuffer_clear_color(framebuffer, clear_color);
32 GPU_finish();
33
34 float4 *read_data = static_cast<float4 *>(GPU_texture_read(texture, GPU_DATA_FLOAT, 0));
35 for (float4 pixel_color : Span<float4>(read_data, size.x * size.y)) {
36 EXPECT_EQ(clear_color, pixel_color);
37 }
38 MEM_freeN(read_data);
39
40 GPU_framebuffer_free(framebuffer);
41 GPU_texture_free(texture);
42}
43GPU_TEST(framebuffer_clear_color_single_attachment);
44
46{
47 const int2 size(10, 10);
49 GPUTexture *texture1 = GPU_texture_create_2d(
50 __func__, UNPACK2(size), 1, GPU_RGBA32F, usage, nullptr);
51 GPUTexture *texture2 = GPU_texture_create_2d(
52 __func__, UNPACK2(size), 1, GPU_RGBA32UI, usage, nullptr);
53
54 GPUFrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
56 &framebuffer,
58 GPU_framebuffer_bind(framebuffer);
59
60 const float4 clear_color(0.1f, 0.2f, 0.5f, 1.0f);
61 GPU_framebuffer_clear_color(framebuffer, clear_color);
62 GPU_finish();
63
64 float4 *read_data1 = static_cast<float4 *>(GPU_texture_read(texture1, GPU_DATA_FLOAT, 0));
65 for (float4 pixel_color : Span<float4>(read_data1, size.x * size.y)) {
66 EXPECT_EQ(clear_color, pixel_color);
67 }
68 MEM_freeN(read_data1);
69
70 uint4 *read_data2 = static_cast<uint4 *>(GPU_texture_read(texture2, GPU_DATA_UINT, 0));
71 uint4 clear_color_uint(1036831949, 1045220557, 1056964608, 1065353216);
72 for (uint4 pixel_color : Span<uint4>(read_data2, size.x * size.y)) {
73 EXPECT_EQ(clear_color_uint, pixel_color);
74 }
75 MEM_freeN(read_data2);
76
77 GPU_framebuffer_free(framebuffer);
78 GPU_texture_free(texture1);
79 GPU_texture_free(texture2);
80}
81GPU_TEST(framebuffer_clear_color_multiple_attachments);
82
84{
85 const int2 size(10, 10);
87 GPUTexture *texture1 = GPU_texture_create_2d(
88 __func__, UNPACK2(size), 1, GPU_RGBA32F, usage, nullptr);
89 GPUTexture *texture2 = GPU_texture_create_2d(
90 __func__, UNPACK2(size), 1, GPU_RGBA32F, usage, nullptr);
91
92 GPUFrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
94 &framebuffer,
96 GPU_framebuffer_bind(framebuffer);
97
98 const float4 clear_color[2] = {float4(0.1f, 0.2f, 0.5f, 1.0f), float4(0.5f, 0.2f, 0.1f, 1.0f)};
100 framebuffer, static_cast<const float(*)[4]>(static_cast<const void *>(clear_color)));
101 GPU_finish();
102
103 float4 *read_data1 = static_cast<float4 *>(GPU_texture_read(texture1, GPU_DATA_FLOAT, 0));
104 for (float4 pixel_color : Span<float4>(read_data1, size.x * size.y)) {
105 EXPECT_EQ(clear_color[0], pixel_color);
106 }
107 MEM_freeN(read_data1);
108
109 float4 *read_data2 = static_cast<float4 *>(GPU_texture_read(texture2, GPU_DATA_FLOAT, 0));
110 for (float4 pixel_color : Span<float4>(read_data2, size.x * size.y)) {
111 EXPECT_EQ(clear_color[1], pixel_color);
112 }
113 MEM_freeN(read_data2);
114
115 GPU_framebuffer_free(framebuffer);
116 GPU_texture_free(texture1);
117 GPU_texture_free(texture2);
118}
119GPU_TEST(framebuffer_clear_multiple_color_multiple_attachments);
120
122{
123 const int2 size(10, 10);
125 GPUTexture *texture = GPU_texture_create_2d(
126 __func__, UNPACK2(size), 1, GPU_DEPTH_COMPONENT32F, usage, nullptr);
127
128 GPUFrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
130 GPU_framebuffer_bind(framebuffer);
131
132 const float clear_depth = 0.5f;
133 GPU_framebuffer_clear_depth(framebuffer, clear_depth);
134 GPU_finish();
135
136 float *read_data = static_cast<float *>(GPU_texture_read(texture, GPU_DATA_FLOAT, 0));
137 for (float pixel_depth : Span<float>(read_data, size.x * size.y)) {
138 EXPECT_EQ(clear_depth, pixel_depth);
139 }
140 MEM_freeN(read_data);
141
142 GPU_framebuffer_free(framebuffer);
143 GPU_texture_free(texture);
144}
145GPU_TEST(framebuffer_clear_depth);
146
148{
149 const int2 size(128, 128);
150 const int bar_size = 16;
152 GPUTexture *texture = GPU_texture_create_2d(
153 __func__, UNPACK2(size), 1, GPU_RGBA32F, usage, nullptr);
154
155 GPUFrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
158 GPU_framebuffer_bind(framebuffer);
159
160 const float4 color1(0.0f);
161 const float4 color2(0.5f);
162 const float4 color3(1.0f);
163 GPU_framebuffer_clear_color(framebuffer, color1);
164
165 GPU_scissor_test(true);
166 for (int x = 0; x < size.x; x += 2 * bar_size) {
167 GPU_scissor(x, 0, bar_size, size.y);
168 GPU_framebuffer_clear_color(framebuffer, color2);
169 }
170 for (int y = 0; y < size.y; y += 2 * bar_size) {
171 GPU_scissor(0, y, size.x, bar_size);
172 GPU_framebuffer_clear_color(framebuffer, color3);
173 }
174 GPU_scissor_test(false);
175 GPU_finish();
176
177 float4 *read_data = static_cast<float4 *>(GPU_texture_read(texture, GPU_DATA_FLOAT, 0));
178 int offset = 0;
179 for (float4 pixel_color : Span<float4>(read_data, size.x * size.y)) {
180 int x = offset % size.x;
181 int y = offset / size.x;
182 int bar_x = x / bar_size;
183 int bar_y = y / bar_size;
184
185 if (bar_y % 2 == 0) {
186 EXPECT_EQ(pixel_color, color3);
187 }
188 else {
189 if (bar_x % 2 == 0) {
190 EXPECT_EQ(color2, pixel_color);
191 }
192 else {
193 EXPECT_EQ(color1, pixel_color);
194 }
195 }
196
197 offset++;
198 }
199 MEM_freeN(read_data);
200
201 GPU_framebuffer_free(framebuffer);
202 GPU_texture_free(texture);
203}
204GPU_TEST(framebuffer_scissor_test);
205
206/* Color each side of a cube-map with a different color. */
208{
209 const int SIZE = 32;
211
213 GPUTexture *tex = GPU_texture_create_cube("tex", SIZE, 1, GPU_RGBA32F, usage, nullptr);
214
215 const float4 clear_colors[6] = {
216 {0.5f, 0.0f, 0.0f, 1.0f},
217 {1.0f, 0.0f, 0.0f, 1.0f},
218 {0.0f, 0.5f, 0.0f, 1.0f},
219 {0.0f, 1.0f, 0.0f, 1.0f},
220 {0.0f, 0.0f, 0.5f, 1.0f},
221 {0.0f, 0.0f, 1.0f, 1.0f},
222 };
223 GPUFrameBuffer *framebuffers[6] = {nullptr};
224
225 for (int i : IndexRange(6)) {
227 {
230 });
232 GPU_framebuffer_clear_color(framebuffers[i], clear_colors[i]);
233 };
234
236 for (int side : IndexRange(6)) {
237 for (int pixel_index : IndexRange(SIZE * SIZE)) {
238 int index = pixel_index + (SIZE * SIZE) * side;
239 EXPECT_EQ(clear_colors[side], data[index]);
240 }
241 }
242 MEM_freeN(data);
243
245
246 for (int i : IndexRange(6)) {
248 }
249
251}
252GPU_TEST(framebuffer_cube)
253
254/* Effectively tests the same way EEVEE-Next shadows are rendered. */
256{
257 using namespace gpu::shader;
261 {
262 GTEST_SKIP() << "NVIDIA fails to compile workaround due to reserved names. Gladly it doesn't "
263 "need the workaround.";
264 }
265
267
268 const int2 size(4, 4);
269 const int layers = 256;
271 GPUTexture *texture = GPU_texture_create_2d_array(
272 __func__, UNPACK2(size), layers, 1, GPU_RG32I, usage, nullptr);
273
274 GPUFrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
277 GPU_framebuffer_bind(framebuffer);
278
279 int viewport_rects[16][4];
280 for (int i = 0; i < 16; i++) {
281 viewport_rects[i][0] = i % 4;
282 viewport_rects[i][1] = i / 4;
283 viewport_rects[i][2] = 1;
284 viewport_rects[i][3] = 1;
285 }
286 GPU_framebuffer_multi_viewports_set(framebuffer, viewport_rects);
287
288 const float4 clear_color(0.0f);
289 GPU_framebuffer_clear_color(framebuffer, clear_color);
290
291 ShaderCreateInfo create_info("");
292 create_info.vertex_source("gpu_framebuffer_layer_viewport_test.glsl");
293 create_info.fragment_source("gpu_framebuffer_layer_viewport_test.glsl");
294 create_info.builtins(BuiltinBits::VIEWPORT_INDEX | BuiltinBits::LAYER);
295 create_info.fragment_out(0, Type::IVEC2, "out_value");
296
298 reinterpret_cast<GPUShaderCreateInfo *>(&create_info));
299
300 /* TODO(fclem): remove this boilerplate. */
306
308
309 int tri_count = size.x * size.y * layers;
310 GPU_batch_draw_advanced(batch, 0, tri_count * 3, 0, 1);
311
313
314 GPU_finish();
315
316 int2 *read_data = static_cast<int2 *>(GPU_texture_read(texture, GPU_DATA_INT, 0));
317 for (auto layer : IndexRange(layers)) {
318 for (auto viewport : IndexRange(16)) {
319 int2 expected_color(layer, viewport);
320 int2 pixel_color = read_data[viewport + layer * 16];
321 EXPECT_EQ(pixel_color, expected_color);
322 }
323 }
324 MEM_freeN(read_data);
325
326 GPU_framebuffer_free(framebuffer);
327 GPU_texture_free(texture);
328 GPU_shader_free(shader);
329
331}
332GPU_TEST(framebuffer_multi_viewport)
333
334
339{
340 using namespace gpu::shader;
341
343
344 const int2 size(1, 1);
346 GPUTexture *texture_a = GPU_texture_create_2d(
347 __func__, UNPACK2(size), 1, GPU_R32I, usage, nullptr);
348 GPUTexture *texture_b = GPU_texture_create_2d(
349 __func__, UNPACK2(size), 1, GPU_R32I, usage, nullptr);
350
351 GPUFrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
353 &framebuffer,
355 GPU_framebuffer_bind(framebuffer);
356
357 const float4 clear_color(0.0f);
358 GPU_framebuffer_clear_color(framebuffer, clear_color);
359
360 ShaderCreateInfo create_info_write("");
361 create_info_write.define("WRITE");
362 create_info_write.vertex_source("gpu_framebuffer_subpass_input_test.glsl");
363 create_info_write.fragment_source("gpu_framebuffer_subpass_input_test.glsl");
364 create_info_write.fragment_out(0, Type::INT, "out_value", DualBlend::NONE, 0);
365
367 reinterpret_cast<GPUShaderCreateInfo *>(&create_info_write));
368
369 ShaderCreateInfo create_info_read("");
370 create_info_read.define("READ");
371 create_info_read.vertex_source("gpu_framebuffer_subpass_input_test.glsl");
372 create_info_read.fragment_source("gpu_framebuffer_subpass_input_test.glsl");
373 create_info_read.subpass_in(0, Type::INT, "in_value", 0);
374 create_info_read.fragment_out(1, Type::INT, "out_value");
375
377 reinterpret_cast<GPUShaderCreateInfo *>(&create_info_read));
378
379 /* TODO(fclem): remove this boilerplate. */
385
386 /* Metal Raster Order Group does not need that. */
389
390 GPU_batch_set_shader(batch, shader_write);
392
393 /* Metal Raster Order Group does not need that. */
396
397 GPU_batch_set_shader(batch, shader_read);
399
401
402 GPU_finish();
403
404 int *read_data_a = static_cast<int *>(GPU_texture_read(texture_a, GPU_DATA_INT, 0));
405 EXPECT_EQ(*read_data_a, 0xDEADBEEF);
406 MEM_freeN(read_data_a);
407
408 int *read_data_b = static_cast<int *>(GPU_texture_read(texture_b, GPU_DATA_INT, 0));
409 EXPECT_EQ(*read_data_b, 0xDEADC0DE);
410 MEM_freeN(read_data_b);
411
412 GPU_framebuffer_free(framebuffer);
413 GPU_texture_free(texture_a);
414 GPU_texture_free(texture_b);
415 GPU_shader_free(shader_write);
416 GPU_shader_free(shader_read);
417
419}
420GPU_TEST(framebuffer_subpass_input)
421
422} // namespace blender::gpu::tests
@ G_DEBUG_GPU_FORCE_WORKAROUNDS
EXPECT_EQ(BLI_expr_pylike_eval(expr, nullptr, 0, &result), EXPR_PYLIKE_INVALID)
#define UNPACK2(a)
blender::gpu::Batch * GPU_batch_create_ex(GPUPrimType primitive_type, blender::gpu::VertBuf *vertex_buf, blender::gpu::IndexBuf *index_buf, eGPUBatchFlag owns_flag)
Definition gpu_batch.cc:56
void GPU_batch_discard(blender::gpu::Batch *batch)
void GPU_batch_draw_advanced(blender::gpu::Batch *batch, int vertex_first, int vertex_count, int instance_first, int instance_count)
void GPU_batch_set_shader(blender::gpu::Batch *batch, GPUShader *shader)
void GPU_batch_draw(blender::gpu::Batch *batch)
@ GPU_BATCH_OWNS_VBO
Definition GPU_batch.hh:42
@ GPU_ATTACHMENT_WRITE
@ GPU_ATTACHMENT_READ
@ GPU_ATTACHMENT_IGNORE
void GPU_render_end()
void GPU_render_begin()
void GPU_framebuffer_multi_viewports_set(GPUFrameBuffer *gpu_fb, const int viewport_rects[GPU_MAX_VIEWPORTS][4])
GPUFrameBuffer * GPU_framebuffer_create(const char *name)
#define GPU_FRAMEBUFFER_FREE_SAFE(fb)
#define GPU_ATTACHMENT_TEXTURE(_texture)
#define GPU_ATTACHMENT_TEXTURE_CUBEFACE(_texture, _face)
#define GPU_ATTACHMENT_NONE
void GPU_framebuffer_multi_clear(GPUFrameBuffer *framebuffer, const float(*clear_colors)[4])
void GPU_framebuffer_bind(GPUFrameBuffer *framebuffer)
void GPU_framebuffer_clear_color(GPUFrameBuffer *fb, const float clear_col[4])
#define GPU_framebuffer_ensure_config(_fb,...)
void GPU_framebuffer_clear_depth(GPUFrameBuffer *fb, float clear_depth)
void GPU_framebuffer_free(GPUFrameBuffer *framebuffer)
#define GPU_framebuffer_subpass_transition(_fb,...)
@ GPU_DRIVER_OFFICIAL
bool GPU_type_matches_ex(eGPUDeviceType device, eGPUOSType os, eGPUDriverType driver, eGPUBackendType backend)
@ GPU_OS_ANY
@ GPU_DEVICE_NVIDIA
@ GPU_PRIM_TRIS
GPUShader * GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
void GPU_shader_free(GPUShader *shader)
void GPU_scissor_test(bool enable)
Definition gpu_state.cc:183
void GPU_finish()
Definition gpu_state.cc:299
void GPU_scissor(int x, int y, int width, int height)
Definition gpu_state.cc:188
GPUTexture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(GPUTexture *texture)
void * GPU_texture_read(GPUTexture *texture, eGPUDataFormat data_format, int mip_level)
@ GPU_DATA_INT
@ GPU_DATA_UINT
@ GPU_DATA_FLOAT
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_HOST_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
GPUTexture * GPU_texture_create_2d_array(const char *name, int width, int height, int layer_len, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
@ GPU_R32I
@ GPU_RG32I
@ GPU_RGBA32UI
@ GPU_DEPTH_COMPONENT32F
GPUTexture * GPU_texture_create_cube(const char *name, int width, int mip_len, eGPUTextureFormat format, eGPUTextureUsage usage, const float *data)
#define GPU_vertbuf_create_with_format(format)
void GPU_vertbuf_data_alloc(blender::gpu::VertBuf &verts, uint v_len)
@ GPU_FETCH_INT
uint GPU_vertformat_attr_add(GPUVertFormat *, const char *name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_U32
struct GPUShader GPUShader
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
additional_info("compositor_sum_float_shared") .push_constant(Type additional_info("compositor_sum_float_shared") .push_constant(Type GPU_RGBA32F
static float verts[][3]
struct @620::@622 batch
GPUFrameBuffer * framebuffers[FRAMEBUFFER_STACK_DEPTH]
#define GPU_TEST(test_name)
format
void MEM_freeN(void *vmemh)
Definition mallocn.cc:105
#define G(x, y, z)
static void test_framebuffer_clear_depth()
static void test_framebuffer_clear_color_single_attachment()
static void test_framebuffer_clear_multiple_color_multiple_attachments()
static void test_framebuffer_cube()
static void test_framebuffer_subpass_input()
static void test_framebuffer_scissor_test()
static void test_framebuffer_multi_viewport()
static void test_framebuffer_clear_color_multiple_attachments()
VecBase< float, 4 > float4
Describe inputs & outputs, stage interfaces, resources and sources of a shader. If all data is correc...
Self & fragment_source(StringRefNull filename)
Self & fragment_out(int slot, Type type, StringRefNull name, DualBlend blend=DualBlend::NONE, int raster_order_group=-1)
Self & vertex_source(StringRefNull filename)
Self & subpass_in(int slot, Type type, StringRefNull name, int raster_order_group=-1)
Self & define(StringRefNull name, StringRefNull value="")