Vulkan: Push constants #104880

Merged
Jeroen Bakker merged 73 commits from Jeroen-Bakker/blender:vulkan-push-constants into main 2023-03-06 12:29:06 +01:00
5 changed files with 124 additions and 17 deletions
Showing only changes of commit a26eca251b - Show all commits

View File

@ -814,6 +814,12 @@ if(WITH_GTESTS)
tests/gpu_testing.hh
)
if(WITH_VULKAN_BACKEND)
list(APPEND TEST_SRC
tests/memory_layout_test.cc
)
endif()
set(TEST_INC
)
set(TEST_LIB

View File

@ -0,0 +1,100 @@
/* SPDX-License-Identifier: Apache-2.0 */
#include "testing/testing.h"
#include "../vulkan/vk_memory_layout.hh"
namespace blender::gpu {
template<typename Layout>
static void def_attr(const shader::Type type,
const int array_size,
const uint32_t expected_alignment,
const uint32_t expected_reserve,
uint32_t *r_offset)
{
align<Layout>(type, array_size, r_offset);
EXPECT_EQ(*r_offset, expected_alignment);
reserve<Layout>(type, array_size, r_offset);
EXPECT_EQ(*r_offset, expected_reserve);
}
TEST(std140, fl)
{
uint32_t offset = 0;
def_attr<Std140>(shader::Type::FLOAT, 0, 0, 4, &offset);
align_end_of_struct<Std140>(&offset);
EXPECT_EQ(offset, 16);
}
TEST(std140, _2fl)
{
uint32_t offset = 0;
def_attr<Std140>(shader::Type::FLOAT, 0, 0, 4, &offset);
def_attr<Std140>(shader::Type::FLOAT, 0, 4, 8, &offset);
align_end_of_struct<Std140>(&offset);
EXPECT_EQ(offset, 16);
}
TEST(std140, _3fl)
{
uint32_t offset = 0;
def_attr<Std140>(shader::Type::FLOAT, 0, 0, 4, &offset);
def_attr<Std140>(shader::Type::FLOAT, 0, 4, 8, &offset);
def_attr<Std140>(shader::Type::FLOAT, 0, 8, 12, &offset);
align_end_of_struct<Std140>(&offset);
EXPECT_EQ(offset, 16);
}
TEST(std140, _4fl)
{
uint32_t offset = 0;
def_attr<Std140>(shader::Type::FLOAT, 0, 0, 4, &offset);
def_attr<Std140>(shader::Type::FLOAT, 0, 4, 8, &offset);
def_attr<Std140>(shader::Type::FLOAT, 0, 8, 12, &offset);
def_attr<Std140>(shader::Type::FLOAT, 0, 12, 16, &offset);
align_end_of_struct<Std140>(&offset);
EXPECT_EQ(offset, 16);
}
TEST(std140, fl2)
{
uint32_t offset = 0;
def_attr<Std140>(shader::Type::FLOAT, 2, 0, 16, &offset);
align_end_of_struct<Std140>(&offset);
EXPECT_EQ(offset, 16);
}
TEST(std140, fl_fl2)
{
uint32_t offset = 0;
def_attr<Std140>(shader::Type::FLOAT, 0, 0, 4, &offset);
def_attr<Std140>(shader::Type::FLOAT, 2, 16, 48, &offset);
align_end_of_struct<Std140>(&offset);
EXPECT_EQ(offset, 48);
}
TEST(std140, fl_vec2)
{
uint32_t offset = 0;
def_attr<Std140>(shader::Type::FLOAT, 0, 0, 4, &offset);
def_attr<Std140>(shader::Type::VEC2, 0, 8, 16, &offset);
align_end_of_struct<Std140>(&offset);
EXPECT_EQ(offset, 16);
}
} // namespace blender::gpu

View File

@ -14,8 +14,11 @@ uint32_t Std430::component_mem_size(const shader::Type /*type*/)
return 4;
}
uint32_t Std430::element_alignment(const shader::Type type)
uint32_t Std430::element_alignment(const shader::Type type, const bool is_array)
{
if (is_array) {
return 16;
}
switch (type) {
case shader::Type::FLOAT:
case shader::Type::UINT:
@ -80,8 +83,11 @@ uint32_t Std140::component_mem_size(const shader::Type /*type*/)
return 4;
}
uint32_t Std140::element_alignment(const shader::Type type)
uint32_t Std140::element_alignment(const shader::Type type, const bool is_array)
{
if (is_array) {
return 16;
}
switch (type) {
case shader::Type::FLOAT:
case shader::Type::UINT:

View File

@ -18,7 +18,7 @@ struct Std430 {
/** Get the memory size in bytes of a single component using by the given type.*/
static uint32_t component_mem_size(const shader::Type type);
/** Get to alignment of the given type in bytes.*/
static uint32_t element_alignment(const shader::Type type);
static uint32_t element_alignment(const shader::Type type, bool is_array);
/** Get the number of components that should be allocated for the given type.*/
static uint32_t element_components_len(const shader::Type type);
/** Get the number of components of the given type when used in an array.*/
@ -32,16 +32,17 @@ struct Std140 {
/** Get the memory size in bytes of a single component using by the given type.*/
static uint32_t component_mem_size(const shader::Type type);
/** Get to alignment of the given type in bytes.*/
static uint32_t element_alignment(const shader::Type type);
static uint32_t element_alignment(const shader::Type type, bool is_array);
/** Get the number of components that should be allocated for the given type.*/
static uint32_t element_components_len(const shader::Type type);
/** Get the number of components of the given type when used in an array.*/
static uint32_t array_components_len(const shader::Type type);
};
template<typename Layout> static void align(const shader::Type &type, uint32_t *r_offset)
template<typename Layout>
Jeroen-Bakker marked this conversation as resolved

I think Layout should be LayoutT to avoid thinking it is the layout itself (as in the content of a UBO/SSBO).

I think `Layout` should be `LayoutT` to avoid thinking it is the layout itself (as in the content of a UBO/SSBO).
static void align(const shader::Type &type, const int32_t array_size, uint32_t *r_offset)
{
uint32_t alignment = Layout::element_alignment(type);
uint32_t alignment = Layout::element_alignment(type, array_size != 0);
uint32_t alignment_mask = alignment - 1;
uint32_t offset = *r_offset;
if ((offset & alignment_mask) != 0) {
@ -69,15 +70,9 @@ static void reserve(const shader::Type type, int32_t array_size, uint32_t *r_off
*r_offset += size;
}
template<typename Layout>
static void reserve(const shader::ShaderCreateInfo::PushConst &push_constant, uint32_t *r_offset)
{
reserve<Layout>(push_constant.type, push_constant.array_size, r_offset);
}
template<typename Layout> static void align_end_of_struct(uint32_t *r_offset)
{
align<Layout>(shader::Type::VEC4, r_offset);
align<Layout>(shader::Type::VEC4, 0, r_offset);
}
} // namespace blender::gpu

View File

@ -20,7 +20,7 @@ static VKPushConstantsLayout::PushConstantLayout init_constant(
const ShaderInput &shader_input,
uint32_t *r_offset)
{
align<Layout>(push_constant.type, r_offset);
align<Layout>(push_constant.type, push_constant.array_size, r_offset);
VKPushConstantsLayout::PushConstantLayout layout;
layout.location = shader_input.location;
@ -28,7 +28,7 @@ static VKPushConstantsLayout::PushConstantLayout init_constant(
layout.array_size = push_constant.array_size;
layout.offset = *r_offset;
reserve<Layout>(push_constant, r_offset);
reserve<Layout>(push_constant.type, push_constant.array_size, r_offset);
return layout;
}
@ -37,8 +37,8 @@ uint32_t struct_size(Span<shader::ShaderCreateInfo::PushConst> push_constants)
{
uint32_t offset = 0;
for (const shader::ShaderCreateInfo::PushConst &push_constant : push_constants) {
align<Layout>(push_constant.type, &offset);
reserve<Layout>(push_constant, &offset);
align<Layout>(push_constant.type, push_constant.array_size, &offset);
reserve<Layout>(push_constant.type, push_constant.array_size, &offset);
}
align_end_of_struct<Layout>(&offset);