Vulkan: Push constants #104880
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue
I think
Layout
should beLayoutT
to avoid thinking it is the layout itself (as in the content of a UBO/SSBO).