anv: implement VK_KHR_dynamic_rendering_local_read

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Reviewed-by: Ivan Briano <ivan.briano@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27270>
This commit is contained in:
Lionel Landwerlin
2024-09-20 14:29:03 +03:00
committed by Marge Bot
parent 15987f49bb
commit d2f7b6d5a7
7 changed files with 143 additions and 88 deletions

View File

@@ -2113,7 +2113,8 @@ anv_image_view_surface_data_for_plane_layout(struct anv_image_view *image_view,
if (desc_type == VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER ||
desc_type == VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE ||
desc_type == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT) {
return layout == VK_IMAGE_LAYOUT_GENERAL ?
return (layout == VK_IMAGE_LAYOUT_GENERAL ||
layout == VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR) ?
&image_view->planes[plane].general_sampler.state_data :
&image_view->planes[plane].optimal_sampler.state_data;
}

View File

@@ -85,6 +85,7 @@ get_device_extensions(const struct anv_physical_device *device,
.KHR_draw_indirect_count = true,
.KHR_driver_properties = true,
.KHR_dynamic_rendering = true,
.KHR_dynamic_rendering_local_read = true,
.KHR_external_fence = has_syncobj_wait,
.KHR_external_fence_fd = has_syncobj_wait,
.KHR_external_memory = true,
@@ -809,6 +810,9 @@ get_features(const struct anv_physical_device *pdevice,
/* VK_KHR_shader_relaxed_extended_instruction */
.shaderRelaxedExtendedInstruction = true,
/* VK_KHR_dynamic_rendering_local_read */
.dynamicRenderingLocalRead = true,
};
/* The new DOOM and Wolfenstein games require depthBounds without

View File

@@ -2969,6 +2969,36 @@ anv_graphics_pipeline_emit(struct anv_graphics_pipeline *pipeline,
pipeline->min_sample_shading = state->ms->min_sample_shading;
}
if (anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT)) {
/* Count the number of color attachments in the binding table */
const struct anv_pipeline_bind_map *bind_map =
&pipeline->base.shaders[MESA_SHADER_FRAGMENT]->bind_map;
memset(pipeline->color_output_mapping,
MESA_VK_ATTACHMENT_UNUSED,
sizeof(pipeline->color_output_mapping));
if (state->cal != NULL) {
for (uint32_t i = 0; i < MAX_RTS; i++) {
if (state->cal->color_map[i] != MESA_VK_ATTACHMENT_UNUSED)
pipeline->color_output_mapping[state->cal->color_map[i]] = i;
}
unsigned i;
for (i = 0; i < MIN2(bind_map->surface_count, MAX_RTS); i++) {
if (bind_map->surface_to_descriptor[i].set !=
ANV_DESCRIPTOR_SET_COLOR_ATTACHMENTS)
break;
/* Helping Alpine builders... */
assert(i < MAX_RTS);
if (bind_map->surface_to_descriptor[i].index >= MAX_RTS)
pipeline->color_output_mapping[i] = MESA_VK_ATTACHMENT_UNUSED;
}
pipeline->num_color_outputs = i;
}
}
const struct anv_device *device = pipeline->base.base.device;
const struct intel_device_info *devinfo = device->info;
anv_genX(devinfo, graphics_pipeline_emit)(pipeline, state);

View File

@@ -3822,11 +3822,10 @@ struct anv_cmd_graphics_state {
struct anv_attachment stencil_att;
struct anv_state null_surface_state;
/* Bitfield of color attachments disabled by a pipeline (pointing a null
* surface state in the last emitted binding table for the fragment
* stage)
/* Map of color output from the last dispatched fragment shader to color
* attachments in the render pass.
*/
uint8_t disabled_color_atts;
uint8_t color_output_mapping[MAX_RTS];
anv_cmd_dirty_mask_t dirty;
uint32_t vb_dirty;
@@ -4781,6 +4780,13 @@ struct anv_graphics_pipeline {
uint32_t vertex_input_elems;
uint32_t vertex_input_data[2 * 31 /* MAX_VES + 2 internal */];
/* Number of color outputs used by the fragment shader. */
uint8_t num_color_outputs;
/* Map of color output of the fragment shader to color attachments in the
* render pass.
*/
uint8_t color_output_mapping[MAX_RTS];
/* Pre computed CS instructions that can directly be copied into
* anv_cmd_buffer.
*/
@@ -5901,7 +5907,8 @@ static inline const struct anv_surface_state *
anv_image_view_texture_surface_state(const struct anv_image_view *iview,
uint32_t plane, VkImageLayout layout)
{
return layout == VK_IMAGE_LAYOUT_GENERAL ?
return (layout == VK_IMAGE_LAYOUT_GENERAL ||
layout == VK_IMAGE_LAYOUT_RENDERING_LOCAL_READ_KHR) ?
&iview->planes[plane].general_sampler :
&iview->planes[plane].optimal_sampler;
}

View File

@@ -2098,9 +2098,12 @@ emit_binding_table(struct anv_cmd_buffer *cmd_buffer,
case ANV_DESCRIPTOR_SET_COLOR_ATTACHMENTS:
/* Color attachment binding */
assert(shader->stage == MESA_SHADER_FRAGMENT);
if (binding->index < cmd_buffer->state.gfx.color_att_count) {
uint32_t index = binding->index < MAX_RTS ?
cmd_buffer->state.gfx.color_output_mapping[binding->index] :
binding->index;
if (index < cmd_buffer->state.gfx.color_att_count) {
const struct anv_attachment *att =
&cmd_buffer->state.gfx.color_att[binding->index];
&cmd_buffer->state.gfx.color_att[index];
surface_state = att->surface_state.state;
} else {
surface_state = cmd_buffer->state.gfx.null_surface_state;

View File

@@ -689,35 +689,24 @@ genX(emit_ds)(struct anv_cmd_buffer *cmd_buffer)
ALWAYS_INLINE static void
cmd_buffer_maybe_flush_rt_writes(struct anv_cmd_buffer *cmd_buffer,
struct anv_graphics_pipeline *pipeline)
const struct anv_graphics_pipeline *pipeline)
{
#if GFX_VER >= 11
if (!anv_pipeline_has_stage(pipeline, MESA_SHADER_FRAGMENT))
return;
const struct anv_shader_bin *shader =
pipeline->base.shaders[MESA_SHADER_FRAGMENT];
const struct anv_pipeline_bind_map *bind_map = &shader->bind_map;
unsigned s;
uint8_t disabled_mask = 0;
for (s = 0; s < bind_map->surface_count; s++) {
const struct anv_pipeline_binding *binding =
&bind_map->surface_to_descriptor[s];
if (binding->set != ANV_DESCRIPTOR_SET_COLOR_ATTACHMENTS)
break;
if (binding->index >= cmd_buffer->state.gfx.color_att_count)
disabled_mask |= BITFIELD_BIT(s);
UNUSED bool need_rt_flush = false;
if (memcmp(cmd_buffer->state.gfx.color_output_mapping,
pipeline->color_output_mapping,
pipeline->num_color_outputs)) {
memcpy(cmd_buffer->state.gfx.color_output_mapping,
pipeline->color_output_mapping,
pipeline->num_color_outputs);
need_rt_flush = true;
cmd_buffer->state.descriptors_dirty |= VK_SHADER_STAGE_FRAGMENT_BIT;
}
const uint8_t diff_mask = (1u << s) - 1;
if ((cmd_buffer->state.gfx.disabled_color_atts & diff_mask) != disabled_mask) {
cmd_buffer->state.gfx.disabled_color_atts = disabled_mask |
(cmd_buffer->state.gfx.disabled_color_atts & ~diff_mask);
#if GFX_VER >= 11
if (need_rt_flush) {
/* The PIPE_CONTROL command description says:
*
* "Whenever a Binding Table Index (BTI) used by a Render Target Message

View File

@@ -132,8 +132,10 @@ get_cps_state_offset(struct anv_cmd_buffer *cmd_buffer, bool cps_enabled,
static bool
has_ds_feedback_loop(const struct vk_dynamic_graphics_state *dyn)
{
return dyn->feedback_loops & (VK_IMAGE_ASPECT_DEPTH_BIT |
VK_IMAGE_ASPECT_STENCIL_BIT);
return (dyn->feedback_loops & (VK_IMAGE_ASPECT_DEPTH_BIT |
VK_IMAGE_ASPECT_STENCIL_BIT)) ||
dyn->ial.depth_att != MESA_VK_ATTACHMENT_UNUSED ||
dyn->ial.stencil_att != MESA_VK_ATTACHMENT_UNUSED;
}
UNUSED static bool
@@ -1081,32 +1083,41 @@ genX(cmd_buffer_flush_gfx_runtime_state)(struct anv_cmd_buffer *cmd_buffer)
SET(BLEND_STATE, blend.AlphaToOneEnable,
dyn->ms.alpha_to_one_enable);
SET(BLEND_STATE, blend.ColorDitherEnable,
cmd_buffer->state.gfx.rendering_flags & VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT);
cmd_buffer->state.gfx.rendering_flags &
VK_RENDERING_ENABLE_LEGACY_DITHERING_BIT_EXT);
bool independent_alpha_blend = false;
/* Wa_14018912822, check if we set these during RT setup. */
bool color_blend_zero = false;
bool alpha_blend_zero = false;
for (uint32_t i = 0; i < MAX_RTS; i++) {
/* Disable anything above the current number of color attachments. */
bool write_disabled = i >= gfx->color_att_count ||
(color_writes & BITFIELD_BIT(i)) == 0;
uint32_t rt_0 = MESA_VK_ATTACHMENT_UNUSED;
for (uint32_t rt = 0; rt < MAX_RTS; rt++) {
if (cmd_buffer->state.gfx.color_output_mapping[rt] >=
cmd_buffer->state.gfx.color_att_count)
continue;
SET(BLEND_STATE, blend.rts[i].WriteDisableAlpha,
uint32_t att = cmd_buffer->state.gfx.color_output_mapping[rt];
if (att == 0)
rt_0 = att;
/* Disable anything above the current number of color attachments. */
bool write_disabled = (color_writes & BITFIELD_BIT(att)) == 0;
SET(BLEND_STATE, blend.rts[rt].WriteDisableAlpha,
write_disabled ||
(dyn->cb.attachments[i].write_mask &
(dyn->cb.attachments[att].write_mask &
VK_COLOR_COMPONENT_A_BIT) == 0);
SET(BLEND_STATE, blend.rts[i].WriteDisableRed,
SET(BLEND_STATE, blend.rts[rt].WriteDisableRed,
write_disabled ||
(dyn->cb.attachments[i].write_mask &
(dyn->cb.attachments[att].write_mask &
VK_COLOR_COMPONENT_R_BIT) == 0);
SET(BLEND_STATE, blend.rts[i].WriteDisableGreen,
SET(BLEND_STATE, blend.rts[rt].WriteDisableGreen,
write_disabled ||
(dyn->cb.attachments[i].write_mask &
(dyn->cb.attachments[att].write_mask &
VK_COLOR_COMPONENT_G_BIT) == 0);
SET(BLEND_STATE, blend.rts[i].WriteDisableBlue,
SET(BLEND_STATE, blend.rts[rt].WriteDisableBlue,
write_disabled ||
(dyn->cb.attachments[i].write_mask &
(dyn->cb.attachments[att].write_mask &
VK_COLOR_COMPONENT_B_BIT) == 0);
/* Vulkan specification 1.2.168, VkLogicOp:
*
@@ -1123,28 +1134,28 @@ genX(cmd_buffer_flush_gfx_runtime_state)(struct anv_cmd_buffer *cmd_buffer)
* "Enabling LogicOp and Color Buffer Blending at the same time is
* UNDEFINED"
*/
SET(BLEND_STATE, blend.rts[i].LogicOpFunction,
SET(BLEND_STATE, blend.rts[rt].LogicOpFunction,
genX(vk_to_intel_logic_op)[dyn->cb.logic_op]);
SET(BLEND_STATE, blend.rts[i].LogicOpEnable, dyn->cb.logic_op_enable);
SET(BLEND_STATE, blend.rts[rt].LogicOpEnable, dyn->cb.logic_op_enable);
SET(BLEND_STATE, blend.rts[i].ColorClampRange, COLORCLAMP_RTFORMAT);
SET(BLEND_STATE, blend.rts[i].PreBlendColorClampEnable, true);
SET(BLEND_STATE, blend.rts[i].PostBlendColorClampEnable, true);
SET(BLEND_STATE, blend.rts[rt].ColorClampRange, COLORCLAMP_RTFORMAT);
SET(BLEND_STATE, blend.rts[rt].PreBlendColorClampEnable, true);
SET(BLEND_STATE, blend.rts[rt].PostBlendColorClampEnable, true);
/* Setup blend equation. */
SET(BLEND_STATE, blend.rts[i].ColorBlendFunction,
SET(BLEND_STATE, blend.rts[rt].ColorBlendFunction,
genX(vk_to_intel_blend_op)[
dyn->cb.attachments[i].color_blend_op]);
SET(BLEND_STATE, blend.rts[i].AlphaBlendFunction,
dyn->cb.attachments[att].color_blend_op]);
SET(BLEND_STATE, blend.rts[rt].AlphaBlendFunction,
genX(vk_to_intel_blend_op)[
dyn->cb.attachments[i].alpha_blend_op]);
dyn->cb.attachments[att].alpha_blend_op]);
if (dyn->cb.attachments[i].src_color_blend_factor !=
dyn->cb.attachments[i].src_alpha_blend_factor ||
dyn->cb.attachments[i].dst_color_blend_factor !=
dyn->cb.attachments[i].dst_alpha_blend_factor ||
dyn->cb.attachments[i].color_blend_op !=
dyn->cb.attachments[i].alpha_blend_op) {
if (dyn->cb.attachments[att].src_color_blend_factor !=
dyn->cb.attachments[att].src_alpha_blend_factor ||
dyn->cb.attachments[att].dst_color_blend_factor !=
dyn->cb.attachments[att].dst_alpha_blend_factor ||
dyn->cb.attachments[att].color_blend_op !=
dyn->cb.attachments[att].alpha_blend_op) {
independent_alpha_blend = true;
}
@@ -1160,12 +1171,12 @@ genX(cmd_buffer_flush_gfx_runtime_state)(struct anv_cmd_buffer *cmd_buffer)
* so we just disable the blending to prevent possible issues.
*/
if (wm_prog_data && !wm_prog_data->dual_src_blend &&
anv_is_dual_src_blend_equation(&dyn->cb.attachments[i])) {
SET(BLEND_STATE, blend.rts[i].ColorBufferBlendEnable, false);
anv_is_dual_src_blend_equation(&dyn->cb.attachments[att])) {
SET(BLEND_STATE, blend.rts[rt].ColorBufferBlendEnable, false);
} else {
SET(BLEND_STATE, blend.rts[i].ColorBufferBlendEnable,
SET(BLEND_STATE, blend.rts[rt].ColorBufferBlendEnable,
!dyn->cb.logic_op_enable &&
dyn->cb.attachments[i].blend_enable);
dyn->cb.attachments[att].blend_enable);
}
/* Our hardware applies the blend factor prior to the blend function
@@ -1178,26 +1189,26 @@ genX(cmd_buffer_flush_gfx_runtime_state)(struct anv_cmd_buffer *cmd_buffer)
uint32_t DestinationBlendFactor;
uint32_t SourceAlphaBlendFactor;
uint32_t DestinationAlphaBlendFactor;
if (dyn->cb.attachments[i].color_blend_op == VK_BLEND_OP_MIN ||
dyn->cb.attachments[i].color_blend_op == VK_BLEND_OP_MAX) {
if (dyn->cb.attachments[att].color_blend_op == VK_BLEND_OP_MIN ||
dyn->cb.attachments[att].color_blend_op == VK_BLEND_OP_MAX) {
SourceBlendFactor = BLENDFACTOR_ONE;
DestinationBlendFactor = BLENDFACTOR_ONE;
} else {
SourceBlendFactor = genX(vk_to_intel_blend)[
dyn->cb.attachments[i].src_color_blend_factor];
dyn->cb.attachments[att].src_color_blend_factor];
DestinationBlendFactor = genX(vk_to_intel_blend)[
dyn->cb.attachments[i].dst_color_blend_factor];
dyn->cb.attachments[att].dst_color_blend_factor];
}
if (dyn->cb.attachments[i].alpha_blend_op == VK_BLEND_OP_MIN ||
dyn->cb.attachments[i].alpha_blend_op == VK_BLEND_OP_MAX) {
if (dyn->cb.attachments[att].alpha_blend_op == VK_BLEND_OP_MIN ||
dyn->cb.attachments[att].alpha_blend_op == VK_BLEND_OP_MAX) {
SourceAlphaBlendFactor = BLENDFACTOR_ONE;
DestinationAlphaBlendFactor = BLENDFACTOR_ONE;
} else {
SourceAlphaBlendFactor = genX(vk_to_intel_blend)[
dyn->cb.attachments[i].src_alpha_blend_factor];
dyn->cb.attachments[att].src_alpha_blend_factor];
DestinationAlphaBlendFactor = genX(vk_to_intel_blend)[
dyn->cb.attachments[i].dst_alpha_blend_factor];
dyn->cb.attachments[att].dst_alpha_blend_factor];
}
/* Replace and Src1 value by 1.0 if dual source blending is not
@@ -1223,32 +1234,42 @@ genX(cmd_buffer_flush_gfx_runtime_state)(struct anv_cmd_buffer *cmd_buffer)
}
}
SET(BLEND_STATE, blend.rts[i].SourceBlendFactor, SourceBlendFactor);
SET(BLEND_STATE, blend.rts[i].DestinationBlendFactor, DestinationBlendFactor);
SET(BLEND_STATE, blend.rts[i].SourceAlphaBlendFactor, SourceAlphaBlendFactor);
SET(BLEND_STATE, blend.rts[i].DestinationAlphaBlendFactor, DestinationAlphaBlendFactor);
SET(BLEND_STATE, blend.rts[rt].SourceBlendFactor, SourceBlendFactor);
SET(BLEND_STATE, blend.rts[rt].DestinationBlendFactor, DestinationBlendFactor);
SET(BLEND_STATE, blend.rts[rt].SourceAlphaBlendFactor, SourceAlphaBlendFactor);
SET(BLEND_STATE, blend.rts[rt].DestinationAlphaBlendFactor, DestinationAlphaBlendFactor);
}
gfx->color_blend_zero = color_blend_zero;
gfx->alpha_blend_zero = alpha_blend_zero;
SET(BLEND_STATE, blend.IndependentAlphaBlendEnable, independent_alpha_blend);
if (rt_0 == MESA_VK_ATTACHMENT_UNUSED)
rt_0 = 0;
/* 3DSTATE_PS_BLEND to be consistent with the rest of the
* BLEND_STATE_ENTRY.
*/
SET(PS_BLEND, ps_blend.HasWriteableRT, has_writeable_rt);
SET(PS_BLEND, ps_blend.ColorBufferBlendEnable, GET(blend.rts[0].ColorBufferBlendEnable));
SET(PS_BLEND, ps_blend.SourceAlphaBlendFactor, GET(blend.rts[0].SourceAlphaBlendFactor));
SET(PS_BLEND, ps_blend.DestinationAlphaBlendFactor, gfx->alpha_blend_zero ?
BLENDFACTOR_CONST_ALPHA :
GET(blend.rts[0].DestinationAlphaBlendFactor));
SET(PS_BLEND, ps_blend.SourceBlendFactor, GET(blend.rts[0].SourceBlendFactor));
SET(PS_BLEND, ps_blend.DestinationBlendFactor, gfx->color_blend_zero ?
BLENDFACTOR_CONST_COLOR :
GET(blend.rts[0].DestinationBlendFactor));
SET(PS_BLEND, ps_blend.ColorBufferBlendEnable,
GET(blend.rts[rt_0].ColorBufferBlendEnable));
SET(PS_BLEND, ps_blend.SourceAlphaBlendFactor,
GET(blend.rts[rt_0].SourceAlphaBlendFactor));
SET(PS_BLEND, ps_blend.DestinationAlphaBlendFactor,
gfx->alpha_blend_zero ?
BLENDFACTOR_CONST_ALPHA :
GET(blend.rts[rt_0].DestinationAlphaBlendFactor));
SET(PS_BLEND, ps_blend.SourceBlendFactor,
GET(blend.rts[rt_0].SourceBlendFactor));
SET(PS_BLEND, ps_blend.DestinationBlendFactor,
gfx->color_blend_zero ?
BLENDFACTOR_CONST_COLOR :
GET(blend.rts[rt_0].DestinationBlendFactor));
SET(PS_BLEND, ps_blend.AlphaTestEnable, false);
SET(PS_BLEND, ps_blend.IndependentAlphaBlendEnable, GET(blend.IndependentAlphaBlendEnable));
SET(PS_BLEND, ps_blend.AlphaToCoverageEnable, dyn->ms.alpha_to_coverage_enable);
SET(PS_BLEND, ps_blend.IndependentAlphaBlendEnable,
GET(blend.IndependentAlphaBlendEnable));
SET(PS_BLEND, ps_blend.AlphaToCoverageEnable,
dyn->ms.alpha_to_coverage_enable);
}
if (BITSET_TEST(dyn->dirty, MESA_VK_DYNAMIC_CB_BLEND_CONSTANTS)) {