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,
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,
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,
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);
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);
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;
}
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,
.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
}