From b908c67816709d0bdcdec02b7926c80531508405 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Fri, 11 Sep 2015 10:25:21 -0700 Subject: [PATCH] vk: Rework the push constants data structure Previously, we simply had a big blob of stuff for "driver constants". Now, we have a very specific data structure that contains the driver constants that we care about. --- src/vulkan/anv_cmd_buffer.c | 46 +++++++++++++++++++++++++++++-------- src/vulkan/anv_compiler.cpp | 6 +---- src/vulkan/anv_private.h | 32 +++++++++++++++++++------- 3 files changed, 62 insertions(+), 22 deletions(-) diff --git a/src/vulkan/anv_cmd_buffer.c b/src/vulkan/anv_cmd_buffer.c index f8a630bece5..17857d9759a 100644 --- a/src/vulkan/anv_cmd_buffer.c +++ b/src/vulkan/anv_cmd_buffer.c @@ -61,6 +61,39 @@ anv_cmd_state_init(struct anv_cmd_state *state) state->gen7.index_buffer = NULL; } +static VkResult +anv_cmd_buffer_ensure_push_constants_size(struct anv_cmd_buffer *cmd_buffer, + VkShaderStage stage, uint32_t size) +{ + struct anv_push_constants **ptr = &cmd_buffer->state.push_constants[stage]; + + if (*ptr == NULL) { + *ptr = anv_device_alloc(cmd_buffer->device, size, 8, + VK_SYSTEM_ALLOC_TYPE_INTERNAL); + if (*ptr == NULL) + return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + (*ptr)->size = size; + } else if ((*ptr)->size < size) { + void *new_data = anv_device_alloc(cmd_buffer->device, size, 8, + VK_SYSTEM_ALLOC_TYPE_INTERNAL); + if (new_data == NULL) + return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY); + + memcpy(new_data, *ptr, (*ptr)->size); + anv_device_free(cmd_buffer->device, *ptr); + + *ptr = new_data; + (*ptr)->size = size; + } + + return VK_SUCCESS; +} + +#define anv_cmd_buffer_ensure_push_constant_field(cmd_buffer, stage, field) \ + anv_cmd_buffer_ensure_push_constants_size(cmd_buffer, stage, \ + (offsetof(struct anv_push_constants, field) + \ + sizeof(cmd_buffer->state.push_constants[0]->field))) + VkResult anv_CreateCommandBuffer( VkDevice _device, const VkCmdBufferCreateInfo* pCreateInfo, @@ -665,8 +698,8 @@ struct anv_state anv_cmd_buffer_push_constants(struct anv_cmd_buffer *cmd_buffer, VkShaderStage stage) { - struct anv_push_constant_data *data = - cmd_buffer->state.push_constants[stage].data; + struct anv_push_constants *data = + cmd_buffer->state.push_constants[stage]; struct brw_stage_prog_data *prog_data = cmd_buffer->state.pipeline->prog_data[stage]; @@ -701,14 +734,9 @@ void anv_CmdPushConstants( uint32_t stage; for_each_bit(stage, stageFlags) { - if (cmd_buffer->state.push_constants[stage].data == NULL) { - cmd_buffer->state.push_constants[stage].data = - anv_device_alloc(cmd_buffer->device, - sizeof(struct anv_push_constant_data), 8, - VK_SYSTEM_ALLOC_TYPE_INTERNAL); - } + anv_cmd_buffer_ensure_push_constant_field(cmd_buffer, stage, client_data); - memcpy(cmd_buffer->state.push_constants[stage].data->client_data + start, + memcpy(cmd_buffer->state.push_constants[stage]->client_data + start, values, length); } diff --git a/src/vulkan/anv_compiler.cpp b/src/vulkan/anv_compiler.cpp index 5f189c7ce8e..06ae61aea5c 100644 --- a/src/vulkan/anv_compiler.cpp +++ b/src/vulkan/anv_compiler.cpp @@ -149,14 +149,10 @@ create_params_array(struct anv_device *device, * actually dereference any of the gl_constant_value pointers in the * params array, it doesn't really matter what we put here. */ - struct anv_push_constant_data *null_data = NULL; + struct anv_push_constants *null_data = NULL; for (unsigned i = 0; i < num_client_params; i++) prog_data->param[i] = (const gl_constant_value *)&null_data->client_data[i * sizeof(float)]; - - for (unsigned i = 0; i < num_driver_params; i++) - prog_data->param[num_client_params + i] = - (const gl_constant_value *)&null_data->driver_data[i * sizeof(float)]; } static void diff --git a/src/vulkan/anv_private.h b/src/vulkan/anv_private.h index 0c7d5e8a536..53eb0b30526 100644 --- a/src/vulkan/anv_private.h +++ b/src/vulkan/anv_private.h @@ -658,6 +658,8 @@ anv_descriptor_set_destroy(struct anv_device *device, #define MAX_SETS 8 #define MAX_RTS 8 #define MAX_PUSH_CONSTANTS_SIZE 128 +#define MAX_DYNAMIC_BUFFERS 16 +#define MAX_IMAGES 8 struct anv_pipeline_layout { struct { @@ -700,14 +702,28 @@ struct anv_descriptor_set_binding { uint32_t dynamic_offsets[128]; }; -struct anv_push_constant_data { - uint8_t client_data[MAX_PUSH_CONSTANTS_SIZE]; - uint8_t driver_data[0]; -}; - struct anv_push_constants { - uint32_t driver_data_size; - struct anv_push_constant_data *data; + /* Current allocated size of this push constants data structure. + * Because a decent chunk of it may not be used (images on SKL, for + * instance), we won't actually allocate the entire structure up-front. + */ + uint32_t size; + + /* Push constant data provided by the client through vkPushConstants */ + uint8_t client_data[MAX_PUSH_CONSTANTS_SIZE]; + + /* Our hardware only provides zero-based vertex and instance id so, in + * order to satisfy the vulkan requirements, we may have to push one or + * both of these into the shader. + */ + uint32_t base_vertex; + uint32_t base_instance; + + /* Offsets for dynamically bound buffers */ + uint32_t dynamic_offsets[MAX_DYNAMIC_BUFFERS]; + + /* Image data for image_load_store on pre-SKL */ + struct brw_image_param images[MAX_IMAGES]; }; /** State required while building cmd buffer */ @@ -731,7 +747,7 @@ struct anv_cmd_state { uint32_t state_vf[GEN8_3DSTATE_VF_length]; struct anv_vertex_binding vertex_bindings[MAX_VBS]; struct anv_descriptor_set_binding descriptors[MAX_SETS]; - struct anv_push_constants push_constants[VK_SHADER_STAGE_NUM]; + struct anv_push_constants * push_constants[VK_SHADER_STAGE_NUM]; struct { struct anv_buffer * index_buffer; -- 2.30.2