anv: Deduplicate anv_CmdDraw calls

These were all duplicated between gen7_cmd_buffer.c and
gen8_cmd_buffer.c. This commit consolidates both copies in
genX_cmd_buffer.c.
This commit is contained in:
Kristian Høgsberg Kristensen 2016-02-05 16:41:56 -08:00
parent 6cdada0360
commit bdefaae2b9
4 changed files with 191 additions and 313 deletions

View File

@ -1274,6 +1274,11 @@ void gen9_cmd_buffer_set_subpass(struct anv_cmd_buffer *cmd_buffer,
void anv_cmd_buffer_set_subpass(struct anv_cmd_buffer *cmd_buffer,
struct anv_subpass *subpass);
void gen7_cmd_buffer_flush_state(struct anv_cmd_buffer *cmd_buffer);
void gen75_cmd_buffer_flush_state(struct anv_cmd_buffer *cmd_buffer);
void gen8_cmd_buffer_flush_state(struct anv_cmd_buffer *cmd_buffer);
void gen9_cmd_buffer_flush_state(struct anv_cmd_buffer *cmd_buffer);
struct anv_state
anv_cmd_buffer_push_constants(struct anv_cmd_buffer *cmd_buffer,
gl_shader_stage stage);

View File

@ -371,8 +371,8 @@ cmd_buffer_flush_compute_state(struct anv_cmd_buffer *cmd_buffer)
cmd_buffer->state.compute_dirty = 0;
}
static void
cmd_buffer_flush_state(struct anv_cmd_buffer *cmd_buffer)
void
genX(cmd_buffer_flush_state)(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
uint32_t *p;
@ -568,164 +568,6 @@ 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 */
.VertexBufferMemoryObjectControlState = GENX(MOCS),
.AddressModifyEnable = true,
.BufferPitch = 0,
.BufferStartingAddress = { bo, offset },
.EndAddress = { bo, offset + 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)[1] = 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,
uint32_t instanceCount,
uint32_t firstVertex,
uint32_t firstInstance)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
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, GEN7_3DPRIMITIVE,
.VertexAccessType = SEQUENTIAL,
.PrimitiveTopologyType = pipeline->topology,
.VertexCountPerInstance = vertexCount,
.StartVertexLocation = firstVertex,
.InstanceCount = instanceCount,
.StartInstanceLocation = firstInstance,
.BaseVertexLocation = 0);
}
void genX(CmdDrawIndexed)(
VkCommandBuffer commandBuffer,
uint32_t indexCount,
uint32_t instanceCount,
uint32_t firstIndex,
int32_t vertexOffset,
uint32_t firstInstance)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
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, GEN7_3DPRIMITIVE,
.VertexAccessType = RANDOM,
.PrimitiveTopologyType = pipeline->topology,
.VertexCountPerInstance = indexCount,
.StartVertexLocation = firstIndex,
.InstanceCount = instanceCount,
.StartInstanceLocation = firstInstance,
.BaseVertexLocation = vertexOffset);
}
/* Auto-Draw / Indirect Registers */
#define GEN7_3DPRIM_END_OFFSET 0x2420
#define GEN7_3DPRIM_START_VERTEX 0x2430
#define GEN7_3DPRIM_VERTEX_COUNT 0x2434
#define GEN7_3DPRIM_INSTANCE_COUNT 0x2438
#define GEN7_3DPRIM_START_INSTANCE 0x243C
#define GEN7_3DPRIM_BASE_VERTEX 0x2440
void genX(CmdDrawIndirect)(
VkCommandBuffer commandBuffer,
VkBuffer _buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
struct anv_bo *bo = buffer->bo;
uint32_t bo_offset = buffer->offset + offset;
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);
emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_INSTANCE, bo, bo_offset + 12);
emit_lri(&cmd_buffer->batch, GEN7_3DPRIM_BASE_VERTEX, 0);
anv_batch_emit(&cmd_buffer->batch, GEN7_3DPRIMITIVE,
.IndirectParameterEnable = true,
.VertexAccessType = SEQUENTIAL,
.PrimitiveTopologyType = pipeline->topology);
}
void genX(CmdDrawIndexedIndirect)(
VkCommandBuffer commandBuffer,
VkBuffer _buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
struct anv_bo *bo = buffer->bo;
uint32_t bo_offset = buffer->offset + offset;
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 + 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);
emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_BASE_VERTEX, bo, bo_offset + 12);
emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_INSTANCE, bo, bo_offset + 16);
anv_batch_emit(&cmd_buffer->batch, GEN7_3DPRIMITIVE,
.IndirectParameterEnable = true,
.VertexAccessType = RANDOM,
.PrimitiveTopologyType = pipeline->topology);
}
void genX(CmdDispatch)(
VkCommandBuffer commandBuffer,
uint32_t x,

View File

@ -260,8 +260,8 @@ __emit_sf_state(struct anv_cmd_buffer *cmd_buffer)
__emit_genx_sf_state(cmd_buffer);
}
static void
cmd_buffer_flush_state(struct anv_cmd_buffer *cmd_buffer)
void
genX(cmd_buffer_flush_state)(struct anv_cmd_buffer *cmd_buffer)
{
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
uint32_t *p;
@ -479,127 +479,6 @@ 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)[1] = 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,
uint32_t instanceCount,
uint32_t firstVertex,
uint32_t firstInstance)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
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,
.StartVertexLocation = firstVertex,
.InstanceCount = instanceCount,
.StartInstanceLocation = firstInstance,
.BaseVertexLocation = 0);
}
void genX(CmdDrawIndexed)(
VkCommandBuffer commandBuffer,
uint32_t indexCount,
uint32_t instanceCount,
uint32_t firstIndex,
int32_t vertexOffset,
uint32_t firstInstance)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
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,
.StartVertexLocation = firstIndex,
.InstanceCount = instanceCount,
.StartInstanceLocation = firstInstance,
.BaseVertexLocation = vertexOffset);
}
/* Auto-Draw / Indirect Registers */
#define GEN7_3DPRIM_END_OFFSET 0x2420
#define GEN7_3DPRIM_START_VERTEX 0x2430
#define GEN7_3DPRIM_VERTEX_COUNT 0x2434
#define GEN7_3DPRIM_INSTANCE_COUNT 0x2438
#define GEN7_3DPRIM_START_INSTANCE 0x243C
#define GEN7_3DPRIM_BASE_VERTEX 0x2440
void genX(CmdDrawIndirect)(
VkCommandBuffer commandBuffer,
VkBuffer _buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
struct anv_bo *bo = buffer->bo;
uint32_t bo_offset = buffer->offset + offset;
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);
emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_INSTANCE, bo, bo_offset + 12);
emit_lri(&cmd_buffer->batch, GEN7_3DPRIM_BASE_VERTEX, 0);
anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE),
.IndirectParameterEnable = true,
.VertexAccessType = SEQUENTIAL);
}
void genX(CmdBindIndexBuffer)(
VkCommandBuffer commandBuffer,
VkBuffer _buffer,
@ -745,36 +624,6 @@ cmd_buffer_flush_compute_state(struct anv_cmd_buffer *cmd_buffer)
cmd_buffer->state.compute_dirty = 0;
}
void genX(CmdDrawIndexedIndirect)(
VkCommandBuffer commandBuffer,
VkBuffer _buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
struct anv_bo *bo = buffer->bo;
uint32_t bo_offset = buffer->offset + offset;
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);
emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_BASE_VERTEX, bo, bo_offset + 12);
emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_INSTANCE, bo, bo_offset + 16);
anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE),
.IndirectParameterEnable = true,
.VertexAccessType = RANDOM);
}
void genX(CmdDispatch)(
VkCommandBuffer commandBuffer,
uint32_t x,

View File

@ -273,3 +273,185 @@ void genX(CmdPipelineBarrier)(
dw = anv_batch_emit_dwords(&cmd_buffer->batch, GENX(PIPE_CONTROL_length));
GENX(PIPE_CONTROL_pack)(&cmd_buffer->batch, dw, &cmd);
}
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 */
.AddressModifyEnable = true,
.BufferPitch = 0,
#if (ANV_GEN >= 8)
.MemoryObjectControlState = GENX(MOCS),
.BufferStartingAddress = { bo, offset },
.BufferSize = 8
#else
.VertexBufferMemoryObjectControlState = GENX(MOCS),
.BufferStartingAddress = { bo, offset },
.EndAddress = { bo, offset + 8 },
#endif
});
}
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)[1] = 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,
uint32_t instanceCount,
uint32_t firstVertex,
uint32_t firstInstance)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
genX(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,
.PrimitiveTopologyType = pipeline->topology,
.VertexCountPerInstance = vertexCount,
.StartVertexLocation = firstVertex,
.InstanceCount = instanceCount,
.StartInstanceLocation = firstInstance,
.BaseVertexLocation = 0);
}
void genX(CmdDrawIndexed)(
VkCommandBuffer commandBuffer,
uint32_t indexCount,
uint32_t instanceCount,
uint32_t firstIndex,
int32_t vertexOffset,
uint32_t firstInstance)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
genX(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,
.PrimitiveTopologyType = pipeline->topology,
.VertexCountPerInstance = indexCount,
.StartVertexLocation = firstIndex,
.InstanceCount = instanceCount,
.StartInstanceLocation = firstInstance,
.BaseVertexLocation = vertexOffset);
}
/* Auto-Draw / Indirect Registers */
#define GEN7_3DPRIM_END_OFFSET 0x2420
#define GEN7_3DPRIM_START_VERTEX 0x2430
#define GEN7_3DPRIM_VERTEX_COUNT 0x2434
#define GEN7_3DPRIM_INSTANCE_COUNT 0x2438
#define GEN7_3DPRIM_START_INSTANCE 0x243C
#define GEN7_3DPRIM_BASE_VERTEX 0x2440
static void
emit_lrm(struct anv_batch *batch,
uint32_t reg, struct anv_bo *bo, uint32_t offset)
{
anv_batch_emit(batch, GENX(MI_LOAD_REGISTER_MEM),
.RegisterAddress = reg,
.MemoryAddress = { bo, offset });
}
static void
emit_lri(struct anv_batch *batch, uint32_t reg, uint32_t imm)
{
anv_batch_emit(batch, GENX(MI_LOAD_REGISTER_IMM),
.RegisterOffset = reg,
.DataDWord = imm);
}
void genX(CmdDrawIndirect)(
VkCommandBuffer commandBuffer,
VkBuffer _buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
struct anv_bo *bo = buffer->bo;
uint32_t bo_offset = buffer->offset + offset;
genX(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);
emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_INSTANCE, bo, bo_offset + 12);
emit_lri(&cmd_buffer->batch, GEN7_3DPRIM_BASE_VERTEX, 0);
anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE),
.IndirectParameterEnable = true,
.VertexAccessType = SEQUENTIAL,
.PrimitiveTopologyType = pipeline->topology);
}
void genX(CmdDrawIndexedIndirect)(
VkCommandBuffer commandBuffer,
VkBuffer _buffer,
VkDeviceSize offset,
uint32_t drawCount,
uint32_t stride)
{
ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer);
ANV_FROM_HANDLE(anv_buffer, buffer, _buffer);
struct anv_pipeline *pipeline = cmd_buffer->state.pipeline;
struct anv_bo *bo = buffer->bo;
uint32_t bo_offset = buffer->offset + offset;
genX(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);
emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_BASE_VERTEX, bo, bo_offset + 12);
emit_lrm(&cmd_buffer->batch, GEN7_3DPRIM_START_INSTANCE, bo, bo_offset + 16);
anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE),
.IndirectParameterEnable = true,
.VertexAccessType = RANDOM,
.PrimitiveTopologyType = pipeline->topology);
}