anv: Convert to using vk_graphics_pipeline_state

This attempts to be a pretty minimal refactor.  We just switch all the
state emit code to use the new graphics pipeline state object.

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17564>
This commit is contained in:
Jason Ekstrand 2022-07-12 16:16:55 -05:00 committed by Marge Bot
parent 44cbb7d9c8
commit b656957c56
4 changed files with 326 additions and 769 deletions

View File

@ -171,9 +171,7 @@ genX(raster_polygon_mode)(struct anv_graphics_pipeline *pipeline,
void
genX(graphics_pipeline_emit)(struct anv_graphics_pipeline *pipeline,
const VkGraphicsPipelineCreateInfo *pCreateInfo,
const VkPipelineRenderingCreateInfo *rendering_info,
const VkRenderingSelfDependencyInfoMESA *rsd_info);
const struct vk_graphics_pipeline_state *state);
void
genX(compute_pipeline_emit)(struct anv_compute_pipeline *pipeline);

View File

@ -374,8 +374,8 @@ populate_gs_prog_key(const struct anv_device *device,
static bool
pipeline_has_coarse_pixel(const struct anv_graphics_pipeline *pipeline,
const VkPipelineMultisampleStateCreateInfo *ms_info,
const VkPipelineFragmentShadingRateStateCreateInfoKHR *fsr_info)
const struct vk_multisample_state *ms,
const struct vk_fragment_shading_rate_state *fsr)
{
/* The Vulkan 1.2.199 spec says:
*
@ -407,21 +407,21 @@ pipeline_has_coarse_pixel(const struct anv_graphics_pipeline *pipeline,
* here. Note that this sample shading being enabled has nothing to do
* with minSampleShading.
*/
if (ms_info && ms_info->sampleShadingEnable)
if (ms != NULL && ms->sample_shading_enable)
return false;
/* Not dynamic & not specified for the pipeline. */
if ((pipeline->dynamic_states & ANV_CMD_DIRTY_DYNAMIC_SHADING_RATE) == 0 && !fsr_info)
if ((pipeline->dynamic_states & ANV_CMD_DIRTY_DYNAMIC_SHADING_RATE) == 0 && fsr == NULL)
return false;
/* Not dynamic & pipeline has a 1x1 fragment shading rate with no
* possibility for element of the pipeline to change the value.
*/
if ((pipeline->dynamic_states & ANV_CMD_DIRTY_DYNAMIC_SHADING_RATE) == 0 &&
fsr_info->fragmentSize.width <= 1 &&
fsr_info->fragmentSize.height <= 1 &&
fsr_info->combinerOps[0] == VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR &&
fsr_info->combinerOps[1] == VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR)
fsr->fragment_size.width <= 1 &&
fsr->fragment_size.height <= 1 &&
fsr->combiner_ops[0] == VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR &&
fsr->combiner_ops[1] == VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR)
return false;
return true;
@ -450,9 +450,9 @@ populate_mesh_prog_key(const struct anv_device *device,
static void
populate_wm_prog_key(const struct anv_graphics_pipeline *pipeline,
bool robust_buffer_acccess,
const VkPipelineMultisampleStateCreateInfo *ms_info,
const VkPipelineFragmentShadingRateStateCreateInfoKHR *fsr_info,
const VkPipelineRenderingCreateInfo *rendering_info,
const struct vk_multisample_state *ms,
const struct vk_fragment_shading_rate_state *fsr,
const struct vk_render_pass_state *rp,
struct brw_wm_prog_key *key)
{
const struct anv_device *device = pipeline->base.device;
@ -471,28 +471,28 @@ populate_wm_prog_key(const struct anv_graphics_pipeline *pipeline,
key->ignore_sample_mask_out = false;
assert(rendering_info->colorAttachmentCount <= MAX_RTS);
assert(rp->color_attachment_count <= MAX_RTS);
/* Consider all inputs as valid until look at the NIR variables. */
key->color_outputs_valid = (1u << rendering_info->colorAttachmentCount) - 1;
key->nr_color_regions = rendering_info->colorAttachmentCount;
key->color_outputs_valid = (1u << rp->color_attachment_count) - 1;
key->nr_color_regions = rp->color_attachment_count;
/* To reduce possible shader recompilations we would need to know if
* there is a SampleMask output variable to compute if we should emit
* code to workaround the issue that hardware disables alpha to coverage
* when there is SampleMask output.
*/
key->alpha_to_coverage = ms_info && ms_info->alphaToCoverageEnable;
key->alpha_to_coverage = ms != NULL && ms->alpha_to_coverage_enable;
/* Vulkan doesn't support fixed-function alpha test */
key->alpha_test_replicate_alpha = false;
if (ms_info) {
if (ms != NULL) {
/* We should probably pull this out of the shader, but it's fairly
* harmless to compute it and then let dead-code take care of it.
*/
if (ms_info->rasterizationSamples > 1) {
key->persample_interp = ms_info->sampleShadingEnable &&
(ms_info->minSampleShading * ms_info->rasterizationSamples) > 1;
if (ms->rasterization_samples > 1) {
key->persample_interp = ms->sample_shading_enable &&
(ms->min_sample_shading * ms->rasterization_samples) > 1;
key->multisample_fbo = true;
}
@ -503,7 +503,7 @@ populate_wm_prog_key(const struct anv_graphics_pipeline *pipeline,
key->coarse_pixel =
!key->persample_interp &&
device->vk.enabled_extensions.KHR_fragment_shading_rate &&
pipeline_has_coarse_pixel(pipeline, ms_info, fsr_info);
pipeline_has_coarse_pixel(pipeline, ms, fsr);
}
static void
@ -1081,7 +1081,7 @@ anv_pipeline_compile_mesh(const struct brw_compiler *compiler,
static void
anv_pipeline_link_fs(const struct brw_compiler *compiler,
struct anv_pipeline_stage *stage,
const VkPipelineRenderingCreateInfo *rendering_info)
const struct vk_render_pass_state *rp)
{
/* Initially the valid outputs value is set to all possible render targets
* valid (see populate_wm_prog_key()), before we look at the shader
@ -1101,7 +1101,7 @@ anv_pipeline_link_fs(const struct brw_compiler *compiler,
stage->key.wm.color_outputs_valid |= BITFIELD_RANGE(rt, array_len);
}
stage->key.wm.color_outputs_valid &=
(1u << rendering_info->colorAttachmentCount) - 1;
(1u << rp->color_attachment_count) - 1;
stage->key.wm.nr_color_regions =
util_last_bit(stage->key.wm.color_outputs_valid);
@ -1333,8 +1333,7 @@ anv_pipeline_init_from_cached_graphics(struct anv_graphics_pipeline *pipeline)
static void
anv_graphics_pipeline_init_keys(struct anv_graphics_pipeline *pipeline,
const VkGraphicsPipelineCreateInfo *info,
const VkPipelineRenderingCreateInfo *rendering_info,
const struct vk_graphics_pipeline_state *state,
struct anv_pipeline_stage *stages)
{
for (uint32_t s = 0; s < ANV_GRAPHICS_SHADER_STAGE_COUNT; s++) {
@ -1355,7 +1354,7 @@ anv_graphics_pipeline_init_keys(struct anv_graphics_pipeline *pipeline,
case MESA_SHADER_TESS_CTRL:
populate_tcs_prog_key(device,
pipeline->base.device->robust_buffer_access,
info->pTessellationState->patchControlPoints,
state->ts->patch_control_points,
&stages[s].key.tcs);
break;
case MESA_SHADER_TESS_EVAL:
@ -1369,15 +1368,9 @@ anv_graphics_pipeline_init_keys(struct anv_graphics_pipeline *pipeline,
&stages[s].key.gs);
break;
case MESA_SHADER_FRAGMENT: {
const bool raster_enabled =
!info->pRasterizationState->rasterizerDiscardEnable ||
pipeline->dynamic_states & ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE;
populate_wm_prog_key(pipeline,
pipeline->base.device->robust_buffer_access,
raster_enabled ? info->pMultisampleState : NULL,
vk_find_struct_const(info->pNext,
PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR),
rendering_info,
state->ms, state->fsr, state->rp,
&stages[s].key.wm);
break;
}
@ -1529,7 +1522,7 @@ static VkResult
anv_graphics_pipeline_compile(struct anv_graphics_pipeline *pipeline,
struct vk_pipeline_cache *cache,
const VkGraphicsPipelineCreateInfo *info,
const VkPipelineRenderingCreateInfo *rendering_info)
const struct vk_graphics_pipeline_state *state)
{
ANV_FROM_HANDLE(anv_pipeline_layout, layout, info->layout);
VkResult result;
@ -1547,7 +1540,7 @@ anv_graphics_pipeline_compile(struct anv_graphics_pipeline *pipeline,
stages[stage].info = &info->pStages[i];
}
anv_graphics_pipeline_init_keys(pipeline, info, rendering_info, stages);
anv_graphics_pipeline_init_keys(pipeline, state, stages);
unsigned char sha1[20];
anv_pipeline_hash_graphics(pipeline, layout, stages, sha1);
@ -1607,7 +1600,7 @@ anv_graphics_pipeline_compile(struct anv_graphics_pipeline *pipeline,
anv_pipeline_link_mesh(compiler, &stages[s], next_stage);
break;
case MESA_SHADER_FRAGMENT:
anv_pipeline_link_fs(compiler, &stages[s], rendering_info);
anv_pipeline_link_fs(compiler, &stages[s], state->rp);
break;
default:
unreachable("Invalid graphics shader stage");
@ -1969,16 +1962,6 @@ anv_pipeline_compile_cs(struct anv_compute_pipeline *pipeline,
return VK_SUCCESS;
}
static bool
anv_rendering_uses_color_attachment(const VkPipelineRenderingCreateInfo *rendering_info)
{
for (unsigned i = 0; i < rendering_info->colorAttachmentCount; i++) {
if (rendering_info->pColorAttachmentFormats[i] != VK_FORMAT_UNDEFINED)
return true;
}
return false;
}
static VkResult
anv_compute_pipeline_create(struct anv_device *device,
struct vk_pipeline_cache *cache,
@ -2077,8 +2060,7 @@ VkResult anv_CreateComputePipelines(
*/
static void
copy_non_dynamic_state(struct anv_graphics_pipeline *pipeline,
const VkGraphicsPipelineCreateInfo *pCreateInfo,
const VkPipelineRenderingCreateInfo *rendering_info)
const struct vk_graphics_pipeline_state *state)
{
anv_cmd_dirty_mask_t states = ANV_CMD_DIRTY_DYNAMIC_ALL;
@ -2088,255 +2070,152 @@ copy_non_dynamic_state(struct anv_graphics_pipeline *pipeline,
struct anv_dynamic_state *dynamic = &pipeline->non_dynamic_state;
bool raster_discard =
pCreateInfo->pRasterizationState->rasterizerDiscardEnable &&
!(pipeline->dynamic_states & ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE);
/* Section 9.2 of the Vulkan 1.0.15 spec says:
*
* pViewportState is [...] NULL if the pipeline
* has rasterization disabled.
*/
if (!raster_discard) {
assert(pCreateInfo->pViewportState);
if (state->vp) {
pipeline->negative_one_to_one = state->vp->negative_one_to_one;
const VkPipelineViewportDepthClipControlCreateInfoEXT *ccontrol =
vk_find_struct_const(pCreateInfo->pViewportState,
PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT);
if (ccontrol)
pipeline->negative_one_to_one = ccontrol->negativeOneToOne;
dynamic->viewport.count = pCreateInfo->pViewportState->viewportCount;
dynamic->viewport.count = state->vp->viewport_count;
if (states & ANV_CMD_DIRTY_DYNAMIC_VIEWPORT) {
typed_memcpy(dynamic->viewport.viewports,
pCreateInfo->pViewportState->pViewports,
pCreateInfo->pViewportState->viewportCount);
state->vp->viewports, state->vp->viewport_count);
}
dynamic->scissor.count = pCreateInfo->pViewportState->scissorCount;
dynamic->scissor.count = state->vp->scissor_count;
if (states & ANV_CMD_DIRTY_DYNAMIC_SCISSOR) {
typed_memcpy(dynamic->scissor.scissors,
pCreateInfo->pViewportState->pScissors,
pCreateInfo->pViewportState->scissorCount);
state->vp->scissors, state->vp->scissor_count);
}
}
if (states & ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH) {
assert(pCreateInfo->pRasterizationState);
dynamic->line_width = pCreateInfo->pRasterizationState->lineWidth;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH)
dynamic->line_width = state->rs->line.width;
if (states & ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS) {
assert(pCreateInfo->pRasterizationState);
dynamic->depth_bias.bias =
pCreateInfo->pRasterizationState->depthBiasConstantFactor;
dynamic->depth_bias.clamp =
pCreateInfo->pRasterizationState->depthBiasClamp;
dynamic->depth_bias.slope =
pCreateInfo->pRasterizationState->depthBiasSlopeFactor;
dynamic->depth_bias.bias = state->rs->depth_bias.constant;
dynamic->depth_bias.clamp = state->rs->depth_bias.clamp;
dynamic->depth_bias.slope = state->rs->depth_bias.slope;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_CULL_MODE) {
assert(pCreateInfo->pRasterizationState);
dynamic->cull_mode =
pCreateInfo->pRasterizationState->cullMode;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_CULL_MODE)
dynamic->cull_mode = state->rs->cull_mode;
if (states & ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE) {
assert(pCreateInfo->pRasterizationState);
dynamic->front_face =
pCreateInfo->pRasterizationState->frontFace;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE)
dynamic->front_face = state->rs->front_face;
if ((states & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY) &&
(pipeline->active_stages & VK_SHADER_STAGE_VERTEX_BIT)) {
assert(pCreateInfo->pInputAssemblyState);
dynamic->primitive_topology = pCreateInfo->pInputAssemblyState->topology;
}
(pipeline->active_stages & VK_SHADER_STAGE_VERTEX_BIT))
dynamic->primitive_topology = state->ia->primitive_topology;
if (states & ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE) {
assert(pCreateInfo->pRasterizationState);
dynamic->raster_discard =
pCreateInfo->pRasterizationState->rasterizerDiscardEnable;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE)
dynamic->raster_discard = state->rs->rasterizer_discard_enable;
if (states & ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE) {
assert(pCreateInfo->pRasterizationState);
dynamic->depth_bias_enable =
pCreateInfo->pRasterizationState->depthBiasEnable;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE)
dynamic->depth_bias_enable = state->rs->depth_bias.enable;
if ((states & ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE) &&
(pipeline->active_stages & VK_SHADER_STAGE_VERTEX_BIT)) {
assert(pCreateInfo->pInputAssemblyState);
dynamic->primitive_restart_enable =
pCreateInfo->pInputAssemblyState->primitiveRestartEnable;
}
(pipeline->active_stages & VK_SHADER_STAGE_VERTEX_BIT))
dynamic->primitive_restart_enable = state->ia->primitive_restart_enable;
/* Section 9.2 of the Vulkan 1.0.15 spec says:
*
* pColorBlendState is [...] NULL if the pipeline has rasterization
* disabled or if the subpass of the render pass the pipeline is
* created against does not use any color attachments.
*/
bool uses_color_att = anv_rendering_uses_color_attachment(rendering_info);
if (uses_color_att && !raster_discard) {
assert(pCreateInfo->pColorBlendState);
if (states & ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS)
typed_memcpy(dynamic->blend_constants,
pCreateInfo->pColorBlendState->blendConstants, 4);
}
/* If there is no depthstencil attachment, then don't read
* pDepthStencilState. The Vulkan spec states that pDepthStencilState may
* be NULL in this case. Even if pDepthStencilState is non-NULL, there is
* no need to override the depthstencil defaults in
* anv_pipeline::dynamic_state when there is no depthstencil attachment.
*
* Section 9.2 of the Vulkan 1.0.15 spec says:
*
* pDepthStencilState is [...] NULL if the pipeline has rasterization
* disabled or if the subpass of the render pass the pipeline is created
* against does not use a depth/stencil attachment.
*/
if (!raster_discard &&
(rendering_info->depthAttachmentFormat != VK_FORMAT_UNDEFINED ||
rendering_info->stencilAttachmentFormat != VK_FORMAT_UNDEFINED)) {
assert(pCreateInfo->pDepthStencilState);
if (state->cb != NULL && (states & ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS))
typed_memcpy(dynamic->blend_constants, state->cb->blend_constants, 4);
if (state->ds != NULL) {
if (states & ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS) {
dynamic->depth_bounds.min =
pCreateInfo->pDepthStencilState->minDepthBounds;
dynamic->depth_bounds.max =
pCreateInfo->pDepthStencilState->maxDepthBounds;
dynamic->depth_bounds.min = state->ds->depth.bounds_test.min;
dynamic->depth_bounds.max = state->ds->depth.bounds_test.max;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK) {
dynamic->stencil_compare_mask.front =
pCreateInfo->pDepthStencilState->front.compareMask;
state->ds->stencil.front.compare_mask;
dynamic->stencil_compare_mask.back =
pCreateInfo->pDepthStencilState->back.compareMask;
state->ds->stencil.back.compare_mask;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK) {
dynamic->stencil_write_mask.front =
pCreateInfo->pDepthStencilState->front.writeMask;
state->ds->stencil.front.write_mask;
dynamic->stencil_write_mask.back =
pCreateInfo->pDepthStencilState->back.writeMask;
state->ds->stencil.back.write_mask;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE) {
dynamic->stencil_reference.front =
pCreateInfo->pDepthStencilState->front.reference;
state->ds->stencil.front.reference;
dynamic->stencil_reference.back =
pCreateInfo->pDepthStencilState->back.reference;
state->ds->stencil.back.reference;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE) {
dynamic->depth_test_enable =
pCreateInfo->pDepthStencilState->depthTestEnable;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE)
dynamic->depth_test_enable = state->ds->depth.test_enable;
if (states & ANV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE) {
dynamic->depth_write_enable =
pCreateInfo->pDepthStencilState->depthWriteEnable;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE)
dynamic->depth_write_enable = state->ds->depth.write_enable;
if (states & ANV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP) {
dynamic->depth_compare_op =
pCreateInfo->pDepthStencilState->depthCompareOp;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP)
dynamic->depth_compare_op = state->ds->depth.compare_op;
if (states & ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE) {
dynamic->depth_bounds_test_enable =
pCreateInfo->pDepthStencilState->depthBoundsTestEnable;
state->ds->depth.bounds_test.enable;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE) {
dynamic->stencil_test_enable =
pCreateInfo->pDepthStencilState->stencilTestEnable;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE)
dynamic->stencil_test_enable = state->ds->stencil.test_enable;
if (states & ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP) {
const VkPipelineDepthStencilStateCreateInfo *info =
pCreateInfo->pDepthStencilState;
memcpy(&dynamic->stencil_op.front, &info->front,
sizeof(dynamic->stencil_op.front));
memcpy(&dynamic->stencil_op.back, &info->back,
sizeof(dynamic->stencil_op.back));
dynamic->stencil_op.front.fail_op = state->ds->stencil.front.op.fail;
dynamic->stencil_op.front.pass_op = state->ds->stencil.front.op.pass;
dynamic->stencil_op.front.depth_fail_op = state->ds->stencil.front.op.depth_fail;
dynamic->stencil_op.front.compare_op = state->ds->stencil.front.op.compare;
dynamic->stencil_op.back.fail_op = state->ds->stencil.back.op.fail;
dynamic->stencil_op.back.pass_op = state->ds->stencil.back.op.pass;
dynamic->stencil_op.back.depth_fail_op = state->ds->stencil.back.op.depth_fail;
dynamic->stencil_op.back.compare_op = state->ds->stencil.back.op.compare;
}
}
const VkPipelineRasterizationLineStateCreateInfoEXT *line_state =
vk_find_struct_const(pCreateInfo->pRasterizationState->pNext,
PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT);
if (!raster_discard && line_state && line_state->stippledLineEnable) {
if (state->rs != NULL) {
if (states & ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE) {
dynamic->line_stipple.factor = line_state->lineStippleFactor;
dynamic->line_stipple.pattern = line_state->lineStipplePattern;
dynamic->line_stipple.factor = state->rs->line.stipple.factor;
dynamic->line_stipple.pattern = state->rs->line.stipple.pattern;
}
}
const VkPipelineMultisampleStateCreateInfo *ms_info =
raster_discard ? NULL : pCreateInfo->pMultisampleState;
if (states & ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS) {
const VkPipelineSampleLocationsStateCreateInfoEXT *sl_info = ms_info ?
vk_find_struct_const(ms_info, PIPELINE_SAMPLE_LOCATIONS_STATE_CREATE_INFO_EXT) : NULL;
uint32_t samples = MAX2(1, ms_info ? ms_info->rasterizationSamples : 1);
if (sl_info && sl_info->sampleLocationsEnable) {
const VkSampleLocationEXT *positions =
sl_info->sampleLocationsInfo.pSampleLocations;
if (state->ms != NULL) {
uint32_t samples = state->ms->rasterization_samples;
for (uint32_t i = 0; i < samples; i++) {
dynamic->sample_locations.locations[i].x = positions[i].x;
dynamic->sample_locations.locations[i].y = positions[i].y;
dynamic->sample_locations.locations[i].x =
state->ms->sample_locations->locations[i].x;
dynamic->sample_locations.locations[i].y =
state->ms->sample_locations->locations[i].y;
}
dynamic->sample_locations.samples = samples;
} else {
const struct intel_sample_position *positions =
intel_get_sample_positions(samples);
for (uint32_t i = 0; i < samples; i++) {
dynamic->sample_locations.locations[i].x = positions[i].x;
dynamic->sample_locations.locations[i].y = positions[i].y;
}
}
dynamic->sample_locations.samples = samples;
}
if (states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE) {
if (!raster_discard && uses_color_att) {
assert(pCreateInfo->pColorBlendState);
const VkPipelineColorWriteCreateInfoEXT *color_write_info =
vk_find_struct_const(pCreateInfo->pColorBlendState->pNext,
PIPELINE_COLOR_WRITE_CREATE_INFO_EXT);
if (color_write_info) {
dynamic->color_writes = (1u << MAX_RTS) - 1;
for (uint32_t i = 0; i < color_write_info->attachmentCount; i++) {
if (color_write_info->pColorWriteEnables[i])
dynamic->color_writes |= BITFIELD_BIT(i);
else
dynamic->color_writes &= ~BITFIELD_BIT(i);
}
}
dynamic->sample_locations.samples = 1;
dynamic->sample_locations.locations[0].x = 0.5;
dynamic->sample_locations.locations[0].y = 0.5;
}
}
if (states & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP) {
if (!raster_discard && anv_rendering_uses_color_attachment(rendering_info))
dynamic->logic_op = pCreateInfo->pColorBlendState->logicOp;
if (state->cb != NULL) {
if (states & ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE)
dynamic->color_writes = state->cb->color_write_enables;
if (states & ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP)
dynamic->logic_op = state->cb->logic_op;
}
const VkPipelineFragmentShadingRateStateCreateInfoKHR *fsr_state =
vk_find_struct_const(pCreateInfo->pNext,
PIPELINE_FRAGMENT_SHADING_RATE_STATE_CREATE_INFO_KHR);
if (fsr_state) {
if (states & ANV_CMD_DIRTY_DYNAMIC_SHADING_RATE) {
dynamic->fragment_shading_rate.rate = fsr_state->fragmentSize;
memcpy(dynamic->fragment_shading_rate.ops, fsr_state->combinerOps,
sizeof(dynamic->fragment_shading_rate.ops));
}
if (states & ANV_CMD_DIRTY_DYNAMIC_SHADING_RATE) {
dynamic->fragment_shading_rate.rate = state->fsr->fragment_size;
memcpy(dynamic->fragment_shading_rate.ops, state->fsr->combiner_ops,
sizeof(dynamic->fragment_shading_rate.ops));
}
/* When binding a mesh pipeline into a command buffer, it should not affect the
@ -2373,31 +2252,12 @@ anv_pipeline_setup_l3_config(struct anv_pipeline *pipeline, bool needs_slm)
pipeline->l3_config = intel_get_l3_config(devinfo, w);
}
static VkLineRasterizationModeEXT
vk_line_rasterization_mode(const VkPipelineRasterizationLineStateCreateInfoEXT *line_info,
const VkPipelineMultisampleStateCreateInfo *ms_info)
{
VkLineRasterizationModeEXT line_mode =
line_info ? line_info->lineRasterizationMode :
VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT;
if (line_mode == VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT) {
if (ms_info && ms_info->rasterizationSamples > 1) {
return VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
} else {
return VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
}
}
return line_mode;
}
static VkResult
anv_graphics_pipeline_init(struct anv_graphics_pipeline *pipeline,
struct anv_device *device,
struct vk_pipeline_cache *cache,
const VkGraphicsPipelineCreateInfo *pCreateInfo,
const VkPipelineRenderingCreateInfo *rendering_info,
const struct VkGraphicsPipelineCreateInfo *pCreateInfo,
const struct vk_graphics_pipeline_state *state,
const VkAllocationCallbacks *alloc)
{
VkResult result;
@ -2411,14 +2271,11 @@ anv_graphics_pipeline_init(struct anv_graphics_pipeline *pipeline,
anv_batch_set_storage(&pipeline->base.batch, ANV_NULL_ADDRESS,
pipeline->batch_data, sizeof(pipeline->batch_data));
assert(pCreateInfo->pRasterizationState);
if (pCreateInfo->pDynamicState) {
uint32_t count = pCreateInfo->pDynamicState->dynamicStateCount;
for (uint32_t s = 0; s < count; s++) {
pipeline->dynamic_states |= anv_cmd_dirty_bit_for_vk_dynamic_state(
pCreateInfo->pDynamicState->pDynamicStates[s]);
}
enum mesa_vk_dynamic_graphics_state s;
BITSET_FOREACH_SET(s, state->dynamic,
MESA_VK_DYNAMIC_GRAPHICS_STATE_ENUM_MAX) {
pipeline->dynamic_states |=
anv_cmd_dirty_bit_for_mesa_vk_dynamic_graphics_state(s);
}
pipeline->active_stages = 0;
@ -2431,23 +2288,13 @@ anv_graphics_pipeline_init(struct anv_graphics_pipeline *pipeline,
if (anv_pipeline_is_mesh(pipeline))
assert(device->physical->vk.supported_extensions.NV_mesh_shader);
copy_non_dynamic_state(pipeline, pCreateInfo, rendering_info);
copy_non_dynamic_state(pipeline, state);
pipeline->depth_clamp_enable = pCreateInfo->pRasterizationState->depthClampEnable;
pipeline->view_mask = rendering_info->viewMask;
pipeline->depth_clamp_enable = state->rs->depth_clamp_enable;
pipeline->depth_clip_enable = state->rs->depth_clip_enable;
pipeline->view_mask = state->rp->view_mask;
/* Previously we enabled depth clipping when !depthClampEnable.
* DepthClipStateCreateInfo now makes depth clipping explicit so if the
* clipping info is available, use its enable value to determine clipping,
* otherwise fallback to the previous !depthClampEnable logic.
*/
const VkPipelineRasterizationDepthClipStateCreateInfoEXT *clip_info =
vk_find_struct_const(pCreateInfo->pRasterizationState->pNext,
PIPELINE_RASTERIZATION_DEPTH_CLIP_STATE_CREATE_INFO_EXT);
pipeline->depth_clip_enable = clip_info ? clip_info->depthClipEnable : !pipeline->depth_clamp_enable;
result = anv_graphics_pipeline_compile(pipeline, cache, pCreateInfo,
rendering_info);
result = anv_graphics_pipeline_compile(pipeline, cache, pCreateInfo, state);
if (result != VK_SUCCESS) {
anv_pipeline_finish(&pipeline->base, device, alloc);
return result;
@ -2456,51 +2303,18 @@ anv_graphics_pipeline_init(struct anv_graphics_pipeline *pipeline,
anv_pipeline_setup_l3_config(&pipeline->base, false);
if (anv_pipeline_is_primitive(pipeline)) {
const VkPipelineVertexInputStateCreateInfo *vi_info =
pCreateInfo->pVertexInputState;
const uint64_t inputs_read = get_vs_prog_data(pipeline)->inputs_read;
for (uint32_t i = 0; i < vi_info->vertexAttributeDescriptionCount; i++) {
const VkVertexInputAttributeDescription *desc =
&vi_info->pVertexAttributeDescriptions[i];
if (inputs_read & (1ull << (VERT_ATTRIB_GENERIC0 + desc->location)))
pipeline->vb_used |= 1 << desc->binding;
u_foreach_bit(a, state->vi->attributes_valid) {
if (inputs_read & BITFIELD64_BIT(VERT_ATTRIB_GENERIC0 + a))
pipeline->vb_used |= BITFIELD64_BIT(state->vi->attributes[a].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;
}
const VkPipelineVertexInputDivisorStateCreateInfoEXT *vi_div_state =
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;
}
u_foreach_bit(b, state->vi->bindings_valid) {
pipeline->vb[b].stride = state->vi->bindings[b].stride;
pipeline->vb[b].instanced = state->vi->bindings[b].input_rate ==
VK_VERTEX_INPUT_RATE_INSTANCE;
pipeline->vb[b].instance_divisor = state->vi->bindings[b].divisor;
}
/* Our implementation of VK_KHR_multiview uses instancing to draw the
@ -2512,50 +2326,39 @@ anv_graphics_pipeline_init(struct anv_graphics_pipeline *pipeline,
if (pipeline->view_mask && !pipeline->use_primitive_replication)
pipeline->instance_multiplier = util_bitcount(pipeline->view_mask);
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 (anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL)) {
pipeline->topology =
_3DPRIM_PATCHLIST(state->ts->patch_control_points);
} else {
pipeline->topology =
vk_to_intel_primitive_type[state->ia->primitive_topology];
}
} else {
assert(anv_pipeline_is_mesh(pipeline));
/* TODO(mesh): Mesh vs. Multiview with Instancing. */
}
/* If rasterization is not enabled, ms_info must be ignored. */
const bool raster_enabled =
!pCreateInfo->pRasterizationState->rasterizerDiscardEnable ||
(pipeline->dynamic_states &
ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE);
const VkPipelineMultisampleStateCreateInfo *ms_info =
raster_enabled ? pCreateInfo->pMultisampleState : NULL;
const VkPipelineRasterizationLineStateCreateInfoEXT *line_info =
vk_find_struct_const(pCreateInfo->pRasterizationState->pNext,
PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT);
/* Store line mode, polygon mode and rasterization samples, these are used
* for dynamic primitive topology.
*/
pipeline->line_mode = vk_line_rasterization_mode(line_info, ms_info);
pipeline->polygon_mode = pCreateInfo->pRasterizationState->polygonMode;
pipeline->polygon_mode = state->rs->polygon_mode;
pipeline->rasterization_samples =
ms_info ? ms_info->rasterizationSamples : 1;
state->ms != NULL ? state->ms->rasterization_samples : 1;
pipeline->line_mode = state->rs->line.mode;
if (pipeline->line_mode == VK_LINE_RASTERIZATION_MODE_DEFAULT_EXT) {
if (pipeline->rasterization_samples > 1) {
pipeline->line_mode = VK_LINE_RASTERIZATION_MODE_RECTANGULAR_EXT;
} else {
pipeline->line_mode = VK_LINE_RASTERIZATION_MODE_BRESENHAM_EXT;
}
}
/* Store the color write masks, to be merged with color write enable if
* dynamic.
*/
if (raster_enabled && anv_rendering_uses_color_attachment(rendering_info)) {
for (unsigned i = 0; i < pCreateInfo->pColorBlendState->attachmentCount; i++) {
const VkPipelineColorBlendAttachmentState *a =
&pCreateInfo->pColorBlendState->pAttachments[i];
pipeline->color_comp_writes[i] = a->colorWriteMask;
}
if (state->cb != NULL) {
for (unsigned i = 0; i < state->cb->attachment_count; i++)
pipeline->color_comp_writes[i] = state->cb->attachments[i].write_mask;
}
return VK_SUCCESS;
@ -2578,40 +2381,24 @@ anv_graphics_pipeline_create(struct anv_device *device,
if (pipeline == NULL)
return vk_error(device, VK_ERROR_OUT_OF_HOST_MEMORY);
/* We'll use these as defaults if we don't have pipeline rendering or
* self-dependency structs. Saves us some NULL checks.
*/
VkRenderingSelfDependencyInfoMESA rsd_info_tmp = {
.sType = VK_STRUCTURE_TYPE_RENDERING_SELF_DEPENDENCY_INFO_MESA,
};
VkPipelineRenderingCreateInfo rendering_info_tmp = {
.sType = VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO,
.pNext = &rsd_info_tmp,
};
const VkPipelineRenderingCreateInfo *rendering_info =
vk_get_pipeline_rendering_create_info(pCreateInfo);
if (rendering_info == NULL)
rendering_info = &rendering_info_tmp;
const VkRenderingSelfDependencyInfoMESA *rsd_info =
vk_find_struct_const(rendering_info->pNext,
RENDERING_SELF_DEPENDENCY_INFO_MESA);
if (rsd_info == NULL)
rsd_info = &rsd_info_tmp;
result = anv_graphics_pipeline_init(pipeline, device, cache,
pCreateInfo, rendering_info,
pAllocator);
struct vk_graphics_pipeline_all_state all;
struct vk_graphics_pipeline_state state = { };
result = vk_graphics_pipeline_state_fill(&device->vk, &state, pCreateInfo,
NULL /* sp_info */,
&all, NULL, 0, NULL);
if (result != VK_SUCCESS) {
vk_free2(&device->vk.alloc, pAllocator, pipeline);
return result;
}
anv_genX(&device->info, graphics_pipeline_emit)(pipeline,
pCreateInfo,
rendering_info,
rsd_info);
result = anv_graphics_pipeline_init(pipeline, device, cache,
pCreateInfo, &state, pAllocator);
if (result != VK_SUCCESS) {
vk_free2(&device->vk.alloc, pAllocator, pipeline);
return result;
}
anv_genX(&device->info, graphics_pipeline_emit)(pipeline, &state);
*pPipeline = anv_pipeline_to_handle(&pipeline->base);

View File

@ -76,6 +76,7 @@
#include "vk_drm_syncobj.h"
#include "vk_enum_defines.h"
#include "vk_framebuffer.h"
#include "vk_graphics_state.h"
#include "vk_image.h"
#include "vk_instance.h"
#include "vk_pipeline_cache.h"
@ -2262,64 +2263,65 @@ typedef enum anv_cmd_dirty_bits anv_cmd_dirty_mask_t;
ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE)
static inline enum anv_cmd_dirty_bits
anv_cmd_dirty_bit_for_vk_dynamic_state(VkDynamicState vk_state)
anv_cmd_dirty_bit_for_mesa_vk_dynamic_graphics_state(
enum mesa_vk_dynamic_graphics_state state)
{
switch (vk_state) {
case VK_DYNAMIC_STATE_VIEWPORT:
case VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT:
switch (state) {
case MESA_VK_DYNAMIC_VP_VIEWPORT_COUNT:
case MESA_VK_DYNAMIC_VP_VIEWPORTS:
return ANV_CMD_DIRTY_DYNAMIC_VIEWPORT;
case VK_DYNAMIC_STATE_SCISSOR:
case VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT:
case MESA_VK_DYNAMIC_VP_SCISSOR_COUNT:
case MESA_VK_DYNAMIC_VP_SCISSORS:
return ANV_CMD_DIRTY_DYNAMIC_SCISSOR;
case VK_DYNAMIC_STATE_LINE_WIDTH:
case MESA_VK_DYNAMIC_RS_LINE_WIDTH:
return ANV_CMD_DIRTY_DYNAMIC_LINE_WIDTH;
case VK_DYNAMIC_STATE_DEPTH_BIAS:
case MESA_VK_DYNAMIC_RS_DEPTH_BIAS_FACTORS:
return ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS;
case VK_DYNAMIC_STATE_BLEND_CONSTANTS:
case MESA_VK_DYNAMIC_CB_BLEND_CONSTANTS:
return ANV_CMD_DIRTY_DYNAMIC_BLEND_CONSTANTS;
case VK_DYNAMIC_STATE_DEPTH_BOUNDS:
case MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_BOUNDS:
return ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS;
case VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK:
case MESA_VK_DYNAMIC_DS_STENCIL_COMPARE_MASK:
return ANV_CMD_DIRTY_DYNAMIC_STENCIL_COMPARE_MASK;
case VK_DYNAMIC_STATE_STENCIL_WRITE_MASK:
case MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK:
return ANV_CMD_DIRTY_DYNAMIC_STENCIL_WRITE_MASK;
case VK_DYNAMIC_STATE_STENCIL_REFERENCE:
case MESA_VK_DYNAMIC_DS_STENCIL_REFERENCE:
return ANV_CMD_DIRTY_DYNAMIC_STENCIL_REFERENCE;
case VK_DYNAMIC_STATE_LINE_STIPPLE_EXT:
case MESA_VK_DYNAMIC_RS_LINE_STIPPLE:
return ANV_CMD_DIRTY_DYNAMIC_LINE_STIPPLE;
case VK_DYNAMIC_STATE_CULL_MODE:
case MESA_VK_DYNAMIC_RS_CULL_MODE:
return ANV_CMD_DIRTY_DYNAMIC_CULL_MODE;
case VK_DYNAMIC_STATE_FRONT_FACE:
case MESA_VK_DYNAMIC_RS_FRONT_FACE:
return ANV_CMD_DIRTY_DYNAMIC_FRONT_FACE;
case VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY:
case MESA_VK_DYNAMIC_IA_PRIMITIVE_TOPOLOGY:
return ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_TOPOLOGY;
case VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE:
case MESA_VK_DYNAMIC_VI_BINDING_STRIDES:
return ANV_CMD_DIRTY_DYNAMIC_VERTEX_INPUT_BINDING_STRIDE;
case VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE:
case MESA_VK_DYNAMIC_DS_DEPTH_TEST_ENABLE:
return ANV_CMD_DIRTY_DYNAMIC_DEPTH_TEST_ENABLE;
case VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE:
case MESA_VK_DYNAMIC_DS_DEPTH_WRITE_ENABLE:
return ANV_CMD_DIRTY_DYNAMIC_DEPTH_WRITE_ENABLE;
case VK_DYNAMIC_STATE_DEPTH_COMPARE_OP:
case MESA_VK_DYNAMIC_DS_DEPTH_COMPARE_OP:
return ANV_CMD_DIRTY_DYNAMIC_DEPTH_COMPARE_OP;
case VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE:
case MESA_VK_DYNAMIC_DS_DEPTH_BOUNDS_TEST_ENABLE:
return ANV_CMD_DIRTY_DYNAMIC_DEPTH_BOUNDS_TEST_ENABLE;
case VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE:
case MESA_VK_DYNAMIC_DS_STENCIL_TEST_ENABLE:
return ANV_CMD_DIRTY_DYNAMIC_STENCIL_TEST_ENABLE;
case VK_DYNAMIC_STATE_STENCIL_OP:
case MESA_VK_DYNAMIC_DS_STENCIL_OP:
return ANV_CMD_DIRTY_DYNAMIC_STENCIL_OP;
case VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT:
case MESA_VK_DYNAMIC_MS_SAMPLE_LOCATIONS:
return ANV_CMD_DIRTY_DYNAMIC_SAMPLE_LOCATIONS;
case VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT:
case MESA_VK_DYNAMIC_CB_COLOR_WRITE_ENABLES:
return ANV_CMD_DIRTY_DYNAMIC_COLOR_BLEND_STATE;
case VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR:
case MESA_VK_DYNAMIC_FSR:
return ANV_CMD_DIRTY_DYNAMIC_SHADING_RATE;
case VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE:
case MESA_VK_DYNAMIC_RS_RASTERIZER_DISCARD_ENABLE:
return ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE;
case VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE:
case MESA_VK_DYNAMIC_RS_DEPTH_BIAS_ENABLE:
return ANV_CMD_DIRTY_DYNAMIC_DEPTH_BIAS_ENABLE;
case VK_DYNAMIC_STATE_LOGIC_OP_EXT:
case MESA_VK_DYNAMIC_CB_LOGIC_OP:
return ANV_CMD_DIRTY_DYNAMIC_LOGIC_OP;
case VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE:
case MESA_VK_DYNAMIC_IA_PRIMITIVE_RESTART_ENABLE:
return ANV_CMD_DIRTY_DYNAMIC_PRIMITIVE_RESTART_ENABLE;
default:
assert(!"Unsupported dynamic state");

View File

@ -89,7 +89,7 @@ vertex_element_comp_control(enum isl_format format, unsigned comp)
static void
emit_vertex_input(struct anv_graphics_pipeline *pipeline,
const VkPipelineVertexInputStateCreateInfo *info)
const struct vk_vertex_input_state *vi)
{
const struct brw_vs_prog_data *vs_prog_data = get_vs_prog_data(pipeline);
@ -147,30 +147,29 @@ emit_vertex_input(struct anv_graphics_pipeline *pipeline,
GENX(VERTEX_ELEMENT_STATE_pack)(NULL, &p[1 + i * 2], &element);
}
for (uint32_t i = 0; i < info->vertexAttributeDescriptionCount; i++) {
const VkVertexInputAttributeDescription *desc =
&info->pVertexAttributeDescriptions[i];
u_foreach_bit(a, vi->attributes_valid) {
enum isl_format format = anv_get_isl_format(&pipeline->base.device->info,
desc->format,
vi->attributes[a].format,
VK_IMAGE_ASPECT_COLOR_BIT,
VK_IMAGE_TILING_LINEAR);
assert(desc->binding < MAX_VBS);
uint32_t binding = vi->attributes[a].binding;
assert(binding < MAX_VBS);
if ((elements & (1 << desc->location)) == 0)
if ((elements & (1 << a)) == 0)
continue; /* Binding unused */
uint32_t slot =
__builtin_popcount(elements & ((1 << desc->location) - 1)) -
__builtin_popcount(elements & ((1 << a) - 1)) -
DIV_ROUND_UP(__builtin_popcount(elements_double &
((1 << desc->location) -1)), 2);
((1 << a) -1)), 2);
struct GENX(VERTEX_ELEMENT_STATE) element = {
.VertexBufferIndex = desc->binding,
.VertexBufferIndex = vi->attributes[a].binding,
.Valid = true,
.SourceElementFormat = format,
.EdgeFlagEnable = false,
.SourceElementOffset = desc->offset,
.SourceElementOffset = vi->attributes[a].offset,
.Component0Control = vertex_element_comp_control(format, 0),
.Component1Control = vertex_element_comp_control(format, 1),
.Component2Control = vertex_element_comp_control(format, 2),
@ -184,8 +183,8 @@ emit_vertex_input(struct anv_graphics_pipeline *pipeline,
* VERTEX_BUFFER_STATE which we emit later.
*/
anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_VF_INSTANCING), vfi) {
bool per_instance = pipeline->vb[desc->binding].instanced;
uint32_t divisor = pipeline->vb[desc->binding].instance_divisor *
bool per_instance = pipeline->vb[binding].instanced;
uint32_t divisor = pipeline->vb[binding].instance_divisor *
pipeline->instance_multiplier;
vfi.InstancingEnable = per_instance;
@ -666,16 +665,6 @@ genX(ms_rasterization_mode)(struct anv_graphics_pipeline *pipeline,
#endif
}
static VkProvokingVertexModeEXT
vk_provoking_vertex_mode(const VkPipelineRasterizationStateCreateInfo *rs_info)
{
const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT *rs_pv_info =
vk_find_struct_const(rs_info, PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT);
return rs_pv_info == NULL ? VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT :
rs_pv_info->provokingVertexMode;
}
const uint32_t genX(vk_to_intel_cullmode)[] = {
[VK_CULL_MODE_NONE] = CULLMODE_NONE,
[VK_CULL_MODE_FRONT_BIT] = CULLMODE_FRONT,
@ -694,18 +683,6 @@ const uint32_t genX(vk_to_intel_front_face)[] = {
[VK_FRONT_FACE_CLOCKWISE] = 0
};
#if GFX_VER >= 9
static VkConservativeRasterizationModeEXT
vk_conservative_rasterization_mode(const VkPipelineRasterizationStateCreateInfo *rs_info)
{
const VkPipelineRasterizationConservativeStateCreateInfoEXT *cr =
vk_find_struct_const(rs_info, PIPELINE_RASTERIZATION_CONSERVATIVE_STATE_CREATE_INFO_EXT);
return cr ? cr->conservativeRasterizationMode :
VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
}
#endif
void
genX(rasterization_mode)(VkPolygonMode raster_mode,
VkLineRasterizationModeEXT line_mode,
@ -761,11 +738,10 @@ genX(rasterization_mode)(VkPolygonMode raster_mode,
static void
emit_rs_state(struct anv_graphics_pipeline *pipeline,
const VkPipelineInputAssemblyStateCreateInfo *ia_info,
const VkPipelineRasterizationStateCreateInfo *rs_info,
const VkPipelineMultisampleStateCreateInfo *ms_info,
const VkPipelineRasterizationLineStateCreateInfoEXT *line_info,
const VkPipelineRenderingCreateInfo *rendering_info,
const struct vk_input_assembly_state *ia,
const struct vk_rasterization_state *rs,
const struct vk_multisample_state *ms,
const struct vk_render_pass_state *rp,
enum intel_urb_deref_block_size urb_deref_block_size)
{
struct GENX(3DSTATE_SF) sf = {
@ -777,7 +753,7 @@ emit_rs_state(struct anv_graphics_pipeline *pipeline,
sf.VertexSubPixelPrecisionSelect = _8Bit;
sf.AALineDistanceMode = true;
switch (vk_provoking_vertex_mode(rs_info)) {
switch (rs->provoking_vertex) {
case VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT:
sf.TriangleStripListProvokingVertexSelect = 0;
sf.LineStripListProvokingVertexSelect = 0;
@ -795,7 +771,7 @@ emit_rs_state(struct anv_graphics_pipeline *pipeline,
}
#if GFX_VERx10 == 75
sf.LineStippleEnable = line_info && line_info->stippledLineEnable;
sf.LineStippleEnable = rs->line.stipple.enable;
#endif
#if GFX_VER >= 12
@ -840,8 +816,8 @@ emit_rs_state(struct anv_graphics_pipeline *pipeline,
raster.ForceMultisampling = false;
#endif
raster.FrontFaceFillMode = genX(vk_to_intel_fillmode)[rs_info->polygonMode];
raster.BackFaceFillMode = genX(vk_to_intel_fillmode)[rs_info->polygonMode];
raster.FrontFaceFillMode = genX(vk_to_intel_fillmode)[rs->polygon_mode];
raster.BackFaceFillMode = genX(vk_to_intel_fillmode)[rs->polygon_mode];
raster.ScissorRectangleEnable = true;
#if GFX_VER >= 9
@ -854,20 +830,19 @@ emit_rs_state(struct anv_graphics_pipeline *pipeline,
#if GFX_VER >= 9
raster.ConservativeRasterizationEnable =
vk_conservative_rasterization_mode(rs_info) !=
VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
rs->conservative_mode != VK_CONSERVATIVE_RASTERIZATION_MODE_DISABLED_EXT;
#endif
#if GFX_VER == 7
/* Gfx7 requires that we provide the depth format in 3DSTATE_SF so that it
* can get the depth offsets correct.
*/
if (rendering_info != NULL &&
rendering_info->depthAttachmentFormat != VK_FORMAT_UNDEFINED) {
assert(vk_format_has_depth(rendering_info->depthAttachmentFormat));
if (rp != NULL &&
rp->depth_attachment_format != VK_FORMAT_UNDEFINED) {
assert(vk_format_has_depth(rp->depth_attachment_format));
enum isl_format isl_format =
anv_get_isl_format(&pipeline->base.device->info,
rendering_info->depthAttachmentFormat,
rp->depth_attachment_format,
VK_IMAGE_ASPECT_DEPTH_BIT,
VK_IMAGE_TILING_OPTIMAL);
sf.DepthBufferSurfaceFormat =
@ -886,7 +861,7 @@ emit_rs_state(struct anv_graphics_pipeline *pipeline,
static void
emit_ms_state(struct anv_graphics_pipeline *pipeline,
const VkPipelineMultisampleStateCreateInfo *info)
const struct vk_multisample_state *ms)
{
#if GFX_VER >= 8
/* On Gfx8+ 3DSTATE_MULTISAMPLE only holds the number of samples. */
@ -907,8 +882,8 @@ emit_ms_state(struct anv_graphics_pipeline *pipeline,
uint32_t sample_mask = 0xff;
#endif
if (info && info->pSampleMask)
sample_mask &= info->pSampleMask[0];
if (ms != NULL)
sample_mask &= ms->sample_mask;
anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_SAMPLE_MASK), sm) {
sm.SampleMask = sample_mask;
@ -999,141 +974,10 @@ const uint32_t genX(vk_to_intel_primitive_type)[] = {
[VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY] = _3DPRIM_TRISTRIP_ADJ,
};
/* This function sanitizes the VkStencilOpState by looking at the compare ops
* and trying to determine whether or not a given stencil op can ever actually
* occur. Stencil ops which can never occur are set to VK_STENCIL_OP_KEEP.
* This function returns true if, after sanitation, any of the stencil ops are
* set to something other than VK_STENCIL_OP_KEEP.
*/
static bool
sanitize_stencil_face(VkStencilOpState *face,
VkCompareOp depthCompareOp)
{
/* If compareOp is ALWAYS then the stencil test will never fail and failOp
* will never happen. Set failOp to KEEP in this case.
*/
if (face->compareOp == VK_COMPARE_OP_ALWAYS)
face->failOp = VK_STENCIL_OP_KEEP;
/* If compareOp is NEVER or depthCompareOp is NEVER then one of the depth
* or stencil tests will fail and passOp will never happen.
*/
if (face->compareOp == VK_COMPARE_OP_NEVER ||
depthCompareOp == VK_COMPARE_OP_NEVER)
face->passOp = VK_STENCIL_OP_KEEP;
/* If compareOp is NEVER or depthCompareOp is ALWAYS then either the
* stencil test will fail or the depth test will pass. In either case,
* depthFailOp will never happen.
*/
if (face->compareOp == VK_COMPARE_OP_NEVER ||
depthCompareOp == VK_COMPARE_OP_ALWAYS)
face->depthFailOp = VK_STENCIL_OP_KEEP;
return face->failOp != VK_STENCIL_OP_KEEP ||
face->depthFailOp != VK_STENCIL_OP_KEEP ||
face->passOp != VK_STENCIL_OP_KEEP;
}
/* Intel hardware is fairly sensitive to whether or not depth/stencil writes
* are enabled. In the presence of discards, it's fairly easy to get into the
* non-promoted case which means a fairly big performance hit. From the Iron
* Lake PRM, Vol 2, pt. 1, section 8.4.3.2, "Early Depth Test Cases":
*
* "Non-promoted depth (N) is active whenever the depth test can be done
* early but it cannot determine whether or not to write source depth to
* the depth buffer, therefore the depth write must be performed post pixel
* shader. This includes cases where the pixel shader can kill pixels,
* including via sampler chroma key, as well as cases where the alpha test
* function is enabled, which kills pixels based on a programmable alpha
* test. In this case, even if the depth test fails, the pixel cannot be
* killed if a stencil write is indicated. Whether or not the stencil write
* happens depends on whether or not the pixel is killed later. In these
* cases if stencil test fails and stencil writes are off, the pixels can
* also be killed early. If stencil writes are enabled, the pixels must be
* treated as Computed depth (described above)."
*
* The same thing as mentioned in the stencil case can happen in the depth
* case as well if it thinks it writes depth but, thanks to the depth test
* being GL_EQUAL, the write doesn't actually matter. A little extra work
* up-front to try and disable depth and stencil writes can make a big
* difference.
*
* Unfortunately, the way depth and stencil testing is specified, there are
* many case where, regardless of depth/stencil writes being enabled, nothing
* actually gets written due to some other bit of state being set. This
* function attempts to "sanitize" the depth stencil state and disable writes
* and sometimes even testing whenever possible.
*/
static void
sanitize_ds_state(VkPipelineDepthStencilStateCreateInfo *state,
bool *stencilWriteEnable,
VkImageAspectFlags ds_aspects)
{
*stencilWriteEnable = state->stencilTestEnable;
/* If the depth test is disabled, we won't be writing anything. Make sure we
* treat the test as always passing later on as well.
*
* Also, the Vulkan spec requires that if either depth or stencil is not
* present, the pipeline is to act as if the test silently passes. In that
* case we won't write either.
*/
if (!state->depthTestEnable || !(ds_aspects & VK_IMAGE_ASPECT_DEPTH_BIT)) {
state->depthWriteEnable = false;
state->depthCompareOp = VK_COMPARE_OP_ALWAYS;
}
if (!(ds_aspects & VK_IMAGE_ASPECT_STENCIL_BIT)) {
*stencilWriteEnable = false;
state->front.compareOp = VK_COMPARE_OP_ALWAYS;
state->back.compareOp = VK_COMPARE_OP_ALWAYS;
}
/* If the stencil test is enabled and always fails, then we will never get
* to the depth test so we can just disable the depth test entirely.
*/
if (state->stencilTestEnable &&
state->front.compareOp == VK_COMPARE_OP_NEVER &&
state->back.compareOp == VK_COMPARE_OP_NEVER) {
state->depthTestEnable = false;
state->depthWriteEnable = false;
}
/* If depthCompareOp is EQUAL then the value we would be writing to the
* depth buffer is the same as the value that's already there so there's no
* point in writing it.
*/
if (state->depthCompareOp == VK_COMPARE_OP_EQUAL)
state->depthWriteEnable = false;
/* If the stencil ops are such that we don't actually ever modify the
* stencil buffer, we should disable writes.
*/
if (!sanitize_stencil_face(&state->front, state->depthCompareOp) &&
!sanitize_stencil_face(&state->back, state->depthCompareOp))
*stencilWriteEnable = false;
/* If the depth test always passes and we never write out depth, that's the
* same as if the depth test is disabled entirely.
*/
if (state->depthCompareOp == VK_COMPARE_OP_ALWAYS &&
!state->depthWriteEnable)
state->depthTestEnable = false;
/* If the stencil test always passes and we never write out stencil, that's
* the same as if the stencil test is disabled entirely.
*/
if (state->front.compareOp == VK_COMPARE_OP_ALWAYS &&
state->back.compareOp == VK_COMPARE_OP_ALWAYS &&
!*stencilWriteEnable)
state->stencilTestEnable = false;
}
static void
emit_ds_state(struct anv_graphics_pipeline *pipeline,
const VkPipelineDepthStencilStateCreateInfo *pCreateInfo,
const VkPipelineRenderingCreateInfo *rendering_info)
const struct vk_depth_stencil_state *ds_in,
const struct vk_render_pass_state *rp)
{
#if GFX_VER == 7
# define depth_stencil_dw pipeline->gfx7.depth_stencil_state
@ -1143,7 +987,7 @@ emit_ds_state(struct anv_graphics_pipeline *pipeline,
# define depth_stencil_dw pipeline->gfx9.wm_depth_stencil
#endif
if (pCreateInfo == NULL) {
if (ds_in == NULL) {
/* We're going to OR this together with the dynamic state. We need
* to make sure it's initialized to something useful.
*/
@ -1157,19 +1001,20 @@ emit_ds_state(struct anv_graphics_pipeline *pipeline,
}
VkImageAspectFlags ds_aspects = 0;
if (rendering_info != NULL) {
if (rendering_info->depthAttachmentFormat != VK_FORMAT_UNDEFINED)
if (rp != NULL) {
if (rp->depth_attachment_format != VK_FORMAT_UNDEFINED)
ds_aspects |= VK_IMAGE_ASPECT_DEPTH_BIT;
if (rendering_info->stencilAttachmentFormat != VK_FORMAT_UNDEFINED)
if (rp->stencil_attachment_format != VK_FORMAT_UNDEFINED)
ds_aspects |= VK_IMAGE_ASPECT_STENCIL_BIT;
}
VkPipelineDepthStencilStateCreateInfo info = *pCreateInfo;
sanitize_ds_state(&info, &pipeline->writes_stencil, ds_aspects);
pipeline->stencil_test_enable = info.stencilTestEnable;
pipeline->writes_depth = info.depthWriteEnable;
pipeline->depth_test_enable = info.depthTestEnable;
pipeline->depth_bounds_test_enable = info.depthBoundsTestEnable;
struct vk_depth_stencil_state ds = *ds_in;
vk_optimize_depth_stencil_state(&ds, ds_aspects);
pipeline->writes_stencil = ds.stencil.write_enable;
pipeline->stencil_test_enable = ds.stencil.test_enable;
pipeline->writes_depth = ds.depth.write_enable;
pipeline->depth_test_enable = ds.depth.test_enable;
pipeline->depth_bounds_test_enable = ds.depth.bounds_test.enable;
#if GFX_VER <= 7
struct GENX(DEPTH_STENCIL_STATE) depth_stencil = {
@ -1210,16 +1055,16 @@ write_disabled_blend(uint32_t *state)
static void
emit_cb_state(struct anv_graphics_pipeline *pipeline,
const VkPipelineColorBlendStateCreateInfo *info,
const VkPipelineMultisampleStateCreateInfo *ms_info)
const struct vk_color_blend_state *cb,
const struct vk_multisample_state *ms)
{
struct anv_device *device = pipeline->base.device;
const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline);
struct GENX(BLEND_STATE) blend_state = {
#if GFX_VER >= 8
.AlphaToCoverageEnable = ms_info && ms_info->alphaToCoverageEnable,
.AlphaToOneEnable = ms_info && ms_info->alphaToOneEnable,
.AlphaToCoverageEnable = ms && ms->alpha_to_coverage_enable,
.AlphaToOneEnable = ms && ms->alpha_to_one_enable,
#endif
};
@ -1249,20 +1094,20 @@ emit_cb_state(struct anv_graphics_pipeline *pipeline,
/* We can have at most 8 attachments */
assert(i < MAX_RTS);
if (info == NULL || binding->index >= info->attachmentCount) {
if (cb == NULL || binding->index >= cb->attachment_count) {
state_pos = write_disabled_blend(state_pos);
continue;
}
const VkPipelineColorBlendAttachmentState *a =
&info->pAttachments[binding->index];
const struct vk_color_blend_attachment_state *a =
&cb->attachments[binding->index];
struct GENX(BLEND_STATE_ENTRY) entry = {
#if GFX_VER < 8
.AlphaToCoverageEnable = ms_info && ms_info->alphaToCoverageEnable,
.AlphaToOneEnable = ms_info && ms_info->alphaToOneEnable,
.AlphaToCoverageEnable = ms && ms->alpha_to_coverage_enable,
.AlphaToOneEnable = ms && ms->alpha_to_one_enable,
#endif
.LogicOpEnable = info->logicOpEnable,
.LogicOpEnable = cb->logic_op_enable,
/* Vulkan specification 1.2.168, VkLogicOp:
*
@ -1279,21 +1124,21 @@ emit_cb_state(struct anv_graphics_pipeline *pipeline,
* "Enabling LogicOp and Color Buffer Blending at the same time is
* UNDEFINED"
*/
.ColorBufferBlendEnable = !info->logicOpEnable && a->blendEnable,
.ColorBufferBlendEnable = !cb->logic_op_enable && a->blend_enable,
.ColorClampRange = COLORCLAMP_RTFORMAT,
.PreBlendColorClampEnable = true,
.PostBlendColorClampEnable = true,
.SourceBlendFactor = vk_to_intel_blend[a->srcColorBlendFactor],
.DestinationBlendFactor = vk_to_intel_blend[a->dstColorBlendFactor],
.ColorBlendFunction = vk_to_intel_blend_op[a->colorBlendOp],
.SourceAlphaBlendFactor = vk_to_intel_blend[a->srcAlphaBlendFactor],
.DestinationAlphaBlendFactor = vk_to_intel_blend[a->dstAlphaBlendFactor],
.AlphaBlendFunction = vk_to_intel_blend_op[a->alphaBlendOp],
.SourceBlendFactor = vk_to_intel_blend[a->src_color_blend_factor],
.DestinationBlendFactor = vk_to_intel_blend[a->dst_color_blend_factor],
.ColorBlendFunction = vk_to_intel_blend_op[a->color_blend_op],
.SourceAlphaBlendFactor = vk_to_intel_blend[a->src_alpha_blend_factor],
.DestinationAlphaBlendFactor = vk_to_intel_blend[a->dst_alpha_blend_factor],
.AlphaBlendFunction = vk_to_intel_blend_op[a->alpha_blend_op],
};
if (a->srcColorBlendFactor != a->srcAlphaBlendFactor ||
a->dstColorBlendFactor != a->dstAlphaBlendFactor ||
a->colorBlendOp != a->alphaBlendOp) {
if (a->src_color_blend_factor != a->src_alpha_blend_factor ||
a->dst_color_blend_factor != a->dst_alpha_blend_factor ||
a->color_blend_op != a->alpha_blend_op) {
#if GFX_VER >= 8
blend_state.IndependentAlphaBlendEnable = true;
#else
@ -1313,10 +1158,10 @@ emit_cb_state(struct anv_graphics_pipeline *pipeline,
* so we just disable the blending to prevent possible issues.
*/
if (!wm_prog_data->dual_src_blend &&
(is_dual_src_blend_factor(a->srcColorBlendFactor) ||
is_dual_src_blend_factor(a->dstColorBlendFactor) ||
is_dual_src_blend_factor(a->srcAlphaBlendFactor) ||
is_dual_src_blend_factor(a->dstAlphaBlendFactor))) {
(is_dual_src_blend_factor(a->src_color_blend_factor) ||
is_dual_src_blend_factor(a->dst_color_blend_factor) ||
is_dual_src_blend_factor(a->src_alpha_blend_factor) ||
is_dual_src_blend_factor(a->dst_alpha_blend_factor))) {
vk_logw(VK_LOG_OBJS(&device->vk.base),
"Enabled dual-src blend factors without writing both targets "
"in the shader. Disabling blending to avoid GPU hangs.");
@ -1329,13 +1174,13 @@ emit_cb_state(struct anv_graphics_pipeline *pipeline,
* means that, for MIN and MAX, we have to stomp the blend factor to
* ONE to make it a no-op.
*/
if (a->colorBlendOp == VK_BLEND_OP_MIN ||
a->colorBlendOp == VK_BLEND_OP_MAX) {
if (a->color_blend_op == VK_BLEND_OP_MIN ||
a->color_blend_op == VK_BLEND_OP_MAX) {
entry.SourceBlendFactor = BLENDFACTOR_ONE;
entry.DestinationBlendFactor = BLENDFACTOR_ONE;
}
if (a->alphaBlendOp == VK_BLEND_OP_MIN ||
a->alphaBlendOp == VK_BLEND_OP_MAX) {
if (a->alpha_blend_op == VK_BLEND_OP_MIN ||
a->alpha_blend_op == VK_BLEND_OP_MAX) {
entry.SourceAlphaBlendFactor = BLENDFACTOR_ONE;
entry.DestinationAlphaBlendFactor = BLENDFACTOR_ONE;
}
@ -1368,9 +1213,9 @@ emit_cb_state(struct anv_graphics_pipeline *pipeline,
static void
emit_3dstate_clip(struct anv_graphics_pipeline *pipeline,
const VkPipelineInputAssemblyStateCreateInfo *ia_info,
const VkPipelineViewportStateCreateInfo *vp_info,
const VkPipelineRasterizationStateCreateInfo *rs_info)
const struct vk_input_assembly_state *ia,
const struct vk_viewport_state *vp,
const struct vk_rasterization_state *rs)
{
const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline);
(void) wm_prog_data;
@ -1390,7 +1235,7 @@ emit_3dstate_clip(struct anv_graphics_pipeline *pipeline,
#endif
clip.ClipMode = CLIPMODE_NORMAL;
switch (vk_provoking_vertex_mode(rs_info)) {
switch (rs->provoking_vertex) {
case VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT:
clip.TriangleStripListProvokingVertexSelect = 0;
clip.LineStripListProvokingVertexSelect = 0;
@ -1421,9 +1266,9 @@ emit_3dstate_clip(struct anv_graphics_pipeline *pipeline,
* interface does not include a variable decorated with
* ViewportIndex, then the first viewport is used."
*/
if (vp_info && (last->vue_map.slots_valid & VARYING_BIT_VIEWPORT)) {
clip.MaximumVPIndex = vp_info->viewportCount > 0 ?
vp_info->viewportCount - 1 : 0;
if (vp && (last->vue_map.slots_valid & VARYING_BIT_VIEWPORT)) {
clip.MaximumVPIndex = vp->viewport_count > 0 ?
vp->viewport_count - 1 : 0;
} else {
clip.MaximumVPIndex = 0;
}
@ -1443,15 +1288,15 @@ emit_3dstate_clip(struct anv_graphics_pipeline *pipeline,
#endif
} else if (anv_pipeline_is_mesh(pipeline)) {
const struct brw_mesh_prog_data *mesh_prog_data = get_mesh_prog_data(pipeline);
if (vp_info && vp_info->viewportCount > 0 &&
mesh_prog_data->map.start_dw[VARYING_SLOT_VIEWPORT] >= 0) {
clip.MaximumVPIndex = vp_info->viewportCount - 1;
if (vp && vp->viewport_count > 0 &&
mesh_prog_data->map.start_dw[VARYING_SLOT_VIEWPORT] >= 0) {
clip.MaximumVPIndex = vp->viewport_count - 1;
}
}
#if GFX_VER == 7
clip.FrontWinding = genX(vk_to_intel_front_face)[rs_info->frontFace];
clip.CullMode = genX(vk_to_intel_cullmode)[rs_info->cullMode];
clip.FrontWinding = genX(vk_to_intel_front_face)[rs->front_face];
clip.CullMode = genX(vk_to_intel_cullmode)[rs->cull_mode];
clip.ViewportZClipTestEnable = pipeline->depth_clip_enable;
#else
clip.NonPerspectiveBarycentricEnable = wm_prog_data ?
@ -1474,7 +1319,7 @@ emit_3dstate_clip(struct anv_graphics_pipeline *pipeline,
static void
emit_3dstate_streamout(struct anv_graphics_pipeline *pipeline,
const VkPipelineRasterizationStateCreateInfo *rs_info)
const struct vk_rasterization_state *rs)
{
const struct brw_vue_prog_data *prog_data =
anv_pipeline_get_last_vue_prog_data(pipeline);
@ -1614,7 +1459,7 @@ emit_3dstate_streamout(struct anv_graphics_pipeline *pipeline,
so.SOFunctionEnable = true;
so.SOStatisticsEnable = true;
switch (vk_provoking_vertex_mode(rs_info)) {
switch (rs->provoking_vertex) {
case VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT:
so.ReorderMode = LEADING;
break;
@ -1627,10 +1472,7 @@ emit_3dstate_streamout(struct anv_graphics_pipeline *pipeline,
unreachable("Invalid provoking vertex mode");
}
const VkPipelineRasterizationStateStreamCreateInfoEXT *stream_info =
vk_find_struct_const(rs_info, PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT);
so.RenderStreamSelect = stream_info ?
stream_info->rasterizationStream : 0;
so.RenderStreamSelect = rs->rasterization_stream;
#if GFX_VER >= 8
so.Buffer0SurfacePitch = xfb_info->buffers[0].stride;
@ -1809,7 +1651,7 @@ emit_3dstate_vs(struct anv_graphics_pipeline *pipeline)
static void
emit_3dstate_hs_te_ds(struct anv_graphics_pipeline *pipeline,
const VkPipelineTessellationStateCreateInfo *tess_info)
const struct vk_tessellation_state *ts)
{
if (!anv_pipeline_has_stage(pipeline, MESA_SHADER_TESS_EVAL)) {
anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_HS), hs);
@ -1880,17 +1722,10 @@ emit_3dstate_hs_te_ds(struct anv_graphics_pipeline *pipeline,
#endif
}
const VkPipelineTessellationDomainOriginStateCreateInfo *domain_origin_state =
tess_info ? vk_find_struct_const(tess_info, PIPELINE_TESSELLATION_DOMAIN_ORIGIN_STATE_CREATE_INFO) : NULL;
VkTessellationDomainOrigin uv_origin =
domain_origin_state ? domain_origin_state->domainOrigin :
VK_TESSELLATION_DOMAIN_ORIGIN_UPPER_LEFT;
anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_TE), te) {
te.Partitioning = tes_prog_data->partitioning;
if (uv_origin == VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT) {
if (ts->domain_origin == VK_TESSELLATION_DOMAIN_ORIGIN_LOWER_LEFT) {
te.OutputTopology = tes_prog_data->output_topology;
} else {
/* When the origin is upper-left, we have to flip the winding order */
@ -2039,44 +1874,13 @@ emit_3dstate_gs(struct anv_graphics_pipeline *pipeline)
}
}
static bool
has_color_buffer_write_enabled(const struct anv_graphics_pipeline *pipeline,
const VkPipelineColorBlendStateCreateInfo *blend)
{
const struct anv_shader_bin *shader_bin =
pipeline->shaders[MESA_SHADER_FRAGMENT];
if (!shader_bin)
return false;
if (!pipeline->non_dynamic_state.color_writes)
return false;
const struct anv_pipeline_bind_map *bind_map = &shader_bin->bind_map;
for (int i = 0; i < bind_map->surface_count; i++) {
struct anv_pipeline_binding *binding = &bind_map->surface_to_descriptor[i];
if (binding->set != ANV_DESCRIPTOR_SET_COLOR_ATTACHMENTS)
continue;
if (binding->index == UINT32_MAX)
continue;
if (blend && binding->index < blend->attachmentCount &&
blend->pAttachments[binding->index].colorWriteMask != 0)
return true;
}
return false;
}
static void
emit_3dstate_wm(struct anv_graphics_pipeline *pipeline,
const VkPipelineInputAssemblyStateCreateInfo *ia,
const VkPipelineRasterizationStateCreateInfo *raster,
const VkPipelineColorBlendStateCreateInfo *blend,
const VkPipelineMultisampleStateCreateInfo *multisample,
const VkPipelineRasterizationLineStateCreateInfoEXT *line,
const VkRenderingSelfDependencyInfoMESA *rsd)
const struct vk_input_assembly_state *ia,
const struct vk_rasterization_state *rs,
const struct vk_multisample_state *ms,
const struct vk_color_blend_state *cb,
const struct vk_render_pass_state *rp)
{
const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline);
@ -2135,8 +1939,8 @@ emit_3dstate_wm(struct anv_graphics_pipeline *pipeline,
* may get the depth or stencil value from the current draw rather
* than the previous one.
*/
wm.PixelShaderKillsPixel = rsd->depthSelfDependency ||
rsd->stencilSelfDependency ||
wm.PixelShaderKillsPixel = rp->depth_self_dependency ||
rp->stencil_self_dependency ||
wm_prog_data->uses_kill;
pipeline->force_fragment_thread_dispatch =
@ -2144,7 +1948,7 @@ emit_3dstate_wm(struct anv_graphics_pipeline *pipeline,
wm_prog_data->has_side_effects ||
wm.PixelShaderKillsPixel;
if (multisample && multisample->rasterizationSamples > 1) {
if (ms != NULL && ms->rasterization_samples > 1) {
if (wm_prog_data->persample_dispatch) {
wm.MultisampleDispatchMode = MSDISPMODE_PERSAMPLE;
} else {
@ -2155,7 +1959,7 @@ emit_3dstate_wm(struct anv_graphics_pipeline *pipeline,
}
#endif
wm.LineStippleEnable = line && line->stippledLineEnable;
wm.LineStippleEnable = rs->line.stipple.enable;
}
const struct intel_device_info *devinfo = &pipeline->base.device->info;
@ -2165,8 +1969,8 @@ emit_3dstate_wm(struct anv_graphics_pipeline *pipeline,
static void
emit_3dstate_ps(struct anv_graphics_pipeline *pipeline,
const VkPipelineColorBlendStateCreateInfo *blend,
const VkPipelineMultisampleStateCreateInfo *multisample)
const struct vk_multisample_state *ms,
const struct vk_color_blend_state *cb)
{
UNUSED const struct intel_device_info *devinfo =
&pipeline->base.device->info;
@ -2192,16 +1996,16 @@ emit_3dstate_ps(struct anv_graphics_pipeline *pipeline,
* source blend factors.
*/
bool dual_src_blend = false;
if (wm_prog_data->dual_src_blend && blend) {
for (uint32_t i = 0; i < blend->attachmentCount; i++) {
const VkPipelineColorBlendAttachmentState *bstate =
&blend->pAttachments[i];
if (wm_prog_data->dual_src_blend && cb) {
for (uint32_t i = 0; i < cb->attachment_count; i++) {
const struct vk_color_blend_attachment_state *a =
&cb->attachments[i];
if (bstate->blendEnable &&
(is_dual_src_blend_factor(bstate->srcColorBlendFactor) ||
is_dual_src_blend_factor(bstate->dstColorBlendFactor) ||
is_dual_src_blend_factor(bstate->srcAlphaBlendFactor) ||
is_dual_src_blend_factor(bstate->dstAlphaBlendFactor))) {
if (a->blend_enable &&
(is_dual_src_blend_factor(a->src_color_blend_factor) ||
is_dual_src_blend_factor(a->dst_color_blend_factor) ||
is_dual_src_blend_factor(a->src_alpha_blend_factor) ||
is_dual_src_blend_factor(a->dst_alpha_blend_factor))) {
dual_src_blend = true;
break;
}
@ -2223,7 +2027,7 @@ emit_3dstate_ps(struct anv_graphics_pipeline *pipeline,
* the workaround on any older hardware.
*/
if (GFX_VER >= 9 && !wm_prog_data->persample_dispatch &&
multisample && multisample->rasterizationSamples == 16) {
ms != NULL && ms->rasterization_samples == 16) {
assert(ps._8PixelDispatchEnable || ps._16PixelDispatchEnable);
ps._32PixelDispatchEnable = false;
}
@ -2286,8 +2090,8 @@ emit_3dstate_ps(struct anv_graphics_pipeline *pipeline,
#if GFX_VER >= 8
static void
emit_3dstate_ps_extra(struct anv_graphics_pipeline *pipeline,
const VkPipelineRasterizationStateCreateInfo *rs_info,
const VkRenderingSelfDependencyInfoMESA *rsd_info)
const struct vk_rasterization_state *rs,
const struct vk_render_pass_state *rp)
{
const struct brw_wm_prog_data *wm_prog_data = get_wm_prog_data(pipeline);
@ -2311,8 +2115,8 @@ emit_3dstate_ps_extra(struct anv_graphics_pipeline *pipeline,
* around to fetching from the input attachment and we may get the depth
* or stencil value from the current draw rather than the previous one.
*/
ps.PixelShaderKillsPixel = rsd_info->depthSelfDependency ||
rsd_info->stencilSelfDependency ||
ps.PixelShaderKillsPixel = rp->depth_self_dependency ||
rp->stencil_self_dependency ||
wm_prog_data->uses_kill;
#if GFX_VER >= 9
@ -2358,8 +2162,8 @@ emit_3dstate_vf_statistics(struct anv_graphics_pipeline *pipeline)
static void
compute_kill_pixel(struct anv_graphics_pipeline *pipeline,
const VkPipelineMultisampleStateCreateInfo *ms_info,
const VkRenderingSelfDependencyInfoMESA *rsd_info)
const struct vk_multisample_state *ms,
const struct vk_render_pass_state *rp)
{
if (!anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT)) {
pipeline->kill_pixel = false;
@ -2383,25 +2187,24 @@ compute_kill_pixel(struct anv_graphics_pipeline *pipeline,
* of an alpha test.
*/
pipeline->kill_pixel =
rsd_info->depthSelfDependency ||
rsd_info->stencilSelfDependency ||
rp->depth_self_dependency ||
rp->stencil_self_dependency ||
wm_prog_data->uses_kill ||
wm_prog_data->uses_omask ||
(ms_info && ms_info->alphaToCoverageEnable);
(ms && ms->alpha_to_coverage_enable);
}
#if GFX_VER == 12
static void
emit_3dstate_primitive_replication(struct anv_graphics_pipeline *pipeline,
const VkPipelineRenderingCreateInfo *rendering_info)
const struct vk_render_pass_state *rp)
{
if (!pipeline->use_primitive_replication) {
anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_PRIMITIVE_REPLICATION), pr);
return;
}
uint32_t view_mask = rendering_info != NULL ? rendering_info->viewMask : 0;
int view_count = util_bitcount(view_mask);
int view_count = util_bitcount(rp->view_mask);
assert(view_count > 1 && view_count <= MAX_VIEWS_FOR_PRIMITIVE_REPLICATION);
anv_batch_emit(&pipeline->base.batch, GENX(3DSTATE_PRIMITIVE_REPLICATION), pr) {
@ -2409,7 +2212,7 @@ emit_3dstate_primitive_replication(struct anv_graphics_pipeline *pipeline,
pr.ReplicationCount = view_count - 1;
int i = 0;
u_foreach_bit(view_index, view_mask) {
u_foreach_bit(view_index, rp->view_mask) {
pr.RTAIOffset[i] = view_index;
i++;
}
@ -2549,53 +2352,23 @@ emit_mesh_state(struct anv_graphics_pipeline *pipeline)
void
genX(graphics_pipeline_emit)(struct anv_graphics_pipeline *pipeline,
const VkGraphicsPipelineCreateInfo *pCreateInfo,
const VkPipelineRenderingCreateInfo *rendering_info,
const VkRenderingSelfDependencyInfoMESA *rsd_info)
const struct vk_graphics_pipeline_state *state)
{
/* If rasterization is not enabled, various CreateInfo structs must be
* ignored.
*/
const bool raster_enabled =
!pCreateInfo->pRasterizationState->rasterizerDiscardEnable ||
(pipeline->dynamic_states & ANV_CMD_DIRTY_DYNAMIC_RASTERIZER_DISCARD_ENABLE);
const VkPipelineViewportStateCreateInfo *vp_info =
raster_enabled ? pCreateInfo->pViewportState : NULL;
const VkPipelineMultisampleStateCreateInfo *ms_info =
raster_enabled ? pCreateInfo->pMultisampleState : NULL;
const VkPipelineDepthStencilStateCreateInfo *ds_info =
raster_enabled ? pCreateInfo->pDepthStencilState : NULL;
const VkPipelineColorBlendStateCreateInfo *cb_info =
raster_enabled ? pCreateInfo->pColorBlendState : NULL;
const VkPipelineRasterizationLineStateCreateInfoEXT *line_info =
vk_find_struct_const(pCreateInfo->pRasterizationState->pNext,
PIPELINE_RASTERIZATION_LINE_STATE_CREATE_INFO_EXT);
enum intel_urb_deref_block_size urb_deref_block_size;
emit_urb_setup(pipeline, &urb_deref_block_size);
assert(pCreateInfo->pRasterizationState);
emit_rs_state(pipeline, pCreateInfo->pInputAssemblyState,
pCreateInfo->pRasterizationState,
ms_info, line_info, rendering_info,
assert(state->rs != NULL);
emit_rs_state(pipeline, state->ia, state->rs, state->ms, state->rp,
urb_deref_block_size);
emit_ms_state(pipeline, ms_info);
emit_ds_state(pipeline, ds_info, rendering_info);
emit_cb_state(pipeline, cb_info, ms_info);
compute_kill_pixel(pipeline, ms_info, rsd_info);
emit_ms_state(pipeline, state->ms);
emit_ds_state(pipeline, state->ds, state->rp);
emit_cb_state(pipeline, state->cb, state->ms);
compute_kill_pixel(pipeline, state->ms, state->rp);
emit_3dstate_clip(pipeline,
pCreateInfo->pInputAssemblyState,
vp_info,
pCreateInfo->pRasterizationState);
emit_3dstate_clip(pipeline, state->ia, state->vp, state->rs);
#if GFX_VER == 12
emit_3dstate_primitive_replication(pipeline, rendering_info);
emit_3dstate_primitive_replication(pipeline, state->rp);
#endif
#if 0
@ -2618,16 +2391,15 @@ genX(graphics_pipeline_emit)(struct anv_graphics_pipeline *pipeline,
#endif
if (anv_pipeline_is_primitive(pipeline)) {
assert(pCreateInfo->pVertexInputState);
emit_vertex_input(pipeline, pCreateInfo->pVertexInputState);
emit_vertex_input(pipeline, state->vi);
emit_3dstate_vs(pipeline);
emit_3dstate_hs_te_ds(pipeline, pCreateInfo->pTessellationState);
emit_3dstate_hs_te_ds(pipeline, state->ts);
emit_3dstate_gs(pipeline);
emit_3dstate_vf_statistics(pipeline);
emit_3dstate_streamout(pipeline, pCreateInfo->pRasterizationState);
emit_3dstate_streamout(pipeline, state->rs);
#if GFX_VERx10 >= 125
const struct anv_device *device = pipeline->base.device;
@ -2652,13 +2424,11 @@ genX(graphics_pipeline_emit)(struct anv_graphics_pipeline *pipeline,
}
emit_3dstate_sbe(pipeline);
emit_3dstate_wm(pipeline,
pCreateInfo->pInputAssemblyState,
pCreateInfo->pRasterizationState,
cb_info, ms_info, line_info, rsd_info);
emit_3dstate_ps(pipeline, cb_info, ms_info);
emit_3dstate_wm(pipeline, state->ia, state->rs,
state->ms, state->cb, state->rp);
emit_3dstate_ps(pipeline, state->ms, state->cb);
#if GFX_VER >= 8
emit_3dstate_ps_extra(pipeline, pCreateInfo->pRasterizationState, rsd_info);
emit_3dstate_ps_extra(pipeline, state->rs, state->rp);
#endif
}