Vulkan: Push constants #104880
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue