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:
@@ -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)
|
||||
|
@@ -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
|
||||
|
@@ -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 */
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user