gen8: Add support for base vertex/instance
authorJason Ekstrand <jason.ekstrand@intel.com>
Tue, 26 Jan 2016 20:08:31 +0000 (12:08 -0800)
committerJason Ekstrand <jason.ekstrand@intel.com>
Tue, 26 Jan 2016 22:56:37 +0000 (14:56 -0800)
src/vulkan/gen8_cmd_buffer.c
src/vulkan/genX_pipeline_util.h

index 096ced5694fd7c90432e7b1bffa5c61054cef481..c919c065ca225ccc2d1c5aee4a0d73c267815315 100644 (file)
@@ -450,6 +450,41 @@ cmd_buffer_flush_state(struct anv_cmd_buffer *cmd_buffer)
    cmd_buffer->state.dirty = 0;
 }
 
+static void
+emit_base_vertex_instance_bo(struct anv_cmd_buffer *cmd_buffer,
+                             struct anv_bo *bo, uint32_t offset)
+{
+   uint32_t *p = anv_batch_emitn(&cmd_buffer->batch, 5,
+                                 GENX(3DSTATE_VERTEX_BUFFERS));
+
+   GENX(VERTEX_BUFFER_STATE_pack)(&cmd_buffer->batch, p + 1,
+      &(struct GENX(VERTEX_BUFFER_STATE)) {
+         .VertexBufferIndex = 32, /* Reserved for this */
+         .MemoryObjectControlState = GENX(MOCS),
+         .AddressModifyEnable = true,
+         .BufferPitch = 0,
+         .BufferStartingAddress = { bo, offset },
+         .BufferSize = 8
+      });
+}
+
+static void
+emit_base_vertex_instance(struct anv_cmd_buffer *cmd_buffer,
+                          uint32_t base_vertex, uint32_t base_instance)
+{
+   struct anv_state id_state =
+      anv_cmd_buffer_alloc_dynamic_state(cmd_buffer, 8, 4);
+
+   ((uint32_t *)id_state.map)[0] = base_vertex;
+   ((uint32_t *)id_state.map)[0] = base_instance;
+
+   if (!cmd_buffer->device->info.has_llc)
+      anv_state_clflush(id_state);
+
+   emit_base_vertex_instance_bo(cmd_buffer,
+      &cmd_buffer->device->dynamic_state_block_pool.bo, id_state.offset);
+}
+
 void genX(CmdDraw)(
     VkCommandBuffer                             commandBuffer,
     uint32_t                                    vertexCount,
@@ -461,6 +496,10 @@ void genX(CmdDraw)(
 
    cmd_buffer_flush_state(cmd_buffer);
 
+   if (cmd_buffer->state.pipeline->vs_prog_data.uses_basevertex ||
+       cmd_buffer->state.pipeline->vs_prog_data.uses_baseinstance)
+      emit_base_vertex_instance(cmd_buffer, firstVertex, firstInstance);
+
    anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE),
                   .VertexAccessType = SEQUENTIAL,
                   .VertexCountPerInstance = vertexCount,
@@ -482,6 +521,10 @@ void genX(CmdDrawIndexed)(
 
    cmd_buffer_flush_state(cmd_buffer);
 
+   if (cmd_buffer->state.pipeline->vs_prog_data.uses_basevertex ||
+       cmd_buffer->state.pipeline->vs_prog_data.uses_baseinstance)
+      emit_base_vertex_instance(cmd_buffer, vertexOffset, firstInstance);
+
    anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE),
                   .VertexAccessType = RANDOM,
                   .VertexCountPerInstance = indexCount,
@@ -513,6 +556,10 @@ void genX(CmdDrawIndirect)(
 
    cmd_buffer_flush_state(cmd_buffer);
 
+   if (cmd_buffer->state.pipeline->vs_prog_data.uses_basevertex ||
+       cmd_buffer->state.pipeline->vs_prog_data.uses_baseinstance)
+      emit_base_vertex_instance_bo(cmd_buffer, bo, bo_offset + 8);
+
    emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_VERTEX_COUNT, bo, bo_offset);
    emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_INSTANCE_COUNT, bo, bo_offset + 4);
    emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_VERTEX, bo, bo_offset + 8);
@@ -683,6 +730,11 @@ void genX(CmdDrawIndexedIndirect)(
 
    cmd_buffer_flush_state(cmd_buffer);
 
+   /* TODO: We need to stomp base vertex to 0 somehow */
+   if (cmd_buffer->state.pipeline->vs_prog_data.uses_basevertex ||
+       cmd_buffer->state.pipeline->vs_prog_data.uses_baseinstance)
+      emit_base_vertex_instance_bo(cmd_buffer, bo, bo_offset + 12);
+
    emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_VERTEX_COUNT, bo, bo_offset);
    emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_INSTANCE_COUNT, bo, bo_offset + 4);
    emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_VERTEX, bo, bo_offset + 8);
index 050c33591cb5b3947ac3a69ce6584a85d376277f..363a1fd23ac7f857bcbaac9b646e70148164aaac 100644 (file)
@@ -68,17 +68,24 @@ emit_vertex_input(struct anv_pipeline *pipeline,
       elements = inputs_read >> VERT_ATTRIB_GENERIC0;
    }
 
-   uint32_t elem_count = __builtin_popcount(elements);
-
-#if ANV_GEN <= 7
+#if ANV_GEN >= 8
+   /* On BDW+, we only need to allocate space for base ids.  Setting up
+    * the actual vertex and instance id is a separate packet.
+    */
+   const bool needs_svgs_elem = pipeline->vs_prog_data.uses_basevertex ||
+                                pipeline->vs_prog_data.uses_baseinstance;
+#else
    /* On Haswell and prior, vertex and instance id are created by using the
     * ComponentControl fields, so we need an element for any of them.
     */
-   if (pipeline->vs_prog_data.uses_vertexid ||
-       pipeline->vs_prog_data.uses_instanceid)
-      elem_count++;
+   const bool needs_svgs_elem = pipeline->vs_prog_data.uses_vertexid ||
+                                pipeline->vs_prog_data.uses_instanceid ||
+                                pipeline->vs_prog_data.uses_basevertex ||
+                                pipeline->vs_prog_data.uses_baseinstance;
 #endif
 
+   uint32_t elem_count = __builtin_popcount(elements) + needs_svgs_elem;
+
    uint32_t *p;
    if (elem_count > 0) {
       const uint32_t num_dwords = 1 + elem_count * 2;
@@ -129,6 +136,28 @@ emit_vertex_input(struct anv_pipeline *pipeline,
    }
 
    const uint32_t id_slot = __builtin_popcount(elements);
+   if (needs_svgs_elem) {
+      struct GENX(VERTEX_ELEMENT_STATE) element = {
+         .VertexBufferIndex = 32, /* Reserved for this */
+         .Valid = true,
+         .SourceElementFormat = ISL_FORMAT_R32G32_UINT,
+         /* FIXME: Do we need to provide the base vertex as component 0 here
+          * to support the correct base vertex ID? */
+         .Component0Control = pipeline->vs_prog_data.uses_basevertex ?
+                              VFCOMP_STORE_SRC : VFCOMP_STORE_0,
+         .Component1Control = pipeline->vs_prog_data.uses_baseinstance ?
+                              VFCOMP_STORE_SRC : VFCOMP_STORE_0,
+#if ANV_GEN >= 8
+         .Component2Control = VFCOMP_STORE_0,
+         .Component3Control = VFCOMP_STORE_0,
+#else
+         .Component2Control = VFCOMP_STORE_VID,
+         .Component3Control = VFCOMP_STORE_IID,
+#endif
+      };
+      GENX(VERTEX_ELEMENT_STATE_pack)(NULL, &p[1 + id_slot * 2], &element);
+   }
+
 #if ANV_GEN >= 8
    anv_batch_emit(&pipeline->batch, GENX(3DSTATE_VF_SGVS),
                   .VertexIDEnable = pipeline->vs_prog_data.uses_vertexid,
@@ -137,20 +166,6 @@ emit_vertex_input(struct anv_pipeline *pipeline,
                   .InstanceIDEnable = pipeline->vs_prog_data.uses_instanceid,
                   .InstanceIDComponentNumber = 3,
                   .InstanceIDElementOffset = id_slot);
-#else
-   if (pipeline->vs_prog_data.uses_vertexid ||
-       pipeline->vs_prog_data.uses_instanceid) {
-      struct GEN7_VERTEX_ELEMENT_STATE element = {
-         .Valid = true,
-         /* FIXME: Do we need to provide the base vertex as component 0 here
-          * to support the correct base vertex ID? */
-         .Component0Control = VFCOMP_STORE_0,
-         .Component1Control = VFCOMP_STORE_0,
-         .Component2Control = VFCOMP_STORE_VID,
-         .Component3Control = VFCOMP_STORE_IID
-      };
-      GEN7_VERTEX_ELEMENT_STATE_pack(NULL, &p[1 + id_slot * 2], &element);
-   }
 #endif
 }