From 4e3ee043c0ab68faf5c853dd361e68974b55e8db Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Wed, 26 Aug 2015 17:57:51 -0700 Subject: [PATCH] vk/gen8: Add support for push constants --- src/vulkan/anv_cmd_buffer.c | 28 ++++++++++++++++++++++++++ src/vulkan/anv_private.h | 4 ++++ src/vulkan/gen8_cmd_buffer.c | 38 ++++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) diff --git a/src/vulkan/anv_cmd_buffer.c b/src/vulkan/anv_cmd_buffer.c index a2a2833b62e..963edcf06ca 100644 --- a/src/vulkan/anv_cmd_buffer.c +++ b/src/vulkan/anv_cmd_buffer.c @@ -661,6 +661,34 @@ void anv_CmdWaitEvents( stub(); } +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 brw_stage_prog_data *prog_data = + cmd_buffer->state.pipeline->prog_data[stage]; + + /* If we don't actually have any push constants, bail. */ + if (data == NULL || prog_data->nr_params == 0) + return (struct anv_state) { .offset = 0 }; + + struct anv_state state = + anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, + prog_data->nr_params * sizeof(float), + 32 /* bottom 5 bits MBZ */); + + /* Walk through the param array and fill the buffer with data */ + uint32_t *u32_map = state.map; + for (unsigned i = 0; i < prog_data->nr_params; i++) { + uint32_t offset = (uintptr_t)prog_data->param[i]; + u32_map[i] = *(uint32_t *)((uint8_t *)data + offset); + } + + return state; +} + void anv_CmdPushConstants( VkCmdBuffer cmdBuffer, VkPipelineLayout layout, diff --git a/src/vulkan/anv_private.h b/src/vulkan/anv_private.h index 05799276718..55affd160d9 100644 --- a/src/vulkan/anv_private.h +++ b/src/vulkan/anv_private.h @@ -841,6 +841,10 @@ void gen8_cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer, void anv_cmd_buffer_begin_subpass(struct anv_cmd_buffer *cmd_buffer, struct anv_subpass *subpass); +struct anv_state +anv_cmd_buffer_push_constants(struct anv_cmd_buffer *cmd_buffer, + VkShaderStage stage); + void anv_cmd_buffer_clear_attachments(struct anv_cmd_buffer *cmd_buffer, struct anv_render_pass *pass, const VkClearValue *clear_values); diff --git a/src/vulkan/gen8_cmd_buffer.c b/src/vulkan/gen8_cmd_buffer.c index 6d5004a1ca2..37a53c00156 100644 --- a/src/vulkan/gen8_cmd_buffer.c +++ b/src/vulkan/gen8_cmd_buffer.c @@ -29,6 +29,41 @@ #include "anv_private.h" +static void +gen8_cmd_buffer_flush_push_constants(struct anv_cmd_buffer *cmd_buffer) +{ + uint32_t stage; + + static const uint32_t push_constant_opcodes[] = { + [VK_SHADER_STAGE_VERTEX] = 21, + [VK_SHADER_STAGE_TESS_CONTROL] = 25, /* HS */ + [VK_SHADER_STAGE_TESS_EVALUATION] = 26, /* DS */ + [VK_SHADER_STAGE_GEOMETRY] = 22, + [VK_SHADER_STAGE_FRAGMENT] = 23, + [VK_SHADER_STAGE_COMPUTE] = 0, + }; + + uint32_t flushed = 0; + + for_each_bit(stage, cmd_buffer->state.push_constants_dirty) { + struct anv_state state = anv_cmd_buffer_push_constants(cmd_buffer, stage); + + if (state.offset == 0) + continue; + + anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_CONSTANT_VS, + ._3DCommandSubOpcode = push_constant_opcodes[stage], + .ConstantBody = { + .PointerToConstantBuffer0 = { .offset = state.offset }, + .ConstantBuffer0ReadLength = DIV_ROUND_UP(state.alloc_size, 32), + }); + + flushed |= 1 << stage; + } + + cmd_buffer->state.push_constants_dirty &= ~flushed; +} + static void gen8_cmd_buffer_flush_state(struct anv_cmd_buffer *cmd_buffer) { @@ -84,6 +119,9 @@ gen8_cmd_buffer_flush_state(struct anv_cmd_buffer *cmd_buffer) if (cmd_buffer->state.descriptors_dirty) anv_flush_descriptor_sets(cmd_buffer); + if (cmd_buffer->state.push_constants_dirty) + gen8_cmd_buffer_flush_push_constants(cmd_buffer); + if (cmd_buffer->state.dirty & ANV_CMD_BUFFER_VP_DIRTY) { struct anv_dynamic_vp_state *vp_state = cmd_buffer->state.vp_state; anv_batch_emit(&cmd_buffer->batch, GEN8_3DSTATE_SCISSOR_STATE_POINTERS, -- 2.30.2