Blender V5.0
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_batch.hh"
8#include "GPU_context.hh"
9#include "GPU_framebuffer.hh"
10#include "GPU_shader.hh"
11#include "GPU_state.hh"
12#include "GPU_vertex_buffer.hh"
13#include "GPU_vertex_format.hh"
14
15#include "gpu_testing.hh"
16
17#include "BLI_math_vector.hh"
18
20
21namespace blender::gpu::tests {
22
24{
25 const int2 size(1, 1);
28 __func__, UNPACK2(size), 1, TextureFormat::SFLOAT_32_32_32_32, usage, nullptr);
29
30 gpu::FrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
33 GPU_framebuffer_bind(framebuffer);
34
35 const float4 clear_color(0.1f, 0.2f, 0.5f, 1.0f);
36 GPU_framebuffer_clear_color(framebuffer, clear_color);
37 GPU_finish();
38
39 float4 *read_data = static_cast<float4 *>(GPU_texture_read(texture, GPU_DATA_FLOAT, 0));
40 for (float4 pixel_color : Span<float4>(read_data, size.x * size.y)) {
41 EXPECT_EQ(clear_color, pixel_color);
42 }
43 MEM_freeN(read_data);
44
45 GPU_framebuffer_free(framebuffer);
47}
48GPU_TEST(framebuffer_clear_color_single_attachment);
49
51{
52 const int2 size(1, 1);
55 __func__, UNPACK2(size), 1, TextureFormat::SFLOAT_32_32_32_32, usage, nullptr);
57 __func__, UNPACK2(size), 1, TextureFormat::UINT_32_32_32_32, usage, nullptr);
58
59 gpu::FrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
61 &framebuffer,
63 GPU_framebuffer_bind(framebuffer);
64
65 const float4 clear_color(0.1f, 0.2f, 0.5f, 1.0f);
66 GPU_framebuffer_clear_color(framebuffer, clear_color);
67 GPU_finish();
68
69 float4 *read_data1 = static_cast<float4 *>(GPU_texture_read(texture1, GPU_DATA_FLOAT, 0));
70 for (float4 pixel_color : Span<float4>(read_data1, size.x * size.y)) {
71 EXPECT_EQ(clear_color, pixel_color);
72 }
73 MEM_freeN(read_data1);
74
75#ifndef __APPLE__ /* FIXME: Behavior is not the same on all backend. \
76 * Current expected value is broken. */
77 uint4 *read_data2 = static_cast<uint4 *>(GPU_texture_read(texture2, GPU_DATA_UINT, 0));
78 uint4 clear_color_uint(1036831949, 1045220557, 1056964608, 1065353216);
79 for (uint4 pixel_color : Span<uint4>(read_data2, size.x * size.y)) {
80 EXPECT_EQ(clear_color_uint, pixel_color);
81 }
82 MEM_freeN(read_data2);
83#endif
84
85 GPU_framebuffer_free(framebuffer);
86 GPU_texture_free(texture1);
87 GPU_texture_free(texture2);
88}
89GPU_TEST(framebuffer_clear_color_multiple_attachments);
90
92{
93 const int2 size(1, 1);
96 __func__, UNPACK2(size), 1, TextureFormat::SFLOAT_32_32_32_32, usage, nullptr);
98 __func__, UNPACK2(size), 1, TextureFormat::SFLOAT_32_32_32_32, usage, nullptr);
99
100 gpu::FrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
102 &framebuffer,
104 GPU_framebuffer_bind(framebuffer);
105
106 const float4 clear_color[2] = {float4(0.1f, 0.2f, 0.5f, 1.0f), float4(0.5f, 0.2f, 0.1f, 1.0f)};
108 framebuffer, static_cast<const float (*)[4]>(static_cast<const void *>(clear_color)));
109 GPU_finish();
110
111 float4 *read_data1 = static_cast<float4 *>(GPU_texture_read(texture1, GPU_DATA_FLOAT, 0));
112 for (float4 pixel_color : Span<float4>(read_data1, size.x * size.y)) {
113 EXPECT_EQ(clear_color[0], pixel_color);
114 }
115 MEM_freeN(read_data1);
116
117 float4 *read_data2 = static_cast<float4 *>(GPU_texture_read(texture2, GPU_DATA_FLOAT, 0));
118 for (float4 pixel_color : Span<float4>(read_data2, size.x * size.y)) {
119 EXPECT_EQ(clear_color[1], pixel_color);
120 }
121 MEM_freeN(read_data2);
122
123 GPU_framebuffer_free(framebuffer);
124 GPU_texture_free(texture1);
125 GPU_texture_free(texture2);
126}
127GPU_TEST(framebuffer_clear_multiple_color_multiple_attachments);
128
130{
131 const int2 size(1, 1);
134 __func__, UNPACK2(size), 1, TextureFormat::SFLOAT_32_DEPTH, usage, nullptr);
135
136 gpu::FrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
138 GPU_framebuffer_bind(framebuffer);
139
140 const float clear_depth = 0.5f;
141 GPU_framebuffer_clear_depth(framebuffer, clear_depth);
142 GPU_finish();
143
144 float *read_data = static_cast<float *>(GPU_texture_read(texture, GPU_DATA_FLOAT, 0));
145 for (float pixel_depth : Span<float>(read_data, size.x * size.y)) {
146 EXPECT_EQ(clear_depth, pixel_depth);
147 }
148 MEM_freeN(read_data);
149
150 GPU_framebuffer_free(framebuffer);
152}
153GPU_TEST(framebuffer_clear_depth);
154
155#ifndef __APPLE__ /* Clearing with scissors is not supported on Metal. */
156
158{
159 const int2 size(2, 2);
162 __func__, UNPACK2(size), 1, TextureFormat::SFLOAT_32_32_32_32, usage, nullptr);
163
164 gpu::FrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
167 GPU_framebuffer_bind(framebuffer);
168
169 const float4 color1(0.0f);
170 const float4 color2(0.5f);
171 const float4 color3(1.0f);
172 GPU_framebuffer_clear_color(framebuffer, color1);
173
174 GPU_scissor_test(true);
175 GPU_scissor(0, 0, 1, 2);
176 GPU_framebuffer_clear_color(framebuffer, color2);
177
178 GPU_scissor(0, 0, 2, 1);
179 GPU_framebuffer_clear_color(framebuffer, color3);
180 GPU_scissor_test(false);
181 GPU_finish();
182
183 float4 *read_data = static_cast<float4 *>(GPU_texture_read(texture, GPU_DATA_FLOAT, 0));
184 EXPECT_EQ(color3, read_data[0]);
185 EXPECT_EQ(color3, read_data[1]);
186 EXPECT_EQ(color2, read_data[2]);
187 EXPECT_EQ(color1, read_data[3]);
188 MEM_freeN(read_data);
189
190 GPU_framebuffer_free(framebuffer);
192}
193GPU_TEST(framebuffer_scissor_test);
194
195#endif
196
197/* Color each side of a cube-map with a different color. */
199{
200 const int SIZE = 32;
202
205 "tex", SIZE, 1, TextureFormat::SFLOAT_32_32_32_32, usage, nullptr);
206
207 const float4 clear_colors[6] = {
208 {0.5f, 0.0f, 0.0f, 1.0f},
209 {1.0f, 0.0f, 0.0f, 1.0f},
210 {0.0f, 0.5f, 0.0f, 1.0f},
211 {0.0f, 1.0f, 0.0f, 1.0f},
212 {0.0f, 0.0f, 0.5f, 1.0f},
213 {0.0f, 0.0f, 1.0f, 1.0f},
214 };
215 gpu::FrameBuffer *framebuffers[6] = {nullptr};
216
217 for (int i : IndexRange(6)) {
219 {
222 });
225 };
226
228 for (int side : IndexRange(6)) {
229 for (int pixel_index : IndexRange(SIZE * SIZE)) {
230 int index = pixel_index + (SIZE * SIZE) * side;
231 EXPECT_EQ(clear_colors[side], data[index]);
232 }
233 }
235
236 GPU_texture_free(tex);
237
238 for (int i : IndexRange(6)) {
240 }
241
243}
244GPU_TEST(framebuffer_cube)
245
246/* Effectively tests the same way EEVEE-Next shadows are rendered. */
248{
249 using namespace gpu::shader;
253 {
254 GTEST_SKIP() << "NVIDIA fails to compile workaround due to reserved names. Gladly it doesn't "
255 "need the workaround.";
256 }
257
259
260 const int2 size(4, 4);
261 const int layers = 256;
264 __func__, UNPACK2(size), layers, 1, TextureFormat::SINT_32_32, usage, nullptr);
265
266 gpu::FrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
269 GPU_framebuffer_bind(framebuffer);
270
271 int viewport_rects[16][4];
272 for (int i = 0; i < 16; i++) {
273 viewport_rects[i][0] = i % 4;
274 viewport_rects[i][1] = i / 4;
275 viewport_rects[i][2] = 1;
276 viewport_rects[i][3] = 1;
277 }
278 GPU_framebuffer_multi_viewports_set(framebuffer, viewport_rects);
279
280 const float4 clear_color(0.0f);
281 GPU_framebuffer_clear_color(framebuffer, clear_color);
282
283 ShaderCreateInfo create_info("");
284 create_info.vertex_source("gpu_framebuffer_layer_viewport_test.glsl");
285 create_info.fragment_source("gpu_framebuffer_layer_viewport_test.glsl");
286 create_info.builtins(BuiltinBits::VIEWPORT_INDEX | BuiltinBits::LAYER);
287 create_info.fragment_out(0, Type::int2_t, "out_value");
288
290 reinterpret_cast<GPUShaderCreateInfo *>(&create_info));
291
292 int tri_count = size.x * size.y * layers;
293
294 Batch *batch = GPU_batch_create_procedural(GPU_PRIM_TRIS, tri_count * 3);
295
297
299
301
302 GPU_finish();
303
304 int2 *read_data = static_cast<int2 *>(GPU_texture_read(texture, GPU_DATA_INT, 0));
305 for (auto layer : IndexRange(layers)) {
306 for (auto viewport : IndexRange(16)) {
307 int2 expected_color(layer, viewport);
308 int2 pixel_color = read_data[viewport + layer * 16];
309 EXPECT_EQ(pixel_color, expected_color);
310 }
311 }
312 MEM_freeN(read_data);
313
315
316 GPU_framebuffer_free(framebuffer);
319
321}
322GPU_TEST(framebuffer_multi_viewport)
323
324
329{
330 using namespace gpu::shader;
331
333
334 const int2 size(1, 1);
337 __func__, UNPACK2(size), 1, TextureFormat::SINT_32, usage, nullptr);
339 __func__, UNPACK2(size), 1, TextureFormat::SINT_32, usage, nullptr);
340
341 gpu::FrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
343 &framebuffer,
345 GPU_framebuffer_bind(framebuffer);
346
347 const float4 clear_color(0.0f);
348 GPU_framebuffer_clear_color(framebuffer, clear_color);
349
350 ShaderCreateInfo create_info_write("");
351 create_info_write.define("WRITE");
352 create_info_write.vertex_source("gpu_framebuffer_subpass_input_test.glsl");
353 create_info_write.fragment_source("gpu_framebuffer_subpass_input_test.glsl");
354 create_info_write.fragment_out(0, Type::int_t, "out_value", DualBlend::NONE, 0);
355
357 reinterpret_cast<GPUShaderCreateInfo *>(&create_info_write));
358
359 ShaderCreateInfo create_info_read("");
360 create_info_read.define("READ");
361 create_info_read.vertex_source("gpu_framebuffer_subpass_input_test.glsl");
362 create_info_read.fragment_source("gpu_framebuffer_subpass_input_test.glsl");
363 create_info_read.subpass_in(0, Type::int_t, ImageType::Int2D, "in_value", 0);
364 create_info_read.fragment_out(1, Type::int_t, "out_value");
365
367 reinterpret_cast<GPUShaderCreateInfo *>(&create_info_read));
368
370
371 /* Metal Raster Order Group does not need that. */
374
375 GPU_batch_set_shader(batch, shader_write);
377
378 /* Metal Raster Order Group does not need that. */
381
382 GPU_batch_set_shader(batch, shader_read);
384
386
387 GPU_finish();
388
389 int *read_data_a = static_cast<int *>(GPU_texture_read(texture_a, GPU_DATA_INT, 0));
390 EXPECT_EQ(*read_data_a, 0xDEADBEEF);
391 MEM_freeN(read_data_a);
392
393 int *read_data_b = static_cast<int *>(GPU_texture_read(texture_b, GPU_DATA_INT, 0));
394 EXPECT_EQ(*read_data_b, 0xDEADC0DE);
395 MEM_freeN(read_data_b);
396
398
399 GPU_framebuffer_free(framebuffer);
400 GPU_texture_free(texture_a);
401 GPU_texture_free(texture_b);
402 GPU_shader_free(shader_write);
403 GPU_shader_free(shader_read);
404
406}
407GPU_TEST(framebuffer_subpass_input)
408
409} // 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)
void GPU_batch_discard(blender::gpu::Batch *batch)
void GPU_batch_draw(blender::gpu::Batch *batch)
blender::gpu::Batch * GPU_batch_create_procedural(GPUPrimType primitive_type, int32_t vertex_count)
Definition gpu_batch.cc:83
void GPU_batch_set_shader(blender::gpu::Batch *batch, blender::gpu::Shader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
@ GPU_ATTACHMENT_WRITE
@ GPU_ATTACHMENT_READ
@ GPU_ATTACHMENT_IGNORE
void GPU_render_end()
void GPU_render_begin()
blender::gpu::FrameBuffer * GPU_framebuffer_create(const char *name)
#define GPU_FRAMEBUFFER_FREE_SAFE(fb)
#define GPU_ATTACHMENT_TEXTURE(_texture)
#define GPU_ATTACHMENT_TEXTURE_CUBEFACE(_texture, _face)
void GPU_framebuffer_multi_clear(blender::gpu::FrameBuffer *fb, const float(*clear_colors)[4])
#define GPU_ATTACHMENT_NONE
void GPU_framebuffer_free(blender::gpu::FrameBuffer *fb)
void GPU_framebuffer_clear_depth(blender::gpu::FrameBuffer *fb, float clear_depth)
void GPU_framebuffer_clear_color(blender::gpu::FrameBuffer *fb, const float clear_col[4])
#define GPU_framebuffer_ensure_config(_fb,...)
void GPU_framebuffer_multi_viewports_set(blender::gpu::FrameBuffer *gpu_fb, const int viewport_rects[GPU_MAX_VIEWPORTS][4])
void GPU_framebuffer_bind(blender::gpu::FrameBuffer *fb)
#define GPU_framebuffer_subpass_transition(_fb,...)
@ GPU_DEVICE_NVIDIA
@ GPU_DRIVER_OFFICIAL
@ GPU_OS_ANY
bool GPU_type_matches_ex(GPUDeviceType device, GPUOSType os, GPUDriverType driver, GPUBackendType backend)
@ GPU_PRIM_TRIS
void GPU_shader_free(blender::gpu::Shader *shader)
blender::gpu::Shader * GPU_shader_create_from_info(const GPUShaderCreateInfo *_info)
void GPU_shader_unbind()
void GPU_scissor_test(bool enable)
Definition gpu_state.cc:188
void GPU_finish()
Definition gpu_state.cc:310
void GPU_scissor(int x, int y, int width, int height)
Definition gpu_state.cc:193
blender::gpu::Texture * GPU_texture_create_2d_array(const char *name, int width, int height, int layer_len, int mip_len, blender::gpu::TextureFormat format, eGPUTextureUsage usage, const float *data)
blender::gpu::Texture * GPU_texture_create_cube(const char *name, int width, int mip_len, blender::gpu::TextureFormat format, eGPUTextureUsage usage, const float *data)
@ GPU_DATA_INT
@ GPU_DATA_UINT
@ GPU_DATA_FLOAT
eGPUTextureUsage
@ GPU_TEXTURE_USAGE_HOST_READ
@ GPU_TEXTURE_USAGE_ATTACHMENT
void * GPU_texture_read(blender::gpu::Texture *texture, eGPUDataFormat data_format, int mip_level)
blender::gpu::Texture * GPU_texture_create_2d(const char *name, int width, int height, int mip_len, blender::gpu::TextureFormat format, eGPUTextureUsage usage, const float *data)
void GPU_texture_free(blender::gpu::Texture *texture)
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
struct @021025263243242147216143265077100330027142264337::@225245033123204053237120173316075113304004012000 batch
gpu::FrameBuffer * framebuffers[FRAMEBUFFER_STACK_DEPTH]
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
#define GPU_TEST(test_name)
void MEM_freeN(void *vmemh)
Definition mallocn.cc:113
#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< uint32_t, 4 > uint4
VecBase< float, 4 > float4
VecBase< int32_t, 2 > int2
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 & subpass_in(int slot, Type type, ImageType img_type, StringRefNull name, int raster_order_group=-1)
Self & define(StringRefNull name, StringRefNull value="")
i
Definition text_draw.cc:230