diff --git a/src/imagination/vulkan/pds/pvr_pds.h b/src/imagination/vulkan/pds/pvr_pds.h index 5354286fe5b..72f00e7c53e 100644 --- a/src/imagination/vulkan/pds/pvr_pds.h +++ b/src/imagination/vulkan/pds/pvr_pds.h @@ -25,6 +25,7 @@ #define PVR_PDS_H #include +#include #include "pvr_device_info.h" #include "pvr_limits.h" @@ -1021,6 +1022,7 @@ struct pvr_pds_vertex_primary_program_input { #define PVR_PDS_CONST_MAP_ENTRY_TYPE_BASE_VERTEX (13) #define PVR_PDS_CONST_MAP_ENTRY_TYPE_BASE_WORKGROUP (14) #define PVR_PDS_CONST_MAP_ENTRY_TYPE_COND_RENDER (15) +#define PVR_PDS_CONST_MAP_ENTRY_TYPE_VERTEX_ATTRIBUTE_STRIDE (16) /* We pack all the following structs tightly into a buffer using += sizeof(x) * offsets, this can lead to data that is not native aligned. Supplying the @@ -1106,6 +1108,12 @@ struct pvr_const_map_entry_vertex_attribute_address { uint8_t size_in_dwords; } PVR_PACKED; +struct pvr_const_map_entry_vertex_attribute_stride { + uint8_t type; + uint8_t const_offset; + uint8_t binding_index; +} PVR_PACKED; + struct pvr_const_map_entry_robust_vertex_attribute_address { uint8_t type; uint8_t const_offset; diff --git a/src/imagination/vulkan/pds/pvr_pipeline_pds.c b/src/imagination/vulkan/pds/pvr_pipeline_pds.c index c1651fac055..06bf0e51635 100644 --- a/src/imagination/vulkan/pds/pvr_pipeline_pds.c +++ b/src/imagination/vulkan/pds/pvr_pipeline_pds.c @@ -741,6 +741,7 @@ void pvr_pds_generate_vertex_primary_program( } for (uint32_t dma = 0; dma < input_program->dma_count; dma++) { + struct pvr_const_map_entry_vertex_attribute_stride *stride_entry; uint32_t const_base = dma * PVR_PDS_DDMAD_NUM_CONSTS; uint32_t control_word; struct pvr_const_map_entry_literal32 *literal_entry; @@ -1011,12 +1012,12 @@ void pvr_pds_generate_vertex_primary_program( use_robust_vertex_fetch); /* DDMAD Const Usage [__XXX---] */ - literal_entry = + stride_entry = pvr_prepare_next_pds_const_map_entry(&entry_write_state, - sizeof(*literal_entry)); - literal_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_LITERAL32; - literal_entry->const_offset = const_base + 3; - literal_entry->literal_value = vertex_dma->stride; + sizeof(*stride_entry)); + stride_entry->type = PVR_PDS_CONST_MAP_ENTRY_TYPE_VERTEX_ATTRIBUTE_STRIDE; + stride_entry->const_offset = const_base + 3; + stride_entry->binding_index = vertex_dma->binding_index; control_word = vertex_dma->size_in_dwords << PVR_ROGUE_PDSINST_DDMAD_FIELDS_SRC3_BSIZE_SHIFT; diff --git a/src/imagination/vulkan/pvr_cmd_buffer.c b/src/imagination/vulkan/pvr_cmd_buffer.c index a4fac53dec4..22ed2e66c1c 100644 --- a/src/imagination/vulkan/pvr_cmd_buffer.c +++ b/src/imagination/vulkan/pvr_cmd_buffer.c @@ -2735,27 +2735,38 @@ void pvr_CmdBindDescriptorSets2KHR( cmd_buffer->state.dirty.compute_desc_dirty = true; } -void pvr_CmdBindVertexBuffers(VkCommandBuffer commandBuffer, - uint32_t firstBinding, - uint32_t bindingCount, - const VkBuffer *pBuffers, - const VkDeviceSize *pOffsets) +void pvr_CmdBindVertexBuffers2(VkCommandBuffer commandBuffer, + uint32_t firstBinding, + uint32_t bindingCount, + const VkBuffer *pBuffers, + const VkDeviceSize *pOffsets, + const VkDeviceSize *pSizes, + const VkDeviceSize *pStrides) { PVR_FROM_HANDLE(pvr_cmd_buffer, cmd_buffer, commandBuffer); struct pvr_vertex_binding *const vb = cmd_buffer->state.vertex_bindings; - /* We have to defer setting up vertex buffer since we need the buffer - * stride from the pipeline. - */ - assert(firstBinding < PVR_MAX_VERTEX_INPUT_BINDINGS && bindingCount <= PVR_MAX_VERTEX_INPUT_BINDINGS); PVR_CHECK_COMMAND_BUFFER_BUILDING_STATE(cmd_buffer); for (uint32_t i = 0; i < bindingCount; i++) { - vb[firstBinding + i].buffer = pvr_buffer_from_handle(pBuffers[i]); - vb[firstBinding + i].offset = pOffsets[i]; + VK_FROM_HANDLE(pvr_buffer, buffer, pBuffers[i]); + const uint64_t size = pSizes ? pSizes[i] : VK_WHOLE_SIZE; + + vb[firstBinding + i] = (struct pvr_vertex_binding){ + .buffer = buffer, + .offset = pOffsets[i], + .size = vk_buffer_range(&buffer->vk, pOffsets[i], size), + }; + } + + if (pStrides != NULL) { + vk_cmd_set_vertex_binding_strides(&cmd_buffer->vk, + firstBinding, + bindingCount, + pStrides); } cmd_buffer->state.dirty.vertex_bindings = true; @@ -3535,7 +3546,7 @@ pvr_setup_vertex_buffers(struct pvr_cmd_buffer *cmd_buffer, &state->vertex_bindings[attribute->binding_index]; pvr_dev_addr_t addr; - if (binding->buffer->vk.size < + if (binding->size < (attribute->offset + attribute->component_size_in_bytes)) { /* Replace with load from robustness buffer when no attribute is in * range @@ -3608,18 +3619,22 @@ pvr_setup_vertex_buffers(struct pvr_cmd_buffer *cmd_buffer, const uint64_t bound_size = binding->buffer->vk.size - binding->offset; const uint32_t attribute_end = attribute->offset + attribute->component_size_in_bytes; + const struct vk_dynamic_graphics_state *dynamic_state = + &cmd_buffer->vk.dynamic_graphics_state; + const uint32_t stride = + dynamic_state->vi_binding_strides[attribute->binding_index]; uint32_t max_index; /* If the stride is 0 then all attributes use the same single * element from the binding so the index can only be up to 0. */ - if (bound_size < attribute_end || attribute->stride == 0) { + if (bound_size < attribute_end || stride == 0) { max_index = 0; } else { - max_index = (uint32_t)(bound_size / attribute->stride) - 1; + max_index = (uint32_t)(bound_size / stride) - 1; /* There's one last attribute that can fit in. */ - if (bound_size % attribute->stride >= attribute_end) + if (bound_size % stride >= attribute_end) max_index++; } @@ -3632,6 +3647,23 @@ pvr_setup_vertex_buffers(struct pvr_cmd_buffer *cmd_buffer, break; } + case PVR_PDS_CONST_MAP_ENTRY_TYPE_VERTEX_ATTRIBUTE_STRIDE: { + const struct pvr_const_map_entry_vertex_attribute_stride *attribute = + (const struct pvr_const_map_entry_vertex_attribute_stride *)entries; + const struct vk_dynamic_graphics_state *dynamic_state = + &cmd_buffer->vk.dynamic_graphics_state; + const uint32_t stride = + dynamic_state->vi_binding_strides[attribute->binding_index]; + + PVR_WRITE(dword_buffer, + stride, + attribute->const_offset, + pds_info->data_size_in_dwords); + + entries += sizeof(*attribute); + break; + } + default: UNREACHABLE("Unsupported data section map"); break; diff --git a/src/imagination/vulkan/pvr_private.h b/src/imagination/vulkan/pvr_private.h index cf4032ccde3..8ec2549f7e0 100644 --- a/src/imagination/vulkan/pvr_private.h +++ b/src/imagination/vulkan/pvr_private.h @@ -142,6 +142,7 @@ struct pvr_queue { struct pvr_vertex_binding { struct pvr_buffer *buffer; VkDeviceSize offset; + VkDeviceSize size; }; struct pvr_pds_upload {