From ad7465be67ea31911437e9c21600f8423c30c3ec Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 8 May 2023 12:28:11 +0200 Subject: [PATCH 1/5] Vulkan: Convert VertexBuffer to Contain Supported Attributes Vulkan doesn't have a conversion from uint32_t/int32_t to float. It does have conversions from 16/8 bits. Main reason is that Vulkan expects that there is no benefit when converting 32 bits from one type to the other and should be solved by passing the right data type. In Blender however this isn't the case as there are benefits on other GPU backends (OpenGL for example). This PR adds helper function to check if conversion is needed and perform any conversions in place. It also implements the function to upload vertex buffers to the GPU. --- .../blender/gpu/vulkan/vk_data_conversion.cc | 52 +++++++++++++++++++ .../blender/gpu/vulkan/vk_data_conversion.hh | 24 +++++++++ source/blender/gpu/vulkan/vk_vertex_buffer.cc | 43 ++++++++++++++- source/blender/gpu/vulkan/vk_vertex_buffer.hh | 6 +++ 4 files changed, 123 insertions(+), 2 deletions(-) diff --git a/source/blender/gpu/vulkan/vk_data_conversion.cc b/source/blender/gpu/vulkan/vk_data_conversion.cc index 5851189c5d3..e31fd3845ff 100644 --- a/source/blender/gpu/vulkan/vk_data_conversion.cc +++ b/source/blender/gpu/vulkan/vk_data_conversion.cc @@ -882,4 +882,56 @@ void convert_device_to_host(void *dst_buffer, /* \} */ +/* -------------------------------------------------------------------- */ +/** \name Vertex Attributes + * \{ */ + +static bool conversion_needed(const GPUVertAttr &vertex_attribute) +{ + return (vertex_attribute.fetch_mode == GPU_FETCH_INT_TO_FLOAT && + ELEM(vertex_attribute.comp_type, GPU_COMP_I32, GPU_COMP_U32)); +} + +bool conversion_needed(const GPUVertFormat &vertex_format) +{ + for (int attr_index : IndexRange(vertex_format.attr_len)) { + const GPUVertAttr &vert_attr = vertex_format.attrs[attr_index]; + if (conversion_needed(vert_attr)) { + return true; + } + } + return false; +} + +void convert_in_place(void *data, const GPUVertFormat &vertex_format, const uint vertex_len) +{ + BLI_assert(vertex_format.deinterleaved == false); + for (int attr_index : IndexRange(vertex_format.attr_len)) { + const GPUVertAttr &vert_attr = vertex_format.attrs[attr_index]; + if (!conversion_needed(vert_attr)) { + continue; + } + void *row_data = static_cast(data) + vert_attr.offset; + for (int vert_index = 0; vert_index < vertex_len; vert_index++) { + if (vert_attr.comp_type == GPU_COMP_I32) { + for (int component : IndexRange(vert_attr.comp_len)) { + int32_t *component_in = static_cast(row_data) + component; + float *component_out = static_cast(row_data) + component; + *component_out = float(*component_in); + } + } + else if (vert_attr.comp_type == GPU_COMP_U32) { + for (int component : IndexRange(vert_attr.comp_len)) { + uint32_t *component_in = static_cast(row_data) + component; + float *component_out = static_cast(row_data) + component; + *component_out = float(*component_in); + } + } + row_data = static_cast(row_data) + vertex_format.stride; + } + } +} + +/* \} */ + } // namespace blender::gpu diff --git a/source/blender/gpu/vulkan/vk_data_conversion.hh b/source/blender/gpu/vulkan/vk_data_conversion.hh index f9fe41da782..1b5405f04c1 100644 --- a/source/blender/gpu/vulkan/vk_data_conversion.hh +++ b/source/blender/gpu/vulkan/vk_data_conversion.hh @@ -72,4 +72,28 @@ void convert_device_to_host(void *dst_buffer, eGPUDataFormat host_format, eGPUTextureFormat device_format); +/** + * Are all attributes of the given vertex format natively supported or does conversion needs to + * happen. + * + * \param vertex_format: the vertex format to check if an associated buffer requires conversion + * being done on the host. + */ +bool conversion_needed(const GPUVertFormat &vertex_format); + +/** + * Convert the given `data` to contain Vulkan natively supported data formats. + * + * When for an vertex attribute the fetch mode is set to GPU_FETCH_INT_TO_FLOAT and the attribute + * is an int32_t or uint32_t the conversion will be done. Attributes of 16 or 8 bits are supported + * natively and will be done in Vulkan. + * + * \param data: Buffer to convert. Data will be converted in place. + * \param vertex_format: Vertex format of the given data. Attributes that aren't supported will be + * converted to a supported one. + * \param vertex_len: Number of vertices of the given data buffer; + * The number of vertices to convert. + */ +void convert_in_place(void *data, const GPUVertFormat &vertex_format, const uint vertex_len); + }; // namespace blender::gpu diff --git a/source/blender/gpu/vulkan/vk_vertex_buffer.cc b/source/blender/gpu/vulkan/vk_vertex_buffer.cc index 1147df5f646..0eb00103cb6 100644 --- a/source/blender/gpu/vulkan/vk_vertex_buffer.cc +++ b/source/blender/gpu/vulkan/vk_vertex_buffer.cc @@ -7,6 +7,7 @@ #include "MEM_guardedalloc.h" +#include "vk_data_conversion.hh" #include "vk_shader.hh" #include "vk_shader_interface.hh" #include "vk_vertex_buffer.hh" @@ -64,13 +65,51 @@ void VKVertexBuffer::release_data() MEM_SAFE_FREE(data); } -void VKVertexBuffer::upload_data() {} +static bool inplace_conversion_supported(const GPUUsageType &usage) +{ + return ELEM(usage, GPU_USAGE_STATIC, GPU_USAGE_STREAM); +} + +void *VKVertexBuffer::convert() const +{ + void *out_data = data; + if (!inplace_conversion_supported(usage_)) { + out_data = MEM_dupallocN(out_data); + } + BLI_assert(format.deinterleaved); + convert_in_place(out_data, format, vertex_len); + return out_data; +} + +void VKVertexBuffer::upload_data() +{ + if (!buffer_.is_allocated()) { + allocate(); + } + + if (flag &= GPU_VERTBUF_DATA_DIRTY) { + void *data_to_upload = data; + if (conversion_needed(format)) { + data_to_upload = convert(); + } + buffer_.update(data_to_upload); + if (data_to_upload != data) { + MEM_SAFE_FREE(data_to_upload); + } + if (usage_ == GPU_USAGE_STATIC) { + MEM_SAFE_FREE(data); + } + + flag &= ~GPU_VERTBUF_DATA_DIRTY; + flag |= GPU_VERTBUF_DATA_UPLOADED; + } +} void VKVertexBuffer::duplicate_data(VertBuf * /*dst*/) {} void VKVertexBuffer::allocate() { - buffer_.create(size_used_get(), + buffer_.create(size_alloc_get(), usage_, static_cast(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT)); diff --git a/source/blender/gpu/vulkan/vk_vertex_buffer.hh b/source/blender/gpu/vulkan/vk_vertex_buffer.hh index faae248f4f9..9aa63261b3f 100644 --- a/source/blender/gpu/vulkan/vk_vertex_buffer.hh +++ b/source/blender/gpu/vulkan/vk_vertex_buffer.hh @@ -40,6 +40,12 @@ class VKVertexBuffer : public VertBuf { private: void allocate(); + void *convert() const; }; +static inline VKVertexBuffer *unwrap(VertBuf *vertex_buffer) +{ + return static_cast(vertex_buffer); +} + } // namespace blender::gpu -- 2.30.2 From 66f7fd6667b4f9eed8e02694cd4c2ab099c78395 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Mon, 8 May 2023 13:49:06 +0200 Subject: [PATCH 2/5] Use correct VkFormat based on the fetch mode and conversion. --- source/blender/gpu/vulkan/vk_common.cc | 272 ++++++++++++++++++++++--- source/blender/gpu/vulkan/vk_common.hh | 4 +- 2 files changed, 248 insertions(+), 28 deletions(-) diff --git a/source/blender/gpu/vulkan/vk_common.cc b/source/blender/gpu/vulkan/vk_common.cc index ede3abf35da..d7a16e4205d 100644 --- a/source/blender/gpu/vulkan/vk_common.cc +++ b/source/blender/gpu/vulkan/vk_common.cc @@ -241,7 +241,7 @@ VkFormat to_vk_format(const eGPUTextureFormat format) return VK_FORMAT_UNDEFINED; } -VkFormat to_vk_format(const GPUVertCompType type, const uint32_t size) +static VkFormat to_vk_format_norm(const GPUVertCompType type, const uint32_t size) { switch (type) { case GPU_COMP_I8: @@ -254,8 +254,11 @@ VkFormat to_vk_format(const GPUVertCompType type, const uint32_t size) return VK_FORMAT_R8G8B8_SNORM; case 4: return VK_FORMAT_R8G8B8A8_SNORM; + case 16: + return VK_FORMAT_R8G8B8A8_SNORM; default: - break; + BLI_assert_unreachable(); + return VK_FORMAT_R8_SNORM; } break; @@ -269,8 +272,11 @@ VkFormat to_vk_format(const GPUVertCompType type, const uint32_t size) return VK_FORMAT_R8G8B8_UNORM; case 4: return VK_FORMAT_R8G8B8A8_UNORM; + case 16: + return VK_FORMAT_R8G8B8A8_UNORM; default: - break; + BLI_assert_unreachable(); + return VK_FORMAT_R8_UNORM; } break; @@ -285,7 +291,8 @@ VkFormat to_vk_format(const GPUVertCompType type, const uint32_t size) case 8: return VK_FORMAT_R16G16B16A16_SNORM; default: - break; + BLI_assert_unreachable(); + return VK_FORMAT_R16_SNORM; } break; @@ -300,39 +307,102 @@ VkFormat to_vk_format(const GPUVertCompType type, const uint32_t size) case 8: return VK_FORMAT_R16G16B16A16_UNORM; default: - break; + BLI_assert_unreachable(); + return VK_FORMAT_R16_UNORM; } break; + case GPU_COMP_I10: + BLI_assert(size == 4); + return VK_FORMAT_A2B10G10R10_SNORM_PACK32; + case GPU_COMP_I32: - switch (size) { - case 4: - return VK_FORMAT_R32_SINT; - case 8: - return VK_FORMAT_R32G32_SINT; - case 12: - return VK_FORMAT_R32G32B32_SINT; - case 16: - return VK_FORMAT_R32G32B32A32_SINT; - default: - break; - } - break; - case GPU_COMP_U32: + case GPU_COMP_F32: + default: + break; + } + BLI_assert_unreachable(); + return VK_FORMAT_R32_SFLOAT; +} + +static VkFormat to_vk_format_float(const GPUVertCompType type, const uint32_t size) +{ + switch (type) { + case GPU_COMP_I8: + switch (size) { + case 1: + return VK_FORMAT_R8_SSCALED; + case 2: + return VK_FORMAT_R8G8_SSCALED; + case 3: + return VK_FORMAT_R8G8B8_SSCALED; + case 4: + return VK_FORMAT_R8G8B8A8_SSCALED; + default: + BLI_assert_unreachable(); + return VK_FORMAT_R8_SSCALED; + } + case GPU_COMP_U8: + switch (size) { + case 1: + return VK_FORMAT_R8_USCALED; + case 2: + return VK_FORMAT_R8G8_USCALED; + case 3: + return VK_FORMAT_R8G8B8_USCALED; + case 4: + return VK_FORMAT_R8G8B8A8_USCALED; + default: + BLI_assert_unreachable(); + return VK_FORMAT_R8_USCALED; + } + case GPU_COMP_I16: + switch (size) { + case 2: + return VK_FORMAT_R16_SSCALED; + case 4: + return VK_FORMAT_R16G16_SSCALED; + case 6: + return VK_FORMAT_R16G16B16_SSCALED; + case 8: + return VK_FORMAT_R16G16B16A16_SSCALED; + default: + BLI_assert_unreachable(); + return VK_FORMAT_R16_SSCALED; + } + case GPU_COMP_U16: + switch (size) { + case 2: + return VK_FORMAT_R16_USCALED; + case 4: + return VK_FORMAT_R16G16_USCALED; + case 6: + return VK_FORMAT_R16G16B16_USCALED; + case 8: + return VK_FORMAT_R16G16B16A16_USCALED; + default: + BLI_assert_unreachable(); + return VK_FORMAT_R16_USCALED; + } + + case GPU_COMP_I32: + case GPU_COMP_U32: + /* NOTE: GPU_COMP_I32/U32 using GPU_FETCH_INT_TO_FLOAT isn't natively supported. These are + * converted on the host and therefor needs to be attached as signed floats. */ switch (size) { case 4: - return VK_FORMAT_R32_UINT; + return VK_FORMAT_R32_SFLOAT; case 8: - return VK_FORMAT_R32G32_UINT; + return VK_FORMAT_R32G32_SFLOAT; case 12: - return VK_FORMAT_R32G32B32_UINT; + return VK_FORMAT_R32G32B32_SFLOAT; case 16: - return VK_FORMAT_R32G32B32A32_UINT; + return VK_FORMAT_R32G32B32A32_SFLOAT; default: - break; + BLI_assert_unreachable(); + return VK_FORMAT_R32_SFLOAT; } - break; case GPU_COMP_F32: switch (size) { @@ -347,17 +417,165 @@ VkFormat to_vk_format(const GPUVertCompType type, const uint32_t size) case 64: return VK_FORMAT_R32G32B32A32_SFLOAT; default: - break; + BLI_assert_unreachable(); + return VK_FORMAT_R32_SFLOAT; + } + + case GPU_COMP_I10: + BLI_assert(size == 4); + return VK_FORMAT_A2B10G10R10_SSCALED_PACK32; + + default: + break; + } + BLI_assert_unreachable(); + return VK_FORMAT_R32_SFLOAT; +} + +static VkFormat to_vk_format_int(const GPUVertCompType type, const uint32_t size) +{ + switch (type) { + case GPU_COMP_I8: + switch (size) { + case 1: + return VK_FORMAT_R8_SINT; + case 2: + return VK_FORMAT_R8G8_SINT; + case 3: + return VK_FORMAT_R8G8B8_SINT; + case 4: + return VK_FORMAT_R8G8B8A8_SINT; + default: + BLI_assert_unreachable(); + return VK_FORMAT_R8_SINT; + } + break; + + case GPU_COMP_U8: + switch (size) { + case 1: + return VK_FORMAT_R8_USCALED; + case 2: + return VK_FORMAT_R8G8_USCALED; + case 3: + return VK_FORMAT_R8G8B8_USCALED; + case 4: + return VK_FORMAT_R8G8B8A8_USCALED; + default: + BLI_assert_unreachable(); + return VK_FORMAT_R8_USCALED; + } + break; + + case GPU_COMP_I16: + switch (size) { + case 2: + return VK_FORMAT_R16_SINT; + case 4: + return VK_FORMAT_R16G16_SINT; + case 6: + return VK_FORMAT_R16G16B16_SINT; + case 8: + return VK_FORMAT_R16G16B16A16_SINT; + default: + BLI_assert_unreachable(); + return VK_FORMAT_R16_SINT; + } + break; + + case GPU_COMP_U16: + switch (size) { + case 2: + return VK_FORMAT_R16_USCALED; + case 4: + return VK_FORMAT_R16G16_USCALED; + case 6: + return VK_FORMAT_R16G16B16_USCALED; + case 8: + return VK_FORMAT_R16G16B16A16_USCALED; + default: + BLI_assert_unreachable(); + return VK_FORMAT_R16_USCALED; + } + break; + + case GPU_COMP_I32: + switch (size) { + case 4: + return VK_FORMAT_R32_SINT; + case 8: + return VK_FORMAT_R32G32_SINT; + case 12: + return VK_FORMAT_R32G32B32_SINT; + case 16: + return VK_FORMAT_R32G32B32A32_SINT; + default: + BLI_assert_unreachable(); + return VK_FORMAT_R32_SINT; + } + break; + + case GPU_COMP_U32: + switch (size) { + case 4: + return VK_FORMAT_R32_UINT; + case 8: + return VK_FORMAT_R32G32_UINT; + case 12: + return VK_FORMAT_R32G32B32_UINT; + case 16: + return VK_FORMAT_R32G32B32A32_UINT; + default: + BLI_assert_unreachable(); + return VK_FORMAT_R32_UINT; + } + break; + + case GPU_COMP_F32: + switch (size) { + case 4: + return VK_FORMAT_R32_SINT; + case 8: + return VK_FORMAT_R32G32_SINT; + case 12: + return VK_FORMAT_R32G32B32_SINT; + case 16: + return VK_FORMAT_R32G32B32A32_SINT; + default: + BLI_assert_unreachable(); + return VK_FORMAT_R32_SINT; } break; case GPU_COMP_I10: BLI_assert(size == 4); - return VK_FORMAT_A2B10G10R10_UNORM_PACK32; + return VK_FORMAT_A2B10G10R10_SINT_PACK32; default: break; } + + BLI_assert_unreachable(); + return VK_FORMAT_R32_SFLOAT; +} + +VkFormat to_vk_format(const GPUVertCompType type, const uint32_t size, GPUVertFetchMode fetch_mode) +{ + switch (fetch_mode) { + case GPU_FETCH_FLOAT: + case GPU_FETCH_INT_TO_FLOAT: + return to_vk_format_float(type, size); + break; + case GPU_FETCH_INT: + return to_vk_format_int(type, size); + break; + case GPU_FETCH_INT_TO_FLOAT_UNIT: + return to_vk_format_norm(type, size); + break; + default: + break; + } + BLI_assert_unreachable(); return VK_FORMAT_R32_SFLOAT; } diff --git a/source/blender/gpu/vulkan/vk_common.hh b/source/blender/gpu/vulkan/vk_common.hh index eebe13bbf55..48aaa634cc4 100644 --- a/source/blender/gpu/vulkan/vk_common.hh +++ b/source/blender/gpu/vulkan/vk_common.hh @@ -24,7 +24,9 @@ namespace blender::gpu { VkImageAspectFlagBits to_vk_image_aspect_flag_bits(const eGPUTextureFormat format); VkFormat to_vk_format(const eGPUTextureFormat format); -VkFormat to_vk_format(const GPUVertCompType type, const uint32_t size); +VkFormat to_vk_format(const GPUVertCompType type, + const uint32_t size, + const GPUVertFetchMode fetch_mode); VkComponentMapping to_vk_component_mapping(const eGPUTextureFormat format); VkImageViewType to_vk_image_view_type(const eGPUTextureType type); VkImageType to_vk_image_type(const eGPUTextureType type); -- 2.30.2 From d77ad93ef8c693cb156c9d959547281ea56dd01b Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Thu, 11 May 2023 10:34:40 +0200 Subject: [PATCH 3/5] Commit before merge. --- source/blender/gpu/CMakeLists.txt | 1 + .../blender/gpu/tests/vertex_buffer_test.cc | 28 +++++++++++++++++++ 2 files changed, 29 insertions(+) create mode 100644 source/blender/gpu/tests/vertex_buffer_test.cc diff --git a/source/blender/gpu/CMakeLists.txt b/source/blender/gpu/CMakeLists.txt index 73137636f6e..c5ca276fe65 100644 --- a/source/blender/gpu/CMakeLists.txt +++ b/source/blender/gpu/CMakeLists.txt @@ -846,6 +846,7 @@ if(WITH_GTESTS) tests/shader_test.cc tests/storage_buffer_test.cc tests/texture_test.cc + tests/vertex_buffer_test.cc tests/gpu_testing.hh ) diff --git a/source/blender/gpu/tests/vertex_buffer_test.cc b/source/blender/gpu/tests/vertex_buffer_test.cc new file mode 100644 index 00000000000..5166a3a99a4 --- /dev/null +++ b/source/blender/gpu/tests/vertex_buffer_test.cc @@ -0,0 +1,28 @@ +#include "testing/testing.h" + +#include "GPU_shader.h" +#include "GPU_vertex_buffer.h" + +#include "gpu_testing.hh" + +namespace blender::gpu::tests { + +template static void test_comp_fetch() +{ + GPUShader *shader = GPU_shader_create_from_info_name("gpu_vertex_buffer_fetch_mode_test"); + EXPECT_NE(shader, nullptr); + GPU_shader_bind(shader); + + GPUVertFormat format = {0}; + GPU_vertformat_attr_add(&format, "pos", comp_type, 2, fetch_mode); + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); + GPU_vertbuf_data_alloc(vbo, 4); +} + +static void test_vertex_buffer_fetch_mode__GPU_COMP_I32__GPU_FETCH_INT_TO_FLOAT() +{ + test_comp_fetch(); +} +GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_I32__GPU_FETCH_INT_TO_FLOAT); + +} // namespace blender::gpu::tests -- 2.30.2 From 253527cd8aa40dcd5ebbe44ddb93784a8ccbae34 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Thu, 11 May 2023 12:05:07 +0200 Subject: [PATCH 4/5] Add COMP_(U/I)(8/16/32) test cases --- .../blender/blenlib/BLI_math_vector_types.hh | 2 + .../blender/gpu/tests/vertex_buffer_test.cc | 100 ++++++++++++++++-- 2 files changed, 96 insertions(+), 6 deletions(-) diff --git a/source/blender/blenlib/BLI_math_vector_types.hh b/source/blender/blenlib/BLI_math_vector_types.hh index a865bb238c1..010d30d1197 100644 --- a/source/blender/blenlib/BLI_math_vector_types.hh +++ b/source/blender/blenlib/BLI_math_vector_types.hh @@ -645,6 +645,7 @@ template struct AssertUnitEpsilon { using char2 = blender::VecBase; using char3 = blender::VecBase; +using char4 = blender::VecBase; using uchar3 = blender::VecBase; using uchar4 = blender::VecBase; @@ -659,6 +660,7 @@ using uint4 = VecBase; using short2 = blender::VecBase; using short3 = blender::VecBase; +using short4 = blender::VecBase; using ushort2 = VecBase; using ushort3 = blender::VecBase; diff --git a/source/blender/gpu/tests/vertex_buffer_test.cc b/source/blender/gpu/tests/vertex_buffer_test.cc index 5166a3a99a4..c7c065d0c17 100644 --- a/source/blender/gpu/tests/vertex_buffer_test.cc +++ b/source/blender/gpu/tests/vertex_buffer_test.cc @@ -1,28 +1,116 @@ #include "testing/testing.h" +#include "GPU_framebuffer.h" +#include "GPU_immediate.h" #include "GPU_shader.h" #include "GPU_vertex_buffer.h" +#include "GPU_vertex_format.h" + +#include "BLI_index_range.hh" +#include "BLI_math_vector_types.hh" #include "gpu_testing.hh" namespace blender::gpu::tests { -template static void test_comp_fetch() +static constexpr int Size = 256; + +template +static void vertex_buffer_fetch_mode(ColorType color) { - GPUShader *shader = GPU_shader_create_from_info_name("gpu_vertex_buffer_fetch_mode_test"); - EXPECT_NE(shader, nullptr); - GPU_shader_bind(shader); + GPUOffScreen *offscreen = GPU_offscreen_create(Size, + Size, + false, + GPU_RGBA16F, + GPU_TEXTURE_USAGE_ATTACHMENT | + GPU_TEXTURE_USAGE_HOST_READ, + 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(0.0f)); GPUVertFormat format = {0}; - GPU_vertformat_attr_add(&format, "pos", comp_type, 2, fetch_mode); + GPU_vertformat_attr_add(&format, "pos", GPU_COMP_F32, 2, GPU_FETCH_FLOAT); + GPU_vertformat_attr_add(&format, "color", comp_type, 4, fetch_mode); + GPUVertBuf *vbo = GPU_vertbuf_create_with_format(&format); GPU_vertbuf_data_alloc(vbo, 4); + + struct Vert { + float2 pos; + ColorType color; + }; + Vert data[4] = { + {float2(-1.0, -1.0), color}, + {float2(1.0, -1.0), color}, + {float2(1.0, 1.0), color}, + {float2(-1.0, 1.0), color}, + }; + for (int i : IndexRange(4)) { + GPU_vertbuf_vert_set(vbo, i, &data[i]); + } + + GPUBatch *batch = GPU_batch_create(GPU_PRIM_TRI_FAN, vbo, NULL); + 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. */ + float read_data[4 * Size * Size]; + GPU_offscreen_read_color(offscreen, GPU_DATA_FLOAT, &read_data); + for (int pixel_index = 0; pixel_index < Size * Size; pixel_index++) { + float4 read_color = float4(&read_data[pixel_index * 4]); + EXPECT_EQ(read_color, float4(color)); + } + + GPU_batch_discard(batch); + GPU_vertbuf_discard(vbo); + GPU_offscreen_free(offscreen); } +static void test_vertex_buffer_fetch_mode__GPU_COMP_I8__GPU_FETCH_INT_TO_FLOAT() +{ + vertex_buffer_fetch_mode(char4(4, 5, 6, 1)); +} +GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_I8__GPU_FETCH_INT_TO_FLOAT); + +static void test_vertex_buffer_fetch_mode__GPU_COMP_U8__GPU_FETCH_INT_TO_FLOAT() +{ + vertex_buffer_fetch_mode(uchar4(4, 5, 6, 1)); +} +GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_U8__GPU_FETCH_INT_TO_FLOAT); + +static void test_vertex_buffer_fetch_mode__GPU_COMP_I16__GPU_FETCH_INT_TO_FLOAT() +{ + vertex_buffer_fetch_mode(short4(4, 5, 6, 1)); +} +GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_I16__GPU_FETCH_INT_TO_FLOAT); + +static void test_vertex_buffer_fetch_mode__GPU_COMP_U16__GPU_FETCH_INT_TO_FLOAT() +{ + vertex_buffer_fetch_mode(ushort4(4, 5, 6, 1)); +} +GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_U16__GPU_FETCH_INT_TO_FLOAT); + static void test_vertex_buffer_fetch_mode__GPU_COMP_I32__GPU_FETCH_INT_TO_FLOAT() { - test_comp_fetch(); + vertex_buffer_fetch_mode(int4(4, 5, 6, 1)); } GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_I32__GPU_FETCH_INT_TO_FLOAT); +static void test_vertex_buffer_fetch_mode__GPU_COMP_U32__GPU_FETCH_INT_TO_FLOAT() +{ + vertex_buffer_fetch_mode(uint4(4, 5, 6, 1)); +} +GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_U32__GPU_FETCH_INT_TO_FLOAT); + +static void test_vertex_buffer_fetch_mode__GPU_COMP_F32__GPU_FETCH_FLOAT() +{ + vertex_buffer_fetch_mode(float4(4, 5, 6, 1)); +} +GPU_TEST(vertex_buffer_fetch_mode__GPU_COMP_F32__GPU_FETCH_FLOAT); + } // namespace blender::gpu::tests -- 2.30.2 From 90a1b998b374e63c772028ff8bf34ade7e2a6b98 Mon Sep 17 00:00:00 2001 From: Jeroen Bakker Date: Thu, 11 May 2023 12:21:19 +0200 Subject: [PATCH 5/5] Fix spelling --- source/blender/gpu/vulkan/vk_common.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/source/blender/gpu/vulkan/vk_common.cc b/source/blender/gpu/vulkan/vk_common.cc index d7a16e4205d..8e059d40402 100644 --- a/source/blender/gpu/vulkan/vk_common.cc +++ b/source/blender/gpu/vulkan/vk_common.cc @@ -389,7 +389,7 @@ static VkFormat to_vk_format_float(const GPUVertCompType type, const uint32_t si case GPU_COMP_I32: case GPU_COMP_U32: /* NOTE: GPU_COMP_I32/U32 using GPU_FETCH_INT_TO_FLOAT isn't natively supported. These are - * converted on the host and therefor needs to be attached as signed floats. */ + * converted on host-side to signed floats. */ switch (size) { case 4: return VK_FORMAT_R32_SFLOAT; -- 2.30.2