Vulkan: Push constants #104880
|
@ -20,6 +20,7 @@ class VKUniformBuffer;
|
|||
class VKVertexBuffer;
|
||||
class VKIndexBuffer;
|
||||
class VKTexture;
|
||||
class VKShaderInterface;
|
||||
|
||||
/**
|
||||
* In vulkan shader resources (images and buffers) are grouped in descriptor sets.
|
||||
|
@ -51,12 +52,13 @@ class VKDescriptorSet : NonCopyable {
|
|||
*/
|
||||
uint32_t binding;
|
||||
|
||||
public:
|
||||
Location() = default;
|
||||
Location(const ShaderInput *shader_input) : binding(shader_input->location)
|
||||
Location(uint32_t binding) : binding(binding)
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
Location() = default;
|
||||
|
||||
bool operator==(const Location &other) const
|
||||
{
|
||||
return binding == other.binding;
|
||||
|
@ -68,6 +70,7 @@ class VKDescriptorSet : NonCopyable {
|
|||
}
|
||||
|
||||
friend struct Binding;
|
||||
friend class VKShaderInterface;
|
||||
};
|
||||
|
||||
private:
|
||||
|
|
|
@ -24,9 +24,9 @@ void VKIndexBuffer::bind_as_ssbo(uint binding)
|
|||
|
||||
VKShader *shader = static_cast<VKShader *>(context.shader);
|
||||
const VKShaderInterface &shader_interface = shader->interface_get();
|
||||
const ShaderInput *shader_input = shader_interface.shader_input_get(
|
||||
const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, binding);
|
||||
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, shader_input);
|
||||
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, location);
|
||||
}
|
||||
|
||||
void VKIndexBuffer::read(uint32_t *data) const
|
||||
|
|
|
@ -85,13 +85,12 @@ VKPushConstantsLayout::StorageType VKPushConstantsLayout::determine_storage_type
|
|||
void VKPushConstantsLayout::init(const shader::ShaderCreateInfo &info,
|
||||
const VKShaderInterface &interface,
|
||||
const StorageType storage_type,
|
||||
const ShaderInput *shader_input)
|
||||
const VKDescriptorSet::Location location)
|
||||
{
|
||||
BLI_assert(push_constants.is_empty());
|
||||
storage_type_ = storage_type;
|
||||
if (ELEM(storage_type, StorageType::STORAGE_BUFFER, StorageType::UNIFORM_BUFFER)) {
|
||||
BLI_assert(shader_input);
|
||||
storage_buffer_binding_ = VKDescriptorSet::Location(shader_input);
|
||||
storage_buffer_binding_ = location;
|
||||
}
|
||||
uint32_t offset = 0;
|
||||
for (const shader::ShaderCreateInfo::PushConst &push_constant : info.push_constants_) {
|
||||
|
@ -173,6 +172,9 @@ VKPushConstants &VKPushConstants::operator=(VKPushConstants &&other)
|
|||
storage_buffer_ = other.storage_buffer_;
|
||||
other.storage_buffer_ = nullptr;
|
||||
|
||||
uniform_buffer_ = other.uniform_buffer_;
|
||||
other.uniform_buffer_ = nullptr;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ struct VKPushConstantsLayout {
|
|||
void init(const shader::ShaderCreateInfo &info,
|
||||
const VKShaderInterface &interface,
|
||||
StorageType storage_type,
|
||||
const ShaderInput *shader_input);
|
||||
VKDescriptorSet::Location location);
|
||||
|
||||
/**
|
||||
* Return the storage type that is used.
|
||||
|
|
|
@ -326,10 +326,10 @@ static std::ostream &print_qualifier(std::ostream &os, const Qualifier &qualifie
|
|||
}
|
||||
|
||||
static void print_resource(std::ostream &os,
|
||||
const ShaderInput &shader_input,
|
||||
const VKDescriptorSet::Location location,
|
||||
const ShaderCreateInfo::Resource &res)
|
||||
{
|
||||
os << "layout(binding = " << shader_input.location;
|
||||
os << "layout(binding = " << (uint32_t)location;
|
||||
if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) {
|
||||
os << ", " << to_string(res.image.format);
|
||||
}
|
||||
|
@ -379,12 +379,8 @@ static void print_resource(std::ostream &os,
|
|||
const VKShaderInterface &shader_interface,
|
||||
const ShaderCreateInfo::Resource &res)
|
||||
{
|
||||
const ShaderInput *shader_input = shader_interface.shader_input_get(res);
|
||||
if (shader_input == nullptr) {
|
||||
BLI_assert_msg(shader_input, "Cannot find shader input for resource");
|
||||
return;
|
||||
}
|
||||
print_resource(os, *shader_input, res);
|
||||
const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(res);
|
||||
print_resource(os, location, res);
|
||||
}
|
||||
|
||||
static void print_resource_alias(std::ostream &os, const ShaderCreateInfo::Resource &res)
|
||||
|
@ -877,10 +873,10 @@ static VkDescriptorType descriptor_type(const shader::ShaderCreateInfo::Resource
|
|||
}
|
||||
|
||||
static VkDescriptorSetLayoutBinding create_descriptor_set_layout_binding(
|
||||
const ShaderInput &shader_input, const shader::ShaderCreateInfo::Resource &resource)
|
||||
const VKDescriptorSet::Location location, const shader::ShaderCreateInfo::Resource &resource)
|
||||
{
|
||||
VkDescriptorSetLayoutBinding binding = {};
|
||||
binding.binding = shader_input.location;
|
||||
binding.binding = location;
|
||||
binding.descriptorType = descriptor_type(resource);
|
||||
binding.descriptorCount = 1;
|
||||
binding.stageFlags = VK_SHADER_STAGE_ALL;
|
||||
|
@ -914,13 +910,8 @@ static void add_descriptor_set_layout_bindings(
|
|||
Vector<VkDescriptorSetLayoutBinding> &r_bindings)
|
||||
{
|
||||
for (const shader::ShaderCreateInfo::Resource &resource : resources) {
|
||||
const ShaderInput *shader_input = interface.shader_input_get(resource);
|
||||
if (shader_input == nullptr) {
|
||||
BLI_assert_msg(shader_input, "Cannot find shader input for resource.");
|
||||
continue;
|
||||
}
|
||||
|
||||
r_bindings.append(create_descriptor_set_layout_binding(*shader_input, resource));
|
||||
const VKDescriptorSet::Location location = interface.descriptor_set_location(resource);
|
||||
r_bindings.append(create_descriptor_set_layout_binding(location, resource));
|
||||
}
|
||||
|
||||
/* Add push constants to the descriptor when push constants are stored in a storage buffer.*/
|
||||
|
|
|
@ -62,30 +62,29 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
|
|||
int32_t input_tot_len = ubo_len_ + uniform_len_ + ssbo_len_;
|
||||
inputs_ = static_cast<ShaderInput *>(
|
||||
MEM_calloc_arrayN(input_tot_len, sizeof(ShaderInput), __func__));
|
||||
descriptor_set_locations_ = Array<VKDescriptorSet::Location>(input_tot_len);
|
||||
ShaderInput *input = inputs_;
|
||||
|
||||
name_buffer_ = (char *)MEM_mallocN(names_size, "name_buffer");
|
||||
uint32_t name_buffer_offset = 0;
|
||||
|
||||
int32_t location = 0;
|
||||
uint32_t descriptor_set_location = 0;
|
||||
|
||||
/* Uniform blocks */
|
||||
for (const ShaderCreateInfo::Resource &res : all_resources) {
|
||||
if (res.bind_type == ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER) {
|
||||
copy_input_name(input, res.image.name, name_buffer_, name_buffer_offset);
|
||||
input->location = location++;
|
||||
input->binding = res.slot;
|
||||
input->location = input->binding = res.slot;
|
||||
descriptor_set_location_update(input, descriptor_set_location++);
|
||||
input++;
|
||||
}
|
||||
}
|
||||
/* Add push constant when using uniform buffer as fallback. */
|
||||
int32_t push_constants_fallback_location = -1;
|
||||
ShaderInput *push_constants_fallback_input = nullptr;
|
||||
if (push_constants_storage_type == VKPushConstantsLayout::StorageType::UNIFORM_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->location = input->binding = -1;
|
||||
push_constants_fallback_location = descriptor_set_location++;
|
||||
descriptor_set_location_update(input, push_constants_fallback_location);
|
||||
input++;
|
||||
}
|
||||
|
||||
|
@ -93,14 +92,14 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
|
|||
for (const ShaderCreateInfo::Resource &res : all_resources) {
|
||||
if (res.bind_type == ShaderCreateInfo::Resource::BindType::SAMPLER) {
|
||||
copy_input_name(input, res.sampler.name, name_buffer_, name_buffer_offset);
|
||||
input->location = location++;
|
||||
input->binding = res.slot;
|
||||
input->location = input->binding = res.slot;
|
||||
descriptor_set_location_update(input, descriptor_set_location++);
|
||||
input++;
|
||||
}
|
||||
else if (res.bind_type == ShaderCreateInfo::Resource::BindType::IMAGE) {
|
||||
copy_input_name(input, res.image.name, name_buffer_, name_buffer_offset);
|
||||
input->location = location++;
|
||||
input->binding = res.slot + image_offset_;
|
||||
input->location = input->binding = res.slot + image_offset_;
|
||||
descriptor_set_location_update(input, descriptor_set_location++);
|
||||
input++;
|
||||
}
|
||||
}
|
||||
|
@ -109,7 +108,7 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
|
|||
/* NOTE: Push constants must be added after other uniform resources as resources have strict
|
||||
* rules for their 'location' due to descriptor sets. Push constants only need an unique location
|
||||
* as it is only used by the GPU module internally.*/
|
||||
int32_t push_constant_location = location + 1024;
|
||||
int32_t push_constant_location = 1024;
|
||||
for (const ShaderCreateInfo::PushConst &push_constant : info.push_constants_) {
|
||||
copy_input_name(input, push_constant.name, name_buffer_, name_buffer_offset);
|
||||
input->location = push_constant_location++;
|
||||
|
@ -121,8 +120,8 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
|
|||
for (const ShaderCreateInfo::Resource &res : all_resources) {
|
||||
if (res.bind_type == ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER) {
|
||||
copy_input_name(input, res.storagebuf.name, name_buffer_, name_buffer_offset);
|
||||
input->location = location++;
|
||||
input->binding = res.slot;
|
||||
input->location = input->binding = res.slot;
|
||||
descriptor_set_location_update(input, descriptor_set_location++);
|
||||
input++;
|
||||
}
|
||||
}
|
||||
|
@ -134,16 +133,46 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
|
|||
*/
|
||||
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->location = input->binding = -1;
|
||||
push_constants_fallback_location = descriptor_set_location++;
|
||||
descriptor_set_location_update(input, push_constants_fallback_location);
|
||||
input++;
|
||||
}
|
||||
push_constants_layout_.init(
|
||||
info, *this, push_constants_storage_type, push_constants_fallback_input);
|
||||
info, *this, push_constants_storage_type, push_constants_fallback_location);
|
||||
|
||||
sort_inputs();
|
||||
debug_print();
|
||||
// debug_print();
|
||||
}
|
||||
|
||||
void VKShaderInterface::descriptor_set_location_update(const ShaderInput *shader_input,
|
||||
const VKDescriptorSet::Location location)
|
||||
{
|
||||
int32_t index = (shader_input - inputs_) / sizeof(ShaderInput);
|
||||
descriptor_set_locations_[index] = location;
|
||||
}
|
||||
|
||||
const VKDescriptorSet::Location VKShaderInterface::descriptor_set_location(
|
||||
const ShaderInput *shader_input) const
|
||||
{
|
||||
int32_t index = (shader_input - inputs_) / sizeof(ShaderInput);
|
||||
return descriptor_set_locations_[index];
|
||||
}
|
||||
|
||||
const VKDescriptorSet::Location VKShaderInterface::descriptor_set_location(
|
||||
const shader::ShaderCreateInfo::Resource &resource) const
|
||||
{
|
||||
const ShaderInput *shader_input = shader_input_get(resource);
|
||||
BLI_assert(shader_input);
|
||||
return descriptor_set_location(shader_input);
|
||||
}
|
||||
|
||||
const VKDescriptorSet::Location VKShaderInterface::descriptor_set_location(
|
||||
const shader::ShaderCreateInfo::Resource::BindType &bind_type, int binding) const
|
||||
{
|
||||
const ShaderInput *shader_input = shader_input_get(bind_type, binding);
|
||||
BLI_assert(shader_input);
|
||||
return descriptor_set_location(shader_input);
|
||||
}
|
||||
|
||||
const ShaderInput *VKShaderInterface::shader_input_get(
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#include "gpu_shader_create_info.hh"
|
||||
#include "gpu_shader_interface.hh"
|
||||
|
||||
#include "BLI_array.hh"
|
||||
|
||||
#include "vk_push_constants.hh"
|
||||
|
||||
namespace blender::gpu {
|
||||
|
@ -25,6 +27,7 @@ class VKShaderInterface : public ShaderInterface {
|
|||
uint32_t image_offset_ = 0;
|
||||
|
||||
VKPushConstantsLayout push_constants_layout_;
|
||||
Array<VKDescriptorSet::Location> descriptor_set_locations_;
|
||||
|
||||
public:
|
||||
static constexpr StringRefNull PUSH_CONSTANTS_FALLBACK_NAME = StringRefNull(
|
||||
|
@ -35,6 +38,18 @@ class VKShaderInterface : public ShaderInterface {
|
|||
VKShaderInterface() = default;
|
||||
|
||||
void init(const shader::ShaderCreateInfo &info);
|
||||
|
||||
const VKDescriptorSet::Location descriptor_set_location(
|
||||
const shader::ShaderCreateInfo::Resource &resource) const;
|
||||
const VKDescriptorSet::Location descriptor_set_location(
|
||||
const shader::ShaderCreateInfo::Resource::BindType &bind_type, int binding) const;
|
||||
|
||||
const VKPushConstantsLayout &push_constants_layout_get() const
|
||||
{
|
||||
return push_constants_layout_;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* Retrieve the shader input for the given resource.
|
||||
*
|
||||
|
@ -44,10 +59,8 @@ class VKShaderInterface : public ShaderInterface {
|
|||
const ShaderInput *shader_input_get(const shader::ShaderCreateInfo::Resource &resource) const;
|
||||
const ShaderInput *shader_input_get(
|
||||
const shader::ShaderCreateInfo::Resource::BindType &bind_type, int binding) const;
|
||||
|
||||
const VKPushConstantsLayout &push_constants_layout_get() const
|
||||
{
|
||||
return push_constants_layout_;
|
||||
}
|
||||
const VKDescriptorSet::Location descriptor_set_location(const ShaderInput *shader_input) const;
|
||||
void descriptor_set_location_update(const ShaderInput *shader_input,
|
||||
const VKDescriptorSet::Location location);
|
||||
};
|
||||
} // namespace blender::gpu
|
||||
|
|
|
@ -34,9 +34,9 @@ void VKStorageBuffer::bind(int slot)
|
|||
}
|
||||
VKShader *shader = static_cast<VKShader *>(context.shader);
|
||||
const VKShaderInterface &shader_interface = shader->interface_get();
|
||||
const ShaderInput *shader_input = shader_interface.shader_input_get(
|
||||
const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, slot);
|
||||
shader->pipeline_get().descriptor_set_get().bind(*this, shader_input);
|
||||
shader->pipeline_get().descriptor_set_get().bind(*this, location);
|
||||
}
|
||||
|
||||
void VKStorageBuffer::unbind()
|
||||
|
|
|
@ -227,8 +227,8 @@ void VKTexture::image_bind(int binding)
|
|||
}
|
||||
VKContext &context = *VKContext::get();
|
||||
VKShader *shader = static_cast<VKShader *>(context.shader);
|
||||
VKDescriptorSet::Location location(shader->interface_get().shader_input_get(
|
||||
shader::ShaderCreateInfo::Resource::BindType::IMAGE, binding));
|
||||
const VKDescriptorSet::Location location = shader->interface_get().descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::IMAGE, binding);
|
||||
shader->pipeline_get().descriptor_set_get().image_bind(*this, location);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,9 +27,9 @@ void VKVertexBuffer::bind_as_ssbo(uint binding)
|
|||
|
||||
VKShader *shader = static_cast<VKShader *>(context.shader);
|
||||
const VKShaderInterface &shader_interface = shader->interface_get();
|
||||
const ShaderInput *shader_input = shader_interface.shader_input_get(
|
||||
const VKDescriptorSet::Location location = shader_interface.descriptor_set_location(
|
||||
shader::ShaderCreateInfo::Resource::BindType::STORAGE_BUFFER, binding);
|
||||
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, shader_input);
|
||||
shader->pipeline_get().descriptor_set_get().bind_as_ssbo(*this, location);
|
||||
}
|
||||
|
||||
void VKVertexBuffer::bind_as_texture(uint /*binding*/)
|
||||
|
|
Loading…
Reference in New Issue