Blender V4.5
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);
27 GPUTexture *texture = GPU_texture_create_2d(
28 __func__, UNPACK2(size), 1, GPU_RGBA32F, usage, nullptr);
29
30 GPUFrameBuffer *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);
54 GPUTexture *texture1 = GPU_texture_create_2d(
55 __func__, UNPACK2(size), 1, GPU_RGBA32F, usage, nullptr);
56 GPUTexture *texture2 = GPU_texture_create_2d(
57 __func__, UNPACK2(size), 1, GPU_RGBA32UI, usage, nullptr);
58
59 GPUFrameBuffer *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);
95 GPUTexture *texture1 = GPU_texture_create_2d(
96 __func__, UNPACK2(size), 1, GPU_RGBA32F, usage, nullptr);
97 GPUTexture *texture2 = GPU_texture_create_2d(
98 __func__, UNPACK2(size), 1, GPU_RGBA32F, usage, nullptr);
99
100 GPUFrameBuffer *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);
133 GPUTexture *texture = GPU_texture_create_2d(
134 __func__, UNPACK2(size), 1, GPU_DEPTH_COMPONENT32F, usage, nullptr);
135
136 GPUFrameBuffer *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);
161 GPUTexture *texture = GPU_texture_create_2d(
162 __func__, UNPACK2(size), 1, GPU_RGBA32F, usage, nullptr);
163
164 GPUFrameBuffer *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
204 GPUTexture *tex = GPU_texture_create_cube("tex", SIZE, 1, GPU_RGBA32F, usage, nullptr);
205
206 const float4 clear_colors[6] = {
207 {0.5f, 0.0f, 0.0f, 1.0f},
208 {1.0f, 0.0f, 0.0f, 1.0f},
209 {0.0f, 0.5f, 0.0f, 1.0f},
210 {0.0f, 1.0f, 0.0f, 1.0f},
211 {0.0f, 0.0f, 0.5f, 1.0f},
212 {0.0f, 0.0f, 1.0f, 1.0f},
213 };
214 GPUFrameBuffer *framebuffers[6] = {nullptr};
215
216 for (int i : IndexRange(6)) {
218 {
221 });
224 };
225
227 for (int side : IndexRange(6)) {
228 for (int pixel_index : IndexRange(SIZE * SIZE)) {
229 int index = pixel_index + (SIZE * SIZE) * side;
230 EXPECT_EQ(clear_colors[side], data[index]);
231 }
232 }
234
235 GPU_texture_free(tex);
236
237 for (int i : IndexRange(6)) {
239 }
240
242}
243GPU_TEST(framebuffer_cube)
244
245/* Effectively tests the same way EEVEE-Next shadows are rendered. */
247{
248 using namespace gpu::shader;
252 {
253 GTEST_SKIP() << "NVIDIA fails to compile workaround due to reserved names. Gladly it doesn't "
254 "need the workaround.";
255 }
256
258
259 const int2 size(4, 4);
260 const int layers = 256;
263 __func__, UNPACK2(size), layers, 1, GPU_RG32I, usage, nullptr);
264
265 GPUFrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
268 GPU_framebuffer_bind(framebuffer);
269
270 int viewport_rects[16][4];
271 for (int i = 0; i < 16; i++) {
272 viewport_rects[i][0] = i % 4;
273 viewport_rects[i][1] = i / 4;
274 viewport_rects[i][2] = 1;
275 viewport_rects[i][3] = 1;
276 }
277 GPU_framebuffer_multi_viewports_set(framebuffer, viewport_rects);
278
279 const float4 clear_color(0.0f);
280 GPU_framebuffer_clear_color(framebuffer, clear_color);
281
282 ShaderCreateInfo create_info("");
283 create_info.vertex_source("gpu_framebuffer_layer_viewport_test.glsl");
284 create_info.fragment_source("gpu_framebuffer_layer_viewport_test.glsl");
285 create_info.builtins(BuiltinBits::VIEWPORT_INDEX | BuiltinBits::LAYER);
286 create_info.fragment_out(0, Type::int2_t, "out_value");
287
289 reinterpret_cast<GPUShaderCreateInfo *>(&create_info));
290
291 /* TODO(fclem): remove this boilerplate. */
297
299
300 int tri_count = size.x * size.y * layers;
301 GPU_batch_draw_advanced(batch, 0, tri_count * 3, 0, 1);
302
304
305 GPU_finish();
306
307 int2 *read_data = static_cast<int2 *>(GPU_texture_read(texture, GPU_DATA_INT, 0));
308 for (auto layer : IndexRange(layers)) {
309 for (auto viewport : IndexRange(16)) {
310 int2 expected_color(layer, viewport);
311 int2 pixel_color = read_data[viewport + layer * 16];
312 EXPECT_EQ(pixel_color, expected_color);
313 }
314 }
315 MEM_freeN(read_data);
316
318
319 GPU_framebuffer_free(framebuffer);
322
324}
325GPU_TEST(framebuffer_multi_viewport)
326
327
332{
333 using namespace gpu::shader;
334
336
337 const int2 size(1, 1);
339 GPUTexture *texture_a = GPU_texture_create_2d(
340 __func__, UNPACK2(size), 1, GPU_R32I, usage, nullptr);
341 GPUTexture *texture_b = GPU_texture_create_2d(
342 __func__, UNPACK2(size), 1, GPU_R32I, usage, nullptr);
343
344 GPUFrameBuffer *framebuffer = GPU_framebuffer_create(__func__);
346 &framebuffer,
348 GPU_framebuffer_bind(framebuffer);
349
350 const float4 clear_color(0.0f);
351 GPU_framebuffer_clear_color(framebuffer, clear_color);
352
353 ShaderCreateInfo create_info_write("");
354 create_info_write.define("WRITE");
355 create_info_write.vertex_source("gpu_framebuffer_subpass_input_test.glsl");
356 create_info_write.fragment_source("gpu_framebuffer_subpass_input_test.glsl");
357 create_info_write.fragment_out(0, Type::int_t, "out_value", DualBlend::NONE, 0);
358
359 GPUShader *shader_write = GPU_shader_create_from_info(
360 reinterpret_cast<GPUShaderCreateInfo *>(&create_info_write));
361
362 ShaderCreateInfo create_info_read("");
363 create_info_read.define("READ");
364 create_info_read.vertex_source("gpu_framebuffer_subpass_input_test.glsl");
365 create_info_read.fragment_source("gpu_framebuffer_subpass_input_test.glsl");
366 create_info_read.subpass_in(0, Type::int_t, ImageType::Int2D, "in_value", 0);
367 create_info_read.fragment_out(1, Type::int_t, "out_value");
368
369 GPUShader *shader_read = GPU_shader_create_from_info(
370 reinterpret_cast<GPUShaderCreateInfo *>(&create_info_read));
371
372 /* TODO(fclem): remove this boilerplate. */
378
379 /* Metal Raster Order Group does not need that. */
382
383 GPU_batch_set_shader(batch, shader_write);
385
386 /* Metal Raster Order Group does not need that. */
389
390 GPU_batch_set_shader(batch, shader_read);
392
394
395 GPU_finish();
396
397 int *read_data_a = static_cast<int *>(GPU_texture_read(texture_a, GPU_DATA_INT, 0));
398 EXPECT_EQ(*read_data_a, 0xDEADBEEF);
399 MEM_freeN(read_data_a);
400
401 int *read_data_b = static_cast<int *>(GPU_texture_read(texture_b, GPU_DATA_INT, 0));
402 EXPECT_EQ(*read_data_b, 0xDEADC0DE);
403 MEM_freeN(read_data_b);
404
406
407 GPU_framebuffer_free(framebuffer);
408 GPU_texture_free(texture_a);
409 GPU_texture_free(texture_b);
410 GPU_shader_free(shader_write);
411 GPU_shader_free(shader_read);
412
414}
415GPU_TEST(framebuffer_subpass_input)
416
417} // 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:51
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_draw(blender::gpu::Batch *batch)
void GPU_batch_set_shader(blender::gpu::Batch *batch, GPUShader *shader, const blender::gpu::shader::SpecializationConstants *constants_state=nullptr)
@ GPU_BATCH_OWNS_VBO
Definition GPU_batch.hh:41
@ 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_free(GPUFrameBuffer *fb)
void GPU_framebuffer_bind(GPUFrameBuffer *fb)
void GPU_framebuffer_multi_clear(GPUFrameBuffer *fb, const float(*clear_colors)[4])
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)
#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_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
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_RGBA32F
@ 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 *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
@ GPU_COMP_U32
BMesh const char void * data
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition btDbvt.cpp:52
static float verts[][3]
struct @064345207361167251075330302113175271221317160336::@113254110077376341056327177062323111323010325277 batch
GPUFrameBuffer * framebuffers[FRAMEBUFFER_STACK_DEPTH]
TEX_TEMPLATE DataVec texture(T, FltCoord, float=0.0f) RET
#define GPU_TEST(test_name)
format
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