Vulkan: Shader Interface Attribute Extraction. #107333

Merged
Jeroen Bakker merged 1 commits from Jeroen-Bakker/blender:vulkan-shader-interface into main 2023-04-25 15:09:31 +02:00
3 changed files with 34 additions and 10 deletions

View File

@ -203,17 +203,22 @@ class VKPushConstants : VKResourceTracker<VKUniformBuffer> {
const T *input_data)
{
const Layout::PushConstant *push_constant_layout = layout_->find(location);
BLI_assert(push_constant_layout);
if (push_constant_layout == nullptr) {
/* Legacy code can still try to update push constants when they don't exist. For example
* `immDrawPixelsTexSetup` will bind an image slot manually. This works in OpenGL, but in
* vulkan images aren't stored as push constants. */
return;
}
uint8_t *bytes = static_cast<uint8_t *>(data_);
T *dst = static_cast<T *>(static_cast<void *>(&bytes[push_constant_layout->offset]));
const bool is_tightly_std140_packed = (comp_len % 4) == 0;
if (layout_->storage_type_get() == StorageType::PUSH_CONSTANTS || array_size == 0 ||
is_tightly_std140_packed) {
BLI_assert_msg(push_constant_layout->offset + comp_len * array_size * sizeof(T) <=
layout_->size_in_bytes(),
push_constant_layout->array_size == 0 || is_tightly_std140_packed) {
const size_t copy_size_in_bytes = comp_len * max_ii(array_size, 1) * sizeof(T);
BLI_assert_msg(push_constant_layout->offset + copy_size_in_bytes <= layout_->size_in_bytes(),
"Tried to write outside the push constant allocated memory.");
memcpy(dst, input_data, comp_len * array_size * sizeof(T));
memcpy(dst, input_data, copy_size_in_bytes);
is_dirty_ = true;
return;
}

View File

@ -984,12 +984,14 @@ void VKShader::unbind()
void VKShader::uniform_float(int location, int comp_len, int array_size, const float *data)
{
pipeline_get().push_constants_get().push_constant_set(location, comp_len, array_size, data);
VKPushConstants &push_constants = pipeline_get().push_constants_get();
push_constants.push_constant_set(location, comp_len, array_size, data);
}
void VKShader::uniform_int(int location, int comp_len, int array_size, const int *data)
{
pipeline_get().push_constants_get().push_constant_set(location, comp_len, array_size, data);
VKPushConstants &push_constants = pipeline_get().push_constants_get();
push_constants.push_constant_set(location, comp_len, array_size, data);
}
std::string VKShader::resources_declare(const shader::ShaderCreateInfo &info) const
@ -1183,6 +1185,7 @@ std::string VKShader::geometry_layout_declare(const shader::ShaderCreateInfo &in
}
ss << "\n";
location = 0;
for (const StageInterfaceInfo *iface : info.geometry_out_interfaces_) {
bool has_matching_input_iface = find_interface_by_name(info.vertex_out_interfaces_,
iface->instance_name) != nullptr;

View File

@ -17,7 +17,7 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
using namespace blender::gpu::shader;
attr_len_ = 0;
attr_len_ = info.vertex_inputs_.size();
uniform_len_ = info.push_constants_.size();
ssbo_len_ = 0;
ubo_len_ = 0;
@ -58,7 +58,7 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
/* Make sure that the image slots don't overlap with the sampler slots. */
image_offset_++;
int32_t input_tot_len = ubo_len_ + uniform_len_ + ssbo_len_;
int32_t input_tot_len = attr_len_ + ubo_len_ + uniform_len_ + ssbo_len_;
inputs_ = static_cast<ShaderInput *>(
MEM_calloc_arrayN(input_tot_len, sizeof(ShaderInput), __func__));
ShaderInput *input = inputs_;
@ -66,6 +66,20 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
name_buffer_ = (char *)MEM_mallocN(names_size, "name_buffer");
uint32_t name_buffer_offset = 0;
/* Attributes */
for (const ShaderCreateInfo::VertIn &attr : info.vertex_inputs_) {
copy_input_name(input, attr.name, name_buffer_, name_buffer_offset);
input->location = input->binding = attr.index;
if (input->location != -1) {
enabled_attr_mask_ |= (1 << input->location);
/* Used in `GPU_shader_get_attribute_info`. */
attr_types_[input->location] = uint8_t(attr.type);
}
input++;
}
/* Uniform blocks */
for (const ShaderCreateInfo::Resource &res : all_resources) {
if (res.bind_type == ShaderCreateInfo::Resource::BindType::UNIFORM_BUFFER) {
@ -131,7 +145,9 @@ void VKShaderInterface::init(const shader::ShaderCreateInfo &info)
}
/* Determine the descriptor set locations after the inputs have been sorted. */
descriptor_set_locations_ = Array<VKDescriptorSet::Location>(input_tot_len);
/* Note: input_tot_len is sometimes more than we need. */
const uint32_t resources_len = input_tot_len;
descriptor_set_locations_ = Array<VKDescriptorSet::Location>(resources_len);
uint32_t descriptor_set_location = 0;
for (ShaderCreateInfo::Resource &res : all_resources) {
const ShaderInput *input = shader_input_get(res);