From 4bf3cadb660f389098254c198c7a6d327ee8ba50 Mon Sep 17 00:00:00 2001 From: Jason Ekstrand Date: Tue, 26 Jan 2016 12:08:31 -0800 Subject: [PATCH] gen8: Add support for base vertex/instance --- src/vulkan/gen8_cmd_buffer.c | 52 +++++++++++++++++++++++++++++++ src/vulkan/genX_pipeline_util.h | 55 +++++++++++++++++++++------------ 2 files changed, 87 insertions(+), 20 deletions(-) diff --git a/src/vulkan/gen8_cmd_buffer.c b/src/vulkan/gen8_cmd_buffer.c index 096ced5694f..c919c065ca2 100644 --- a/src/vulkan/gen8_cmd_buffer.c +++ b/src/vulkan/gen8_cmd_buffer.c @@ -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); diff --git a/src/vulkan/genX_pipeline_util.h b/src/vulkan/genX_pipeline_util.h index 050c33591cb..363a1fd23ac 100644 --- a/src/vulkan/genX_pipeline_util.h +++ b/src/vulkan/genX_pipeline_util.h @@ -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 } -- 2.30.2