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:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user