diff --git a/src/intel/vulkan/anv_descriptor_set.c b/src/intel/vulkan/anv_descriptor_set.c index fda64485af0..6dd7e5740e2 100644 --- a/src/intel/vulkan/anv_descriptor_set.c +++ b/src/intel/vulkan/anv_descriptor_set.c @@ -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; } diff --git a/src/intel/vulkan/anv_physical_device.c b/src/intel/vulkan/anv_physical_device.c index f49e6c178d1..63f32088de7 100644 --- a/src/intel/vulkan/anv_physical_device.c +++ b/src/intel/vulkan/anv_physical_device.c @@ -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 diff --git a/src/intel/vulkan/anv_pipeline.c b/src/intel/vulkan/anv_pipeline.c index c0c3f30a79b..f1e5875f9a6 100644 --- a/src/intel/vulkan/anv_pipeline.c +++ b/src/intel/vulkan/anv_pipeline.c @@ -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); diff --git a/src/intel/vulkan/anv_private.h b/src/intel/vulkan/anv_private.h index 6771eadd8f1..e7d4f1688a5 100644 --- a/src/intel/vulkan/anv_private.h +++ b/src/intel/vulkan/anv_private.h @@ -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; } diff --git a/src/intel/vulkan/genX_cmd_buffer.c b/src/intel/vulkan/genX_cmd_buffer.c index d4f12a7d4cb..df1a7f3face 100644 --- a/src/intel/vulkan/genX_cmd_buffer.c +++ b/src/intel/vulkan/genX_cmd_buffer.c @@ -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; diff --git a/src/intel/vulkan/genX_cmd_draw.c b/src/intel/vulkan/genX_cmd_draw.c index a7ac8592bcf..fbbac454b22 100644 --- a/src/intel/vulkan/genX_cmd_draw.c +++ b/src/intel/vulkan/genX_cmd_draw.c @@ -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 diff --git a/src/intel/vulkan/genX_gfx_state.c b/src/intel/vulkan/genX_gfx_state.c index fe55942b7b1..fffe2f6916c 100644 --- a/src/intel/vulkan/genX_gfx_state.c +++ b/src/intel/vulkan/genX_gfx_state.c @@ -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)) {