vk/gen8: Add support for push constants
authorJason Ekstrand <jason.ekstrand@intel.com>
Thu, 27 Aug 2015 00:57:51 +0000 (17:57 -0700)
committerJason Ekstrand <jason.ekstrand@intel.com>
Thu, 27 Aug 2015 17:25:58 +0000 (10:25 -0700)
src/vulkan/anv_cmd_buffer.c
src/vulkan/anv_private.h
src/vulkan/gen8_cmd_buffer.c

index a2a2833b62e6cc162cddfe969c103b30cf0d838d..963edcf06ca200acff825290918ab327f7a4a525 100644 (file)
@@ -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,
index 05799276718fb4daa7973a9373b65bb83832a350..55affd160d95cc8b4596da852d6bb36796ac5e55 100644 (file)
@@ -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);
index 6d5004a1ca24d5ebf9125bcb3361f27f4f332dc8..37a53c00156c96799aad1f63e903ca30925a8c0d 100644 (file)
 
 #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,