vk/graphics_state, tu: Rewrite renderpass flags handling

Before this, the render pass code or the driver combined the pipeline
create flags and the implicit flags from the render pass, but the
pipeline create flags will need to be sanitized when they are dynamic
state, so we need to do it in vk_graphics_state where we know that
information.

We also weren't combining pipeline flags correctly when linking, which
on turnip was being hidden by the lack of sanitizing for driver-provided
flags. We can't combine them correctly if they're part of the render
pass state, so they need to be pulled out into the overall pipeline
state.

For drivers using emulated renderpasses or tracking feedback loop
information themselves, this won't make a difference, but we have to
adapt turnip to not pass pipeline flags. This also means that we can
drop all handling of feedback_loop_input_only in turnip and just set it
in the runtime.

Reviewed-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25436>
This commit is contained in:
Connor Abbott
2023-05-24 19:33:38 +02:00
committed by Marge Bot
parent 2b62d90158
commit 55f3f952aa
12 changed files with 112 additions and 81 deletions
+44 -9
View File
@@ -5,6 +5,7 @@
#include "vk_common_entrypoints.h"
#include "vk_device.h"
#include "vk_log.h"
#include "vk_pipeline.h"
#include "vk_render_pass.h"
#include "vk_standard_sample_locations.h"
#include "vk_util.h"
@@ -1032,11 +1033,11 @@ vk_render_pass_state_is_complete(const struct vk_render_pass_state *rp)
}
static void
vk_render_pass_state_init(struct vk_render_pass_state *rp,
const struct vk_render_pass_state *old_rp,
const struct vk_render_pass_state *driver_rp,
const VkGraphicsPipelineCreateInfo *info,
VkGraphicsPipelineLibraryFlagsEXT lib)
vk_pipeline_flags_init(struct vk_graphics_pipeline_state *state,
VkPipelineCreateFlags2KHR driver_rp_flags,
bool has_driver_rp,
const VkGraphicsPipelineCreateInfo *info,
VkGraphicsPipelineLibraryFlagsEXT lib)
{
VkPipelineCreateFlags2KHR valid_pipeline_flags = 0;
if (lib & VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT) {
@@ -1049,22 +1050,43 @@ vk_render_pass_state_init(struct vk_render_pass_state *rp,
VK_PIPELINE_CREATE_2_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT |
VK_PIPELINE_CREATE_2_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT;
}
const VkPipelineCreateFlags2KHR pipeline_flags =
(driver_rp ? driver_rp->pipeline_flags :
const VkPipelineCreateFlags2KHR renderpass_flags =
(has_driver_rp ? driver_rp_flags :
vk_get_pipeline_rendering_flags(info)) & valid_pipeline_flags;
const VkPipelineCreateFlags2KHR pipeline_flags =
vk_graphics_pipeline_create_flags(info) & valid_pipeline_flags;
bool pipeline_feedback_loop = pipeline_flags &
(VK_PIPELINE_CREATE_2_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT |
VK_PIPELINE_CREATE_2_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT);
bool renderpass_feedback_loop = renderpass_flags &
(VK_PIPELINE_CREATE_2_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT |
VK_PIPELINE_CREATE_2_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT);
state->pipeline_flags |= renderpass_flags | pipeline_flags;
state->feedback_loop_not_input_only |=
pipeline_feedback_loop || (!has_driver_rp && renderpass_feedback_loop);
}
static void
vk_render_pass_state_init(struct vk_render_pass_state *rp,
const struct vk_render_pass_state *old_rp,
const struct vk_render_pass_state *driver_rp,
const VkGraphicsPipelineCreateInfo *info,
VkGraphicsPipelineLibraryFlagsEXT lib)
{
/* If we already have render pass state and it has attachment info, then
* it's complete and we don't need a new one. The one caveat here is that
* we may need to add in some rendering flags.
*/
if (old_rp != NULL && vk_render_pass_state_is_complete(old_rp)) {
*rp = *old_rp;
rp->pipeline_flags |= pipeline_flags;
return;
}
*rp = (struct vk_render_pass_state) {
.pipeline_flags = pipeline_flags,
.depth_attachment_format = VK_FORMAT_UNDEFINED,
.stencil_attachment_format = VK_FORMAT_UNDEFINED,
};
@@ -1228,6 +1250,7 @@ vk_graphics_pipeline_state_fill(const struct vk_device *device,
struct vk_graphics_pipeline_state *state,
const VkGraphicsPipelineCreateInfo *info,
const struct vk_render_pass_state *driver_rp,
VkPipelineCreateFlags2KHR driver_rp_flags,
struct vk_graphics_pipeline_all_state *all,
const VkAllocationCallbacks *alloc,
VkSystemAllocationScope scope,
@@ -1360,6 +1383,11 @@ vk_graphics_pipeline_state_fill(const struct vk_device *device,
state->rp = NULL;
}
if (lib & (VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_SHADER_BIT_EXT |
VK_GRAPHICS_PIPELINE_LIBRARY_FRAGMENT_OUTPUT_INTERFACE_BIT_EXT)) {
vk_pipeline_flags_init(state, driver_rp_flags, !!driver_rp, info, lib);
}
if (lib & VK_GRAPHICS_PIPELINE_LIBRARY_PRE_RASTERIZATION_SHADERS_BIT_EXT) {
/* From the Vulkan 1.3.218 spec:
*
@@ -1599,6 +1627,9 @@ vk_graphics_pipeline_state_merge(struct vk_graphics_pipeline_state *dst,
dst->shader_stages |= src->shader_stages;
dst->pipeline_flags |= src->pipeline_flags;
dst->feedback_loop_not_input_only |= src->feedback_loop_not_input_only;
/* Render pass state needs special care because a render pass state may be
* incomplete (view mask only). See vk_render_pass_state_init().
*/
@@ -1690,6 +1721,10 @@ vk_graphics_pipeline_state_copy(const struct vk_device *device,
#undef COPY_STATE_IF_NEEDED
state->pipeline_flags = old_state->pipeline_flags;
state->feedback_loop_not_input_only =
old_state->feedback_loop_not_input_only;
vk_graphics_pipeline_state_validate(state);
return VK_SUCCESS;
}
+23 -11
View File
@@ -675,16 +675,6 @@ struct vk_render_pass_state {
/** VkPipelineRenderingCreateInfo::viewMask */
uint32_t view_mask;
/** Render pass flags from VkGraphicsPipelineCreateInfo::flags
*
* For drivers which use vk_render_pass, this will also include flags
* generated based on subpass self-dependencies and fragment density map.
*/
VkPipelineCreateFlags2KHR pipeline_flags;
/* True if any feedback loops only involve input attachments. */
bool feedback_loop_input_only;
/** VkPipelineRenderingCreateInfo::colorAttachmentCount */
uint8_t color_attachment_count;
@@ -858,6 +848,23 @@ struct vk_graphics_pipeline_state {
VkShaderStageFlags shader_stages;
/** Flags from VkGraphicsPipelineCreateInfo::flags that are considered part
* of a stage and need to be merged when linking libraries.
*
* For drivers which use vk_render_pass, this will also include flags
* generated based on subpass self-dependencies and fragment density map.
*/
VkPipelineCreateFlags2KHR pipeline_flags;
/* True if there are feedback loops that do not involve input attachments
* managed by the driver. This is set to true by the runtime if there
* are loops indicated by a pipeline flag (which may involve any image
* rather than only input attachments under the control of the driver) or
* there was no driver-provided render pass info struct (because input
* attachments for emulated renderpasses cannot be managed by the driver).
*/
bool feedback_loop_not_input_only;
/** Vertex input state */
const struct vk_vertex_input_state *vi;
@@ -922,6 +929,10 @@ struct vk_graphics_pipeline_state {
* passes itself. This should be NULL for drivers
* that use the common render pass infrastructure
* built on top of dynamic rendering.
* :param driver_rp_flags: |in| Pipeline create flags implied by the
* renderpass or subpass if the driver implements
* render passes itself. This is only used if
* driver_rp is non-NULL.
* :param all: |in| The vk_graphics_pipeline_all_state to use to
* back any newly needed states. If NULL, newly
* needed states will be dynamically allocated
@@ -938,7 +949,8 @@ VkResult
vk_graphics_pipeline_state_fill(const struct vk_device *device,
struct vk_graphics_pipeline_state *state,
const VkGraphicsPipelineCreateInfo *info,
const struct vk_render_pass_state *rp_info,
const struct vk_render_pass_state *driver_rp,
VkPipelineCreateFlags2KHR driver_rp_flags,
struct vk_graphics_pipeline_all_state *all,
const VkAllocationCallbacks *alloc,
VkSystemAllocationScope scope,
+1 -7
View File
@@ -30,7 +30,6 @@
#include "vk_format.h"
#include "vk_framebuffer.h"
#include "vk_image.h"
#include "vk_pipeline.h"
#include "vk_util.h"
#include "util/log.h"
@@ -842,12 +841,7 @@ vk_get_pipeline_rendering_create_info(const VkGraphicsPipelineCreateInfo *info)
VkPipelineCreateFlags2KHR
vk_get_pipeline_rendering_flags(const VkGraphicsPipelineCreateInfo *info)
{
VkPipelineCreateFlags2KHR rendering_flags =
vk_graphics_pipeline_create_flags(info) &
(VK_PIPELINE_CREATE_2_COLOR_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT |
VK_PIPELINE_CREATE_2_DEPTH_STENCIL_ATTACHMENT_FEEDBACK_LOOP_BIT_EXT |
VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_SHADING_RATE_ATTACHMENT_BIT_KHR |
VK_PIPELINE_CREATE_2_RENDERING_FRAGMENT_DENSITY_MAP_ATTACHMENT_BIT_EXT);
VkPipelineCreateFlags2KHR rendering_flags = 0;
VK_FROM_HANDLE(vk_render_pass, render_pass, info->renderPass);
if (render_pass != NULL) {