Files
test/source/blender/gpu/tests/vertex_buffer_test.cc
Clément Foucault e57359726f GPU: VertexFormat: Use new data types
This prevents the use of unaligned data types in
vertex formats. These formats are not supported on many
platform.

This simplify the `GPUVertexFormat` class a lot as
we do not need packing shenanigans anymore and just
compute the vertex stride.

The old enums are kept for progressive porting of the
backends and user code.

This will break compatibility with python addons.

TODO:
- [x] Deprecation warning for PyGPU (4.5)
  - [x] Deprecate matrix attributes
- [x] Error handling for PyGPU (5.0)
- [x] Backends
  - [x] Metal
  - [x] OpenGL
  - [x] Vulkan

Pull Request: https://projects.blender.org/blender/blender/pulls/138846
2025-06-10 17:20:45 +02:00

142 lines
4.5 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<VertAttrType attr_type, 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::VertAttrType::SFLOAT_32_32);
GPU_vertformat_attr_add(&format, "color", attr_type);
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());
switch (attr_type) {
case VertAttrType::SNORM_8_8_8_8:
read_data[0] = read_data[0] * float(127);
break;
case VertAttrType::UNORM_8_8_8_8:
read_data[0] = read_data[0] * float(255);
break;
case VertAttrType::SNORM_16_16_16_16:
read_data[0] = read_data[0] * float(32767);
break;
case VertAttrType::UNORM_16_16_16_16:
read_data[0] = read_data[0] * float(65535);
break;
case VertAttrType::SNORM_10_10_10_2:
read_data[0] = read_data[0] * float4(511, 511, 511, 1);
break;
case VertAttrType::SFLOAT_32_32_32_32:
break;
default:
BLI_assert_unreachable();
}
if (attr_type == VertAttrType::SFLOAT_32_32_32_32) {
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<VertAttrType::SNORM_8_8_8_8, 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<VertAttrType::UNORM_8_8_8_8, 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<VertAttrType::SNORM_16_16_16_16, 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<VertAttrType::UNORM_16_16_16_16, 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<VertAttrType::SNORM_10_10_10_2, 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<VertAttrType::SFLOAT_32_32_32_32, float4>(float4(4, 5, 6, 1));
}
GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_F32__GPU_FETCH_FLOAT);
} // namespace blender::gpu::tests