Files
test/source/blender/gpu/tests/vertex_buffer_test.cc
Christoph Neuhauser 282d703f6b Fix #139443: WM: Clear draw region framebuffers to avoid corruption
This PR adds a clear on creation for draw region framebuffers, which
fixes issue https://projects.blender.org/blender/blender/issues/139443.
When using the "Lock Interface" option, redrawing is disabled until the
rendering process has finished. When the GPU driver does not initialize
framebuffer textures with zero, this means that visual corruption can
be perceived when resizing the main window while rendering.
This fix makes sure that framebuffer textures are initialized with zero
on all GPU platforms.

Pull Request: https://projects.blender.org/blender/blender/pulls/139445
2025-05-28 13:17:37 +02:00

144 lines
4.6 KiB
C++

/* SPDX-FileCopyrightText: 2023 Blender Authors
*
* SPDX-License-Identifier: Apache-2.0 */
#include "testing/testing.h"
#include "GPU_attribute_convert.hh"
#include "GPU_batch.hh"
#include "GPU_framebuffer.hh"
#include "GPU_shader.hh"
#include "GPU_state.hh"
#include "GPU_vertex_buffer.hh"
#include "GPU_vertex_format.hh"
#include "BLI_index_range.hh"
#include "BLI_math_vector_types.hh"
#include "gpu_testing.hh"
namespace blender::gpu::tests {
static constexpr int Size = 2;
template<GPUVertCompType comp_type, GPUVertFetchMode fetch_mode, typename ColorType>
static void vertex_buffer_fetch_mode(ColorType color)
{
eGPUTextureUsage usage = GPU_TEXTURE_USAGE_ATTACHMENT | GPU_TEXTURE_USAGE_HOST_READ;
GPUOffScreen *offscreen = GPU_offscreen_create(
Size, Size, false, GPU_RGBA32F, usage, false, nullptr);
BLI_assert(offscreen != nullptr);
GPU_offscreen_bind(offscreen, false);
GPUTexture *color_texture = GPU_offscreen_color_texture(offscreen);
GPU_texture_clear(color_texture, GPU_DATA_FLOAT, float4(1.0f, 2.0f, 3.0f, 0.0f));
GPUVertFormat format = {0};
GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT);
GPU_vertformat_attr_add(&format, "color", comp_type, 4, fetch_mode);
struct Vert {
float2 pos;
ColorType color;
};
std::array<Vert, 3> data = {
Vert{float2(-1.0, -1.0), color},
Vert{float2(3.0, -1.0), color},
Vert{float2(-1.0, 3.0), color},
};
VertBuf *vbo = GPU_vertbuf_create_with_format(format);
GPU_vertbuf_data_alloc(*vbo, data.size());
for (int i : IndexRange(data.size())) {
GPU_vertbuf_vert_set(vbo, i, &data[i]);
}
Batch *batch = GPU_batch_create_ex(GPU_PRIM_TRIS, vbo, nullptr, GPU_BATCH_OWNS_VBO);
GPU_batch_program_set_builtin(batch, GPU_SHADER_3D_FLAT_COLOR);
GPU_batch_draw(batch);
GPU_offscreen_unbind(offscreen, false);
GPU_flush();
/* Read back data and perform some basic tests. */
Vector<float4> read_data(Size * Size);
GPU_offscreen_read_color(offscreen, GPU_DATA_FLOAT, read_data.data());
if constexpr (fetch_mode == GPU_FETCH_INT_TO_FLOAT_UNIT) {
switch (comp_type) {
case GPU_COMP_I8:
read_data[0] = read_data[0] * float(127);
break;
case GPU_COMP_U8:
read_data[0] = read_data[0] * float(255);
break;
case GPU_COMP_I16:
read_data[0] = read_data[0] * float(32767);
break;
case GPU_COMP_U16:
read_data[0] = read_data[0] * float(65535);
break;
case GPU_COMP_I10:
read_data[0] = read_data[0] * float4(511, 511, 511, 1);
break;
default:
BLI_assert_unreachable();
}
}
if (fetch_mode == GPU_FETCH_FLOAT) {
EXPECT_EQ(read_data[0], float4(color));
}
else {
/* Do integer comparison to avoid floating point inaccuracies from each conversion steps. */
EXPECT_EQ(int4(read_data[0]), int4(float4(color)));
}
GPU_batch_discard(batch);
GPU_offscreen_free(offscreen);
}
static void test_vertex_buffer_fetch_mode__GPU_COMP_I8__GPU_FETCH_INT_TO_FLOAT_UNIT()
{
vertex_buffer_fetch_mode<GPU_COMP_I8, GPU_FETCH_INT_TO_FLOAT_UNIT, char4>(
char4(100, -127, 127, 0));
}
GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_I8__GPU_FETCH_INT_TO_FLOAT_UNIT);
static void test_vertex_buffer_fetch_mode__GPU_COMP_U8__GPU_FETCH_INT_TO_FLOAT_UNIT()
{
vertex_buffer_fetch_mode<GPU_COMP_U8, GPU_FETCH_INT_TO_FLOAT_UNIT, uchar4>(
uchar4(100, 0, 255, 127));
}
GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_U8__GPU_FETCH_INT_TO_FLOAT_UNIT);
static void test_vertex_buffer_fetch_mode__GPU_COMP_I16__GPU_FETCH_INT_TO_FLOAT_UNIT()
{
vertex_buffer_fetch_mode<GPU_COMP_I16, GPU_FETCH_INT_TO_FLOAT_UNIT, short4>(
short4(12034, -32767, 32767, 0));
}
GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_I16__GPU_FETCH_INT_TO_FLOAT_UNIT);
static void test_vertex_buffer_fetch_mode__GPU_COMP_U16__GPU_FETCH_INT_TO_FLOAT_UNIT()
{
vertex_buffer_fetch_mode<GPU_COMP_U16, GPU_FETCH_INT_TO_FLOAT_UNIT, ushort4>(
ushort4(12034, 0, 65535, 32767));
}
GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_U16__GPU_FETCH_INT_TO_FLOAT_UNIT);
static void test_vertex_buffer_fetch_mode__GPU_COMP_I10__GPU_FETCH_INT_TO_FLOAT_UNIT()
{
vertex_buffer_fetch_mode<GPU_COMP_I10, GPU_FETCH_INT_TO_FLOAT_UNIT, PackedNormal>(
PackedNormal(321, -511, 511, 0));
}
GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_I10__GPU_FETCH_INT_TO_FLOAT_UNIT);
static void test_vertex_buffer_fetch_mode__GPU_COMP_F32__GPU_FETCH_FLOAT()
{
vertex_buffer_fetch_mode<GPU_COMP_F32, GPU_FETCH_FLOAT, float4>(float4(4, 5, 6, 1));
}
GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_F32__GPU_FETCH_FLOAT);
} // namespace blender::gpu::tests