Vulkan: Push constants #104880
|
@ -55,6 +55,7 @@ GPU_SHADER_CREATE_INFO(gpu_compute_ssbo_binding_test)
|
||||||
.compute_source("gpu_compute_dummy_test.glsl")
|
.compute_source("gpu_compute_dummy_test.glsl")
|
||||||
.do_static_compilation(true);
|
.do_static_compilation(true);
|
||||||
|
|
||||||
|
/* Push constants*/
|
||||||
GPU_SHADER_CREATE_INFO(gpu_push_constants_base_test)
|
GPU_SHADER_CREATE_INFO(gpu_push_constants_base_test)
|
||||||
.local_group_size(1)
|
.local_group_size(1)
|
||||||
.storage_buf(0, Qualifier::WRITE, "float", "data_out[]")
|
.storage_buf(0, Qualifier::WRITE, "float", "data_out[]")
|
||||||
|
@ -68,6 +69,23 @@ GPU_SHADER_CREATE_INFO(gpu_push_constants_packed_test)
|
||||||
.push_constant(Type::VEC4, "vec4_in")
|
.push_constant(Type::VEC4, "vec4_in")
|
||||||
.do_static_compilation(true);
|
.do_static_compilation(true);
|
||||||
|
|
||||||
|
/* Push constants size test. */
|
||||||
|
GPU_SHADER_CREATE_INFO(gpu_push_constants_128bytes_test)
|
||||||
|
.additional_info("gpu_push_constants_packed_test")
|
||||||
|
.push_constant(Type::FLOAT, "filler", 20)
|
||||||
|
.do_static_compilation(true);
|
||||||
|
|
||||||
|
GPU_SHADER_CREATE_INFO(gpu_push_constants_256bytes_test)
|
||||||
|
.additional_info("gpu_push_constants_128bytes_test")
|
||||||
|
.push_constant(Type::FLOAT, "filler2", 32)
|
||||||
|
.do_static_compilation(true);
|
||||||
|
|
||||||
|
/* It is expected that this shader will use uniform buffers and not push constants.*/
|
||||||
Jeroen-Bakker marked this conversation as resolved
|
|||||||
|
GPU_SHADER_CREATE_INFO(gpu_push_constants_512bytes_test)
|
||||||
|
.additional_info("gpu_push_constants_256bytes_test")
|
||||||
|
.push_constant(Type::FLOAT, "filler3", 64)
|
||||||
|
.do_static_compilation(true);
|
||||||
|
|
||||||
GPU_SHADER_CREATE_INFO(eevee_shadow_test)
|
GPU_SHADER_CREATE_INFO(eevee_shadow_test)
|
||||||
.fragment_source("eevee_shadow_test.glsl")
|
.fragment_source("eevee_shadow_test.glsl")
|
||||||
.additional_info("gpu_shader_test")
|
.additional_info("gpu_shader_test")
|
||||||
|
|
|
@ -77,4 +77,22 @@ static void test_push_constants_packed()
|
||||||
}
|
}
|
||||||
GPU_TEST(push_constants_packed)
|
GPU_TEST(push_constants_packed)
|
||||||
|
|
||||||
|
static void test_push_constants_128bytes()
|
||||||
|
{
|
||||||
|
push_constants("gpu_push_constants_128bytes_test");
|
||||||
|
}
|
||||||
|
GPU_TEST(push_constants_128bytes)
|
||||||
|
|
||||||
|
static void test_push_constants_256bytes()
|
||||||
|
{
|
||||||
|
push_constants("gpu_push_constants_256bytes_test");
|
||||||
|
}
|
||||||
|
GPU_TEST(push_constants_256bytes)
|
||||||
|
|
||||||
|
static void test_push_constants_512bytes()
|
||||||
|
{
|
||||||
|
push_constants("gpu_push_constants_512bytes_test");
|
||||||
|
}
|
||||||
|
GPU_TEST(push_constants_512bytes)
|
||||||
|
|
||||||
} // namespace blender::gpu::tests
|
} // namespace blender::gpu::tests
|
|
@ -67,11 +67,27 @@ void VKBackend::compute_dispatch(int groups_x_len, int groups_y_len, int groups_
|
||||||
VKCommandBuffer &command_buffer = context.command_buffer_get();
|
VKCommandBuffer &command_buffer = context.command_buffer_get();
|
||||||
VKPipeline &pipeline = shader->pipeline_get();
|
VKPipeline &pipeline = shader->pipeline_get();
|
||||||
VKDescriptorSet &descriptor_set = pipeline.descriptor_set_get();
|
VKDescriptorSet &descriptor_set = pipeline.descriptor_set_get();
|
||||||
|
VKPushConstants &push_constants = pipeline.push_constants_get();
|
||||||
|
|
||||||
|
/* Update push constants based on their storage type.*/
|
||||||
|
switch (push_constants.storage_type_get()) {
|
||||||
Jeroen-Bakker marked this conversation as resolved
Bastien Montagne
commented
I may be missing something, but this whole Would rather see that logic as part of the I may be missing something, but this whole `switch` block feels like it does not belong here. It looks way too specific to me.
Would rather see that logic as part of the `VKPushConstants` class itself, but no idea if this is doable in practice... At the very least would have it in a dedicated util function of `VKBackend` otherwise?
Jeroen Bakker
commented
Yes you're right, will move this part into a method of VKPushConstants. Yes you're right, will move this part into a method of VKPushConstants.
|
|||||||
|
case VKPushConstantsLayout::StorageType::NONE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VKPushConstantsLayout::StorageType::PUSH_CONSTANTS:
|
||||||
|
command_buffer.push_constants(
|
||||||
|
push_constants, shader->vk_pipeline_layout_get(), VK_SHADER_STAGE_ALL);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case VKPushConstantsLayout::StorageType::STORAGE_BUFFER:
|
||||||
|
push_constants.update_storage_buffer(context.device_get());
|
||||||
|
descriptor_set.bind(push_constants.storage_buffer_get(),
|
||||||
|
push_constants.storage_buffer_binding_get());
|
||||||
|
break;
|
||||||
|
}
|
||||||
descriptor_set.update(context.device_get());
|
descriptor_set.update(context.device_get());
|
||||||
command_buffer.bind(
|
command_buffer.bind(
|
||||||
descriptor_set, shader->vk_pipeline_layout_get(), VK_PIPELINE_BIND_POINT_COMPUTE);
|
descriptor_set, shader->vk_pipeline_layout_get(), VK_PIPELINE_BIND_POINT_COMPUTE);
|
||||||
command_buffer.push_constants(
|
|
||||||
pipeline.push_constants_get(), shader->vk_pipeline_layout_get(), VK_SHADER_STAGE_ALL);
|
|
||||||
command_buffer.dispatch(groups_x_len, groups_y_len, groups_z_len);
|
command_buffer.dispatch(groups_x_len, groups_y_len, groups_z_len);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "vk_buffer.hh"
|
#include "vk_buffer.hh"
|
||||||
|
#include "vk_context.hh"
|
||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
|
|
||||||
|
|
|
@ -10,11 +10,11 @@
|
||||||
#include "gpu_context_private.hh"
|
#include "gpu_context_private.hh"
|
||||||
|
|
||||||
#include "vk_common.hh"
|
#include "vk_common.hh"
|
||||||
#include "vk_context.hh"
|
|
||||||
|
|
||||||
#include "vk_mem_alloc.h"
|
#include "vk_mem_alloc.h"
|
||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
|
class VKContext;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class for handing vulkan buffers (allocation/updating/binding).
|
* Class for handing vulkan buffers (allocation/updating/binding).
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "vk_context.hh"
|
#include "vk_context.hh"
|
||||||
#include "vk_memory.hh"
|
#include "vk_memory.hh"
|
||||||
#include "vk_texture.hh"
|
#include "vk_texture.hh"
|
||||||
|
#include "vk_pipeline.hh"
|
||||||
|
|
||||||
#include "BLI_assert.h"
|
#include "BLI_assert.h"
|
||||||
|
|
||||||
|
@ -75,7 +76,7 @@ void VKCommandBuffer::push_constants(const VKPushConstants &push_constants,
|
||||||
const VkPipelineLayout vk_pipeline_layout,
|
const VkPipelineLayout vk_pipeline_layout,
|
||||||
const VkShaderStageFlags vk_shader_stages)
|
const VkShaderStageFlags vk_shader_stages)
|
||||||
{
|
{
|
||||||
if (push_constants.size_in_bytes() == 0) {
|
if (push_constants.storage_type_get() != VKPushConstantsLayout::StorageType::PUSH_CONSTANTS) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
vkCmdPushConstants(vk_command_buffer_,
|
vkCmdPushConstants(vk_command_buffer_,
|
||||||
|
|
|
@ -8,12 +8,15 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "vk_common.hh"
|
#include "vk_common.hh"
|
||||||
#include "vk_pipeline.hh"
|
|
||||||
|
#include "BLI_utility_mixins.hh"
|
||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
class VKBuffer;
|
class VKBuffer;
|
||||||
class VKTexture;
|
class VKTexture;
|
||||||
class VKPushConstants;
|
class VKPushConstants;
|
||||||
|
class VKPipeline;
|
||||||
|
class VKDescriptorSet;
|
||||||
|
|
||||||
/** Command buffer to keep track of the life-time of a command buffer.*/
|
/** Command buffer to keep track of the life-time of a command buffer.*/
|
||||||
class VKCommandBuffer : NonCopyable, NonMovable {
|
class VKCommandBuffer : NonCopyable, NonMovable {
|
||||||
|
|
|
@ -50,9 +50,8 @@ class VKDescriptorSet : NonCopyable {
|
||||||
*/
|
*/
|
||||||
uint32_t binding;
|
uint32_t binding;
|
||||||
|
|
||||||
Location() = default;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
Location() = default;
|
||||||
Location(const ShaderInput *shader_input) : binding(shader_input->location)
|
Location(const ShaderInput *shader_input) : binding(shader_input->location)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ VKPipeline VKPipeline::create_compute_pipeline(VKContext &context,
|
||||||
VkShaderModule compute_module,
|
VkShaderModule compute_module,
|
||||||
VkDescriptorSetLayout &descriptor_set_layout,
|
VkDescriptorSetLayout &descriptor_set_layout,
|
||||||
VkPipelineLayout &pipeline_layout,
|
VkPipelineLayout &pipeline_layout,
|
||||||
VKPushConstantsLayout &push_constants_layout)
|
const VKPushConstantsLayout &push_constants_layout)
|
||||||
{
|
{
|
||||||
VK_ALLOCATION_CALLBACKS
|
VK_ALLOCATION_CALLBACKS
|
||||||
VkDevice vk_device = context.device_get();
|
VkDevice vk_device = context.device_get();
|
||||||
|
@ -52,13 +52,12 @@ VKPipeline VKPipeline::create_compute_pipeline(VKContext &context,
|
||||||
if (vkCreateComputePipelines(
|
if (vkCreateComputePipelines(
|
||||||
vk_device, nullptr, 1, &pipeline_info, vk_allocation_callbacks, &vk_pipeline) !=
|
vk_device, nullptr, 1, &pipeline_info, vk_allocation_callbacks, &vk_pipeline) !=
|
||||||
VK_SUCCESS) {
|
VK_SUCCESS) {
|
||||||
return VKPipeline();
|
//return VKPipeline();
|
||||||
Jeroen-Bakker marked this conversation as resolved
Jeroen Bakker
commented
This should be fixed. This should be fixed.
|
|||||||
}
|
}
|
||||||
|
|
||||||
VKDescriptorSet descriptor_set = context.descriptor_pools_get().allocate(descriptor_set_layout);
|
VKDescriptorSet descriptor_set = context.descriptor_pools_get().allocate(descriptor_set_layout);
|
||||||
VKPushConstants push_constants(push_constants_layout);
|
VKPushConstants push_constants(&push_constants_layout);
|
||||||
return VKPipeline(
|
return VKPipeline(vk_pipeline, std::move(descriptor_set), std::move(push_constants));
|
||||||
vk_pipeline, std::move(descriptor_set), std::move(push_constants));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
VkPipeline VKPipeline::vk_handle() const
|
VkPipeline VKPipeline::vk_handle() const
|
||||||
|
|
|
@ -44,7 +44,7 @@ class VKPipeline : NonCopyable {
|
||||||
VkShaderModule compute_module,
|
VkShaderModule compute_module,
|
||||||
VkDescriptorSetLayout &descriptor_set_layout,
|
VkDescriptorSetLayout &descriptor_set_layout,
|
||||||
VkPipelineLayout &pipeline_layouts,
|
VkPipelineLayout &pipeline_layouts,
|
||||||
VKPushConstantsLayout &push_constants_layout);
|
const VKPushConstantsLayout &push_constants_layout);
|
||||||
|
|
||||||
VKDescriptorSet &descriptor_set_get()
|
VKDescriptorSet &descriptor_set_get()
|
||||||
{
|
{
|
||||||
|
|
|
@ -6,15 +6,17 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "vk_push_constants.hh"
|
#include "vk_push_constants.hh"
|
||||||
|
#include "vk_backend.hh"
|
||||||
|
#include "vk_shader_interface.hh"
|
||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
|
|
||||||
static uint32_t to_component_size(const shader::Type /*type*/)
|
constexpr uint32_t to_component_size(const shader::Type /*type*/)
|
||||||
{
|
{
|
||||||
return 4;
|
return 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t to_num_components(const shader::Type type)
|
constexpr uint32_t to_num_components(const shader::Type type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case shader::Type::FLOAT:
|
case shader::Type::FLOAT:
|
||||||
|
@ -43,7 +45,7 @@ static uint32_t to_num_components(const shader::Type type)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint32_t to_alignment(const shader::Type type)
|
constexpr uint32_t to_alignment(const shader::Type type)
|
||||||
{
|
{
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case shader::Type::FLOAT:
|
case shader::Type::FLOAT:
|
||||||
|
@ -70,38 +72,71 @@ static uint32_t to_alignment(const shader::Type type)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void align(const shader::ShaderCreateInfo::PushConst &push_constant, uint32_t *r_offset)
|
||||||
|
{
|
||||||
|
uint32_t alignment = to_alignment(push_constant.type);
|
||||||
|
uint32_t alignment_mask = alignment - 1;
|
||||||
|
uint32_t offset = *r_offset;
|
||||||
|
if ((offset & alignment_mask) != 0) {
|
||||||
|
offset &= ~alignment_mask;
|
||||||
|
offset += alignment;
|
||||||
|
*r_offset = offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void reserve(const shader::ShaderCreateInfo::PushConst &push_constant, uint32_t *r_offset)
|
||||||
|
{
|
||||||
|
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 += size;
|
||||||
|
}
|
||||||
|
|
||||||
static VKPushConstantsLayout::PushConstantLayout init_constant(
|
static VKPushConstantsLayout::PushConstantLayout init_constant(
|
||||||
const shader::ShaderCreateInfo::PushConst &push_constant,
|
const shader::ShaderCreateInfo::PushConst &push_constant,
|
||||||
const ShaderInput &shader_input,
|
const ShaderInput &shader_input,
|
||||||
uint32_t *r_offset)
|
uint32_t *r_offset)
|
||||||
{
|
{
|
||||||
|
align(push_constant, r_offset);
|
||||||
|
|
||||||
VKPushConstantsLayout::PushConstantLayout layout;
|
VKPushConstantsLayout::PushConstantLayout layout;
|
||||||
layout.location = shader_input.location;
|
layout.location = shader_input.location;
|
||||||
layout.type = push_constant.type;
|
layout.type = push_constant.type;
|
||||||
layout.array_size = push_constant.array_size;
|
layout.array_size = push_constant.array_size;
|
||||||
layout.offset = *r_offset;
|
layout.offset = *r_offset;
|
||||||
|
|
||||||
/* Perform alignment. */
|
reserve(push_constant, r_offset);
|
||||||
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;
|
return layout;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VKPushConstantsLayout::StorageType VKPushConstantsLayout::determine_storage_type(
|
||||||
|
const shader::ShaderCreateInfo &info, const VkPhysicalDeviceLimits &vk_physical_device_limits)
|
||||||
|
{
|
||||||
|
if (info.push_constants_.is_empty()) {
|
||||||
|
return StorageType::NONE;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t offset = 0;
|
||||||
|
for (const shader::ShaderCreateInfo::PushConst &push_constant : info.push_constants_) {
|
||||||
|
align(push_constant, &offset);
|
||||||
|
reserve(push_constant, &offset);
|
||||||
|
}
|
||||||
|
return offset <= vk_physical_device_limits.maxPushConstantsSize ? StorageType::PUSH_CONSTANTS :
|
||||||
|
StorageType::STORAGE_BUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
void VKPushConstantsLayout::init(const shader::ShaderCreateInfo &info,
|
void VKPushConstantsLayout::init(const shader::ShaderCreateInfo &info,
|
||||||
const VKShaderInterface &interface)
|
const VKShaderInterface &interface,
|
||||||
|
const StorageType storage_type,
|
||||||
|
const ShaderInput *shader_input)
|
||||||
{
|
{
|
||||||
BLI_assert(push_constants.is_empty());
|
BLI_assert(push_constants.is_empty());
|
||||||
|
storage_type_ = storage_type;
|
||||||
|
if (storage_type == StorageType::STORAGE_BUFFER) {
|
||||||
|
BLI_assert(shader_input);
|
||||||
|
storage_buffer_binding_ = VKDescriptorSet::Location(shader_input);
|
||||||
|
}
|
||||||
uint32_t offset = 0;
|
uint32_t offset = 0;
|
||||||
for (const shader::ShaderCreateInfo::PushConst &push_constant : info.push_constants_) {
|
for (const shader::ShaderCreateInfo::PushConst &push_constant : info.push_constants_) {
|
||||||
const ShaderInput *shader_input = interface.uniform_get(push_constant.name.c_str());
|
const ShaderInput *shader_input = interface.uniform_get(push_constant.name.c_str());
|
||||||
|
@ -121,16 +156,22 @@ const VKPushConstantsLayout::PushConstantLayout *VKPushConstantsLayout::find(
|
||||||
}
|
}
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
VKPushConstants::VKPushConstants() = default;
|
||||||
VKPushConstants::VKPushConstants(VKPushConstantsLayout &layout) : layout_(layout)
|
VKPushConstants::VKPushConstants(const VKPushConstantsLayout *layout) : layout_(layout)
|
||||||
{
|
{
|
||||||
data_ = MEM_mallocN(layout.size_in_bytes(), __func__);
|
data_ = MEM_mallocN(layout->size_in_bytes(), __func__);
|
||||||
|
if (storage_type_get() == VKPushConstantsLayout::StorageType::STORAGE_BUFFER) {
|
||||||
|
storage_buffer_ = new VKStorageBuffer(size_in_bytes(), GPU_USAGE_DYNAMIC, __func__);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
VKPushConstants::VKPushConstants(VKPushConstants &&other) : layout_(other.layout_)
|
VKPushConstants::VKPushConstants(VKPushConstants &&other) : layout_(other.layout_)
|
||||||
{
|
{
|
||||||
data_ = other.data_;
|
data_ = other.data_;
|
||||||
other.data_ = nullptr;
|
other.data_ = nullptr;
|
||||||
|
|
||||||
|
storage_buffer_ = other.storage_buffer_;
|
||||||
|
other.storage_buffer_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
VKPushConstants::~VKPushConstants()
|
VKPushConstants::~VKPushConstants()
|
||||||
|
@ -139,15 +180,37 @@ VKPushConstants::~VKPushConstants()
|
||||||
MEM_freeN(data_);
|
MEM_freeN(data_);
|
||||||
data_ = nullptr;
|
data_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
delete storage_buffer_;
|
||||||
|
storage_buffer_ = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
VKPushConstants &VKPushConstants::operator=(VKPushConstants &&other)
|
VKPushConstants &VKPushConstants::operator=(VKPushConstants &&other)
|
||||||
{
|
{
|
||||||
layout_ = other.layout_;
|
layout_ = other.layout_;
|
||||||
|
|
||||||
data_ = other.data_;
|
data_ = other.data_;
|
||||||
other.data_ = nullptr;
|
other.data_ = nullptr;
|
||||||
|
|
||||||
|
storage_buffer_ = other.storage_buffer_;
|
||||||
|
other.storage_buffer_ = nullptr;
|
||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VKPushConstants::update_storage_buffer(VkDevice /*vk_device*/)
|
||||||
|
{
|
||||||
|
BLI_assert(storage_type_get() == VKPushConstantsLayout::StorageType::STORAGE_BUFFER);
|
||||||
|
BLI_assert(storage_buffer_ != nullptr);
|
||||||
|
BLI_assert(data_ != nullptr);
|
||||||
|
storage_buffer_->update(data_);
|
||||||
|
}
|
||||||
|
|
||||||
|
VKStorageBuffer &VKPushConstants::storage_buffer_get()
|
||||||
|
{
|
||||||
|
BLI_assert(storage_type_get() == VKPushConstantsLayout::StorageType::STORAGE_BUFFER);
|
||||||
|
BLI_assert(storage_buffer_ != nullptr);
|
||||||
|
return *storage_buffer_;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace blender::gpu
|
} // namespace blender::gpu
|
||||||
|
|
|
@ -3,6 +3,17 @@
|
||||||
|
|
||||||
/** \file
|
/** \file
|
||||||
* \ingroup gpu
|
* \ingroup gpu
|
||||||
|
*
|
||||||
|
* Push constants is a way to quickly provide a small amount of uniform data to shaders. It should
|
||||||
|
* be much quicker than UBOs but a huge limitation is the size of data - spec requires 128 bytes to
|
||||||
|
* be available for a push constant range. Hardware vendors may support more, but compared to other
|
||||||
|
* means it is still very little (for example 256 bytes).
|
||||||
|
*
|
||||||
|
* Due to this size requirements we try to use push constants when it fits on the device. If it
|
||||||
|
* doesn't fit we fallback to use an uniform buffer.
|
||||||
|
*
|
||||||
|
* Shader developers are responsible to fine-tune the performance of the shader. One way to do this
|
||||||
|
* is to tailor what will be sent as a push constant to keep the push constants within the limits.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
@ -10,12 +21,27 @@
|
||||||
#include "BLI_utility_mixins.hh"
|
#include "BLI_utility_mixins.hh"
|
||||||
#include "BLI_vector.hh"
|
#include "BLI_vector.hh"
|
||||||
|
|
||||||
|
#include "gpu_shader_create_info.hh"
|
||||||
|
|
||||||
#include "vk_common.hh"
|
#include "vk_common.hh"
|
||||||
#include "vk_shader_interface.hh"
|
//#include "vk_context.hh"
|
||||||
|
#include "vk_descriptor_set.hh"
|
||||||
|
#include "vk_storage_buffer.hh"
|
||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
|
class VKShaderInterface;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Describe the layout of the push constants and the storage type that should be used.
|
||||||
|
*/
|
||||||
struct VKPushConstantsLayout {
|
struct VKPushConstantsLayout {
|
||||||
|
/* Should the push constant use regular push constants or a buffer.*/
|
||||||
|
enum class StorageType {
|
||||||
|
NONE,
|
||||||
|
PUSH_CONSTANTS,
|
||||||
|
STORAGE_BUFFER,
|
||||||
|
};
|
||||||
|
|
||||||
struct PushConstantLayout {
|
struct PushConstantLayout {
|
||||||
/* TODO: location requires sequential lookups, we should make the location index based for
|
/* TODO: location requires sequential lookups, we should make the location index based for
|
||||||
* quicker access. */
|
* quicker access. */
|
||||||
|
@ -29,10 +55,34 @@ struct VKPushConstantsLayout {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Vector<PushConstantLayout> push_constants;
|
Vector<PushConstantLayout> push_constants;
|
||||||
uint32_t size_in_bytes_;
|
uint32_t size_in_bytes_ = 0;
|
||||||
|
StorageType storage_type_ = StorageType::NONE;
|
||||||
|
/**
|
||||||
|
* Binding index in the descriptor set when the push constants use an uniform buffer.
|
||||||
|
*/
|
||||||
|
VKDescriptorSet::Location storage_buffer_binding_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void init(const shader::ShaderCreateInfo &info, const VKShaderInterface &interface);
|
static StorageType determine_storage_type(
|
||||||
|
const shader::ShaderCreateInfo &info,
|
||||||
|
const VkPhysicalDeviceLimits &vk_physical_device_limits);
|
||||||
|
void init(const shader::ShaderCreateInfo &info,
|
||||||
|
const VKShaderInterface &interface,
|
||||||
|
StorageType storage_type,
|
||||||
|
const ShaderInput *shader_input);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the storage type that is used.
|
||||||
|
*/
|
||||||
|
StorageType storage_type_get() const
|
||||||
|
{
|
||||||
|
return storage_type_;
|
||||||
|
}
|
||||||
|
|
||||||
|
VKDescriptorSet::Location storage_buffer_binding_get() const
|
||||||
|
{
|
||||||
|
return storage_buffer_binding_;
|
||||||
|
}
|
||||||
|
|
||||||
uint32_t size_in_bytes() const
|
uint32_t size_in_bytes() const
|
||||||
{
|
{
|
||||||
|
@ -42,16 +92,16 @@ struct VKPushConstantsLayout {
|
||||||
const PushConstantLayout *find(int32_t location) const;
|
const PushConstantLayout *find(int32_t location) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
static VKPushConstantsLayout dummy_layout;
|
|
||||||
class VKPushConstants : NonCopyable {
|
class VKPushConstants : NonCopyable {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VKPushConstantsLayout &layout_ = dummy_layout;
|
const VKPushConstantsLayout *layout_ = nullptr;
|
||||||
void *data_ = nullptr;
|
void *data_ = nullptr;
|
||||||
|
VKStorageBuffer *storage_buffer_ = nullptr;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VKPushConstants() = default;
|
VKPushConstants();
|
||||||
VKPushConstants(VKPushConstantsLayout &layout);
|
VKPushConstants(const VKPushConstantsLayout *layout);
|
||||||
VKPushConstants(VKPushConstants &&other);
|
VKPushConstants(VKPushConstants &&other);
|
||||||
virtual ~VKPushConstants();
|
virtual ~VKPushConstants();
|
||||||
|
|
||||||
|
@ -64,9 +114,22 @@ class VKPushConstants : NonCopyable {
|
||||||
|
|
||||||
size_t size_in_bytes() const
|
size_t size_in_bytes() const
|
||||||
Jeroen-Bakker marked this conversation as resolved
Jeroen Bakker
commented
Add Add `const VKPushConstantsLayout& layout_get() const` as API and clean up the interface.
|
|||||||
{
|
{
|
||||||
return layout_.size_in_bytes();
|
return layout_->size_in_bytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
VKPushConstantsLayout::StorageType storage_type_get() const
|
||||||
|
{
|
||||||
|
return layout_->storage_type_get();
|
||||||
|
}
|
||||||
|
|
||||||
|
VKDescriptorSet::Location storage_buffer_binding_get() const
|
||||||
|
{
|
||||||
|
return layout_->storage_buffer_binding_get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void update_storage_buffer(VkDevice vk_device);
|
||||||
|
VKStorageBuffer &storage_buffer_get();
|
||||||
|
|
||||||
const void *data() const
|
const void *data() const
|
||||||
{
|
{
|
||||||
return data_;
|
return data_;
|
||||||
|
@ -78,14 +141,15 @@ class VKPushConstants : NonCopyable {
|
||||||
int32_t array_size,
|
int32_t array_size,
|
||||||
const T *input_data)
|
const T *input_data)
|
||||||
{
|
{
|
||||||
const VKPushConstantsLayout::PushConstantLayout *push_constant_layout = layout_.find(location);
|
const VKPushConstantsLayout::PushConstantLayout *push_constant_layout = layout_->find(
|
||||||
|
location);
|
||||||
if (push_constant_layout == nullptr) {
|
if (push_constant_layout == nullptr) {
|
||||||
/* Currently the builtin uniforms are set using a predefined location each time a shader is
|
/* TODO: Currently the builtin uniforms are set using a predefined location each time a
|
||||||
* bound.*/
|
* shader is bound. This needs to be fixed in the VKShaderInterface.*/
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BLI_assert_msg(push_constant_layout->offset + comp_len * array_size * sizeof(T) <=
|
BLI_assert_msg(push_constant_layout->offset + comp_len * array_size * sizeof(T) <=
|
||||||
layout_.size_in_bytes(),
|
layout_->size_in_bytes(),
|
||||||
"Tried to write outside the push constant allocated memory.");
|
"Tried to write outside the push constant allocated memory.");
|
||||||
uint8_t *bytes = static_cast<uint8_t *>(data_);
|
uint8_t *bytes = static_cast<uint8_t *>(data_);
|
||||||
T *dst = static_cast<T *>(static_cast<void *>(&bytes[push_constant_layout->offset]));
|
T *dst = static_cast<T *>(static_cast<void *>(&bytes[push_constant_layout->offset]));
|
||||||
|
|
|
@ -680,8 +680,7 @@ bool VKShader::finalize(const shader::ShaderCreateInfo *info)
|
||||||
if (!finalize_descriptor_set_layouts(vk_device, *vk_interface, *info)) {
|
if (!finalize_descriptor_set_layouts(vk_device, *vk_interface, *info)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
push_constants_layout_.init(*info, *vk_interface);
|
if (!finalize_pipeline_layout(vk_device, *vk_interface)) {
|
||||||
if (!finalize_pipeline_layout(vk_device, *info)) {
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -700,7 +699,11 @@ bool VKShader::finalize(const shader::ShaderCreateInfo *info)
|
||||||
BLI_assert(fragment_module_ == VK_NULL_HANDLE);
|
BLI_assert(fragment_module_ == VK_NULL_HANDLE);
|
||||||
BLI_assert(compute_module_ != VK_NULL_HANDLE);
|
BLI_assert(compute_module_ != VK_NULL_HANDLE);
|
||||||
compute_pipeline_ = VKPipeline::create_compute_pipeline(
|
compute_pipeline_ = VKPipeline::create_compute_pipeline(
|
||||||
*context_, compute_module_, layout_, pipeline_layout_, push_constants_layout_);
|
*context_,
|
||||||
|
compute_module_,
|
||||||
|
layout_,
|
||||||
|
pipeline_layout_,
|
||||||
|
vk_interface->push_constants_layout_get());
|
||||||
result = compute_pipeline_.is_valid();
|
result = compute_pipeline_.is_valid();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -744,7 +747,7 @@ bool VKShader::finalize_graphics_pipeline(VkDevice /*vk_device */)
|
||||||
}
|
}
|
||||||
|
|
||||||
bool VKShader::finalize_pipeline_layout(VkDevice vk_device,
|
bool VKShader::finalize_pipeline_layout(VkDevice vk_device,
|
||||||
const shader::ShaderCreateInfo & /*info*/)
|
const VKShaderInterface &shader_interface)
|
||||||
{
|
{
|
||||||
VK_ALLOCATION_CALLBACKS
|
VK_ALLOCATION_CALLBACKS
|
||||||
|
|
||||||
|
@ -755,9 +758,14 @@ bool VKShader::finalize_pipeline_layout(VkDevice vk_device,
|
||||||
pipeline_info.flags = 0;
|
pipeline_info.flags = 0;
|
||||||
pipeline_info.setLayoutCount = layout_count;
|
pipeline_info.setLayoutCount = layout_count;
|
||||||
pipeline_info.pSetLayouts = &layout_;
|
pipeline_info.pSetLayouts = &layout_;
|
||||||
if (push_constants_layout_.size_in_bytes() != 0) {
|
|
||||||
|
/* Setup push constants. */
|
||||||
|
const VKPushConstantsLayout &push_constants_layout =
|
||||||
|
shader_interface.push_constants_layout_get();
|
||||||
|
if (push_constants_layout.storage_type_get() ==
|
||||||
|
VKPushConstantsLayout::StorageType::PUSH_CONSTANTS) {
|
||||||
push_constant_range.offset = 0;
|
push_constant_range.offset = 0;
|
||||||
push_constant_range.size = push_constants_layout_.size_in_bytes();
|
push_constant_range.size = push_constants_layout.size_in_bytes();
|
||||||
push_constant_range.stageFlags = VK_SHADER_STAGE_ALL;
|
push_constant_range.stageFlags = VK_SHADER_STAGE_ALL;
|
||||||
pipeline_info.pushConstantRangeCount = 1;
|
pipeline_info.pushConstantRangeCount = 1;
|
||||||
pipeline_info.pPushConstantRanges = &push_constant_range;
|
pipeline_info.pPushConstantRanges = &push_constant_range;
|
||||||
|
@ -881,6 +889,21 @@ static VkDescriptorSetLayoutBinding create_descriptor_set_layout_binding(
|
||||||
return binding;
|
return binding;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static VkDescriptorSetLayoutBinding create_descriptor_set_layout_binding(
|
||||||
|
const VKPushConstantsLayout &push_constants_layout)
|
||||||
|
{
|
||||||
|
BLI_assert(push_constants_layout.storage_type_get() ==
|
||||||
|
VKPushConstantsLayout::StorageType::STORAGE_BUFFER);
|
||||||
|
VkDescriptorSetLayoutBinding binding = {};
|
||||||
|
binding.binding = push_constants_layout.storage_buffer_binding_get();
|
||||||
|
binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
|
||||||
|
binding.descriptorCount = 1;
|
||||||
|
binding.stageFlags = VK_SHADER_STAGE_ALL;
|
||||||
|
binding.pImmutableSamplers = nullptr;
|
||||||
|
|
||||||
|
return binding;
|
||||||
|
}
|
||||||
|
|
||||||
static void add_descriptor_set_layout_bindings(
|
static void add_descriptor_set_layout_bindings(
|
||||||
const VKShaderInterface &interface,
|
const VKShaderInterface &interface,
|
||||||
const Vector<shader::ShaderCreateInfo::Resource> &resources,
|
const Vector<shader::ShaderCreateInfo::Resource> &resources,
|
||||||
|
@ -895,6 +918,13 @@ static void add_descriptor_set_layout_bindings(
|
||||||
|
|
||||||
r_bindings.append(create_descriptor_set_layout_binding(*shader_input, resource));
|
r_bindings.append(create_descriptor_set_layout_binding(*shader_input, resource));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Add push constants to the descriptor when push constants are stored in a storage buffer.*/
|
||||||
|
const VKPushConstantsLayout &push_constants_layout = interface.push_constants_layout_get();
|
||||||
|
if (push_constants_layout.storage_type_get() ==
|
||||||
|
VKPushConstantsLayout::StorageType::STORAGE_BUFFER) {
|
||||||
|
r_bindings.append(create_descriptor_set_layout_binding(push_constants_layout));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Jeroen-Bakker marked this conversation as resolved
Jeroen Bakker
commented
Also check for uniform_buffer Also check for uniform_buffer
|
|||||||
static VkDescriptorSetLayoutCreateInfo create_descriptor_set_layout(
|
static VkDescriptorSetLayoutCreateInfo create_descriptor_set_layout(
|
||||||
|
@ -912,11 +942,19 @@ static VkDescriptorSetLayoutCreateInfo create_descriptor_set_layout(
|
||||||
return set_info;
|
return set_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool descriptor_sets_needed(const VKShaderInterface &shader_interface,
|
||||||
|
const shader::ShaderCreateInfo &info)
|
||||||
|
{
|
||||||
|
return !info.pass_resources_.is_empty() || !info.batch_resources_.is_empty() ||
|
||||||
|
shader_interface.push_constants_layout_get().storage_type_get() ==
|
||||||
|
VKPushConstantsLayout::StorageType::STORAGE_BUFFER;
|
||||||
|
}
|
||||||
|
|
||||||
bool VKShader::finalize_descriptor_set_layouts(VkDevice vk_device,
|
bool VKShader::finalize_descriptor_set_layouts(VkDevice vk_device,
|
||||||
const VKShaderInterface &shader_interface,
|
const VKShaderInterface &shader_interface,
|
||||||
const shader::ShaderCreateInfo &info)
|
const shader::ShaderCreateInfo &info)
|
||||||
{
|
{
|
||||||
if (info.pass_resources_.is_empty() && info.batch_resources_.is_empty()) {
|
if (!descriptor_sets_needed(shader_interface, info)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -981,18 +1019,13 @@ void VKShader::uniform_float(int location, int comp_len, int array_size, const f
|
||||||
pipeline_get().push_constants_get().push_constant_set(location, comp_len, array_size, data);
|
pipeline_get().push_constants_get().push_constant_set(location, comp_len, array_size, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VKShader::uniform_int(int /*location*/,
|
void VKShader::uniform_int(int location, int comp_len, int array_size, const int *data)
|
||||||
int /*comp_len*/,
|
|
||||||
int /*array_size*/,
|
|
||||||
const int * /*data*/)
|
|
||||||
{
|
{
|
||||||
|
pipeline_get().push_constants_get().push_constant_set(location, comp_len, array_size, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string VKShader::resources_declare(const shader::ShaderCreateInfo &info) const
|
std::string VKShader::resources_declare(const shader::ShaderCreateInfo &info) const
|
||||||
{
|
{
|
||||||
if (info.name_ == "workbench_next_prepass_ptcloud_opaque_flat_texture_clip") {
|
|
||||||
printf("%s\n", info.name_.c_str());
|
|
||||||
}
|
|
||||||
VKShaderInterface interface;
|
VKShaderInterface interface;
|
||||||
interface.init(info);
|
interface.init(info);
|
||||||
std::stringstream ss;
|
std::stringstream ss;
|
||||||
|
@ -1013,9 +1046,19 @@ std::string VKShader::resources_declare(const shader::ShaderCreateInfo &info) co
|
||||||
print_resource_alias(ss, res);
|
print_resource_alias(ss, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!info.push_constants_.is_empty()) {
|
/* Push constants. */
|
||||||
|
const VKPushConstantsLayout &push_constants_layout = interface.push_constants_layout_get();
|
||||||
|
const VKPushConstantsLayout::StorageType push_constants_storage =
|
||||||
|
push_constants_layout.storage_type_get();
|
||||||
|
if (push_constants_storage != VKPushConstantsLayout::StorageType::NONE) {
|
||||||
ss << "\n/* Push Constants. */\n";
|
ss << "\n/* Push Constants. */\n";
|
||||||
ss << "layout(push_constant) uniform constants\n";
|
if (push_constants_storage == VKPushConstantsLayout::StorageType::PUSH_CONSTANTS) {
|
||||||
|
ss << "layout(push_constant) uniform constants\n";
|
||||||
|
}
|
||||||
|
else /* VKPushConstantsLayout::StorageType::STORAGE_BUFFER*/ {
|
||||||
|
ss << "layout(binding = " << push_constants_layout.storage_buffer_binding_get()
|
||||||
|
<< ", std430) buffer constants\n";
|
||||||
|
}
|
||||||
ss << "{\n";
|
ss << "{\n";
|
||||||
for (const ShaderCreateInfo::PushConst &uniform : info.push_constants_) {
|
for (const ShaderCreateInfo::PushConst &uniform : info.push_constants_) {
|
||||||
ss << " " << to_string(uniform.type) << " pc_" << uniform.name;
|
ss << " " << to_string(uniform.type) << " pc_" << uniform.name;
|
||||||
|
@ -1044,12 +1087,6 @@ std::string VKShader::vertex_interface_declare(const shader::ShaderCreateInfo &i
|
||||||
ss << "layout(location = " << attr.index << ") ";
|
ss << "layout(location = " << attr.index << ") ";
|
||||||
ss << "in " << to_string(attr.type) << " " << attr.name << ";\n";
|
ss << "in " << to_string(attr.type) << " " << attr.name << ";\n";
|
||||||
}
|
}
|
||||||
/* NOTE(D4490): Fix a bug where shader without any vertex attributes do not behave correctly.
|
|
||||||
*/
|
|
||||||
if (GPU_type_matches_ex(GPU_DEVICE_APPLE, GPU_OS_MAC, GPU_DRIVER_ANY, GPU_BACKEND_OPENGL) &&
|
|
||||||
info.vertex_inputs_.is_empty()) {
|
|
||||||
ss << "in float gpu_dummy_workaround;\n";
|
|
||||||
}
|
|
||||||
ss << "\n/* Interfaces. */\n";
|
ss << "\n/* Interfaces. */\n";
|
||||||
int location = 0;
|
int location = 0;
|
||||||
for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
|
for (const StageInterfaceInfo *iface : info.vertex_out_interfaces_) {
|
||||||
|
@ -1223,6 +1260,9 @@ VKPipeline &VKShader::pipeline_get()
|
||||||
|
|
||||||
const VKShaderInterface &VKShader::interface_get() const
|
const VKShaderInterface &VKShader::interface_get() const
|
||||||
{
|
{
|
||||||
|
BLI_assert_msg(interface != nullptr,
|
||||||
|
"Unable to access the shader interface when finalizing the shader, use the "
|
||||||
|
"instance created in the finalize method.");
|
||||||
return *static_cast<const VKShaderInterface *>(interface);
|
return *static_cast<const VKShaderInterface *>(interface);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,7 +11,7 @@
|
||||||
|
|
||||||
#include "vk_backend.hh"
|
#include "vk_backend.hh"
|
||||||
#include "vk_context.hh"
|
#include "vk_context.hh"
|
||||||
#include "vk_push_constants.hh"
|
#include "vk_pipeline.hh"
|
||||||
|
|
||||||
#include "BLI_string_ref.hh"
|
#include "BLI_string_ref.hh"
|
||||||
|
|
||||||
|
@ -28,7 +28,6 @@ class VKShader : public Shader {
|
||||||
bool compilation_failed_ = false;
|
bool compilation_failed_ = false;
|
||||||
VkDescriptorSetLayout layout_ = VK_NULL_HANDLE;
|
VkDescriptorSetLayout layout_ = VK_NULL_HANDLE;
|
||||||
VkPipelineLayout pipeline_layout_ = VK_NULL_HANDLE;
|
VkPipelineLayout pipeline_layout_ = VK_NULL_HANDLE;
|
||||||
VKPushConstantsLayout push_constants_layout_;
|
|
||||||
VKPipeline compute_pipeline_;
|
VKPipeline compute_pipeline_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -80,7 +79,7 @@ class VKShader : public Shader {
|
||||||
bool finalize_descriptor_set_layouts(VkDevice vk_device,
|
bool finalize_descriptor_set_layouts(VkDevice vk_device,
|
||||||
const VKShaderInterface &shader_interface,
|
const VKShaderInterface &shader_interface,
|
||||||
const shader::ShaderCreateInfo &info);
|
const shader::ShaderCreateInfo &info);
|
||||||
bool finalize_pipeline_layout(VkDevice vk_device, const shader::ShaderCreateInfo &info);
|
bool finalize_pipeline_layout(VkDevice vk_device, const VKShaderInterface &shader_interface);
|
||||||
bool finalize_graphics_pipeline(VkDevice vk_device);
|
bool finalize_graphics_pipeline(VkDevice vk_device);
|
||||||
|
|
||||||
bool is_graphics_shader() const
|
bool is_graphics_shader() const
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "vk_shader_interface.hh"
|
#include "vk_shader_interface.hh"
|
||||||
|
#include "vk_context.hh"
|
||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
|
|
||||||
|
@ -40,15 +41,26 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reserve 1 storage buffer for push constants fallback. */
|
||||||
|
size_t names_size = info.interface_names_size_;
|
||||||
|
VKContext &context = *VKContext::get();
|
||||||
|
const VKPushConstantsLayout::StorageType push_constants_storage_type =
|
||||||
|
VKPushConstantsLayout::determine_storage_type(info, context.physical_device_limits_get());
|
||||||
|
if (push_constants_storage_type == VKPushConstantsLayout::StorageType::STORAGE_BUFFER) {
|
||||||
|
ssbo_len_++;
|
||||||
|
names_size += PUSH_CONSTANTS_FALLBACK_NAME_LEN + 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* Make sure that the image slots don't overlap with the sampler slots.*/
|
/* Make sure that the image slots don't overlap with the sampler slots.*/
|
||||||
image_offset_ += 1;
|
image_offset_++;
|
||||||
|
|
||||||
int32_t input_tot_len = ubo_len_ + uniform_len_ + ssbo_len_;
|
int32_t input_tot_len = ubo_len_ + uniform_len_ + ssbo_len_;
|
||||||
inputs_ = static_cast<ShaderInput *>(
|
inputs_ = static_cast<ShaderInput *>(
|
||||||
MEM_calloc_arrayN(input_tot_len, sizeof(ShaderInput), __func__));
|
MEM_calloc_arrayN(input_tot_len, sizeof(ShaderInput), __func__));
|
||||||
ShaderInput *input = inputs_;
|
ShaderInput *input = inputs_;
|
||||||
|
|
||||||
name_buffer_ = (char *)MEM_mallocN(info.interface_names_size_, "name_buffer");
|
name_buffer_ = (char *)MEM_mallocN(names_size, "name_buffer");
|
||||||
uint32_t name_buffer_offset = 0;
|
uint32_t name_buffer_offset = 0;
|
||||||
|
|
||||||
int32_t location = 0;
|
int32_t location = 0;
|
||||||
|
@ -101,6 +113,23 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Push constant post initialization.*/
|
||||||
|
/*
|
||||||
|
* When using storage buffer storage type we need to add it to the the name list here.
|
||||||
|
* Also determine the location as this is used inside the descriptor set as its binding number.
|
||||||
|
*/
|
||||||
|
int32_t push_constants_fallback_location = -1;
|
||||||
|
ShaderInput *push_constants_fallback_input = nullptr;
|
||||||
|
if (push_constants_storage_type == VKPushConstantsLayout::StorageType::STORAGE_BUFFER) {
|
||||||
|
copy_input_name(input, PUSH_CONSTANTS_FALLBACK_NAME, name_buffer_, name_buffer_offset);
|
||||||
|
input->location = push_constants_fallback_location = location++;
|
||||||
|
input->binding = -1;
|
||||||
|
push_constants_fallback_input = input;
|
||||||
|
input++;
|
||||||
|
}
|
||||||
|
push_constants_layout_.init(
|
||||||
|
info, *this, push_constants_storage_type, push_constants_fallback_input);
|
||||||
|
|
||||||
sort_inputs();
|
sort_inputs();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "gpu_shader_create_info.hh"
|
#include "gpu_shader_create_info.hh"
|
||||||
#include "gpu_shader_interface.hh"
|
#include "gpu_shader_interface.hh"
|
||||||
|
|
||||||
|
#include "vk_push_constants.hh"
|
||||||
|
|
||||||
namespace blender::gpu {
|
namespace blender::gpu {
|
||||||
class VKShaderInterface : public ShaderInterface {
|
class VKShaderInterface : public ShaderInterface {
|
||||||
private:
|
private:
|
||||||
|
@ -22,6 +24,13 @@ class VKShaderInterface : public ShaderInterface {
|
||||||
*/
|
*/
|
||||||
uint32_t image_offset_ = 0;
|
uint32_t image_offset_ = 0;
|
||||||
|
|
||||||
|
VKPushConstantsLayout push_constants_layout_;
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr StringRefNull PUSH_CONSTANTS_FALLBACK_NAME = StringRefNull(
|
||||||
|
"push_constants_fallback", 23);
|
||||||
|
static constexpr size_t PUSH_CONSTANTS_FALLBACK_NAME_LEN = PUSH_CONSTANTS_FALLBACK_NAME.size();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
VKShaderInterface() = default;
|
VKShaderInterface() = default;
|
||||||
|
|
||||||
|
@ -35,5 +44,10 @@ class VKShaderInterface : public ShaderInterface {
|
||||||
const ShaderInput *shader_input_get(const shader::ShaderCreateInfo::Resource &resource) const;
|
const ShaderInput *shader_input_get(const shader::ShaderCreateInfo::Resource &resource) const;
|
||||||
const ShaderInput *shader_input_get(
|
const ShaderInput *shader_input_get(
|
||||||
const shader::ShaderCreateInfo::Resource::BindType &bind_type, int binding) const;
|
const shader::ShaderCreateInfo::Resource::BindType &bind_type, int binding) const;
|
||||||
|
|
||||||
|
const VKPushConstantsLayout &push_constants_layout_get() const
|
||||||
|
{
|
||||||
|
return push_constants_layout_;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
} // namespace blender::gpu
|
} // namespace blender::gpu
|
||||||
|
|
Loading…
Reference in New Issue
Remove line as this is vulkan specific.