diff --git a/src/nouveau/vulkan/nvk_cmd_buffer.c b/src/nouveau/vulkan/nvk_cmd_buffer.c index 061561caf5c..26b348447e6 100644 --- a/src/nouveau/vulkan/nvk_cmd_buffer.c +++ b/src/nouveau/vulkan/nvk_cmd_buffer.c @@ -651,6 +651,16 @@ nvk_bind_descriptor_sets(struct nvk_cmd_buffer *cmd, struct nvk_device *dev = nvk_cmd_buffer_device(cmd); struct nvk_physical_device *pdev = nvk_device_physical(dev); + union nvk_buffer_descriptor dynamic_buffers[NVK_MAX_DYNAMIC_BUFFERS]; + uint8_t set_dynamic_buffer_start[NVK_MAX_SETS]; + + /* Read off the current dynamic buffer start array so we can use it to + * determine where we should start binding dynamic buffers. + */ + nvk_descriptor_state_get_root_array(desc, set_dynamic_buffer_start, + 0, NVK_MAX_SETS, + set_dynamic_buffer_start); + /* Fro the Vulkan 1.3.275 spec: * * "When binding a descriptor set (see Descriptor Set Binding) to @@ -668,8 +678,7 @@ nvk_bind_descriptor_sets(struct nvk_cmd_buffer *cmd, * range and it's only our responsibility to adjust all * set_dynamic_buffer_start[p] for p > s as needed. */ - const uint8_t dyn_buffer_start = - desc->root.set_dynamic_buffer_start[info->firstSet]; + const uint8_t dyn_buffer_start = set_dynamic_buffer_start[info->firstSet]; uint8_t dyn_buffer_end = dyn_buffer_start; uint32_t next_dyn_offset = 0; @@ -678,15 +687,14 @@ nvk_bind_descriptor_sets(struct nvk_cmd_buffer *cmd, VK_FROM_HANDLE(nvk_descriptor_set, set, info->pDescriptorSets[i]); if (desc->sets[s] != set) { - if (set != NULL) { - desc->root.sets[s] = nvk_descriptor_set_addr(set); - } else { - desc->root.sets[s] = NVK_BUFFER_ADDRESS_NULL; - } + struct nvk_buffer_address set_addr = + set != NULL ? nvk_descriptor_set_addr(set) + : NVK_BUFFER_ADDRESS_NULL; + nvk_descriptor_state_set_root(cmd, desc, sets[s], set_addr); desc->sets[s] = set; } - desc->root.set_dynamic_buffer_start[s] = dyn_buffer_end; + set_dynamic_buffer_start[s] = dyn_buffer_end; if (pipeline_layout->set_layouts[s] != NULL) { const struct nvk_descriptor_set_layout *set_layout = @@ -703,7 +711,7 @@ nvk_bind_descriptor_sets(struct nvk_cmd_buffer *cmd, } else { db.addr.base_addr += offset; } - desc->root.dynamic_buffers[dyn_buffer_end + j] = db; + dynamic_buffers[dyn_buffer_end + j] = db; } next_dyn_offset += set->layout->dynamic_buffer_count; } @@ -716,9 +724,25 @@ nvk_bind_descriptor_sets(struct nvk_cmd_buffer *cmd, assert(dyn_buffer_end <= NVK_MAX_DYNAMIC_BUFFERS); assert(next_dyn_offset <= info->dynamicOffsetCount); + nvk_descriptor_state_set_root_array(cmd, desc, dynamic_buffers, + dyn_buffer_start, dyn_buffer_end, + &dynamic_buffers[dyn_buffer_start]); + + /* We need to set everything above first_set because later calls to + * nvk_bind_descriptor_sets() depend on it for knowing where to start and + * they may not be called on the next consecutive set. + */ for (uint32_t s = info->firstSet + info->descriptorSetCount; s < NVK_MAX_SETS; s++) - desc->root.set_dynamic_buffer_start[s] = dyn_buffer_end; + set_dynamic_buffer_start[s] = dyn_buffer_end; + + /* We need to at least sync everything from first_set to NVK_MAX_SETS. + * However, we only save anything if firstSet >= 4 so we may as well sync + * everything just to be safe. + */ + nvk_descriptor_state_set_root_array(cmd, desc, set_dynamic_buffer_start, + 0, NVK_MAX_SETS, + set_dynamic_buffer_start); nvk_cmd_dirty_cbufs_for_descriptors(cmd, info->stageFlags, info->firstSet, info->firstSet + info->descriptorSetCount, @@ -747,7 +771,9 @@ nvk_push_constants(UNUSED struct nvk_cmd_buffer *cmd, struct nvk_descriptor_state *desc, const VkPushConstantsInfoKHR *info) { - memcpy(desc->root.push + info->offset, info->pValues, info->size); + nvk_descriptor_state_set_root_array(cmd, desc, push, + info->offset, info->size, + (char *)info->pValues); } @@ -854,10 +880,11 @@ nvk_cmd_buffer_flush_push_descriptors(struct nvk_cmd_buffer *cmd, return; } - desc->root.sets[set_idx] = (struct nvk_buffer_address) { + struct nvk_buffer_address set_addr = { .base_addr = push_set_addr, .size = sizeof(push_set->data), }; + nvk_descriptor_state_set_root(cmd, desc, sets[set_idx], set_addr); } } @@ -888,14 +915,17 @@ nvk_cmd_buffer_get_cbuf_addr(struct nvk_cmd_buffer *cmd, return true; case NVK_CBUF_TYPE_DESC_SET: - *addr_out = desc->root.sets[cbuf->desc_set]; + nvk_descriptor_state_get_root(desc, sets[cbuf->desc_set], addr_out); return true; case NVK_CBUF_TYPE_DYNAMIC_UBO: { - const uint32_t dyn_start = - desc->root.set_dynamic_buffer_start[cbuf->desc_set]; - *addr_out = nvk_ubo_descriptor_addr(pdev, - desc->root.dynamic_buffers[dyn_start + cbuf->dynamic_idx]); + uint8_t dyn_idx; + nvk_descriptor_state_get_root( + desc, set_dynamic_buffer_start[cbuf->desc_set], &dyn_idx); + dyn_idx += cbuf->dynamic_idx; + union nvk_buffer_descriptor ubo_desc; + nvk_descriptor_state_get_root(desc, dynamic_buffers[dyn_idx], &ubo_desc); + *addr_out = nvk_ubo_descriptor_addr(pdev, ubo_desc); return true; } @@ -926,8 +956,11 @@ nvk_cmd_buffer_get_cbuf_descriptor_addr(struct nvk_cmd_buffer *cmd, { assert(cbuf->type == NVK_CBUF_TYPE_UBO_DESC); - assert(cbuf->desc_offset < desc->root.sets[cbuf->desc_set].size); - return desc->root.sets[cbuf->desc_set].base_addr + cbuf->desc_offset; + struct nvk_buffer_address set_addr; + nvk_descriptor_state_get_root(desc, sets[cbuf->desc_set], &set_addr); + + assert(cbuf->desc_offset < set_addr.size); + return set_addr.base_addr + cbuf->desc_offset; } void diff --git a/src/nouveau/vulkan/nvk_cmd_buffer.h b/src/nouveau/vulkan/nvk_cmd_buffer.h index 88d1645717a..27723169cd1 100644 --- a/src/nouveau/vulkan/nvk_cmd_buffer.h +++ b/src/nouveau/vulkan/nvk_cmd_buffer.h @@ -22,6 +22,7 @@ struct nvk_buffer; struct nvk_cbuf; struct nvk_cmd_bo; +struct nvk_cmd_buffer; struct nvk_cmd_pool; struct nvk_image_view; struct nvk_push_descriptor_set; @@ -75,12 +76,46 @@ struct nvk_root_descriptor_table { offsetof(struct nvk_root_descriptor_table, member) struct nvk_descriptor_state { - struct nvk_root_descriptor_table root; + alignas(16) char root[sizeof(struct nvk_root_descriptor_table)]; struct nvk_descriptor_set *sets[NVK_MAX_SETS]; struct nvk_push_descriptor_set *push[NVK_MAX_SETS]; uint32_t push_dirty; }; +#define nvk_descriptor_state_get_root(desc, member, dst) do { \ + const struct nvk_root_descriptor_table *root = \ + (const struct nvk_root_descriptor_table *)(desc)->root; \ + *dst = root->member; \ +} while (0) + +#define nvk_descriptor_state_get_root_array(desc, member, \ + start, count, dst) do { \ + const struct nvk_root_descriptor_table *root = \ + (const struct nvk_root_descriptor_table *)(desc)->root; \ + unsigned _start = start; \ + assert(_start + count <= ARRAY_SIZE(root->member)); \ + for (unsigned i = 0; i < count; i++) \ + (dst)[i] = root->member[i + _start]; \ +} while (0) + +#define nvk_descriptor_state_set_root(cmd, desc, member, src) do { \ + struct nvk_descriptor_state *_desc = (desc); \ + struct nvk_root_descriptor_table *root = \ + (struct nvk_root_descriptor_table *)_desc->root; \ + root->member = (src); \ +} while (0) + +#define nvk_descriptor_state_set_root_array(cmd, desc, member, \ + start, count, src) do { \ + struct nvk_descriptor_state *_desc = (desc); \ + struct nvk_root_descriptor_table *root = \ + (struct nvk_root_descriptor_table *)_desc->root; \ + unsigned _start = start; \ + assert(_start + count <= ARRAY_SIZE(root->member)); \ + for (unsigned i = 0; i < count; i++) \ + root->member[i + _start] = (src)[i]; \ +} while (0) + struct nvk_attachment { VkFormat vk_format; struct nvk_image_view *iview; diff --git a/src/nouveau/vulkan/nvk_cmd_dispatch.c b/src/nouveau/vulkan/nvk_cmd_dispatch.c index 75a4896775e..fe86f264af4 100644 --- a/src/nouveau/vulkan/nvk_cmd_dispatch.c +++ b/src/nouveau/vulkan/nvk_cmd_dispatch.c @@ -116,12 +116,10 @@ nvk_flush_compute_state(struct nvk_cmd_buffer *cmd, nvk_cmd_buffer_flush_push_descriptors(cmd, desc); - desc->root.cs.base_group[0] = base_workgroup[0]; - desc->root.cs.base_group[1] = base_workgroup[1]; - desc->root.cs.base_group[2] = base_workgroup[2]; - desc->root.cs.group_count[0] = global_size[0]; - desc->root.cs.group_count[1] = global_size[1]; - desc->root.cs.group_count[2] = global_size[2]; + nvk_descriptor_state_set_root_array(cmd, desc, cs.base_group, + 0, 3, base_workgroup); + nvk_descriptor_state_set_root_array(cmd, desc, cs.group_count, + 0, 3, global_size); /* pre Pascal the constant buffer sizes need to be 0x100 aligned. As we * simply allocated a buffer and upload data to it, make sure its size is diff --git a/src/nouveau/vulkan/nvk_cmd_draw.c b/src/nouveau/vulkan/nvk_cmd_draw.c index 6b078a5c7eb..205f1069d32 100644 --- a/src/nouveau/vulkan/nvk_cmd_draw.c +++ b/src/nouveau/vulkan/nvk_cmd_draw.c @@ -1804,7 +1804,6 @@ vk_to_nvk_sample_location(VkSampleLocationEXT loc) static void nvk_flush_ms_state(struct nvk_cmd_buffer *cmd) { - struct nvk_descriptor_state *desc = &cmd->state.gfx.descriptors; const struct nvk_rendering_state *render = &cmd->state.gfx.render; const struct vk_dynamic_graphics_state *dyn = &cmd->vk.dynamic_graphics_state; @@ -1865,10 +1864,13 @@ nvk_flush_ms_state(struct nvk_cmd_buffer *cmd) sl = vk_standard_sample_locations_state(samples); } - for (uint32_t i = 0; i < sl->per_pixel; i++) { - desc->root.draw.sample_locations[i] = - vk_to_nvk_sample_location(sl->locations[i]); - } + struct nvk_sample_location push_sl[NVK_MAX_SAMPLES]; + for (uint32_t i = 0; i < sl->per_pixel; i++) + push_sl[i] = vk_to_nvk_sample_location(sl->locations[i]); + + nvk_descriptor_state_set_root_array(cmd, &cmd->state.gfx.descriptors, + draw.sample_locations, + 0, NVK_MAX_SAMPLES, push_sl); if (nvk_cmd_buffer_3d_cls(cmd) >= MAXWELL_B) { struct nvk_sample_location loc[16]; diff --git a/src/nouveau/vulkan/nvk_cmd_meta.c b/src/nouveau/vulkan/nvk_cmd_meta.c index 3521832e6a4..e1ea2d8287a 100644 --- a/src/nouveau/vulkan/nvk_cmd_meta.c +++ b/src/nouveau/vulkan/nvk_cmd_meta.c @@ -66,7 +66,7 @@ struct nvk_meta_save { bool has_push_desc0; struct nvk_push_descriptor_set push_desc0; uint8_t set_dynamic_buffer_start[NVK_MAX_SETS]; - uint8_t push[128]; + uint8_t push[NVK_MAX_PUSH_SIZE]; }; static void @@ -89,14 +89,11 @@ nvk_meta_begin(struct nvk_cmd_buffer *cmd, if (save->has_push_desc0) save->push_desc0 = *desc->push[0]; - STATIC_ASSERT(sizeof(save->set_dynamic_buffer_start) == - sizeof(desc->root.set_dynamic_buffer_start)); - memcpy(save->set_dynamic_buffer_start, - desc->root.set_dynamic_buffer_start, - sizeof(save->set_dynamic_buffer_start)); - - STATIC_ASSERT(sizeof(save->push) == sizeof(desc->root.push)); - memcpy(save->push, desc->root.push, sizeof(save->push)); + nvk_descriptor_state_get_root_array(desc, set_dynamic_buffer_start, + 0, NVK_MAX_SETS, + save->set_dynamic_buffer_start); + nvk_descriptor_state_get_root_array(desc, push, 0, NVK_MAX_PUSH_SIZE, + save->push); struct nv_push *p = nvk_cmd_buffer_push(cmd, 2); P_IMMD(p, NV9097, SET_STATISTICS_COUNTER, { @@ -142,7 +139,8 @@ nvk_meta_end(struct nvk_cmd_buffer *cmd, if (save->desc0) { desc->sets[0] = save->desc0; - desc->root.sets[0] = nvk_descriptor_set_addr(save->desc0); + struct nvk_buffer_address addr = nvk_descriptor_set_addr(save->desc0); + nvk_descriptor_state_set_root(cmd, desc, sets[0], addr); } else if (save->has_push_desc0) { *desc->push[0] = save->push_desc0; desc->push_dirty |= BITFIELD_BIT(0); @@ -152,11 +150,9 @@ nvk_meta_end(struct nvk_cmd_buffer *cmd, /* Restore set_dynaic_buffer_start because meta binding set 0 can disturb * all dynamic buffers starts for all sets. */ - STATIC_ASSERT(sizeof(save->set_dynamic_buffer_start) == - sizeof(desc->root.set_dynamic_buffer_start)); - memcpy(desc->root.set_dynamic_buffer_start, - save->set_dynamic_buffer_start, - sizeof(save->set_dynamic_buffer_start)); + nvk_descriptor_state_set_root_array(cmd, desc, set_dynamic_buffer_start, + 0, NVK_MAX_SETS, + save->set_dynamic_buffer_start); /* Restore the dynamic state */ assert(save->dynamic.vi == &cmd->state.gfx._dynamic_vi); @@ -177,7 +173,8 @@ nvk_meta_end(struct nvk_cmd_buffer *cmd, nvk_cmd_bind_vertex_buffer(cmd, 0, save->vb0); - memcpy(desc->root.push, save->push, sizeof(save->push)); + nvk_descriptor_state_set_root_array(cmd, desc, push, 0, sizeof(save->push), + save->push); struct nv_push *p = nvk_cmd_buffer_push(cmd, 2); P_IMMD(p, NV9097, SET_STATISTICS_COUNTER, { diff --git a/src/nouveau/vulkan/nvk_query_pool.c b/src/nouveau/vulkan/nvk_query_pool.c index d3a8e7d03fe..3b86682eba6 100644 --- a/src/nouveau/vulkan/nvk_query_pool.c +++ b/src/nouveau/vulkan/nvk_query_pool.c @@ -931,7 +931,6 @@ nvk_meta_copy_query_pool_results(struct nvk_cmd_buffer *cmd, VkQueryResultFlags flags) { struct nvk_device *dev = nvk_cmd_buffer_device(cmd); - struct nvk_descriptor_state *desc = &cmd->state.cs.descriptors; VkResult result; const struct nvk_copy_query_push push = { @@ -968,7 +967,8 @@ nvk_meta_copy_query_pool_results(struct nvk_cmd_buffer *cmd, /* Save pipeline and push constants */ struct nvk_shader *shader_save = cmd->state.cs.shader; uint8_t push_save[NVK_MAX_PUSH_SIZE]; - memcpy(push_save, desc->root.push, NVK_MAX_PUSH_SIZE); + nvk_descriptor_state_get_root_array(&cmd->state.cs.descriptors, push, + 0, NVK_MAX_PUSH_SIZE, push_save); dev->vk.dispatch_table.CmdBindPipeline(nvk_cmd_buffer_to_handle(cmd), VK_PIPELINE_BIND_POINT_COMPUTE, @@ -983,7 +983,8 @@ nvk_meta_copy_query_pool_results(struct nvk_cmd_buffer *cmd, /* Restore pipeline and push constants */ if (shader_save) nvk_cmd_bind_compute_shader(cmd, shader_save); - memcpy(desc->root.push, push_save, NVK_MAX_PUSH_SIZE); + nvk_descriptor_state_set_root_array(cmd, &cmd->state.cs.descriptors, push, + 0, NVK_MAX_PUSH_SIZE, push_save); } VKAPI_ATTR void VKAPI_CALL