pvr: implement dynamically set vertex buffer strides
Co-Authored-by: Frank Binns <frank.binns@imgtec.com> Signed-off-by: Frank Binns <frank.binns@imgtec.com> Signed-off-by: Vlad Schiller <vlad-radu.schiller@imgtec.com> Acked-by: Erik Faye-Lund <erik.faye-lund@collabora.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36412>
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#define PVR_PDS_H
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -142,6 +142,7 @@ struct pvr_queue {
|
||||
struct pvr_vertex_binding {
|
||||
struct pvr_buffer *buffer;
|
||||
VkDeviceSize offset;
|
||||
VkDeviceSize size;
|
||||
};
|
||||
|
||||
struct pvr_pds_upload {
|
||||
|
||||
Reference in New Issue
Block a user