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
8 changed files with 274 additions and 6 deletions
Showing only changes of commit e7d683106e - Show all commits

View File

@ -204,6 +204,7 @@ set(VULKAN_SRC
vulkan/vk_pipeline.cc
vulkan/vk_memory.cc
vulkan/vk_pixel_buffer.cc
vulkan/vk_push_constants.cc
vulkan/vk_query.cc
vulkan/vk_shader.cc
vulkan/vk_shader_interface.cc
@ -229,6 +230,7 @@ set(VULKAN_SRC
vulkan/vk_pipeline.hh
vulkan/vk_memory.hh
vulkan/vk_pixel_buffer.hh
vulkan/vk_push_constants.hh
vulkan/vk_query.hh
vulkan/vk_shader.hh
vulkan/vk_shader_interface.hh
@ -802,6 +804,7 @@ if(WITH_GTESTS)
tests/gpu_testing.cc
tests/gpu_index_buffer_test.cc
tests/gpu_push_constants_test.cc
tests/gpu_shader_builtin_test.cc
tests/gpu_shader_test.cc
tests/gpu_storage_buffer_test.cc

View File

@ -0,0 +1,19 @@
/* SPDX-License-Identifier: Apache-2.0 */
#include "testing/testing.h"
#include "GPU_storage_buffer.h"
#include "BLI_vector.hh"
#include "gpu_testing.hh"
namespace blender::gpu::tests {
static void test_push_constants()
{
}
GPU_TEST(push_constants);
} // namespace blender::gpu::tests

View File

@ -43,6 +43,7 @@ void VKDescriptorPools::add_new_pool()
{VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, POOL_SIZE_STORAGE_IMAGE},
{VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, POOL_SIZE_COMBINED_IMAGE_SAMPLER},
{VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, POOL_SIZE_UNIFORM_BUFFER},
{VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER, POOL_SIZE_UNIFORM_TEXEL_BUFFER},
};
VkDescriptorPoolCreateInfo pool_info = {};
pool_info.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO;

View File

@ -35,6 +35,7 @@ class VKDescriptorPools {
static constexpr uint32_t POOL_SIZE_STORAGE_IMAGE = 1000;
static constexpr uint32_t POOL_SIZE_COMBINED_IMAGE_SAMPLER = 1000;
static constexpr uint32_t POOL_SIZE_UNIFORM_BUFFER = 1000;
static constexpr uint32_t POOL_SIZE_UNIFORM_TEXEL_BUFFER = 1000;
VkDevice vk_device_ = VK_NULL_HANDLE;
Vector<VkDescriptorPool> pools_;

View File

@ -0,0 +1,109 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation. All rights reserved. */
/** \file
* \ingroup gpu
*/
#include "vk_push_constants.hh"
namespace blender::gpu {
static uint32_t to_component_size(const shader::Type /*type*/)
{
return 4;
}
static uint32_t to_num_components(const shader::Type type)
{
switch (type) {
case shader::Type::FLOAT:
case shader::Type::UINT:
case shader::Type::INT:
case shader::Type::BOOL:
return 1;
case shader::Type::VEC2:
case shader::Type::UVEC2:
case shader::Type::IVEC2:
return 2;
case shader::Type::VEC3:
case shader::Type::UVEC3:
case shader::Type::IVEC3:
case shader::Type::VEC4:
case shader::Type::UVEC4:
case shader::Type::IVEC4:
return 4;
case shader::Type::MAT3:
return 12;
case shader::Type::MAT4:
return 16;
default:
BLI_assert_msg(false, "Type not supported as push constant");
}
return 0;
}
static uint32_t to_alignment(const shader::Type type)
{
switch (type) {
case shader::Type::FLOAT:
case shader::Type::UINT:
case shader::Type::INT:
case shader::Type::BOOL:
return 4;
case shader::Type::VEC2:
case shader::Type::UVEC2:
case shader::Type::IVEC2:
return 8;
case shader::Type::VEC3:
case shader::Type::UVEC3:
case shader::Type::IVEC3:
case shader::Type::VEC4:
case shader::Type::UVEC4:
case shader::Type::IVEC4:
case shader::Type::MAT3:
case shader::Type::MAT4:
return 16;
default:
BLI_assert_msg(false, "Type not supported as push constant");
}
return 0;
}
static VKPushConstantsLayout::PushConstantLayout init_constant(
const shader::ShaderCreateInfo::PushConst &push_constant, uint32_t *r_offset)
{
VKPushConstantsLayout::PushConstantLayout layout;
layout.type = push_constant.type;
layout.array_size = push_constant.array_size;
layout.offset = *r_offset;
/* Perform alignment. */
uint32_t alignment = to_alignment(push_constant.type);
uint32_t alignment_mask = alignment - 1;
if ((layout.offset & alignment_mask) != 0) {
layout.offset &= ~alignment_mask;
layout.offset += alignment;
}
uint32_t size = to_num_components(push_constant.type) * to_component_size(push_constant.type);
if (push_constant.array_size != 0) {
size *= push_constant.array_size;
}
*r_offset = layout.offset + size;
return layout;
}
void VKPushConstantsLayout::init(const shader::ShaderCreateInfo &info,
const VKShaderInterface &interface)
{
BLI_assert(push_constants.is_empty());
uint32_t offset = 0;
for (const shader::ShaderCreateInfo::PushConst &push_constant : info.push_constants_) {
push_constants.append(init_constant(push_constant, &offset));
}
size_in_bytes_ = offset;
}
} // namespace blender::gpu

View File

@ -0,0 +1,44 @@
/* SPDX-License-Identifier: GPL-2.0-or-later
* Copyright 2023 Blender Foundation. All rights reserved. */
/** \file
* \ingroup gpu
*/
#pragma once
#include "BLI_vector.hh"
#include "vk_common.hh"
#include "vk_shader_interface.hh"
namespace blender::gpu {
struct VKPushConstantsLayout {
struct PushConstantLayout {
uint32_t offset;
shader::Type type;
int array_size;
};
private:
Vector<PushConstantLayout> push_constants;
uint32_t size_in_bytes_;
public:
void init(const shader::ShaderCreateInfo &info, const VKShaderInterface &interface);
uint32_t size_in_bytes() const
{
return size_in_bytes_;
}
};
struct VKPushConstants {
const VKPushConstantsLayout &layout_;
uint32_t *data = nullptr;
VKPushConstants(const VKPushConstantsLayout &layout);
};
} // namespace blender::gpu

View File

@ -680,6 +680,7 @@ bool VKShader::finalize(const shader::ShaderCreateInfo *info)
if (!finalize_descriptor_set_layouts(vk_device, *vk_interface, *info)) {
return false;
}
push_constants_layout_.init(*info, *vk_interface);
if (!finalize_pipeline_layout(vk_device, *info)) {
return false;
}
@ -749,10 +750,18 @@ bool VKShader::finalize_pipeline_layout(VkDevice vk_device,
const uint32_t layout_count = layout_ == VK_NULL_HANDLE ? 0 : 1;
VkPipelineLayoutCreateInfo pipeline_info = {};
VkPushConstantRange push_constant_range = {};
pipeline_info.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO;
pipeline_info.flags = 0;
pipeline_info.setLayoutCount = layout_count;
pipeline_info.pSetLayouts = &layout_;
if (push_constants_layout_.size_in_bytes() != 0) {
push_constant_range.offset = 0;
push_constant_range.size = push_constants_layout_.size_in_bytes();
push_constant_range.stageFlags = VK_SHADER_STAGE_ALL;
pipeline_info.pushConstantRangeCount = 1;
pipeline_info.pPushConstantRanges = &push_constant_range;
}
if (vkCreatePipelineLayout(
vk_device, &pipeline_info, vk_allocation_callbacks, &pipeline_layout_) != VK_SUCCESS) {
@ -762,14 +771,94 @@ bool VKShader::finalize_pipeline_layout(VkDevice vk_device,
return true;
}
static VkDescriptorType descriptor_type(
const shader::ShaderCreateInfo::Resource::BindType bind_type)
static VkDescriptorType storage_descriptor_type(const shader::ImageType &image_type)
{
switch (bind_type) {
case shader::ShaderCreateInfo::Resource::BindType::IMAGE:
switch (image_type) {
case shader::ImageType::FLOAT_1D:
case shader::ImageType::FLOAT_1D_ARRAY:
case shader::ImageType::FLOAT_2D:
case shader::ImageType::FLOAT_2D_ARRAY:
case shader::ImageType::FLOAT_3D:
case shader::ImageType::FLOAT_CUBE:
case shader::ImageType::FLOAT_CUBE_ARRAY:
case shader::ImageType::INT_1D:
case shader::ImageType::INT_1D_ARRAY:
case shader::ImageType::INT_2D:
case shader::ImageType::INT_2D_ARRAY:
case shader::ImageType::INT_3D:
case shader::ImageType::INT_CUBE:
case shader::ImageType::INT_CUBE_ARRAY:
case shader::ImageType::UINT_1D:
case shader::ImageType::UINT_1D_ARRAY:
case shader::ImageType::UINT_2D:
case shader::ImageType::UINT_2D_ARRAY:
case shader::ImageType::UINT_3D:
case shader::ImageType::UINT_CUBE:
case shader::ImageType::UINT_CUBE_ARRAY:
return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
case shader::ShaderCreateInfo::Resource::BindType::SAMPLER:
case shader::ImageType::FLOAT_BUFFER:
case shader::ImageType::INT_BUFFER:
case shader::ImageType::UINT_BUFFER:
return VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
default:
BLI_assert_msg(false, "ImageType not supported.");
}
return VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
}
static VkDescriptorType sampler_descriptor_type(const shader::ImageType &image_type)
{
switch (image_type) {
case shader::ImageType::FLOAT_1D:
case shader::ImageType::FLOAT_1D_ARRAY:
case shader::ImageType::FLOAT_2D:
case shader::ImageType::FLOAT_2D_ARRAY:
case shader::ImageType::FLOAT_3D:
case shader::ImageType::FLOAT_CUBE:
case shader::ImageType::FLOAT_CUBE_ARRAY:
case shader::ImageType::INT_1D:
case shader::ImageType::INT_1D_ARRAY:
case shader::ImageType::INT_2D:
case shader::ImageType::INT_2D_ARRAY:
case shader::ImageType::INT_3D:
case shader::ImageType::INT_CUBE:
case shader::ImageType::INT_CUBE_ARRAY:
case shader::ImageType::UINT_1D:
case shader::ImageType::UINT_1D_ARRAY:
case shader::ImageType::UINT_2D:
case shader::ImageType::UINT_2D_ARRAY:
case shader::ImageType::UINT_3D:
case shader::ImageType::UINT_CUBE:
case shader::ImageType::UINT_CUBE_ARRAY:
case shader::ImageType::SHADOW_2D:
case shader::ImageType::SHADOW_2D_ARRAY:
case shader::ImageType::SHADOW_CUBE:
case shader::ImageType::SHADOW_CUBE_ARRAY:
case shader::ImageType::DEPTH_2D:
case shader::ImageType::DEPTH_2D_ARRAY:
case shader::ImageType::DEPTH_CUBE:
case shader::ImageType::DEPTH_CUBE_ARRAY:
return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
case shader::ImageType::FLOAT_BUFFER:
case shader::ImageType::INT_BUFFER:
case shader::ImageType::UINT_BUFFER:
return VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER;
}
return VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
}
static VkDescriptorType descriptor_type(const shader::ShaderCreateInfo::Resource &resource)
{
switch (resource.bind_type) {
case shader::ShaderCreateInfo::Resource::BindType::IMAGE:
return storage_descriptor_type(resource.image.type);
case shader::ShaderCreateInfo::Resource::BindType::SAMPLER:
return sampler_descriptor_type(resource.sampler.type);
case shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER:
return VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
case shader::ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER:
@ -784,7 +873,7 @@ static VkDescriptorSetLayoutBinding create_descriptor_set_layout_binding(
{
VkDescriptorSetLayoutBinding binding = {};
binding.binding = shader_input.location;
binding.descriptorType = descriptor_type(resource.bind_type);
binding.descriptorType = descriptor_type(resource);
binding.descriptorCount = 1;
binding.stageFlags = VK_SHADER_STAGE_ALL;
binding.pImmutableSamplers = nullptr;

View File

@ -11,6 +11,7 @@
#include "vk_backend.hh"
#include "vk_context.hh"
#include "vk_push_constants.hh"
#include "BLI_string_ref.hh"
@ -27,6 +28,7 @@ class VKShader : public Shader {
bool compilation_failed_ = false;
VkDescriptorSetLayout layout_ = VK_NULL_HANDLE;
VkPipelineLayout pipeline_layout_ = VK_NULL_HANDLE;
VKPushConstantsLayout push_constants_layout_;
VKPipeline compute_pipeline_;
public: