Vulkan: Convert VertexBuffer to Contain Supported Attributes #107733
|
@ -645,6 +645,7 @@ template<typename T> struct AssertUnitEpsilon {
|
|||
|
||||
using char2 = blender::VecBase<int8_t, 2>;
|
||||
using char3 = blender::VecBase<int8_t, 3>;
|
||||
using char4 = blender::VecBase<int8_t, 4>;
|
||||
|
||||
using uchar3 = blender::VecBase<uint8_t, 3>;
|
||||
using uchar4 = blender::VecBase<uint8_t, 4>;
|
||||
|
@ -659,6 +660,7 @@ using uint4 = VecBase<uint32_t, 4>;
|
|||
|
||||
using short2 = blender::VecBase<int16_t, 2>;
|
||||
using short3 = blender::VecBase<int16_t, 3>;
|
||||
using short4 = blender::VecBase<int16_t, 4>;
|
||||
|
||||
using ushort2 = VecBase<uint16_t, 2>;
|
||||
using ushort3 = blender::VecBase<uint16_t, 3>;
|
||||
|
|
|
@ -848,6 +848,7 @@ if(WITH_GTESTS)
|
|||
tests/state_blend_test.cc
|
||||
tests/storage_buffer_test.cc
|
||||
tests/texture_test.cc
|
||||
tests/vertex_buffer_test.cc
|
||||
|
||||
tests/gpu_testing.hh
|
||||
)
|
||||
|
|
|
@ -0,0 +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 {
|
||||
|
||||
static constexpr int Size = 256;
|
||||
|
||||
template<GPUVertCompType comp_type, GPUVertFetchMode fetch_mode, typename ColorType>
|
||||
static void vertex_buffer_fetch_mode(ColorType color)
|
||||
{
|
||||
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", 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<GPU_COMP_I8, GPU_FETCH_INT_TO_FLOAT, char4>(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<GPU_COMP_U8, GPU_FETCH_INT_TO_FLOAT, uchar4>(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<GPU_COMP_I16, GPU_FETCH_INT_TO_FLOAT, short4>(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<GPU_COMP_U16, GPU_FETCH_INT_TO_FLOAT, ushort4>(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()
|
||||
{
|
||||
vertex_buffer_fetch_mode<GPU_COMP_I32, GPU_FETCH_INT_TO_FLOAT, int4>(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<GPU_COMP_U32, GPU_FETCH_INT_TO_FLOAT, uint4>(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<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
|
|
@ -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 host-side to signed floats. */
|
||||
Jeroen-Bakker marked this conversation as resolved
Outdated
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<uint8_t *>(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<int32_t *>(row_data) + component;
|
||||
float *component_out = static_cast<float *>(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<uint32_t *>(row_data) + component;
|
||||
float *component_out = static_cast<float *>(row_data) + component;
|
||||
*component_out = float(*component_in);
|
||||
}
|
||||
}
|
||||
row_data = static_cast<uint8_t *>(row_data) + vertex_format.stride;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* \} */
|
||||
|
||||
} // namespace blender::gpu
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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"
|
||||
|
@ -66,13 +67,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<VkBufferUsageFlagBits>(VK_BUFFER_USAGE_STORAGE_BUFFER_BIT |
|
||||
VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
|
||||
|
|
|
@ -40,6 +40,12 @@ class VKVertexBuffer : public VertBuf {
|
|||
|
||||
private:
|
||||
void allocate();
|
||||
void *convert() const;
|
||||
};
|
||||
|
||||
static inline VKVertexBuffer *unwrap(VertBuf *vertex_buffer)
|
||||
{
|
||||
return static_cast<VKVertexBuffer *>(vertex_buffer);
|
||||
}
|
||||
|
||||
} // namespace blender::gpu
|
||||
|
|
Loading…
Reference in New Issue
spelling