mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-27 14:10:25 +01:00
zink: hook up global GENERAL image layouts
on some hardware/drivers, image layouts other than WSI are discarded, which means a bunch of layout-specific synchronization can be omitted Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35259>
This commit is contained in:
parent
35ee74181e
commit
622612f67e
7 changed files with 188 additions and 90 deletions
|
|
@ -566,14 +566,14 @@ zink_blit_barriers(struct zink_context *ctx, struct zink_resource *src, struct z
|
|||
pipeline = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
|
||||
}
|
||||
if (src == dst) {
|
||||
VkImageLayout layout = zink_screen(ctx->base.screen)->info.have_EXT_attachment_feedback_loop_layout ?
|
||||
VkImageLayout layout = !screen->driver_workarounds.general_layout && screen->info.have_EXT_attachment_feedback_loop_layout ?
|
||||
VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT :
|
||||
VK_IMAGE_LAYOUT_GENERAL;
|
||||
screen->image_barrier(ctx, src, layout, VK_ACCESS_SHADER_READ_BIT | flags, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | pipeline);
|
||||
} else {
|
||||
if (src) {
|
||||
VkImageLayout layout = util_format_is_depth_or_stencil(src->base.b.format) &&
|
||||
src->obj->vkusage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ?
|
||||
VkImageLayout layout = screen->driver_workarounds.general_layout ? VK_IMAGE_LAYOUT_GENERAL :
|
||||
util_format_is_depth_or_stencil(src->base.b.format) && src->obj->vkusage & VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT ?
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL :
|
||||
VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
screen->image_barrier(ctx, src, layout,
|
||||
|
|
@ -581,9 +581,10 @@ zink_blit_barriers(struct zink_context *ctx, struct zink_resource *src, struct z
|
|||
if (!ctx->unordered_blitting)
|
||||
src->obj->unordered_read = false;
|
||||
}
|
||||
VkImageLayout layout = util_format_is_depth_or_stencil(dst->base.b.format) ?
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL :
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
VkImageLayout layout = screen->driver_workarounds.general_layout ? VK_IMAGE_LAYOUT_GENERAL :
|
||||
util_format_is_depth_or_stencil(dst->base.b.format) ?
|
||||
VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL :
|
||||
VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
screen->image_barrier(ctx, dst, layout, flags, pipeline);
|
||||
}
|
||||
if (!ctx->unordered_blitting)
|
||||
|
|
|
|||
|
|
@ -608,6 +608,8 @@ get_layout_for_binding(const struct zink_context *ctx, struct zink_resource *res
|
|||
{
|
||||
if (res->obj->is_buffer)
|
||||
return 0;
|
||||
if (zink_screen(ctx->base.screen)->driver_workarounds.general_layout)
|
||||
return VK_IMAGE_LAYOUT_GENERAL;
|
||||
switch (type) {
|
||||
case ZINK_DESCRIPTOR_TYPE_SAMPLER_VIEW:
|
||||
return zink_descriptor_util_image_layout_eval(ctx, res, is_compute);
|
||||
|
|
@ -1837,13 +1839,14 @@ unbind_shader_image_counts(struct zink_context *ctx, struct zink_resource *res,
|
|||
res->write_bind_count[is_compute]--;
|
||||
res->image_bind_count[is_compute]--;
|
||||
/* if this was the last image bind, the sampler bind layouts must be updated */
|
||||
if (!res->obj->is_buffer && !res->image_bind_count[is_compute] && res->bind_count[is_compute])
|
||||
if (!zink_screen(ctx->base.screen)->driver_workarounds.general_layout && !res->obj->is_buffer && !res->image_bind_count[is_compute] && res->bind_count[is_compute])
|
||||
update_binds_for_samplerviews(ctx, res, is_compute);
|
||||
}
|
||||
|
||||
ALWAYS_INLINE static bool
|
||||
check_for_layout_update(struct zink_context *ctx, struct zink_resource *res, bool is_compute)
|
||||
{
|
||||
assert(!zink_screen(ctx->base.screen)->driver_workarounds.general_layout);
|
||||
VkImageLayout layout = res->bind_count[is_compute] ? zink_descriptor_util_image_layout_eval(ctx, res, is_compute) : VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
VkImageLayout other_layout = res->bind_count[!is_compute] ? zink_descriptor_util_image_layout_eval(ctx, res, !is_compute) : VK_IMAGE_LAYOUT_UNDEFINED;
|
||||
bool ret = false;
|
||||
|
|
@ -1889,7 +1892,7 @@ unbind_shader_image(struct zink_context *ctx, gl_shader_stage stage, unsigned sl
|
|||
} else {
|
||||
unbind_descriptor_stage(res, stage);
|
||||
unbind_descriptor_reads(res, stage == MESA_SHADER_COMPUTE);
|
||||
if (!res->image_bind_count[is_compute])
|
||||
if (!zink_screen(ctx->base.screen)->driver_workarounds.general_layout && !res->image_bind_count[is_compute])
|
||||
check_for_layout_update(ctx, res, is_compute);
|
||||
zink_surface_reference(zink_screen(ctx->base.screen), &image_view->surface, NULL);
|
||||
}
|
||||
|
|
@ -1912,20 +1915,27 @@ create_image_bufferview(struct zink_context *ctx, const struct pipe_image_view *
|
|||
}
|
||||
|
||||
static void
|
||||
finalize_image_bind(struct zink_context *ctx, struct zink_resource *res, bool is_compute)
|
||||
finalize_image_bind(struct zink_context *ctx, struct zink_resource *res, bool is_compute, VkAccessFlags flags, VkPipelineStageFlags pipeline)
|
||||
{
|
||||
/* if this is the first image bind and there are sampler binds, the image's sampler layout
|
||||
* must be updated to GENERAL
|
||||
*/
|
||||
if (res->image_bind_count[is_compute] == 1 &&
|
||||
res->bind_count[is_compute] > 1)
|
||||
update_binds_for_samplerviews(ctx, res, is_compute);
|
||||
if (!check_for_layout_update(ctx, res, is_compute)) {
|
||||
/* no deferred barrier: unset unordered usage immediately */
|
||||
// TODO: figure out a way to link up layouts between unordered and main cmdbuf
|
||||
// if (zink_resource_access_is_write(res->barrier_access[is_compute]))
|
||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||
bool general_layout = screen->driver_workarounds.general_layout;
|
||||
if (general_layout) {
|
||||
/* no need to check later */
|
||||
screen->image_barrier(ctx, res, VK_IMAGE_LAYOUT_GENERAL, flags, pipeline);
|
||||
res->obj->unordered_write = false;
|
||||
res->obj->unordered_read = false;
|
||||
} else {
|
||||
/* if this is the first image bind and there are sampler binds, the image's sampler layout
|
||||
* must be updated to GENERAL
|
||||
*/
|
||||
if (res->image_bind_count[is_compute] == 1 &&
|
||||
res->bind_count[is_compute] > 1)
|
||||
update_binds_for_samplerviews(ctx, res, is_compute);
|
||||
if (!check_for_layout_update(ctx, res, is_compute)) {
|
||||
/* no deferred barrier: unset unordered usage immediately */
|
||||
res->obj->unordered_write = false;
|
||||
res->obj->unordered_read = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -2110,7 +2120,7 @@ zink_set_shader_images(struct pipe_context *pctx,
|
|||
res->gfx_barrier);
|
||||
zink_batch_resource_usage_set(ctx->bs, res,
|
||||
zink_resource_access_is_write(access), true);
|
||||
finalize_image_bind(ctx, a->import2d, is_compute);
|
||||
finalize_image_bind(ctx, a->import2d, is_compute, access, res->gfx_barrier);
|
||||
zink_batch_resource_usage_set(ctx->bs, a->import2d,
|
||||
zink_resource_access_is_write(access), false);
|
||||
if (zink_resource_access_is_write(access))
|
||||
|
|
@ -2125,7 +2135,7 @@ zink_set_shader_images(struct pipe_context *pctx,
|
|||
res->obj->unordered_write = false;
|
||||
res->obj->unordered_read = false;
|
||||
} else {
|
||||
finalize_image_bind(ctx, res, is_compute);
|
||||
finalize_image_bind(ctx, res, is_compute, access, res->gfx_barrier);
|
||||
zink_batch_resource_usage_set(ctx->bs, res,
|
||||
zink_resource_access_is_write(access), false);
|
||||
}
|
||||
|
|
@ -2189,10 +2199,11 @@ update_feedback_loop_state(struct zink_context *ctx, unsigned idx, unsigned feed
|
|||
ALWAYS_INLINE static void
|
||||
unbind_samplerview_res(struct zink_context *ctx, gl_shader_stage stage, unsigned slot, struct zink_resource *res)
|
||||
{
|
||||
bool general_layout = zink_screen(ctx->base.screen)->driver_workarounds.general_layout;
|
||||
res->sampler_bind_count[stage == MESA_SHADER_COMPUTE]--;
|
||||
if (stage != MESA_SHADER_COMPUTE && !res->sampler_bind_count[0] && res->fb_bind_count) {
|
||||
u_foreach_bit(idx, res->fb_binds) {
|
||||
if (ctx->feedback_loops & BITFIELD_BIT(idx)) {
|
||||
if (!general_layout && ctx->feedback_loops & BITFIELD_BIT(idx)) {
|
||||
ctx->dynamic_fb.attachments[idx].imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
ctx->rp_layout_changed = true;
|
||||
}
|
||||
|
|
@ -2207,7 +2218,7 @@ unbind_samplerview_res(struct zink_context *ctx, gl_shader_stage stage, unsigned
|
|||
} else {
|
||||
unbind_descriptor_stage(res, stage);
|
||||
unbind_descriptor_reads(res, stage == MESA_SHADER_COMPUTE);
|
||||
if (!res->sampler_bind_count[stage == MESA_SHADER_COMPUTE])
|
||||
if (!general_layout && !res->sampler_bind_count[stage == MESA_SHADER_COMPUTE])
|
||||
check_for_layout_update(ctx, res, stage == MESA_SHADER_COMPUTE);
|
||||
}
|
||||
assert(slot < 32);
|
||||
|
|
@ -2246,6 +2257,7 @@ zink_set_sampler_views(struct pipe_context *pctx,
|
|||
struct pipe_sampler_view **views)
|
||||
{
|
||||
struct zink_context *ctx = zink_context(pctx);
|
||||
bool general_layout = zink_screen(ctx->base.screen)->driver_workarounds.general_layout;
|
||||
const uint32_t mask = BITFIELD_RANGE(start_slot, num_views);
|
||||
uint32_t shadow_mask = ctx->di.zs_swizzle[shader_type].mask;
|
||||
ctx->di.cubes[shader_type] &= ~mask;
|
||||
|
|
@ -2317,10 +2329,16 @@ zink_set_sampler_views(struct pipe_context *pctx,
|
|||
if (b->cube_array) {
|
||||
ctx->di.cubes[shader_type] |= BITFIELD_BIT(start_slot + i);
|
||||
}
|
||||
if (!check_for_layout_update(ctx, res, shader_type == MESA_SHADER_COMPUTE) && !ctx->unordered_blitting) {
|
||||
|
||||
if (general_layout) {
|
||||
if (!ctx->blitting)
|
||||
zink_screen(ctx->base.screen)->image_barrier(ctx, res, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_SHADER_READ_BIT, res->gfx_barrier);
|
||||
if (!ctx->unordered_blitting)
|
||||
/* no deferred barrier: unset unordered usage immediately */
|
||||
res->obj->unordered_read = false;
|
||||
} else if (!check_for_layout_update(ctx, res, shader_type == MESA_SHADER_COMPUTE) && !ctx->unordered_blitting) {
|
||||
/* no deferred barrier: unset unordered usage immediately */
|
||||
res->obj->unordered_read = false;
|
||||
// TODO: figure out a way to link up layouts between unordered and main cmdbuf
|
||||
res->obj->unordered_write = false;
|
||||
}
|
||||
if (!a)
|
||||
|
|
@ -2507,6 +2525,8 @@ unbind_bindless_descriptor(struct zink_context *ctx, struct zink_resource *res)
|
|||
unbind_descriptor_reads(res, i);
|
||||
}
|
||||
}
|
||||
if (zink_screen(ctx->base.screen)->driver_workarounds.general_layout)
|
||||
return;
|
||||
for (unsigned i = 0; i < 2; i++) {
|
||||
if (!res->image_bind_count[i])
|
||||
check_for_layout_update(ctx, res, i);
|
||||
|
|
@ -2517,6 +2537,7 @@ static void
|
|||
zink_make_texture_handle_resident(struct pipe_context *pctx, uint64_t handle, bool resident)
|
||||
{
|
||||
struct zink_context *ctx = zink_context(pctx);
|
||||
bool general_layout = zink_screen(ctx->base.screen)->driver_workarounds.general_layout;
|
||||
bool is_buffer = ZINK_BINDLESS_IS_BUFFER(handle);
|
||||
struct hash_entry *he = _mesa_hash_table_search(&ctx->di.bindless[is_buffer].tex_handles, (void*)(uintptr_t)handle);
|
||||
assert(he);
|
||||
|
|
@ -2549,15 +2570,18 @@ zink_make_texture_handle_resident(struct pipe_context *pctx, uint64_t handle, bo
|
|||
ii->imageView = ds->surface->image_view;
|
||||
ii->imageLayout = zink_descriptor_util_image_layout_eval(ctx, res, false);
|
||||
flush_pending_clears(ctx, res, ds->surface->base.first_layer, ds->surface->base.last_layer - ds->surface->base.first_layer + 1);
|
||||
if (!check_for_layout_update(ctx, res, false)) {
|
||||
if (general_layout) {
|
||||
res->obj->unordered_read = false;
|
||||
// TODO: figure out a way to link up layouts between unordered and main cmdbuf
|
||||
res->obj->unordered_write = false;
|
||||
}
|
||||
if (!check_for_layout_update(ctx, res, true)) {
|
||||
res->obj->unordered_read = false;
|
||||
// TODO: figure out a way to link up layouts between unordered and main cmdbuf
|
||||
res->obj->unordered_write = false;
|
||||
zink_screen(ctx->base.screen)->image_barrier(ctx, res, VK_IMAGE_LAYOUT_GENERAL, VK_ACCESS_SHADER_READ_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||
} else {
|
||||
if (!check_for_layout_update(ctx, res, false)) {
|
||||
res->obj->unordered_read = false;
|
||||
res->obj->unordered_write = false;
|
||||
}
|
||||
if (!check_for_layout_update(ctx, res, true)) {
|
||||
res->obj->unordered_read = false;
|
||||
res->obj->unordered_write = false;
|
||||
}
|
||||
}
|
||||
zink_batch_resource_usage_set(ctx->bs, res, false, false);
|
||||
res->obj->unordered_write = false;
|
||||
|
|
@ -2692,8 +2716,8 @@ zink_make_image_handle_resident(struct pipe_context *pctx, uint64_t handle, unsi
|
|||
ii->sampler = VK_NULL_HANDLE;
|
||||
ii->imageView = ds->surface->image_view;
|
||||
ii->imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
finalize_image_bind(ctx, res, false);
|
||||
finalize_image_bind(ctx, res, true);
|
||||
finalize_image_bind(ctx, res, false, access, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||
finalize_image_bind(ctx, res, true, access, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT);
|
||||
zink_batch_resource_usage_set(ctx->bs, res, zink_resource_access_is_write(access), false);
|
||||
res->obj->unordered_write = false;
|
||||
}
|
||||
|
|
@ -3408,12 +3432,14 @@ zink_prep_fb_attachment(struct zink_context *ctx, struct zink_surface *surf, uns
|
|||
layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
|
||||
}
|
||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||
if (screen->driver_workarounds.general_layout)
|
||||
layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
/*
|
||||
The image subresources for a storage image must be in the VK_IMAGE_LAYOUT_SHARED_PRESENT_KHR or
|
||||
VK_IMAGE_LAYOUT_GENERAL layout in order to access its data in a shader.
|
||||
- 14.1.1. Storage Image
|
||||
*/
|
||||
if (res->image_bind_count[0])
|
||||
else if (res->image_bind_count[0])
|
||||
layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
else if (!screen->info.have_EXT_attachment_feedback_loop_layout &&
|
||||
layout == VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT)
|
||||
|
|
@ -3734,6 +3760,7 @@ rebind_fb_state(struct zink_context *ctx, struct zink_resource *match_res, bool
|
|||
static void
|
||||
unbind_fb_surface(struct zink_context *ctx, struct pipe_surface *surf, unsigned idx, bool changed)
|
||||
{
|
||||
bool general_layout = zink_screen(ctx->base.screen)->driver_workarounds.general_layout;
|
||||
ctx->dynamic_fb.attachments[idx].imageView = VK_NULL_HANDLE;
|
||||
if (!surf)
|
||||
return;
|
||||
|
|
@ -3745,7 +3772,7 @@ unbind_fb_surface(struct zink_context *ctx, struct pipe_surface *surf, unsigned
|
|||
if (!res->fb_bind_count && !res->bind_count[0])
|
||||
_mesa_set_remove_key(ctx->need_barriers[0], res);
|
||||
unsigned feedback_loops = ctx->feedback_loops;
|
||||
if (ctx->feedback_loops & BITFIELD_BIT(idx)) {
|
||||
if (!general_layout && ctx->feedback_loops & BITFIELD_BIT(idx)) {
|
||||
ctx->dynamic_fb.attachments[idx].imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
ctx->rp_layout_changed = true;
|
||||
}
|
||||
|
|
@ -3764,7 +3791,7 @@ unbind_fb_surface(struct zink_context *ctx, struct pipe_surface *surf, unsigned
|
|||
res->fb_binds &= ~BITFIELD_BIT(idx);
|
||||
batch_ref_fb_surface(ctx, surf);
|
||||
/* this is called just before the resource loses a reference, so a refcount==1 means the resource will be destroyed */
|
||||
if (!res->fb_bind_count && res->base.b.reference.count > 1) {
|
||||
if (!general_layout && !res->fb_bind_count && res->base.b.reference.count > 1) {
|
||||
if (ctx->track_renderpasses && !ctx->blitting) {
|
||||
if (!(res->base.b.bind & PIPE_BIND_DISPLAY_TARGET) && util_format_is_depth_or_stencil(surf->format))
|
||||
/* assume that all depth buffers which are not swapchain images will be used for sampling to avoid splitting renderpasses */
|
||||
|
|
@ -5122,6 +5149,7 @@ rebind_image(struct zink_context *ctx, struct zink_resource *res)
|
|||
zink_rebind_framebuffer(ctx, res);
|
||||
if (!zink_resource_has_binds(res))
|
||||
return;
|
||||
bool general_layout = zink_screen(ctx->base.screen)->driver_workarounds.general_layout;
|
||||
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
|
||||
if (res->sampler_binds[i]) {
|
||||
for (unsigned j = 0; j < ctx->di.num_sampler_views[i]; j++) {
|
||||
|
|
@ -5141,7 +5169,8 @@ rebind_image(struct zink_context *ctx, struct zink_resource *res)
|
|||
if (zink_resource(ctx->image_views[i][j].base.resource) == res) {
|
||||
ctx->invalidate_descriptor_state(ctx, i, ZINK_DESCRIPTOR_TYPE_IMAGE, j, 1);
|
||||
update_descriptor_state_image(ctx, i, j, res);
|
||||
_mesa_set_add(ctx->need_barriers[i == MESA_SHADER_COMPUTE], res);
|
||||
if (!general_layout)
|
||||
_mesa_set_add(ctx->need_barriers[i == MESA_SHADER_COMPUTE], res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5196,7 +5225,8 @@ zink_rebind_all_images(struct zink_context *ctx)
|
|||
{
|
||||
assert(!ctx->blitting);
|
||||
rebind_fb_state(ctx, NULL, false);
|
||||
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
|
||||
bool general_layout = zink_screen(ctx->base.screen)->driver_workarounds.general_layout;
|
||||
for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) {
|
||||
for (unsigned j = 0; j < ctx->di.num_sampler_views[i]; j++) {
|
||||
struct zink_sampler_view *sv = zink_sampler_view(ctx->sampler_views[i][j]);
|
||||
if (!sv || !sv->image_view || sv->image_view->base.texture->target == PIPE_BUFFER)
|
||||
|
|
@ -5220,7 +5250,8 @@ zink_rebind_all_images(struct zink_context *ctx)
|
|||
image_view->surface = create_image_surface(ctx, &image_view->base, i == MESA_SHADER_COMPUTE);
|
||||
ctx->invalidate_descriptor_state(ctx, i, ZINK_DESCRIPTOR_TYPE_IMAGE, j, 1);
|
||||
update_descriptor_state_image(ctx, i, j, res);
|
||||
_mesa_set_add(ctx->need_barriers[i == MESA_SHADER_COMPUTE], res);
|
||||
if (!general_layout)
|
||||
_mesa_set_add(ctx->need_barriers[i == MESA_SHADER_COMPUTE], res);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5531,11 +5562,13 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
|
|||
_mesa_set_init(&ctx->rendering_state_cache[i], ctx, hash_rendering_state, equals_rendering_state);
|
||||
ctx->dynamic_fb.info.pColorAttachments = ctx->dynamic_fb.attachments;
|
||||
ctx->dynamic_fb.info.sType = VK_STRUCTURE_TYPE_RENDERING_INFO;
|
||||
|
||||
bool general_layout = screen->driver_workarounds.general_layout;
|
||||
for (unsigned i = 0; i < ARRAY_SIZE(ctx->dynamic_fb.attachments); i++) {
|
||||
VkRenderingAttachmentInfo *att = &ctx->dynamic_fb.attachments[i];
|
||||
att->sType = VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO;
|
||||
att->imageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
att->resolveImageLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
att->imageLayout = general_layout ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
att->resolveImageLayout = general_layout ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||
att->storeOp = VK_ATTACHMENT_STORE_OP_STORE;
|
||||
}
|
||||
ctx->dynamic_fb.fbfetch_att = (VkAttachmentFeedbackLoopInfoEXT){
|
||||
|
|
@ -5822,11 +5855,13 @@ add_implicit_feedback_loop(struct zink_context *ctx, struct zink_resource *res)
|
|||
}
|
||||
ctx->rp_layout_changed = true;
|
||||
ctx->feedback_loops |= res->fb_binds;
|
||||
u_foreach_bit(idx, res->fb_binds) {
|
||||
if (zink_screen(ctx->base.screen)->info.have_EXT_attachment_feedback_loop_layout)
|
||||
ctx->dynamic_fb.attachments[idx].imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
else
|
||||
ctx->dynamic_fb.attachments[idx].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
if (!zink_screen(ctx->base.screen)->driver_workarounds.general_layout) {
|
||||
u_foreach_bit(idx, res->fb_binds) {
|
||||
if (zink_screen(ctx->base.screen)->info.have_EXT_attachment_feedback_loop_layout)
|
||||
ctx->dynamic_fb.attachments[idx].imageLayout = VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
|
||||
else
|
||||
ctx->dynamic_fb.attachments[idx].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
}
|
||||
}
|
||||
update_feedback_loop_dynamic_state(ctx);
|
||||
return true;
|
||||
|
|
@ -5842,14 +5877,18 @@ zink_update_barriers(struct zink_context *ctx, bool is_compute,
|
|||
struct set *need_barriers = ctx->need_barriers[is_compute];
|
||||
ctx->barrier_set_idx[is_compute] = !ctx->barrier_set_idx[is_compute];
|
||||
ctx->need_barriers[is_compute] = &ctx->update_barriers[is_compute][ctx->barrier_set_idx[is_compute]];
|
||||
bool general_layout = zink_screen(ctx->base.screen)->driver_workarounds.general_layout;
|
||||
ASSERTED bool check_rp = ctx->in_rp && ctx->dynamic_fb.tc_info.zsbuf_invalidate;
|
||||
set_foreach(need_barriers, he) {
|
||||
struct zink_resource *res = (struct zink_resource *)he->key;
|
||||
if (res->bind_count[is_compute]) {
|
||||
VkPipelineStageFlagBits pipeline = is_compute ? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT : res->gfx_barrier;
|
||||
if (res->base.b.target == PIPE_BUFFER)
|
||||
if (res->base.b.target == PIPE_BUFFER) {
|
||||
zink_screen(ctx->base.screen)->buffer_barrier(ctx, res, res->barrier_access[is_compute], pipeline);
|
||||
else {
|
||||
} else if (general_layout) {
|
||||
/* let sync figure this out */
|
||||
zink_screen(ctx->base.screen)->image_barrier(ctx, res, VK_IMAGE_LAYOUT_GENERAL, res->barrier_access[is_compute], pipeline);
|
||||
} else {
|
||||
bool is_feedback = is_compute ? false : add_implicit_feedback_loop(ctx, res);
|
||||
VkImageLayout layout = zink_descriptor_util_image_layout_eval(ctx, res, is_compute);
|
||||
/* GENERAL is only used for feedback loops and storage image binds */
|
||||
|
|
|
|||
|
|
@ -264,6 +264,8 @@ zink_descriptor_util_push_layouts_get(struct zink_context *ctx, struct zink_desc
|
|||
VkImageLayout
|
||||
zink_descriptor_util_image_layout_eval(const struct zink_context *ctx, const struct zink_resource *res, bool is_compute)
|
||||
{
|
||||
if (zink_screen(ctx->base.screen)->driver_workarounds.general_layout)
|
||||
return VK_IMAGE_LAYOUT_GENERAL;
|
||||
if (res->bindless[0] || res->bindless[1]) {
|
||||
/* bindless needs most permissive layout */
|
||||
if (res->image_bind_count[0] || res->image_bind_count[1])
|
||||
|
|
|
|||
|
|
@ -163,6 +163,21 @@ zink_debug_mem_print_stats(struct zink_screen *screen)
|
|||
simple_mtx_unlock(&screen->debug_mem_lock);
|
||||
}
|
||||
|
||||
static void
|
||||
image_hic_transition(struct zink_screen *screen, struct zink_resource *res, VkImageLayout layout)
|
||||
{
|
||||
VkHostImageLayoutTransitionInfoEXT t = {
|
||||
VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,
|
||||
NULL,
|
||||
res->obj->image,
|
||||
res->layout,
|
||||
layout,
|
||||
{res->aspect, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS}
|
||||
};
|
||||
VKSCR(TransitionImageLayoutEXT)(screen->dev, 1, &t);
|
||||
res->layout = layout;
|
||||
}
|
||||
|
||||
static bool
|
||||
equals_ivci(const void *a, const void *b)
|
||||
{
|
||||
|
|
@ -1694,6 +1709,11 @@ resource_create(struct pipe_screen *pscreen,
|
|||
} else {
|
||||
_mesa_hash_table_init(&res->surface_cache, NULL, NULL, equals_ivci);
|
||||
simple_mtx_init(&res->surface_mtx, mtx_plain);
|
||||
|
||||
/* immediately switch to GENERAL layout if possible to avoid extra sync */
|
||||
if (res->obj->image && res->queue != VK_QUEUE_FAMILY_FOREIGN_EXT && (res->obj->vkusage & VK_IMAGE_USAGE_HOST_TRANSFER_BIT_EXT) &&
|
||||
screen->driver_workarounds.general_layout)
|
||||
image_hic_transition(screen, res, VK_IMAGE_LAYOUT_GENERAL);
|
||||
}
|
||||
if (res->obj->exportable)
|
||||
res->base.b.bind |= ZINK_BIND_DMABUF;
|
||||
|
|
@ -2678,20 +2698,9 @@ zink_image_subdata(struct pipe_context *pctx,
|
|||
unsigned vk_layer_stride = util_format_get_2d_size(pres->format, stride, 1) * vk_stride;
|
||||
layer_stride /= vk_layer_stride;
|
||||
|
||||
VkHostImageLayoutTransitionInfoEXT t = {
|
||||
VK_STRUCTURE_TYPE_HOST_IMAGE_LAYOUT_TRANSITION_INFO_EXT,
|
||||
NULL,
|
||||
res->obj->image,
|
||||
res->layout,
|
||||
/* GENERAL support is guaranteed */
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
{res->aspect, 0, VK_REMAINING_MIP_LEVELS, 0, VK_REMAINING_ARRAY_LAYERS}
|
||||
};
|
||||
/* only pre-transition uninit images to avoid thrashing */
|
||||
if (change_layout) {
|
||||
VKSCR(TransitionImageLayoutEXT)(screen->dev, 1, &t);
|
||||
res->layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
}
|
||||
if (change_layout)
|
||||
image_hic_transition(screen, res, VK_IMAGE_LAYOUT_GENERAL);
|
||||
VkMemoryToImageCopyEXT region = {
|
||||
VK_STRUCTURE_TYPE_MEMORY_TO_IMAGE_COPY_EXT,
|
||||
NULL,
|
||||
|
|
@ -2712,14 +2721,12 @@ zink_image_subdata(struct pipe_context *pctx,
|
|||
®ion
|
||||
};
|
||||
VKSCR(CopyMemoryToImageEXT)(screen->dev, ©);
|
||||
if (change_layout && screen->can_hic_shader_read && !pres->last_level && !box->x && !box->y && !box->z &&
|
||||
if (change_layout && !screen->driver_workarounds.general_layout && screen->can_hic_shader_read &&
|
||||
!pres->last_level && !box->x && !box->y && !box->z &&
|
||||
box->width == pres->width0 && box->height == pres->height0 &&
|
||||
((is_arrayed && box->depth == pres->array_size) || (!is_arrayed && box->depth == pres->depth0))) {
|
||||
/* assume full copy single-mip images use shader read access */
|
||||
t.oldLayout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
t.newLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
VKSCR(TransitionImageLayoutEXT)(screen->dev, 1, &t);
|
||||
res->layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
image_hic_transition(screen, res, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
|
||||
/* assume multi-mip where further subdata calls may happen */
|
||||
}
|
||||
/* make sure image is marked as having data */
|
||||
|
|
@ -3157,6 +3164,7 @@ zink_resource_get_address(struct zink_screen *screen, struct zink_resource *res)
|
|||
void
|
||||
zink_resource_setup_transfer_layouts(struct zink_context *ctx, struct zink_resource *src, struct zink_resource *dst)
|
||||
{
|
||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||
if (src == dst) {
|
||||
/* The Vulkan 1.1 specification says the following about valid usage
|
||||
* of vkCmdBlitImage:
|
||||
|
|
@ -3174,20 +3182,20 @@ zink_resource_setup_transfer_layouts(struct zink_context *ctx, struct zink_resou
|
|||
* VK_IMAGE_LAYOUT_GENERAL. And since this isn't a present-related
|
||||
* operation, VK_IMAGE_LAYOUT_GENERAL seems most appropriate.
|
||||
*/
|
||||
zink_screen(ctx->base.screen)->image_barrier(ctx, src,
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
screen->image_barrier(ctx, src,
|
||||
VK_IMAGE_LAYOUT_GENERAL,
|
||||
VK_ACCESS_TRANSFER_READ_BIT | VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
} else {
|
||||
zink_screen(ctx->base.screen)->image_barrier(ctx, src,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
screen->image_barrier(ctx, src,
|
||||
screen->driver_workarounds.general_layout ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_READ_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
|
||||
zink_screen(ctx->base.screen)->image_barrier(ctx, dst,
|
||||
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
screen->image_barrier(ctx, dst,
|
||||
screen->driver_workarounds.general_layout ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
|
||||
VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||
VK_PIPELINE_STAGE_TRANSFER_BIT);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3023,6 +3023,19 @@ init_driver_workarounds(struct zink_screen *screen)
|
|||
break;
|
||||
}
|
||||
|
||||
switch (zink_driverid(screen)) {
|
||||
case VK_DRIVER_ID_MESA_LLVMPIPE:
|
||||
case VK_DRIVER_ID_MESA_NVK:
|
||||
case VK_DRIVER_ID_NVIDIA_PROPRIETARY:
|
||||
case VK_DRIVER_ID_MESA_TURNIP:
|
||||
case VK_DRIVER_ID_QUALCOMM_PROPRIETARY:
|
||||
screen->driver_workarounds.general_layout = true;
|
||||
break;
|
||||
default:
|
||||
screen->driver_workarounds.general_layout = screen->info.have_KHR_unified_image_layouts;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!screen->resizable_bar)
|
||||
screen->info.have_EXT_host_image_copy = false;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -689,7 +689,7 @@ resource_needs_barrier(struct zink_resource *res, VkAccessFlags flags, VkPipelin
|
|||
|
||||
|
||||
|
||||
template <barrier_type BARRIER_API, bool UNSYNCHRONIZED>
|
||||
template <barrier_type BARRIER_API, bool UNSYNCHRONIZED, bool GENERAL_IMAGE>
|
||||
void
|
||||
zink_resource_memory_barrier(struct zink_context *ctx, struct zink_resource *res, VkAccessFlags flags, VkPipelineStageFlags pipeline)
|
||||
{
|
||||
|
|
@ -761,8 +761,16 @@ zink_resource_memory_barrier(struct zink_context *ctx, struct zink_resource *res
|
|||
zink_cmd_debug_marker_end(ctx, cmdbuf, marker);
|
||||
}
|
||||
|
||||
if (!UNSYNCHRONIZED)
|
||||
resource_check_defer_buffer_barrier(ctx, res, pipeline);
|
||||
if (!UNSYNCHRONIZED) {
|
||||
if (GENERAL_IMAGE) {
|
||||
bool is_compute = (pipeline & VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT) == pipeline;
|
||||
if (res->bind_count[!is_compute] || (is_compute && res->fb_bind_count))
|
||||
/* compute rebind */
|
||||
_mesa_set_add(ctx->need_barriers[is_compute], res);
|
||||
} else {
|
||||
resource_check_defer_buffer_barrier(ctx, res, pipeline);
|
||||
}
|
||||
}
|
||||
|
||||
if (is_write)
|
||||
res->obj->last_write = flags;
|
||||
|
|
@ -780,21 +788,47 @@ zink_resource_memory_barrier(struct zink_context *ctx, struct zink_resource *res
|
|||
res->obj->access_stage = pipeline;
|
||||
res->obj->ordered_access_is_copied = unordered;
|
||||
}
|
||||
if (pipeline != VK_PIPELINE_STAGE_TRANSFER_BIT && is_write)
|
||||
if (pipeline != VK_PIPELINE_STAGE_TRANSFER_BIT && is_write && !GENERAL_IMAGE)
|
||||
zink_resource_copies_reset(res);
|
||||
}
|
||||
|
||||
template <bool UNSYNCHRONIZED>
|
||||
void
|
||||
zink_resource_image_barrier_general(struct zink_context *ctx, struct zink_resource *res, VkImageLayout new_layout, VkAccessFlags flags, VkPipelineStageFlags pipeline)
|
||||
{
|
||||
if (!pipeline)
|
||||
pipeline = pipeline_dst_stage(new_layout);
|
||||
if (!flags)
|
||||
flags = access_dst_flags(new_layout);
|
||||
|
||||
assert(new_layout == VK_IMAGE_LAYOUT_GENERAL || new_layout == VK_IMAGE_LAYOUT_PRESENT_SRC_KHR);
|
||||
/* if this requires an actual image barrier, send it through to the image barrier handlers */
|
||||
if (res->obj->needs_zs_evaluate || res->obj->exportable || zink_is_swapchain(res) || res->layout != new_layout ||
|
||||
res->queue != zink_screen(ctx->base.screen)->gfx_queue || res->queue != VK_QUEUE_FAMILY_IGNORED) {
|
||||
zink_resource_image_barrier<barrier_KHR_synchronzation2, UNSYNCHRONIZED>(ctx, res, new_layout, flags, pipeline);
|
||||
return;
|
||||
}
|
||||
|
||||
/* this is just a synchronization barrier with GENERAL layout: use memory barrier for better granularity */
|
||||
zink_resource_memory_barrier<barrier_KHR_synchronzation2, false, true>(ctx, res, flags, pipeline);
|
||||
}
|
||||
|
||||
void
|
||||
zink_synchronization_init(struct zink_screen *screen)
|
||||
{
|
||||
if (screen->info.have_vulkan13 || screen->info.have_KHR_synchronization2) {
|
||||
screen->buffer_barrier = zink_resource_memory_barrier<barrier_KHR_synchronzation2, false>;
|
||||
screen->buffer_barrier_unsync = zink_resource_memory_barrier<barrier_KHR_synchronzation2, true>;
|
||||
screen->image_barrier = zink_resource_image_barrier<barrier_KHR_synchronzation2, false>;
|
||||
screen->image_barrier_unsync = zink_resource_image_barrier<barrier_KHR_synchronzation2, true>;
|
||||
screen->buffer_barrier = zink_resource_memory_barrier<barrier_KHR_synchronzation2, false, false>;
|
||||
screen->buffer_barrier_unsync = zink_resource_memory_barrier<barrier_KHR_synchronzation2, true, false>;
|
||||
if (screen->driver_workarounds.general_layout) {
|
||||
screen->image_barrier = zink_resource_image_barrier<barrier_KHR_synchronzation2, false>;
|
||||
screen->image_barrier_unsync = zink_resource_image_barrier<barrier_KHR_synchronzation2, true>;
|
||||
} else {
|
||||
screen->image_barrier = zink_resource_image_barrier<barrier_KHR_synchronzation2, false>;
|
||||
screen->image_barrier_unsync = zink_resource_image_barrier<barrier_KHR_synchronzation2, true>;
|
||||
}
|
||||
} else {
|
||||
screen->buffer_barrier = zink_resource_memory_barrier<barrier_default, false>;
|
||||
screen->buffer_barrier_unsync = zink_resource_memory_barrier<barrier_default, true>;
|
||||
screen->buffer_barrier = zink_resource_memory_barrier<barrier_default, false, false>;
|
||||
screen->buffer_barrier_unsync = zink_resource_memory_barrier<barrier_default, true, false>;
|
||||
screen->image_barrier = zink_resource_image_barrier<barrier_default, false>;
|
||||
screen->image_barrier_unsync = zink_resource_image_barrier<barrier_default, true>;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1520,6 +1520,7 @@ struct zink_screen {
|
|||
bool inconsistent_interpolation;
|
||||
bool can_2d_view_sparse;
|
||||
bool general_depth_layout;
|
||||
bool general_layout;
|
||||
} driver_workarounds;
|
||||
};
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue