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 <tapani.palli@intel.com>
Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/5604>
This commit is contained in:
Tapani Pälli 2020-06-16 08:37:26 +03:00 committed by Marge Bot
parent f426663f9c
commit f6fa4a8000
6 changed files with 95 additions and 7 deletions

View file

@ -78,6 +78,7 @@ const struct anv_dynamic_state default_dynamic_state = {
}, },
.cull_mode = 0, .cull_mode = 0,
.front_face = 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(cull_mode, ANV_CMD_DIRTY_DYNAMIC_CULL_MODE);
ANV_CMP_COPY(front_face, ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE); 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 #undef ANV_CMP_COPY
@ -537,6 +539,17 @@ void anv_CmdSetScissorWithCountEXT(
cmd_buffer->state.gfx.dirty |= ANV_CMD_DIRTY_DYNAMIC_SCISSOR; 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( void anv_CmdSetLineWidth(
VkCommandBuffer commandBuffer, VkCommandBuffer commandBuffer,
float lineWidth) float lineWidth)

View file

@ -1883,6 +1883,24 @@ copy_non_dynamic_state(struct anv_graphics_pipeline *pipeline,
pCreateInfo->pRasterizationState->frontFace; 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: /* Section 9.2 of the Vulkan 1.0.15 spec says:
* *
* pColorBlendState is [...] NULL if the pipeline has rasterization * pColorBlendState is [...] NULL if the pipeline has rasterization

View file

@ -2691,6 +2691,7 @@ struct anv_dynamic_state {
VkCullModeFlags cull_mode; VkCullModeFlags cull_mode;
VkFrontFace front_face; VkFrontFace front_face;
VkPrimitiveTopology primitive_topology;
}; };
extern const struct anv_dynamic_state default_dynamic_state; extern const struct anv_dynamic_state default_dynamic_state;
@ -2804,6 +2805,8 @@ struct anv_cmd_graphics_state {
struct anv_dynamic_state dynamic; struct anv_dynamic_state dynamic;
uint32_t primitive_topology;
struct { struct {
struct anv_buffer *index_buffer; struct anv_buffer *index_buffer;
uint32_t index_type; /**< 3DSTATE_INDEX_BUFFER.IndexFormat */ uint32_t index_type; /**< 3DSTATE_INDEX_BUFFER.IndexFormat */

View file

@ -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; cmd_buffer->state.gfx.dirty = 0;
} }

View file

@ -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_COUNTER_CLOCKWISE] = 1,
[VK_FRONT_FACE_CLOCKWISE] = 0 [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 | if (cmd_buffer->state.gfx.dirty & (ANV_CMD_DIRTY_PIPELINE |
ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS | 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; cmd_buffer->state.gfx.dirty = 0;
} }

View file

@ -3404,6 +3404,9 @@ genX(cmd_buffer_flush_state)(struct anv_cmd_buffer *cmd_buffer)
cmd_buffer_alloc_push_constants(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 GEN_GEN <= 7
if (cmd_buffer->state.descriptors_dirty & VK_SHADER_STAGE_VERTEX_BIT || if (cmd_buffer->state.descriptors_dirty & VK_SHADER_STAGE_VERTEX_BIT ||
cmd_buffer->state.push_constants_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) { anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE), prim) {
prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled; prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled;
prim.VertexAccessType = SEQUENTIAL; prim.VertexAccessType = SEQUENTIAL;
prim.PrimitiveTopologyType = pipeline->topology; prim.PrimitiveTopologyType = cmd_buffer->state.gfx.primitive_topology;
prim.VertexCountPerInstance = vertexCount; prim.VertexCountPerInstance = vertexCount;
prim.StartVertexLocation = firstVertex; prim.StartVertexLocation = firstVertex;
prim.InstanceCount = instanceCount; prim.InstanceCount = instanceCount;
@ -3656,7 +3659,7 @@ void genX(CmdDrawIndexed)(
anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE), prim) { anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE), prim) {
prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled; prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled;
prim.VertexAccessType = RANDOM; prim.VertexAccessType = RANDOM;
prim.PrimitiveTopologyType = pipeline->topology; prim.PrimitiveTopologyType = cmd_buffer->state.gfx.primitive_topology;
prim.VertexCountPerInstance = indexCount; prim.VertexCountPerInstance = indexCount;
prim.StartVertexLocation = firstIndex; prim.StartVertexLocation = firstIndex;
prim.InstanceCount = instanceCount; prim.InstanceCount = instanceCount;
@ -3736,7 +3739,7 @@ void genX(CmdDrawIndirectByteCountEXT)(
anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE), prim) { anv_batch_emit(&cmd_buffer->batch, GENX(3DPRIMITIVE), prim) {
prim.IndirectParameterEnable = true; prim.IndirectParameterEnable = true;
prim.VertexAccessType = SEQUENTIAL; 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); update_dirty_vbs_for_gen8_vb_flush(cmd_buffer, SEQUENTIAL);
@ -3821,7 +3824,7 @@ void genX(CmdDrawIndirect)(
prim.IndirectParameterEnable = true; prim.IndirectParameterEnable = true;
prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled; prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled;
prim.VertexAccessType = SEQUENTIAL; 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); update_dirty_vbs_for_gen8_vb_flush(cmd_buffer, SEQUENTIAL);
@ -3871,7 +3874,7 @@ void genX(CmdDrawIndexedIndirect)(
prim.IndirectParameterEnable = true; prim.IndirectParameterEnable = true;
prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled; prim.PredicateEnable = cmd_buffer->state.conditional_render_enabled;
prim.VertexAccessType = RANDOM; 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); update_dirty_vbs_for_gen8_vb_flush(cmd_buffer, RANDOM);
@ -4026,7 +4029,7 @@ void genX(CmdDrawIndirectCount)(
prim.IndirectParameterEnable = true; prim.IndirectParameterEnable = true;
prim.PredicateEnable = true; prim.PredicateEnable = true;
prim.VertexAccessType = SEQUENTIAL; 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); update_dirty_vbs_for_gen8_vb_flush(cmd_buffer, SEQUENTIAL);
@ -4098,7 +4101,7 @@ void genX(CmdDrawIndexedIndirectCount)(
prim.IndirectParameterEnable = true; prim.IndirectParameterEnable = true;
prim.PredicateEnable = true; prim.PredicateEnable = true;
prim.VertexAccessType = RANDOM; 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); update_dirty_vbs_for_gen8_vb_flush(cmd_buffer, RANDOM);