anv: Identify code paths specific to graphics primitive pipeline

In preparation for adding support for the graphics mesh pipeline,
identify all the paths that are specific the primitive pipeline.

This shouldn't change any behavior since the code currently only
supports the primitive pipeline.

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/13047>
This commit is contained in:
Caio Marcelo de Oliveira Filho
2021-07-08 14:47:08 -07:00
committed by Marge Bot
parent a63aa9ad41
commit 1a20cfb7d6
4 changed files with 204 additions and 181 deletions

View File

@@ -1371,20 +1371,22 @@ anv_pipeline_init_from_cached_graphics(struct anv_graphics_pipeline *pipeline)
{ {
/* TODO: Cache this pipeline-wide information. */ /* TODO: Cache this pipeline-wide information. */
/* Primitive replication depends on information from all the shaders. if (anv_pipeline_is_primitive(pipeline)) {
* Recover this bit from the fact that we have more than one position slot /* Primitive replication depends on information from all the shaders.
* in the vertex shader when using it. * Recover this bit from the fact that we have more than one position slot
*/ * in the vertex shader when using it.
assert(pipeline->active_stages & VK_SHADER_STAGE_VERTEX_BIT); */
int pos_slots = 0; assert(pipeline->active_stages & VK_SHADER_STAGE_VERTEX_BIT);
const struct brw_vue_prog_data *vue_prog_data = int pos_slots = 0;
(const void *) pipeline->shaders[MESA_SHADER_VERTEX]->prog_data; const struct brw_vue_prog_data *vue_prog_data =
const struct brw_vue_map *vue_map = &vue_prog_data->vue_map; (const void *) pipeline->shaders[MESA_SHADER_VERTEX]->prog_data;
for (int i = 0; i < vue_map->num_slots; i++) { const struct brw_vue_map *vue_map = &vue_prog_data->vue_map;
if (vue_map->slot_to_varying[i] == VARYING_SLOT_POS) for (int i = 0; i < vue_map->num_slots; i++) {
pos_slots++; if (vue_map->slot_to_varying[i] == VARYING_SLOT_POS)
pos_slots++;
}
pipeline->use_primitive_replication = pos_slots > 1;
} }
pipeline->use_primitive_replication = pos_slots > 1;
} }
static VkResult static VkResult
@@ -2403,80 +2405,80 @@ anv_graphics_pipeline_init(struct anv_graphics_pipeline *pipeline,
return result; return result;
} }
assert(pipeline->shaders[MESA_SHADER_VERTEX]);
anv_pipeline_setup_l3_config(&pipeline->base, false); anv_pipeline_setup_l3_config(&pipeline->base, false);
const VkPipelineVertexInputStateCreateInfo *vi_info = if (anv_pipeline_is_primitive(pipeline)) {
pCreateInfo->pVertexInputState; const VkPipelineVertexInputStateCreateInfo *vi_info =
pCreateInfo->pVertexInputState;
const uint64_t inputs_read = get_vs_prog_data(pipeline)->inputs_read; const uint64_t inputs_read = get_vs_prog_data(pipeline)->inputs_read;
for (uint32_t i = 0; i < vi_info->vertexAttributeDescriptionCount; i++) { for (uint32_t i = 0; i < vi_info->vertexAttributeDescriptionCount; i++) {
const VkVertexInputAttributeDescription *desc = const VkVertexInputAttributeDescription *desc =
&vi_info->pVertexAttributeDescriptions[i]; &vi_info->pVertexAttributeDescriptions[i];
if (inputs_read & (1ull << (VERT_ATTRIB_GENERIC0 + desc->location))) if (inputs_read & (1ull << (VERT_ATTRIB_GENERIC0 + desc->location)))
pipeline->vb_used |= 1 << desc->binding; pipeline->vb_used |= 1 << desc->binding;
}
for (uint32_t i = 0; i < vi_info->vertexBindingDescriptionCount; i++) {
const VkVertexInputBindingDescription *desc =
&vi_info->pVertexBindingDescriptions[i];
pipeline->vb[desc->binding].stride = desc->stride;
/* Step rate is programmed per vertex element (attribute), not
* binding. Set up a map of which bindings step per instance, for
* reference by vertex element setup. */
switch (desc->inputRate) {
default:
case VK_VERTEX_INPUT_RATE_VERTEX:
pipeline->vb[desc->binding].instanced = false;
break;
case VK_VERTEX_INPUT_RATE_INSTANCE:
pipeline->vb[desc->binding].instanced = true;
break;
} }
pipeline->vb[desc->binding].instance_divisor = 1; for (uint32_t i = 0; i < vi_info->vertexBindingDescriptionCount; i++) {
} const VkVertexInputBindingDescription *desc =
&vi_info->pVertexBindingDescriptions[i];
const VkPipelineVertexInputDivisorStateCreateInfoEXT *vi_div_state = pipeline->vb[desc->binding].stride = desc->stride;
vk_find_struct_const(vi_info->pNext,
PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT);
if (vi_div_state) {
for (uint32_t i = 0; i < vi_div_state->vertexBindingDivisorCount; i++) {
const VkVertexInputBindingDivisorDescriptionEXT *desc =
&vi_div_state->pVertexBindingDivisors[i];
pipeline->vb[desc->binding].instance_divisor = desc->divisor; /* Step rate is programmed per vertex element (attribute), not
* binding. Set up a map of which bindings step per instance, for
* reference by vertex element setup. */
switch (desc->inputRate) {
default:
case VK_VERTEX_INPUT_RATE_VERTEX:
pipeline->vb[desc->binding].instanced = false;
break;
case VK_VERTEX_INPUT_RATE_INSTANCE:
pipeline->vb[desc->binding].instanced = true;
break;
}
pipeline->vb[desc->binding].instance_divisor = 1;
} }
}
/* Our implementation of VK_KHR_multiview uses instancing to draw the const VkPipelineVertexInputDivisorStateCreateInfoEXT *vi_div_state =
* different views. If the client asks for instancing, we need to multiply vk_find_struct_const(vi_info->pNext,
* the instance divisor by the number of views ensure that we repeat the PIPELINE_VERTEX_INPUT_DIVISOR_STATE_CREATE_INFO_EXT);
* client's per-instance data once for each view. if (vi_div_state) {
*/ for (uint32_t i = 0; i < vi_div_state->vertexBindingDivisorCount; i++) {
if (pipeline->subpass->view_mask && !pipeline->use_primitive_replication) { const VkVertexInputBindingDivisorDescriptionEXT *desc =
const uint32_t view_count = anv_subpass_view_count(pipeline->subpass); &vi_div_state->pVertexBindingDivisors[i];
for (uint32_t vb = 0; vb < MAX_VBS; vb++) {
if (pipeline->vb[vb].instanced) pipeline->vb[desc->binding].instance_divisor = desc->divisor;
pipeline->vb[vb].instance_divisor *= view_count; }
} }
/* Our implementation of VK_KHR_multiview uses instancing to draw the
* different views. If the client asks for instancing, we need to multiply
* the instance divisor by the number of views ensure that we repeat the
* client's per-instance data once for each view.
*/
if (pipeline->subpass->view_mask && !pipeline->use_primitive_replication) {
const uint32_t view_count = anv_subpass_view_count(pipeline->subpass);
for (uint32_t vb = 0; vb < MAX_VBS; vb++) {
if (pipeline->vb[vb].instanced)
pipeline->vb[vb].instance_divisor *= view_count;
}
}
const VkPipelineInputAssemblyStateCreateInfo *ia_info =
pCreateInfo->pInputAssemblyState;
const VkPipelineTessellationStateCreateInfo *tess_info =
pCreateInfo->pTessellationState;
if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL))
pipeline->topology = _3DPRIM_PATCHLIST(tess_info->patchControlPoints);
else
pipeline->topology = vk_to_intel_primitive_type[ia_info->topology];
} }
const VkPipelineInputAssemblyStateCreateInfo *ia_info =
pCreateInfo->pInputAssemblyState;
const VkPipelineTessellationStateCreateInfo *tess_info =
pCreateInfo->pTessellationState;
if (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL))
pipeline->topology = _3DPRIM_PATCHLIST(tess_info->patchControlPoints);
else
pipeline->topology = vk_to_intel_primitive_type[ia_info->topology];
/* If rasterization is not enabled, ms_info must be ignored. */ /* If rasterization is not enabled, ms_info must be ignored. */
const bool raster_enabled = const bool raster_enabled =
!pCreateInfo->pRasterizationState->rasterizerDiscardEnable || !pCreateInfo->pRasterizationState->rasterizerDiscardEnable ||

View File

@@ -3697,6 +3697,12 @@ anv_pipeline_has_stage(const struct anv_graphics_pipeline *pipeline,
return (pipeline->active_stages & mesa_to_vk_shader_stage(stage)) != 0; return (pipeline->active_stages & mesa_to_vk_shader_stage(stage)) != 0;
} }
static inline bool
anv_pipeline_is_primitive(const struct anv_graphics_pipeline *pipeline)
{
return anv_pipeline_has_stage(pipeline, MESA_SHADER_VERTEX);
}
#define ANV_DECL_GET_GRAPHICS_PROG_DATA_FUNC(prefix, stage) \ #define ANV_DECL_GET_GRAPHICS_PROG_DATA_FUNC(prefix, stage) \
static inline const struct brw_##prefix##_prog_data * \ static inline const struct brw_##prefix##_prog_data * \
get_##prefix##_prog_data(const struct anv_graphics_pipeline *pipeline) \ get_##prefix##_prog_data(const struct anv_graphics_pipeline *pipeline) \

View File

@@ -2494,6 +2494,8 @@ void genX(CmdPipelineBarrier)(
static void static void
cmd_buffer_alloc_push_constants(struct anv_cmd_buffer *cmd_buffer) cmd_buffer_alloc_push_constants(struct anv_cmd_buffer *cmd_buffer)
{ {
assert(anv_pipeline_is_primitive(cmd_buffer->state.gfx.pipeline));
VkShaderStageFlags stages = VkShaderStageFlags stages =
cmd_buffer->state.gfx.pipeline->active_stages; cmd_buffer->state.gfx.pipeline->active_stages;
@@ -3487,12 +3489,14 @@ cmd_buffer_emit_clip(struct anv_cmd_buffer *cmd_buffer)
uint32_t dwords[GENX(3DSTATE_CLIP_length)]; uint32_t dwords[GENX(3DSTATE_CLIP_length)];
struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline; struct anv_graphics_pipeline *pipeline = cmd_buffer->state.gfx.pipeline;
const struct brw_vue_prog_data *last = if (anv_pipeline_is_primitive(pipeline)) {
anv_pipeline_get_last_vue_prog_data(pipeline); const struct brw_vue_prog_data *last =
if (last->vue_map.slots_valid & VARYING_BIT_VIEWPORT) { anv_pipeline_get_last_vue_prog_data(pipeline);
clip.MaximumVPIndex = if (last->vue_map.slots_valid & VARYING_BIT_VIEWPORT) {
cmd_buffer->state.gfx.dynamic.viewport.count > 0 ? clip.MaximumVPIndex =
cmd_buffer->state.gfx.dynamic.viewport.count - 1 : 0; cmd_buffer->state.gfx.dynamic.viewport.count > 0 ?
cmd_buffer->state.gfx.dynamic.viewport.count - 1 : 0;
}
} }
GENX(3DSTATE_CLIP_pack)(NULL, dwords, &clip); GENX(3DSTATE_CLIP_pack)(NULL, dwords, &clip);

View File

@@ -340,9 +340,6 @@ emit_3dstate_sbe(struct anv_graphics_pipeline *pipeline)
return; return;
} }
const struct brw_vue_map *fs_input_map =
&anv_pipeline_get_last_vue_prog_data(pipeline)->vue_map;
struct GENX(3DSTATE_SBE) sbe = { struct GENX(3DSTATE_SBE) sbe = {
GENX(3DSTATE_SBE_header), GENX(3DSTATE_SBE_header),
.AttributeSwizzleEnable = true, .AttributeSwizzleEnable = true,
@@ -365,72 +362,77 @@ emit_3dstate_sbe(struct anv_graphics_pipeline *pipeline)
# define swiz sbe # define swiz sbe
#endif #endif
int first_slot = brw_compute_first_urb_slot_required(wm_prog_data->inputs, if (anv_pipeline_is_primitive(pipeline)) {
fs_input_map); const struct brw_vue_map *fs_input_map =
assert(first_slot % 2 == 0); &anv_pipeline_get_last_vue_prog_data(pipeline)->vue_map;
unsigned urb_entry_read_offset = first_slot / 2;
int max_source_attr = 0;
for (uint8_t idx = 0; idx < wm_prog_data->urb_setup_attribs_count; idx++) {
uint8_t attr = wm_prog_data->urb_setup_attribs[idx];
int input_index = wm_prog_data->urb_setup[attr];
assert(0 <= input_index); int first_slot = brw_compute_first_urb_slot_required(wm_prog_data->inputs,
fs_input_map);
assert(first_slot % 2 == 0);
unsigned urb_entry_read_offset = first_slot / 2;
int max_source_attr = 0;
for (uint8_t idx = 0; idx < wm_prog_data->urb_setup_attribs_count; idx++) {
uint8_t attr = wm_prog_data->urb_setup_attribs[idx];
int input_index = wm_prog_data->urb_setup[attr];
/* gl_Viewport, gl_Layer and FragmentShadingRateKHR are stored in the assert(0 <= input_index);
* VUE header
*/
if (attr == VARYING_SLOT_VIEWPORT ||
attr == VARYING_SLOT_LAYER ||
attr == VARYING_SLOT_PRIMITIVE_SHADING_RATE) {
continue;
}
if (attr == VARYING_SLOT_PNTC) { /* gl_Viewport, gl_Layer and FragmentShadingRateKHR are stored in the
sbe.PointSpriteTextureCoordinateEnable = 1 << input_index; * VUE header
continue;
}
const int slot = fs_input_map->varying_to_slot[attr];
if (slot == -1) {
/* This attribute does not exist in the VUE--that means that the
* vertex shader did not write to it. It could be that it's a
* regular varying read by the fragment shader but not written by
* the vertex shader or it's gl_PrimitiveID. In the first case the
* value is undefined, in the second it needs to be
* gl_PrimitiveID.
*/ */
swiz.Attribute[input_index].ConstantSource = PRIM_ID; if (attr == VARYING_SLOT_VIEWPORT ||
swiz.Attribute[input_index].ComponentOverrideX = true; attr == VARYING_SLOT_LAYER ||
swiz.Attribute[input_index].ComponentOverrideY = true; attr == VARYING_SLOT_PRIMITIVE_SHADING_RATE) {
swiz.Attribute[input_index].ComponentOverrideZ = true; continue;
swiz.Attribute[input_index].ComponentOverrideW = true; }
continue;
if (attr == VARYING_SLOT_PNTC) {
sbe.PointSpriteTextureCoordinateEnable = 1 << input_index;
continue;
}
const int slot = fs_input_map->varying_to_slot[attr];
if (slot == -1) {
/* This attribute does not exist in the VUE--that means that the
* vertex shader did not write to it. It could be that it's a
* regular varying read by the fragment shader but not written by
* the vertex shader or it's gl_PrimitiveID. In the first case the
* value is undefined, in the second it needs to be
* gl_PrimitiveID.
*/
swiz.Attribute[input_index].ConstantSource = PRIM_ID;
swiz.Attribute[input_index].ComponentOverrideX = true;
swiz.Attribute[input_index].ComponentOverrideY = true;
swiz.Attribute[input_index].ComponentOverrideZ = true;
swiz.Attribute[input_index].ComponentOverrideW = true;
continue;
}
/* We have to subtract two slots to accout for the URB entry output
* read offset in the VS and GS stages.
*/
const int source_attr = slot - 2 * urb_entry_read_offset;
assert(source_attr >= 0 && source_attr < 32);
max_source_attr = MAX2(max_source_attr, source_attr);
/* The hardware can only do overrides on 16 overrides at a time, and the
* other up to 16 have to be lined up so that the input index = the
* output index. We'll need to do some tweaking to make sure that's the
* case.
*/
if (input_index < 16)
swiz.Attribute[input_index].SourceAttribute = source_attr;
else
assert(source_attr == input_index);
} }
/* We have to subtract two slots to accout for the URB entry output sbe.VertexURBEntryReadOffset = urb_entry_read_offset;
* read offset in the VS and GS stages. sbe.VertexURBEntryReadLength = DIV_ROUND_UP(max_source_attr + 1, 2);
*/
const int source_attr = slot - 2 * urb_entry_read_offset;
assert(source_attr >= 0 && source_attr < 32);
max_source_attr = MAX2(max_source_attr, source_attr);
/* The hardware can only do overrides on 16 overrides at a time, and the
* other up to 16 have to be lined up so that the input index = the
* output index. We'll need to do some tweaking to make sure that's the
* case.
*/
if (input_index < 16)
swiz.Attribute[input_index].SourceAttribute = source_attr;
else
assert(source_attr == input_index);
}
sbe.VertexURBEntryReadOffset = urb_entry_read_offset;
sbe.VertexURBEntryReadLength = DIV_ROUND_UP(max_source_attr + 1, 2);
#if GFX_VER >= 8 #if GFX_VER >= 8
sbe.ForceVertexURBEntryReadOffset = true; sbe.ForceVertexURBEntryReadOffset = true;
sbe.ForceVertexURBEntryReadLength = true; sbe.ForceVertexURBEntryReadLength = true;
#endif #endif
}
uint32_t *dw = anv_batch_emit_dwords(&pipeline->base.batch, uint32_t *dw = anv_batch_emit_dwords(&pipeline->base.batch,
GENX(3DSTATE_SBE_length)); GENX(3DSTATE_SBE_length));
@@ -676,14 +678,16 @@ emit_rs_state(struct anv_graphics_pipeline *pipeline,
sf.DerefBlockSize = urb_deref_block_size; sf.DerefBlockSize = urb_deref_block_size;
#endif #endif
const struct brw_vue_prog_data *last_vue_prog_data = if (anv_pipeline_is_primitive(pipeline)) {
anv_pipeline_get_last_vue_prog_data(pipeline); const struct brw_vue_prog_data *last_vue_prog_data =
anv_pipeline_get_last_vue_prog_data(pipeline);
if (last_vue_prog_data->vue_map.slots_valid & VARYING_BIT_PSIZ) { if (last_vue_prog_data->vue_map.slots_valid & VARYING_BIT_PSIZ) {
sf.PointWidthSource = Vertex; sf.PointWidthSource = Vertex;
} else { } else {
sf.PointWidthSource = State; sf.PointWidthSource = State;
sf.PointWidth = 1.0; sf.PointWidth = 1.0;
}
} }
#if GFX_VER >= 8 #if GFX_VER >= 8
@@ -1457,37 +1461,42 @@ emit_3dstate_clip(struct anv_graphics_pipeline *pipeline,
clip.MinimumPointWidth = 0.125; clip.MinimumPointWidth = 0.125;
clip.MaximumPointWidth = 255.875; clip.MaximumPointWidth = 255.875;
const struct brw_vue_prog_data *last = if (anv_pipeline_is_primitive(pipeline)) {
anv_pipeline_get_last_vue_prog_data(pipeline); const struct brw_vue_prog_data *last =
anv_pipeline_get_last_vue_prog_data(pipeline);
/* From the Vulkan 1.0.45 spec: /* From the Vulkan 1.0.45 spec:
* *
* "If the last active vertex processing stage shader entry point's * "If the last active vertex processing stage shader entry point's
* interface does not include a variable decorated with * interface does not include a variable decorated with
* ViewportIndex, then the first viewport is used." * ViewportIndex, then the first viewport is used."
*/ */
if (vp_info && (last->vue_map.slots_valid & VARYING_BIT_VIEWPORT)) { if (vp_info && (last->vue_map.slots_valid & VARYING_BIT_VIEWPORT)) {
clip.MaximumVPIndex = vp_info->viewportCount > 0 ? clip.MaximumVPIndex = vp_info->viewportCount > 0 ?
vp_info->viewportCount - 1 : 0; vp_info->viewportCount - 1 : 0;
} else { } else {
clip.MaximumVPIndex = 0; clip.MaximumVPIndex = 0;
}
/* From the Vulkan 1.0.45 spec:
*
* "If the last active vertex processing stage shader entry point's
* interface does not include a variable decorated with Layer, then
* the first layer is used."
*/
clip.ForceZeroRTAIndexEnable =
!(last->vue_map.slots_valid & VARYING_BIT_LAYER);
#if GFX_VER == 7
clip.UserClipDistanceClipTestEnableBitmask = last->clip_distance_mask;
clip.UserClipDistanceCullTestEnableBitmask = last->cull_distance_mask;
#endif
} }
/* From the Vulkan 1.0.45 spec:
*
* "If the last active vertex processing stage shader entry point's
* interface does not include a variable decorated with Layer, then
* the first layer is used."
*/
clip.ForceZeroRTAIndexEnable =
!(last->vue_map.slots_valid & VARYING_BIT_LAYER);
#if GFX_VER == 7 #if GFX_VER == 7
clip.FrontWinding = genX(vk_to_intel_front_face)[rs_info->frontFace]; clip.FrontWinding = genX(vk_to_intel_front_face)[rs_info->frontFace];
clip.CullMode = genX(vk_to_intel_cullmode)[rs_info->cullMode]; clip.CullMode = genX(vk_to_intel_cullmode)[rs_info->cullMode];
clip.ViewportZClipTestEnable = pipeline->depth_clip_enable; clip.ViewportZClipTestEnable = pipeline->depth_clip_enable;
clip.UserClipDistanceClipTestEnableBitmask = last->clip_distance_mask;
clip.UserClipDistanceCullTestEnableBitmask = last->cull_distance_mask;
#else #else
clip.NonPerspectiveBarycentricEnable = wm_prog_data ? clip.NonPerspectiveBarycentricEnable = wm_prog_data ?
(wm_prog_data->barycentric_interp_modes & (wm_prog_data->barycentric_interp_modes &
@@ -2552,22 +2561,24 @@ genX(graphics_pipeline_create)(
gfx7_emit_vs_workaround_flush(brw); gfx7_emit_vs_workaround_flush(brw);
#endif #endif
assert(pCreateInfo->pVertexInputState); if (anv_pipeline_is_primitive(pipeline)) {
emit_vertex_input(pipeline, pCreateInfo->pVertexInputState); assert(pCreateInfo->pVertexInputState);
emit_vertex_input(pipeline, pCreateInfo->pVertexInputState);
emit_3dstate_vs(pipeline); emit_3dstate_vs(pipeline);
emit_3dstate_hs_te_ds(pipeline, pCreateInfo->pTessellationState); emit_3dstate_hs_te_ds(pipeline, pCreateInfo->pTessellationState);
emit_3dstate_gs(pipeline); emit_3dstate_gs(pipeline);
#if GFX_VER >= 8 #if GFX_VER >= 8
if (!(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY)) if (!(dynamic_states & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY))
emit_3dstate_vf_topology(pipeline); emit_3dstate_vf_topology(pipeline);
#endif #endif
emit_3dstate_vf_statistics(pipeline); emit_3dstate_vf_statistics(pipeline);
emit_3dstate_streamout(pipeline, pCreateInfo->pRasterizationState, emit_3dstate_streamout(pipeline, pCreateInfo->pRasterizationState,
dynamic_states); dynamic_states);
}
emit_3dstate_sbe(pipeline); emit_3dstate_sbe(pipeline);
emit_3dstate_wm(pipeline, subpass, emit_3dstate_wm(pipeline, subpass,