diff --git a/src/gallium/drivers/zink/zink_blit.c b/src/gallium/drivers/zink/zink_blit.c index b8fc1f88a23..9b49a5c9bce 100644 --- a/src/gallium/drivers/zink/zink_blit.c +++ b/src/gallium/drivers/zink/zink_blit.c @@ -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) diff --git a/src/gallium/drivers/zink/zink_context.c b/src/gallium/drivers/zink/zink_context.c index 0bcd2944afe..c0fc405048d 100644 --- a/src/gallium/drivers/zink/zink_context.c +++ b/src/gallium/drivers/zink/zink_context.c @@ -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 */ diff --git a/src/gallium/drivers/zink/zink_descriptors.c b/src/gallium/drivers/zink/zink_descriptors.c index 194cb7fe13e..69f8f637968 100644 --- a/src/gallium/drivers/zink/zink_descriptors.c +++ b/src/gallium/drivers/zink/zink_descriptors.c @@ -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]) diff --git a/src/gallium/drivers/zink/zink_resource.c b/src/gallium/drivers/zink/zink_resource.c index f9175a4c1f9..bd2fafe4f5d 100644 --- a/src/gallium/drivers/zink/zink_resource.c +++ b/src/gallium/drivers/zink/zink_resource.c @@ -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); } } diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index f98fc5bd320..029ee203184 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -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; } diff --git a/src/gallium/drivers/zink/zink_synchronization.cpp b/src/gallium/drivers/zink/zink_synchronization.cpp index ee58e2bc383..4cd536204ae 100644 --- a/src/gallium/drivers/zink/zink_synchronization.cpp +++ b/src/gallium/drivers/zink/zink_synchronization.cpp @@ -689,7 +689,7 @@ resource_needs_barrier(struct zink_resource *res, VkAccessFlags flags, VkPipelin -template +template 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 +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(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(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; - screen->buffer_barrier_unsync = zink_resource_memory_barrier; - screen->image_barrier = zink_resource_image_barrier; - screen->image_barrier_unsync = zink_resource_image_barrier; + screen->buffer_barrier = zink_resource_memory_barrier; + screen->buffer_barrier_unsync = zink_resource_memory_barrier; + if (screen->driver_workarounds.general_layout) { + screen->image_barrier = zink_resource_image_barrier; + screen->image_barrier_unsync = zink_resource_image_barrier; + } else { + screen->image_barrier = zink_resource_image_barrier; + screen->image_barrier_unsync = zink_resource_image_barrier; + } } else { - screen->buffer_barrier = zink_resource_memory_barrier; - screen->buffer_barrier_unsync = zink_resource_memory_barrier; + screen->buffer_barrier = zink_resource_memory_barrier; + screen->buffer_barrier_unsync = zink_resource_memory_barrier; screen->image_barrier = zink_resource_image_barrier; screen->image_barrier_unsync = zink_resource_image_barrier; } diff --git a/src/gallium/drivers/zink/zink_types.h b/src/gallium/drivers/zink/zink_types.h index 4f0e3c53e3d..c8defb20dc2 100644 --- a/src/gallium/drivers/zink/zink_types.h +++ b/src/gallium/drivers/zink/zink_types.h @@ -1520,6 +1520,7 @@ struct zink_screen { bool inconsistent_interpolation; bool can_2d_view_sparse; bool general_depth_layout; + bool general_layout; } driver_workarounds; };