From: Tapani Pälli Date: Tue, 16 Jun 2020 05:37:26 +0000 (+0300) Subject: anv: add support for dynamic primitive topology change X-Git-Url: https://git.libre-soc.org/?p=mesa.git;a=commitdiff_plain;h=f6fa4a8000053fc6e9a25a30f482c59466390898 anv: add support for dynamic primitive topology change This is done using 3DSTATE_VF_TOPOLOGY packet that overrides topology used in subsequent 3DPRIMITIVE commands. For gen7[5] we override the pipeline topology when emitting draw commands. v2: fix the way gen7[5] is handled (Lionel) Signed-off-by: Tapani Pälli Reviewed-by: Lionel Landwerlin Part-of: --- diff --git a/src/intel/vulkan/anv_cmd_buffer.c b/src/intel/vulkan/anv_cmd_buffer.c index 95bc38db4e1..0c73632a4a9 100644 --- a/src/intel/vulkan/anv_cmd_buffer.c +++ b/src/intel/vulkan/anv_cmd_buffer.c @@ -78,6 +78,7 @@ const struct anv_dynamic_state default_dynamic_state = { }, .cull_mode = 0, .front_face = 0, + .primitive_topology = 0, }; /** @@ -145,6 +146,7 @@ anv_dynamic_state_copy(struct anv_dynamic_state *dest, ANV_CMP_COPY(cull_mode, ANV_CMD_DIRTY_DYNAMIC_CULL_MODE); ANV_CMP_COPY(front_face, ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE); + ANV_CMP_COPY(primitive_topology, ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY); #undef ANV_CMP_COPY @@ -537,6 +539,17 @@ void anv_CmdSetScissorWithCountEXT( cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_SCISSOR; } +void anv_CmdSetPrimitiveTopologyEXT( + VkCommandBuffer commandBuffer, + VkPrimitiveTopology primitiveTopology) +{ + ANV_FROM_HANDLE(anv_cmd_buffer, cmd_buffer, commandBuffer); + + cmd_buffer->state.gfx.dynamic.primitive_topology = primitiveTopology; + + cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY; +} + void anv_CmdSetLineWidth( VkCommandBuffer commandBuffer, float lineWidth) diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c index 3d04fa3f62a..ed666fd6485 100644 --- a/src/intel/vulkan/anv_pipeline.c +++ b/src/intel/vulkan/anv_pipeline.c @@ -1883,6 +1883,24 @@ copy_non_dynamic_state(struct anv_graphics_pipeline *pipeline, pCreateInfo->pRasterizationState->frontFace; } + if (states & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) { + assert(pCreateInfo->pInputAssemblyState); + bool has_tess = false; + for (uint32_t i = 0; i < pCreateInfo->stageCount; i++) { + const VkPipelineShaderStageCreateInfo *sinfo = &pCreateInfo->pStages[i]; + gl_shader_stage stage = vk_to_mesa_shader_stage(sinfo->stage); + if (stage == MESA_SHADER_TESS_CTRL || stage == MESA_SHADER_TESS_EVAL) + has_tess = true; + } + if (has_tess) { + const VkPipelineTessellationStateCreateInfo *tess_info = + pCreateInfo->pTessellationState; + dynamic->primitive_topology = _3DPRIM_PATCHLIST(tess_info->patchControlPoints); + } else { + dynamic->primitive_topology = pCreateInfo->pInputAssemblyState->topology; + } + } + /* Section 9.2 of the Vulkan 1.0.15 spec says: * * pColorBlendState is [...] NULL if the pipeline has rasterization diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index fb885d11999..b26e2461db1 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -2691,6 +2691,7 @@ struct anv_dynamic_state { VkCullModeFlags cull_mode; VkFrontFace front_face; + VkPrimitiveTopology primitive_topology; }; extern const struct anv_dynamic_state default_dynamic_state; @@ -2804,6 +2805,8 @@ struct anv_cmd_graphics_state { struct anv_dynamic_state dynamic; + uint32_t primitive_topology; + struct { struct anv_buffer *index_buffer; uint32_t index_type; /**< 3DSTATE_INDEX_BUFFER.IndexFormat */ diff --git a/src/intel/vulkan/gen7_cmd_buffer.c b/src/intel/vulkan/gen7_cmd_buffer.c index 0d713d33919..076c2455563 100644 --- a/src/intel/vulkan/gen7_cmd_buffer.c +++ b/src/intel/vulkan/gen7_cmd_buffer.c @@ -319,6 +319,30 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer) } } + static const uint32_t vk_to_gen_primitive_type[] = { + [VK_PRIMITIVE_TOPOLOGY_POINT_LIST] = _3DPRIM_POINTLIST, + [VK_PRIMITIVE_TOPOLOGY_LINE_LIST] = _3DPRIM_LINELIST, + [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP] = _3DPRIM_LINESTRIP, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST] = _3DPRIM_TRILIST, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP] = _3DPRIM_TRISTRIP, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN] = _3DPRIM_TRIFAN, + [VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY] = _3DPRIM_LINELIST_ADJ, + [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY] = _3DPRIM_LINESTRIP_ADJ, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY] = _3DPRIM_TRILIST_ADJ, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY] = _3DPRIM_TRISTRIP_ADJ, + }; + + if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE | + ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) { + uint32_t topology; + if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL)) + topology = d->primitive_topology; + else + topology = vk_to_gen_primitive_type[d->primitive_topology]; + + cmd_buffer->state.gfx.primitive_topology = topology; + } + cmd_buffer->state.gfx.dirty = 0; } diff --git a/src/intel/vulkan/gen8_cmd_buffer.c b/src/intel/vulkan/gen8_cmd_buffer.c index 1e7b746ee17..2fbc313131e 100644 --- a/src/intel/vulkan/gen8_cmd_buffer.c +++ b/src/intel/vulkan/gen8_cmd_buffer.c @@ -449,6 +449,18 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer) [VK_FRONT_FACE_COUNTER_CLOCKWISE] = 1, [VK_FRONT_FACE_CLOCKWISE] = 0 }; + static const uint32_t vk_to_gen_primitive_type[] = { + [VK_PRIMITIVE_TOPOLOGY_POINT_LIST] = _3DPRIM_POINTLIST, + [VK_PRIMITIVE_TOPOLOGY_LINE_LIST] = _3DPRIM_LINELIST, + [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP] = _3DPRIM_LINESTRIP, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST] = _3DPRIM_TRILIST, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP] = _3DPRIM_TRISTRIP, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN] = _3DPRIM_TRIFAN, + [VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY] = _3DPRIM_LINELIST_ADJ, + [VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY] = _3DPRIM_LINESTRIP_ADJ, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY] = _3DPRIM_TRILIST_ADJ, + [VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY] = _3DPRIM_TRISTRIP_ADJ, + }; if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE | ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS | @@ -606,6 +618,21 @@ genX(cmd_buffer_flush_dynamic_state)(struct anv_cmd_buffer *cmd_buffer) } } + if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE | + ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) { + uint32_t topology; + if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL)) + topology = d->primitive_topology; + else + topology = vk_to_gen_primitive_type[d->primitive_topology]; + + cmd_buffer->state.gfx.primitive_topology = topology; + + anv_batch_emit(&cmd_buffer->batch, GENX(3DSTATE_VF_TOPOLOGY), vft) { + vft.PrimitiveTopologyType = topology; + } + } + cmd_buffer->state.gfx.dirty = 0; } diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c index 773aa3b63c5..76a0aae1a1b 100644 --- a/src/intel/vulkan/genX_cmd_buffer.c +++ b/src/intel/vulkan/genX_cmd_buffer.c @@ -3404,6 +3404,9 @@ genX(cmd_buffer_flush_state)(struct anv_cmd_buffer *cmd_buffer) cmd_buffer_alloc_push_constants(cmd_buffer); } + if (cmd_buffer->state.gfx.dirty & ANV_CMD_DIRTY_PIPELINE) + cmd_buffer->state.gfx.primitive_topology = pipeline->topology; + #if GEN_GEN <= 7 if (cmd_buffer->state.descriptors_dirty & VK_SHADER_STAGE_VERTEX_BIT || cmd_buffer->state.push_constants_dirty & VK_SHADER_STAGE_VERTEX_BIT) { @@ -3605,7 +3608,7 @@ void genX(CmdDraw)( anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE), prim) { prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled; prim.VertexAccessType = SEQUENTIAL; - prim.PrimitiveTopologyType = pipeline->topology; + prim.PrimitiveTopologyType = cmd_buffer->state.gfx.primitive_topology; prim.VertexCountPerInstance = vertexCount; prim.StartVertexLocation = firstVertex; prim.InstanceCount = instanceCount; @@ -3656,7 +3659,7 @@ void genX(CmdDrawIndexed)( anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE), prim) { prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled; prim.VertexAccessType = RANDOM; - prim.PrimitiveTopologyType = pipeline->topology; + prim.PrimitiveTopologyType = cmd_buffer->state.gfx.primitive_topology; prim.VertexCountPerInstance = indexCount; prim.StartVertexLocation = firstIndex; prim.InstanceCount = instanceCount; @@ -3736,7 +3739,7 @@ void genX(CmdDrawIndirectByteCountEXT)( anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE), prim) { prim.IndirectParameterEnable = true; prim.VertexAccessType = SEQUENTIAL; - prim.PrimitiveTopologyType = pipeline->topology; + prim.PrimitiveTopologyType = cmd_buffer->state.gfx.primitive_topology; } update_dirty_vbs_for_gen8_vb_flush(cmd_buffer, SEQUENTIAL); @@ -3821,7 +3824,7 @@ void genX(CmdDrawIndirect)( prim.IndirectParameterEnable = true; prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled; prim.VertexAccessType = SEQUENTIAL; - prim.PrimitiveTopologyType = pipeline->topology; + prim.PrimitiveTopologyType = cmd_buffer->state.gfx.primitive_topology; } update_dirty_vbs_for_gen8_vb_flush(cmd_buffer, SEQUENTIAL); @@ -3871,7 +3874,7 @@ void genX(CmdDrawIndexedIndirect)( prim.IndirectParameterEnable = true; prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled; prim.VertexAccessType = RANDOM; - prim.PrimitiveTopologyType = pipeline->topology; + prim.PrimitiveTopologyType = cmd_buffer->state.gfx.primitive_topology; } update_dirty_vbs_for_gen8_vb_flush(cmd_buffer, RANDOM); @@ -4026,7 +4029,7 @@ void genX(CmdDrawIndirectCount)( prim.IndirectParameterEnable = true; prim.PredicateEnable = true; prim.VertexAccessType = SEQUENTIAL; - prim.PrimitiveTopologyType = pipeline->topology; + prim.PrimitiveTopologyType = cmd_buffer->state.gfx.primitive_topology; } update_dirty_vbs_for_gen8_vb_flush(cmd_buffer, SEQUENTIAL); @@ -4098,7 +4101,7 @@ void genX(CmdDrawIndexedIndirectCount)( prim.IndirectParameterEnable = true; prim.PredicateEnable = true; prim.VertexAccessType = RANDOM; - prim.PrimitiveTopologyType = pipeline->topology; + prim.PrimitiveTopologyType = cmd_buffer->state.gfx.primitive_topology; } update_dirty_vbs_for_gen8_vb_flush(cmd_buffer, RANDOM);