nvk: Rework descriptor set binding

This prepares us for VK_EXT_graphics_pipeline_library by allowing null
descriptor sets to be bound and handling holes in pipeline layouts.  We
also add a set_dynamic_buffer_start map to the root descriptor table
which says where in dynamic_buffers each set starts.  This can be used
by the pipeline layout lowering in the case where we can't statically
the dynamic buffer index for a binding.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27048>
This commit is contained in:
Faith Ekstrand
2024-01-12 13:53:30 -06:00
committed by Marge Bot
parent a11adbe408
commit e0d907f56f
2 changed files with 43 additions and 11 deletions

View File

@@ -572,12 +572,29 @@ nvk_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,
struct nvk_descriptor_state *desc =
nvk_get_descriptors_state(cmd, pipelineBindPoint);
/* Fro the Vulkan 1.3.275 spec:
*
* "When binding a descriptor set (see Descriptor Set Binding) to
* set number N...
*
* If, additionally, the previously bound descriptor set for set
* N was bound using a pipeline layout not compatible for set N,
* then all bindings in sets numbered greater than N are
* disturbed."
*
* This means that, if some earlier set gets bound in such a way that
* it changes set_dynamic_buffer_start[s], this binding is implicitly
* invalidated. Therefore, we can always look at the current value
* of set_dynamic_buffer_start[s] as the base of our dynamic buffer
* range and it's only our responsibility to adjust all
* set_dynamic_buffer_start[p] for p > s as needed.
*/
uint8_t dyn_buffer_start = desc->root.set_dynamic_buffer_start[firstSet];
uint32_t next_dyn_offset = 0;
for (uint32_t i = 0; i < descriptorSetCount; ++i) {
unsigned s = i + firstSet;
VK_FROM_HANDLE(nvk_descriptor_set, set, pDescriptorSets[i]);
const struct nvk_descriptor_set_layout *set_layout =
vk_to_nvk_descriptor_set_layout(pipeline_layout->set_layouts[s]);
if (desc->sets[s] != set) {
desc->root.sets[s] = nvk_descriptor_set_addr(set);
@@ -589,19 +606,31 @@ nvk_CmdBindDescriptorSets(VkCommandBuffer commandBuffer,
desc->push_dirty &= ~BITFIELD_BIT(s);
}
if (set_layout->dynamic_buffer_count > 0) {
const uint32_t dynamic_buffer_start =
nvk_descriptor_set_layout_dynbuf_start(pipeline_layout, s);
desc->root.set_dynamic_buffer_start[s] = dyn_buffer_start;
for (uint32_t j = 0; j < set_layout->dynamic_buffer_count; j++) {
struct nvk_buffer_address addr = set->dynamic_buffers[j];
addr.base_addr += pDynamicOffsets[next_dyn_offset + j];
desc->root.dynamic_buffers[dynamic_buffer_start + j] = addr;
if (pipeline_layout->set_layouts[s] != NULL) {
const struct nvk_descriptor_set_layout *set_layout =
vk_to_nvk_descriptor_set_layout(pipeline_layout->set_layouts[s]);
if (set != NULL && set_layout->dynamic_buffer_count > 0) {
for (uint32_t j = 0; j < set_layout->dynamic_buffer_count; j++) {
struct nvk_buffer_address addr = set->dynamic_buffers[j];
addr.base_addr += pDynamicOffsets[next_dyn_offset + j];
desc->root.dynamic_buffers[dyn_buffer_start + j] = addr;
}
next_dyn_offset += set->layout->dynamic_buffer_count;
}
next_dyn_offset += set->layout->dynamic_buffer_count;
dyn_buffer_start += set_layout->dynamic_buffer_count;
} else {
assert(set == NULL);
}
}
assert(dyn_buffer_start <= NVK_MAX_DYNAMIC_BUFFERS);
assert(next_dyn_offset <= dynamicOffsetCount);
for (uint32_t s = firstSet + descriptorSetCount; s < NVK_MAX_SETS; s++)
desc->root.set_dynamic_buffer_start[s] = dyn_buffer_start;
}
VKAPI_ATTR void VKAPI_CALL

View File

@@ -56,8 +56,11 @@ struct nvk_root_descriptor_table {
/* Dynamic buffer bindings */
struct nvk_buffer_address dynamic_buffers[NVK_MAX_DYNAMIC_BUFFERS];
/* Start index in dynamic_buffers where each set starts */
uint8_t set_dynamic_buffer_start[NVK_MAX_SETS];
/* enfore alignment to 0x100 as needed pre pascal */
uint8_t __padding[0x20];
uint8_t __padding[0x18];
};
/* helper macro for computing root descriptor byte offsets */