zink: it's kopperin' time

Reviewed-by: Adam Jackson <ajax@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14541>
This commit is contained in:
Mike Blumenkrantz 2022-01-13 15:29:54 -05:00 committed by Marge Bot
parent 8ade5588e3
commit 7f56fd9655
20 changed files with 326 additions and 303 deletions

View File

@ -59,7 +59,7 @@ sw_screen_create_named(struct sw_winsys *winsys, const char *driver)
#if defined(GALLIUM_ZINK)
if (screen == NULL && strcmp(driver, "zink") == 0)
screen = zink_create_screen(winsys);
screen = zink_create_screen(winsys, NULL);
#endif
#if defined(GALLIUM_D3D12)

View File

@ -63,7 +63,7 @@ sw_screen_create_named(struct sw_winsys *winsys, const struct pipe_screen_config
#if defined(GALLIUM_ZINK)
if (screen == NULL && strcmp(driver, "zink") == 0)
screen = zink_create_screen(winsys);
screen = zink_create_screen(winsys, config);
#endif
#if defined(GALLIUM_D3D12)
@ -114,7 +114,7 @@ struct pipe_screen *
sw_screen_create_zink(struct sw_winsys *winsys, const struct pipe_screen_config *config, bool whatever)
{
#if defined(GALLIUM_ZINK)
return zink_create_screen(winsys);
return zink_create_screen(winsys, config);
#else
return NULL;
#endif

View File

@ -28,6 +28,7 @@ files_libzink = files(
'zink_clear.c',
'zink_compiler.c',
'zink_context.c',
'zink_kopper.c',
'zink_descriptors.c',
'zink_descriptors_lazy.c',
'zink_draw.cpp',

View File

@ -1,6 +1,7 @@
#include "zink_batch.h"
#include "zink_context.h"
#include "zink_kopper.h"
#include "zink_fence.h"
#include "zink_framebuffer.h"
#include "zink_query.h"
@ -87,19 +88,24 @@ zink_reset_batch_state(struct zink_context *ctx, struct zink_batch_state *bs)
zink_program_reference(ctx, &pg, NULL);
}
pipe_resource_reference(&bs->flush_res, NULL);
bs->resource_size = 0;
bs->signal_semaphore = VK_NULL_HANDLE;
util_dynarray_clear(&bs->wait_semaphores);
util_dynarray_clear(&bs->wait_semaphore_stages);
bs->present = VK_NULL_HANDLE;
while (util_dynarray_contains(&bs->acquires, VkSemaphore))
VKSCR(DestroySemaphore)(screen->dev, util_dynarray_pop(&bs->acquires, VkSemaphore), NULL);
bs->swapchain = NULL;
while (util_dynarray_contains(&bs->dead_swapchains, VkImageView))
VKSCR(DestroyImageView)(screen->dev, util_dynarray_pop(&bs->dead_swapchains, VkImageView), NULL);
/* only reset submitted here so that tc fence desync can pick up the 'completed' flag
* before the state is reused
*/
bs->fence.submitted = false;
bs->has_barriers = false;
bs->scanout_flush = false;
if (bs->fence.batch_id)
zink_screen_update_last_finished(screen, bs->fence.batch_id);
bs->submit_count++;
@ -175,6 +181,8 @@ zink_batch_state_destroy(struct zink_screen *screen, struct zink_batch_state *bs
util_dynarray_fini(&bs->unref_resources);
util_dynarray_fini(&bs->bindless_releases[0]);
util_dynarray_fini(&bs->bindless_releases[1]);
util_dynarray_fini(&bs->acquires);
util_dynarray_fini(&bs->dead_swapchains);
_mesa_set_destroy(bs->surfaces, NULL);
_mesa_set_destroy(bs->bufferviews, NULL);
_mesa_set_destroy(bs->programs, NULL);
@ -225,6 +233,8 @@ create_batch_state(struct zink_context *ctx)
util_dynarray_init(&bs->dead_framebuffers, NULL);
util_dynarray_init(&bs->persistent_resources, NULL);
util_dynarray_init(&bs->unref_resources, NULL);
util_dynarray_init(&bs->acquires, NULL);
util_dynarray_init(&bs->dead_swapchains, NULL);
util_dynarray_init(&bs->bindless_releases[0], NULL);
util_dynarray_init(&bs->bindless_releases[1], NULL);
@ -369,7 +379,15 @@ submit_queue(void *data, void *gdata, int thread_index)
}
uint64_t batch_id = bs->fence.batch_id;
/* first submit is just for acquire waits since they have a separate array */
si[0].sType = si[1].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
si[0].waitSemaphoreCount = util_dynarray_num_elements(&bs->acquires, VkSemaphore);
si[0].pWaitSemaphores = bs->acquires.data;
VkPipelineStageFlags mask[32]; //can't imagine having more dumbass than this
assert(util_dynarray_num_elements(&bs->acquires, VkSemaphore) < ARRAY_SIZE(mask));
for (unsigned i = 0; i < ARRAY_SIZE(mask); i++)
mask[i] = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
si[0].pWaitDstStageMask = mask;
/* then the real submit */
si[1].waitSemaphoreCount = util_dynarray_num_elements(&bs->wait_semaphores, VkSemaphore);
@ -382,7 +400,7 @@ submit_queue(void *data, void *gdata, int thread_index)
};
si[1].pCommandBuffers = bs->has_barriers ? cmdbufs : &cmdbufs[1];
VkSemaphore signals[2];
VkSemaphore signals[3];
si[1].signalSemaphoreCount = !!bs->signal_semaphore;
signals[0] = bs->signal_semaphore;
si[1].pSignalSemaphores = signals;
@ -397,16 +415,9 @@ submit_queue(void *data, void *gdata, int thread_index)
tsi.signalSemaphoreValueCount = si[1].signalSemaphoreCount;
}
struct wsi_memory_signal_submit_info mem_signal = {
.sType = VK_STRUCTURE_TYPE_WSI_MEMORY_SIGNAL_SUBMIT_INFO_MESA,
.pNext = si[1].pNext,
};
if (bs->flush_res && screen->needs_mesa_flush_wsi) {
struct zink_resource *flush_res = zink_resource(bs->flush_res);
mem_signal.memory = zink_bo_get_mem(flush_res->scanout_obj ? flush_res->scanout_obj->bo : flush_res->obj->bo);
si[1].pNext = &mem_signal;
}
if (bs->present)
signals[si[1].signalSemaphoreCount++] = bs->present;
tsi.signalSemaphoreValueCount = si[1].signalSemaphoreCount;
if (VKSCR(EndCommandBuffer)(bs->cmdbuf) != VK_SUCCESS) {
mesa_loge("ZINK: vkEndCommandBuffer failed");
@ -441,149 +452,9 @@ end:
unref_resources(screen, bs);
}
/* TODO: remove for wsi */
static void
copy_scanout(struct zink_batch_state *bs, struct zink_resource *res)
{
if (!bs->scanout_flush)
return;
struct zink_context *ctx = bs->ctx;
VkImageCopy region = {0};
struct pipe_box box = {0, 0, 0,
u_minify(res->base.b.width0, 0),
u_minify(res->base.b.height0, 0), res->base.b.array_size};
box.depth = util_num_layers(&res->base.b, 0);
struct pipe_box *src_box = &box;
unsigned dstz = 0;
region.srcSubresource.aspectMask = res->aspect;
region.srcSubresource.mipLevel = 0;
switch (res->base.b.target) {
case PIPE_TEXTURE_CUBE:
case PIPE_TEXTURE_CUBE_ARRAY:
case PIPE_TEXTURE_2D_ARRAY:
case PIPE_TEXTURE_1D_ARRAY:
/* these use layer */
region.srcSubresource.baseArrayLayer = src_box->z;
region.srcSubresource.layerCount = src_box->depth;
region.srcOffset.z = 0;
region.extent.depth = 1;
break;
case PIPE_TEXTURE_3D:
/* this uses depth */
region.srcSubresource.baseArrayLayer = 0;
region.srcSubresource.layerCount = 1;
region.srcOffset.z = src_box->z;
region.extent.depth = src_box->depth;
break;
default:
/* these must only copy one layer */
region.srcSubresource.baseArrayLayer = 0;
region.srcSubresource.layerCount = 1;
region.srcOffset.z = 0;
region.extent.depth = 1;
}
region.srcOffset.x = src_box->x;
region.srcOffset.y = src_box->y;
region.dstSubresource.aspectMask = res->aspect;
region.dstSubresource.mipLevel = 0;
switch (res->base.b.target) {
case PIPE_TEXTURE_CUBE:
case PIPE_TEXTURE_CUBE_ARRAY:
case PIPE_TEXTURE_2D_ARRAY:
case PIPE_TEXTURE_1D_ARRAY:
/* these use layer */
region.dstSubresource.baseArrayLayer = dstz;
region.dstSubresource.layerCount = src_box->depth;
region.dstOffset.z = 0;
break;
case PIPE_TEXTURE_3D:
/* this uses depth */
region.dstSubresource.baseArrayLayer = 0;
region.dstSubresource.layerCount = 1;
region.dstOffset.z = dstz;
break;
default:
/* these must only copy one layer */
region.dstSubresource.baseArrayLayer = 0;
region.dstSubresource.layerCount = 1;
region.dstOffset.z = 0;
}
region.dstOffset.x = 0;
region.dstOffset.y = 0;
region.extent.width = src_box->width;
region.extent.height = src_box->height;
VkImageMemoryBarrier imb1;
zink_resource_image_barrier_init(&imb1, res, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
VKCTX(CmdPipelineBarrier)(
bs->cmdbuf,
res->obj->access_stage ? res->obj->access_stage : VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
0,
0, NULL,
0, NULL,
1, &imb1
);
res->layout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
VkImageSubresourceRange isr = {
res->aspect,
0, VK_REMAINING_MIP_LEVELS,
0, VK_REMAINING_ARRAY_LAYERS
};
VkImageMemoryBarrier imb = {
VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,
NULL,
0,
VK_ACCESS_TRANSFER_WRITE_BIT,
res->scanout_obj_init ? VK_IMAGE_LAYOUT_PRESENT_SRC_KHR : VK_IMAGE_LAYOUT_UNDEFINED,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
VK_QUEUE_FAMILY_IGNORED,
VK_QUEUE_FAMILY_IGNORED,
res->scanout_obj->image,
isr
};
VKCTX(CmdPipelineBarrier)(
bs->cmdbuf,
VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,
VK_PIPELINE_STAGE_TRANSFER_BIT,
0,
0, NULL,
0, NULL,
1, &imb
);
VKCTX(CmdCopyImage)(bs->cmdbuf, res->obj->image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
res->scanout_obj->image, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
1, &region);
imb.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
imb.dstAccessMask = 0;
imb.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL;
imb.newLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR;
VKCTX(CmdPipelineBarrier)(
bs->cmdbuf,
VK_PIPELINE_STAGE_TRANSFER_BIT,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
0,
0, NULL,
0, NULL,
1, &imb
);
/* separate flag to avoid annoying validation errors for new scanout objs */
res->scanout_obj_init = true;
}
void
zink_end_batch(struct zink_context *ctx, struct zink_batch *batch)
{
if (batch->state->flush_res)
copy_scanout(batch->state, zink_resource(batch->state->flush_res));
if (!ctx->queries_disabled)
zink_suspend_queries(ctx, batch);
@ -625,6 +496,12 @@ zink_end_batch(struct zink_context *ctx, struct zink_batch *batch)
simple_mtx_unlock(&ctx->batch_mtx);
batch->work_count = 0;
if (batch->swapchain) {
batch->state->present = zink_kopper_present(screen, batch->swapchain);
batch->state->swapchain = batch->swapchain;
batch->swapchain = NULL;
}
if (screen->device_lost)
return;
@ -640,9 +517,14 @@ zink_end_batch(struct zink_context *ctx, struct zink_batch *batch)
void
zink_batch_resource_usage_set(struct zink_batch *batch, struct zink_resource *res, bool write)
{
if (res->obj->dt) {
VkSemaphore acquire = zink_kopper_acquire_submit(zink_screen(batch->state->ctx->base.screen), res);
if (acquire) {
util_dynarray_append(&batch->state->acquires, VkSemaphore, acquire);
res->obj->dt_has_data = true;
}
}
zink_resource_usage_set(res, batch->state, write);
if (write && res->scanout_obj)
batch->state->scanout_flush = true;
/* multiple array entries are fine */
if (!res->obj->coherent && res->obj->persistent_maps)
util_dynarray_append(&batch->state->persistent_resources, struct zink_resource_object*, res->obj);

View File

@ -103,12 +103,13 @@ struct zink_batch_state {
struct util_dynarray wait_semaphore_stages; //external wait semaphores
VkQueue queue; //duplicated from batch for threading
VkSemaphore sem;
VkSemaphore present;
struct zink_resource *swapchain;
struct util_dynarray acquires;
struct util_dynarray dead_swapchains;
struct util_queue_fence flush_completed;
struct pipe_resource *flush_res;
struct set *programs;
struct set *resources;
@ -134,13 +135,13 @@ struct zink_batch_state {
bool is_device_lost;
bool have_timelines;
bool has_barriers;
bool scanout_flush;
};
struct zink_batch {
struct zink_batch_state *state;
struct zink_batch_usage *last_batch_usage;
struct zink_resource *swapchain;
unsigned work_count;

View File

@ -1,4 +1,5 @@
#include "zink_context.h"
#include "zink_kopper.h"
#include "zink_helpers.h"
#include "zink_query.h"
#include "zink_resource.h"
@ -21,7 +22,7 @@ apply_dst_clears(struct zink_context *ctx, const struct pipe_blit_info *info, bo
}
static bool
blit_resolve(struct zink_context *ctx, const struct pipe_blit_info *info)
blit_resolve(struct zink_context *ctx, const struct pipe_blit_info *info, bool *needs_present_readback)
{
if (util_format_get_mask(info->dst.format) != info->mask ||
util_format_get_mask(info->src.format) != info->mask ||
@ -53,6 +54,9 @@ blit_resolve(struct zink_context *ctx, const struct pipe_blit_info *info)
apply_dst_clears(ctx, info, false);
zink_fb_clears_apply_region(ctx, info->src.resource, zink_rect_from_box(&info->src.box));
if (src->obj->dt)
*needs_present_readback = zink_kopper_acquire_readback(ctx, src);
struct zink_batch *batch = &ctx->batch;
zink_batch_no_rp(ctx);
zink_batch_reference_resource_rw(batch, src, false);
@ -113,7 +117,7 @@ get_resource_features(struct zink_screen *screen, struct zink_resource *res)
}
static bool
blit_native(struct zink_context *ctx, const struct pipe_blit_info *info)
blit_native(struct zink_context *ctx, const struct pipe_blit_info *info, bool *needs_present_readback)
{
if (util_format_get_mask(info->dst.format) != info->mask ||
util_format_get_mask(info->src.format) != info->mask ||
@ -159,6 +163,9 @@ blit_native(struct zink_context *ctx, const struct pipe_blit_info *info)
apply_dst_clears(ctx, info, false);
zink_fb_clears_apply_region(ctx, info->src.resource, zink_rect_from_box(&info->src.box));
if (src->obj->dt)
*needs_present_readback = zink_kopper_acquire_readback(ctx, src);
struct zink_batch *batch = &ctx->batch;
zink_batch_no_rp(ctx);
zink_batch_reference_resource_rw(batch, src, false);
@ -266,6 +273,9 @@ zink_blit(struct pipe_context *pctx,
struct zink_resource *src = zink_resource(info->src.resource);
struct zink_resource *dst = zink_resource(info->dst.resource);
bool needs_present_readback = false;
if (dst->obj->dt)
zink_kopper_acquire(ctx, dst, UINT64_MAX);
if (src_desc == dst_desc ||
src_desc->nr_channels != 4 || src_desc->layout != UTIL_FORMAT_LAYOUT_PLAIN ||
@ -275,10 +285,10 @@ zink_blit(struct pipe_context *pctx,
*/
if (info->src.resource->nr_samples > 1 &&
info->dst.resource->nr_samples <= 1) {
if (blit_resolve(ctx, info))
if (blit_resolve(ctx, info, &needs_present_readback))
goto end;
} else {
if (blit_native(ctx, info))
if (blit_native(ctx, info, &needs_present_readback))
goto end;
}
}
@ -303,6 +313,8 @@ zink_blit(struct pipe_context *pctx,
goto end;
}
if (src->obj->dt)
needs_present_readback = zink_kopper_acquire_readback(ctx, src);
/* this is discard_only because we're about to start a renderpass that will
* flush all pending clears anyway
*/
@ -315,6 +327,8 @@ zink_blit(struct pipe_context *pctx,
util_blitter_blit(ctx->blitter, info);
end:
if (needs_present_readback)
zink_kopper_present_readback(ctx, src);
}
/* similar to radeonsi */

View File

@ -22,6 +22,7 @@
*/
#include "zink_context.h"
#include "zink_kopper.h"
#include "zink_query.h"
#include "zink_resource.h"
#include "zink_screen.h"
@ -139,6 +140,8 @@ clear_color_no_rp(struct zink_context *ctx, struct zink_resource *res, const uni
color.uint32[2] = pcolor->ui[2];
color.uint32[3] = pcolor->ui[3];
if (res->obj->dt)
zink_kopper_acquire(ctx, res, UINT64_MAX);
if (zink_resource_image_needs_barrier(res, VK_IMAGE_LAYOUT_GENERAL, 0, 0) &&
zink_resource_image_needs_barrier(res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0))
zink_resource_image_barrier(ctx, res, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0);

View File

@ -25,6 +25,7 @@
#include "zink_batch.h"
#include "zink_compiler.h"
#include "zink_kopper.h"
#include "zink_fence.h"
#include "zink_format.h"
#include "zink_framebuffer.h"
@ -80,7 +81,7 @@ check_resource_for_batch_ref(struct zink_context *ctx, struct zink_resource *res
* - if tracking will be added here, also reapply usage to avoid dangling usage once tracking is removed
* TODO: somehow fix this for perf because it's an extra hash lookup
*/
if (res->obj->bo->reads || res->obj->bo->writes)
if (!res->obj->dt && (res->obj->bo->reads || res->obj->bo->writes))
zink_batch_reference_resource_rw(&ctx->batch, res, !!res->obj->bo->writes);
else
zink_batch_reference_resource(&ctx->batch, res);
@ -759,6 +760,9 @@ zink_create_sampler_view(struct pipe_context *pctx, struct pipe_resource *pres,
templ.u.tex.last_layer = state->u.tex.last_layer;
}
if (res->obj->dt)
zink_kopper_acquire(ctx, res, UINT64_MAX);
ivci = create_ivci(screen, res, &templ, state->target);
ivci.subresourceRange.levelCount = state->u.tex.last_level - state->u.tex.first_level + 1;
ivci.subresourceRange.aspectMask = sampler_aspect_from_format(state->format);
@ -1883,6 +1887,9 @@ zink_update_fbfetch(struct zink_context *ctx)
bool changed = !had_fbfetch;
if (ctx->fb_state.cbufs[0]) {
VkImageView fbfetch = zink_csurface(ctx->fb_state.cbufs[0])->image_view;
if (!fbfetch)
/* swapchain image: retry later */
return;
changed |= fbfetch != ctx->di.fbfetch.imageView;
ctx->di.fbfetch.imageView = zink_csurface(ctx->fb_state.cbufs[0])->image_view;
}
@ -1951,7 +1958,7 @@ get_render_pass(struct zink_context *ctx)
state.rts[i].samples = MAX3(transient ? transient->base.nr_samples : 0, surf->texture->nr_samples, 1);
state.rts[i].clear_color = zink_fb_clear_enabled(ctx, i) && !zink_fb_clear_first_needs_explicit(&ctx->fb_clears[i]);
clears |= !!state.rts[i].clear_color ? PIPE_CLEAR_COLOR0 << i : 0;
state.rts[i].swapchain = surf->texture->bind & PIPE_BIND_SCANOUT;
state.rts[i].swapchain = surf->texture->bind & PIPE_BIND_DISPLAY_TARGET;
if (transient) {
state.num_cresolves++;
state.rts[i].resolve = true;
@ -2114,6 +2121,23 @@ setup_framebuffer(struct zink_context *ctx)
}
ctx->rp_changed = false;
for (unsigned i = 0; i < ctx->fb_state.nr_cbufs; i++) {
if (!ctx->fb_state.cbufs[i])
continue;
struct zink_resource *res = zink_resource(ctx->fb_state.cbufs[i]->texture);
if (res->obj->dt) {
zink_kopper_acquire(ctx, res, UINT64_MAX);
zink_surface_swapchain_update(ctx, zink_csurface(ctx->fb_state.cbufs[i]));
}
}
if (ctx->swapchain_size.width || ctx->swapchain_size.height) {
unsigned old_w = ctx->fb_state.width;
unsigned old_h = ctx->fb_state.height;
ctx->fb_state.width = ctx->swapchain_size.width;
ctx->fb_state.height = ctx->swapchain_size.height;
update_framebuffer_state(ctx, old_w, old_h);
ctx->swapchain_size.width = ctx->swapchain_size.height = 0;
}
if (!ctx->fb_changed)
return;
@ -2138,6 +2162,12 @@ prep_fb_attachment(struct zink_context *ctx, struct zink_surface *surf, unsigned
VkAccessFlags access;
VkPipelineStageFlags pipeline;
if (res->obj->dt) {
zink_kopper_acquire(ctx, res, UINT64_MAX);
zink_surface_swapchain_update(ctx, surf);
if (!i)
zink_update_fbfetch(ctx);
}
VkImageLayout layout = zink_render_pass_attachment_get_barrier_info(ctx->gfx_pipeline_state.render_pass,
i, &pipeline, &access);
zink_resource_image_barrier(ctx, res, layout, access, pipeline);
@ -2583,6 +2613,10 @@ unbind_fb_surface(struct zink_context *ctx, struct pipe_surface *surf, unsigned
struct zink_resource *res = zink_resource(surf->texture);
if (changed) {
if (zink_fb_clear_enabled(ctx, idx)) {
if (res->obj->dt) {
zink_kopper_acquire(ctx, res, UINT64_MAX);
zink_surface_swapchain_update(ctx, zink_csurface(surf));
}
zink_fb_clears_apply(ctx, surf->texture);
}
if (zink_batch_usage_exists(zink_csurface(surf)->batch_uses)) {
@ -2629,6 +2663,8 @@ zink_set_framebuffer_state(struct pipe_context *pctx,
if (i < state->nr_cbufs)
ctx->rp_changed |= !!zink_transient_surface(surf) != !!zink_transient_surface(state->cbufs[i]);
unbind_fb_surface(ctx, surf, i, i >= state->nr_cbufs || surf != state->cbufs[i]);
if (surf && ctx->needs_present == zink_resource(surf->texture))
ctx->needs_present = NULL;
}
if (ctx->fb_state.zsbuf) {
struct pipe_surface *surf = ctx->fb_state.zsbuf;
@ -2660,7 +2696,12 @@ zink_set_framebuffer_state(struct pipe_context *pctx,
struct zink_surface *transient = zink_transient_surface(surf);
if (!samples)
samples = MAX3(transient ? transient->base.nr_samples : 1, surf->texture->nr_samples, 1);
zink_resource(surf->texture)->fb_binds++;
struct zink_resource *res = zink_resource(surf->texture);
if (res->modifiers) {
assert(!ctx->needs_present || ctx->needs_present == res);
ctx->needs_present = res;
}
res->fb_binds++;
ctx->gfx_pipeline_state.void_alpha_attachments |= util_format_has_alpha1(surf->format) ? BITFIELD_BIT(i) : 0;
}
}
@ -3130,6 +3171,10 @@ zink_flush(struct pipe_context *pctx,
/* start rp to do all the clears */
zink_begin_render_pass(ctx);
if (ctx->needs_present && (flags & PIPE_FLUSH_END_OF_FRAME)) {
zink_resource_image_barrier(ctx, ctx->needs_present, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 0, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
}
if (!batch->has_work) {
if (pfence) {
/* reuse last fence */
@ -3434,11 +3479,11 @@ zink_flush_resource(struct pipe_context *pctx,
{
struct zink_context *ctx = zink_context(pctx);
struct zink_resource *res = zink_resource(pres);
/* TODO: this is not futureproof and should be updated once proper
* WSI support is added
*/
if (res->scanout_obj && (pres->bind & (PIPE_BIND_SHARED | PIPE_BIND_SCANOUT)))
pipe_resource_reference(&ctx->batch.state->flush_res, pres);
if (pres->bind & PIPE_BIND_DISPLAY_TARGET && res->obj->acquire) {
zink_resource_image_barrier(ctx, res, VK_IMAGE_LAYOUT_PRESENT_SRC_KHR, 0, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
zink_batch_reference_resource_rw(&ctx->batch, res, true);
ctx->batch.swapchain = res;
}
}
void
@ -3473,9 +3518,13 @@ zink_copy_image_buffer(struct zink_context *ctx, struct zink_resource *dst, stru
bool buf2img = buf == src;
if (buf2img) {
if (img->obj->dt)
zink_kopper_acquire(ctx, img, UINT64_MAX);
zink_resource_image_barrier(ctx, img, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 0, 0);
zink_resource_buffer_barrier(ctx, buf, VK_ACCESS_TRANSFER_READ_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
} else {
if (img->obj->dt)
zink_kopper_acquire_readback(ctx, img);
zink_resource_image_barrier(ctx, img, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 0, 0);
zink_resource_buffer_barrier(ctx, buf, VK_ACCESS_TRANSFER_WRITE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT);
util_range_add(&dst->base.b, &dst->valid_buffer_range, dstx, dstx + src_box->width);
@ -3554,6 +3603,8 @@ zink_copy_image_buffer(struct zink_context *ctx, struct zink_resource *dst, stru
else
VKCTX(CmdCopyImageToBuffer)(batch->state->cmdbuf, img->obj->image, img->layout, buf->obj->buffer, 1, &region);
}
if (!buf2img && img->obj->dt)
zink_kopper_present_readback(ctx, img);
}
static void

View File

@ -252,6 +252,7 @@ struct zink_context {
struct set render_pass_state_cache;
struct hash_table *render_pass_cache;
bool new_swapchain;
VkExtent2D swapchain_size;
bool fb_changed;
bool rp_changed;
@ -260,6 +261,7 @@ struct zink_context {
uint16_t clears_enabled;
uint16_t rp_clears_enabled;
uint16_t fbfetch_outputs;
struct zink_resource *needs_present;
struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS];
bool vertex_buffers_dirty;

View File

@ -112,8 +112,8 @@ populate_attachment_info(VkFramebufferAttachmentImageInfo *att, struct zink_surf
att->sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_ATTACHMENT_IMAGE_INFO;
att->pNext = NULL;
memcpy(&att->flags, &info->flags, offsetof(struct zink_surface_info, format));
att->viewFormatCount = 1;
att->pViewFormats = &info->format;
att->viewFormatCount = 1 + !!info->format[1];
att->pViewFormats = info->format;
}
static struct zink_framebuffer *

View File

@ -107,6 +107,10 @@ void zink_stub_${cmd.lstrip("vk")}(void);
%endif
%endfor
struct pipe_screen;
struct pipe_resource;
bool zink_kopper_update(struct pipe_screen *pscreen, struct pipe_resource *pres, int *w, int *h);
#endif
"""

View File

@ -29,7 +29,7 @@ struct sw_winsys;
struct pipe_screen_config;
struct pipe_screen *
zink_create_screen(struct sw_winsys *winsys);
zink_create_screen(struct sw_winsys *winsys, const struct pipe_screen_config *config);
struct pipe_screen *
zink_drm_create_screen(int fd, const struct pipe_screen_config *config);

View File

@ -28,6 +28,7 @@
#include "zink_fence.h"
#include "zink_program.h"
#include "zink_screen.h"
#include "zink_kopper.h"
#ifdef VK_USE_PLATFORM_METAL_EXT
#include "QuartzCore/CAMetalLayer.h"
@ -95,12 +96,18 @@ zink_destroy_resource_object(struct zink_screen *screen, struct zink_resource_ob
if (obj->is_buffer) {
VKSCR(DestroyBuffer)(screen->dev, obj->buffer, NULL);
VKSCR(DestroyBuffer)(screen->dev, obj->storage_buffer, NULL);
} else if (obj->dt) {
zink_kopper_displaytarget_destroy(screen, obj->dt);
} else {
VKSCR(DestroyImage)(screen->dev, obj->image, NULL);
}
zink_descriptor_set_refs_clear(&obj->desc_set_refs, obj);
zink_bo_unref(screen, obj->bo);
if (obj->dt) {
util_queue_fence_destroy(&obj->present_fence);
FREE(obj->bo); //this is a dummy struct
} else
zink_bo_unref(screen, obj->bo);
FREE(obj);
}
@ -124,7 +131,6 @@ zink_resource_destroy(struct pipe_screen *pscreen,
/* no need to do anything for the caches, these objects own the resource lifetimes */
zink_resource_object_reference(screen, &res->obj, NULL);
zink_resource_object_reference(screen, &res->scanout_obj, NULL);
threaded_resource_deinit(pres);
FREE_CL(res);
}
@ -471,11 +477,12 @@ create_ici(struct zink_screen *screen, VkImageCreateInfo *ici, const struct pipe
static struct zink_resource_object *
resource_object_create(struct zink_screen *screen, const struct pipe_resource *templ, struct winsys_handle *whandle, bool *optimal_tiling,
const uint64_t *modifiers, int modifiers_count)
const uint64_t *modifiers, int modifiers_count, const void *loader_private)
{
struct zink_resource_object *obj = CALLOC_STRUCT(zink_resource_object);
if (!obj)
return NULL;
obj->last_dt_idx = obj->dt_idx = UINT32_MAX; //TODO: unionize
VkMemoryRequirements reqs = {0};
VkMemoryPropertyFlags flags;
@ -509,12 +516,14 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t
if (shared && screen->info.have_EXT_external_memory_dma_buf)
export_types |= VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
/* TODO: remove linear for wsi */
bool scanout = templ->bind & PIPE_BIND_SCANOUT;
pipe_reference_init(&obj->reference, 1);
util_dynarray_init(&obj->desc_set_refs.refs, NULL);
if (templ->target == PIPE_BUFFER) {
if (loader_private) {
obj->bo = CALLOC_STRUCT(zink_bo);
obj->transfer_dst = true;
util_queue_fence_init(&obj->present_fence);
return obj;
} else if (templ->target == PIPE_BUFFER) {
VkBufferCreateInfo bci = create_bci(screen, templ, templ->bind);
if (VKSCR(CreateBuffer)(screen->dev, &bci, NULL, &obj->buffer) != VK_SUCCESS) {
@ -588,10 +597,8 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t
idfmlci.pDrmFormatModifiers = modifiers;
ici.pNext = &idfmlci;
} else if (ici.tiling == VK_IMAGE_TILING_OPTIMAL) {
// TODO: remove for wsi
if (!external)
ici.pNext = NULL;
scanout = false;
shared = false;
}
}
@ -602,16 +609,6 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t
if (ici.usage & VK_IMAGE_USAGE_TRANSFER_DST_BIT)
obj->transfer_dst = true;
struct wsi_image_create_info image_wsi_info = {
VK_STRUCTURE_TYPE_WSI_IMAGE_CREATE_INFO_MESA,
NULL,
.scanout = scanout && ici.tiling != VK_IMAGE_TILING_DRM_FORMAT_MODIFIER_EXT,
};
if ((screen->needs_mesa_wsi || screen->needs_mesa_flush_wsi) && scanout) {
image_wsi_info.pNext = ici.pNext;
ici.pNext = &image_wsi_info;
}
if (util_format_is_yuv(templ->format)) {
VkFormatFeatureFlags feats = VK_FORMAT_FEATURE_FLAG_BITS_MAX_ENUM;
switch (ici.tiling) {
@ -808,18 +805,6 @@ resource_object_create(struct zink_screen *screen, const struct pipe_resource *t
}
#endif
struct wsi_memory_allocate_info memory_wsi_info = {
VK_STRUCTURE_TYPE_WSI_MEMORY_ALLOCATE_INFO_MESA,
NULL,
};
if (screen->needs_mesa_wsi && scanout) {
memory_wsi_info.implicit_sync = true;
memory_wsi_info.pNext = mai.pNext;
mai.pNext = &memory_wsi_info;
}
unsigned alignment = MAX2(reqs.alignment, 256);
if (templ->usage == PIPE_USAGE_STAGING && obj->is_buffer)
alignment = MAX2(alignment, screen->info.props.limits.minMemoryMapAlignment);
@ -899,7 +884,8 @@ resource_create(struct pipe_screen *pscreen,
const struct pipe_resource *templ,
struct winsys_handle *whandle,
unsigned external_usage,
const uint64_t *modifiers, int modifiers_count)
const uint64_t *modifiers, int modifiers_count,
const void *loader_private)
{
struct zink_screen *screen = zink_screen(pscreen);
struct zink_resource *res = CALLOC_STRUCT_CL(zink_resource);
@ -928,12 +914,7 @@ resource_create(struct pipe_screen *pscreen,
templ2.flags &= ~PIPE_RESOURCE_FLAG_SPARSE;
res->base.b.flags &= ~PIPE_RESOURCE_FLAG_SPARSE;
}
unsigned scanout_flags = templ->bind & (PIPE_BIND_SCANOUT | PIPE_BIND_SHARED);
if (whandle && whandle->type == ZINK_EXTERNAL_MEMORY_HANDLE)
scanout_flags = 0;
else if (!(templ->bind & PIPE_BIND_LINEAR))
templ2.bind &= ~scanout_flags;
res->obj = resource_object_create(screen, &templ2, whandle, &optimal_tiling, NULL, 0);
res->obj = resource_object_create(screen, &templ2, whandle, &optimal_tiling, modifiers, modifiers_count, loader_private);
if (!res->obj) {
free(res->modifiers);
FREE_CL(res);
@ -969,24 +950,34 @@ resource_create(struct pipe_screen *pscreen,
res->layout = res->dmabuf_acquire ? VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED;
res->optimal_tiling = optimal_tiling;
res->aspect = aspect_from_format(templ->format);
if (scanout_flags && optimal_tiling) {
// TODO: remove for wsi
templ2 = res->base.b;
templ2.bind = scanout_flags | PIPE_BIND_LINEAR;
res->scanout_obj = resource_object_create(screen, &templ2, whandle, &optimal_tiling, res->modifiers, res->modifiers_count);
assert(!optimal_tiling);
}
}
if (screen->winsys && (templ->bind & PIPE_BIND_DISPLAY_TARGET)) {
struct sw_winsys *winsys = screen->winsys;
res->dt = winsys->displaytarget_create(screen->winsys,
res->base.b.bind,
res->base.b.format,
templ->width0,
templ->height0,
64, NULL,
&res->dt_stride);
if (loader_private) {
if (templ->bind & PIPE_BIND_DISPLAY_TARGET) {
/* backbuffer */
res->obj->dt = zink_kopper_displaytarget_create(screen,
res->base.b.bind,
res->base.b.format,
templ->width0,
templ->height0,
64, loader_private,
&res->dt_stride);
assert(res->obj->dt);
} else {
/* frontbuffer */
struct zink_resource *back = (void*)loader_private;
struct kopper_displaytarget *cdt = back->obj->dt;
cdt->refcount++;
assert(back->obj->dt);
res->obj->dt = back->obj->dt;
}
struct kopper_displaytarget *cdt = res->obj->dt;
if (zink_kopper_has_srgb(cdt))
res->obj->vkflags |= VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT;
if (cdt->swapchain->scci.flags == VK_SWAPCHAIN_CREATE_MUTABLE_FORMAT_BIT_KHR)
res->obj->vkflags = VK_IMAGE_CREATE_MUTABLE_FORMAT_BIT | VK_IMAGE_CREATE_EXTENDED_USAGE_BIT_KHR;
res->obj->vkusage = cdt->swapchain->scci.imageUsage;
res->base.b.bind |= PIPE_BIND_DISPLAY_TARGET;
}
if (res->obj->is_buffer) {
res->base.buffer_id_unique = util_idalloc_mt_alloc(&screen->buffer_ids);
@ -1003,14 +994,22 @@ static struct pipe_resource *
zink_resource_create(struct pipe_screen *pscreen,
const struct pipe_resource *templ)
{
return resource_create(pscreen, templ, NULL, 0, NULL, 0);
return resource_create(pscreen, templ, NULL, 0, NULL, 0, NULL);
}
static struct pipe_resource *
zink_resource_create_with_modifiers(struct pipe_screen *pscreen, const struct pipe_resource *templ,
const uint64_t *modifiers, int modifiers_count)
{
return resource_create(pscreen, templ, NULL, 0, modifiers, modifiers_count);
return resource_create(pscreen, templ, NULL, 0, modifiers, modifiers_count, NULL);
}
static struct pipe_resource *
zink_resource_create_drawable(struct pipe_screen *pscreen,
const struct pipe_resource *templ,
const void *loader_private)
{
return resource_create(pscreen, templ, NULL, 0, NULL, 0, loader_private);
}
static bool
@ -1025,8 +1024,7 @@ zink_resource_get_param(struct pipe_screen *pscreen, struct pipe_context *pctx,
{
struct zink_screen *screen = zink_screen(pscreen);
struct zink_resource *res = zink_resource(pres);
//TODO: remove for wsi
struct zink_resource_object *obj = res->scanout_obj ? res->scanout_obj : res->obj;
struct zink_resource_object *obj = res->obj;
struct winsys_handle whandle;
VkImageAspectFlags aspect;
if (res->modifiers) {
@ -1140,13 +1138,12 @@ zink_resource_get_handle(struct pipe_screen *pscreen,
#ifdef ZINK_USE_DMABUF
struct zink_resource *res = zink_resource(tex);
struct zink_screen *screen = zink_screen(pscreen);
//TODO: remove for wsi
struct zink_resource_object *obj = res->scanout_obj ? res->scanout_obj : res->obj;
struct zink_resource_object *obj = res->obj;
assert(screen->drm_fd >= 0);
VkMemoryGetFdInfoKHR fd_info = {0};
int fd;
fd_info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
//TODO: remove for wsi
fd_info.memory = zink_bo_get_mem(obj->bo);
if (whandle->type == WINSYS_HANDLE_TYPE_FD)
fd_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
@ -1203,7 +1200,7 @@ zink_resource_from_handle(struct pipe_screen *pscreen,
modifier = whandle->modifier;
modifier_count = 1;
}
return resource_create(pscreen, &templ2, whandle, usage, &modifier, modifier_count);
return resource_create(pscreen, &templ2, whandle, usage, &modifier, modifier_count, NULL);
#else
return NULL;
#endif
@ -1246,7 +1243,7 @@ zink_resource_from_memobj(struct pipe_screen *pscreen,
{
struct zink_memory_object *memobj = (struct zink_memory_object *)pmemobj;
return resource_create(pscreen, templ, &memobj->whandle, 0, NULL, 0);
return resource_create(pscreen, templ, &memobj->whandle, 0, NULL, 0, NULL);
}
static bool
@ -1272,7 +1269,7 @@ invalidate_buffer(struct zink_context *ctx, struct zink_resource *res)
return false;
struct zink_resource_object *old_obj = res->obj;
struct zink_resource_object *new_obj = resource_object_create(screen, &res->base.b, NULL, NULL, NULL, 0);
struct zink_resource_object *new_obj = resource_object_create(screen, &res->base.b, NULL, NULL, NULL, 0, NULL);
if (!new_obj) {
debug_printf("new backing resource alloc failed!");
return false;
@ -1820,11 +1817,12 @@ zink_resource_object_init_storage(struct zink_context *ctx, struct zink_resource
if (res->obj->is_buffer) {
unreachable("zink: all buffers should have this bit");
} else {
assert(!res->obj->dt);
zink_fb_clears_apply_region(ctx, &res->base.b, (struct u_rect){0, res->base.b.width0, 0, res->base.b.height0});
zink_resource_image_barrier(ctx, res, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, 0, 0);
res->base.b.bind |= PIPE_BIND_SHADER_IMAGE;
struct zink_resource_object *old_obj = res->obj;
struct zink_resource_object *new_obj = resource_object_create(screen, &res->base.b, NULL, &res->optimal_tiling, res->modifiers, res->modifiers_count);
struct zink_resource_object *new_obj = resource_object_create(screen, &res->base.b, NULL, &res->optimal_tiling, res->modifiers, res->modifiers_count, NULL);
if (!new_obj) {
debug_printf("new backing resource alloc failed!");
res->base.b.bind &= ~PIPE_BIND_SHADER_IMAGE;
@ -1948,6 +1946,7 @@ zink_screen_resource_init(struct pipe_screen *pscreen)
struct zink_screen *screen = zink_screen(pscreen);
pscreen->resource_create = zink_resource_create;
pscreen->resource_create_with_modifiers = zink_resource_create_with_modifiers;
pscreen->resource_create_drawable = zink_resource_create_drawable;
pscreen->resource_destroy = zink_resource_destroy;
pscreen->transfer_helper = u_transfer_helper_create(&transfer_vtbl, true, true, false, false, !screen->have_D24_UNORM_S8_UINT);

View File

@ -79,7 +79,22 @@ struct zink_resource_object {
bool render_target;
bool is_buffer;
/* TODO: this should be a union */
struct zink_bo *bo;
// struct {
void *dt;
uint32_t dt_idx;
uint32_t last_dt_idx;
VkSemaphore acquire;
VkSemaphore present;
bool acquired;
bool new_dt;
bool dt_has_data;
bool indefinite_acquire;
struct util_queue_fence present_fence;
// }
VkDeviceSize offset, size, alignment;
VkImageCreateFlags vkflags;
VkImageUsageFlags vkusage;
@ -98,8 +113,6 @@ struct zink_resource {
enum pipe_format internal_format:16;
struct zink_resource_object *obj;
struct zink_resource_object *scanout_obj; //TODO: remove for wsi
bool scanout_obj_init;
union {
struct {
struct util_range valid_buffer_range;
@ -141,7 +154,6 @@ struct zink_resource {
};
bool dmabuf_acquire;
struct sw_displaytarget *dt;
unsigned dt_stride;
uint8_t modifiers_count;

View File

@ -23,6 +23,7 @@
#include "zink_screen.h"
#include "zink_kopper.h"
#include "zink_compiler.h"
#include "zink_context.h"
#include "zink_device_info.h"
@ -50,6 +51,8 @@
#include "util/u_cpu_detect.h"
#include "driver_trace/tr_context.h"
#include "frontend/sw_winsys.h"
#if DETECT_OS_WINDOWS
@ -1204,6 +1207,10 @@ zink_destroy_screen(struct pipe_screen *pscreen)
{
struct zink_screen *screen = zink_screen(pscreen);
hash_table_foreach(&screen->dts, entry)
zink_kopper_deinit_displaytarget(screen, entry->data);
simple_mtx_destroy(&screen->dt_lock);
if (VK_NULL_HANDLE != screen->debugUtilsCallbackHandle) {
VKSCR(DestroyDebugUtilsMessengerEXT)(screen->instance, screen->debugUtilsCallbackHandle, NULL);
}
@ -1341,36 +1348,43 @@ init_queue(struct zink_screen *screen)
static void
zink_flush_frontbuffer(struct pipe_screen *pscreen,
struct pipe_context *pcontext,
struct pipe_context *pctx,
struct pipe_resource *pres,
unsigned level, unsigned layer,
void *winsys_drawable_handle,
struct pipe_box *sub_box)
{
struct zink_screen *screen = zink_screen(pscreen);
struct sw_winsys *winsys = screen->winsys;
struct zink_resource *res = zink_resource(pres);
struct zink_context *ctx = zink_context(pctx);
if (!winsys)
return;
void *map = winsys->displaytarget_map(winsys, res->dt, 0);
/* if the surface has never been acquired, there's nothing to present,
* so this is a no-op */
if (!res->obj->acquired && res->obj->last_dt_idx == UINT32_MAX)
return;
if (map) {
struct pipe_transfer *transfer = NULL;
void *res_map = pipe_texture_map(pcontext, pres, level, layer, PIPE_MAP_READ, 0, 0,
u_minify(pres->width0, level),
u_minify(pres->height0, level),
&transfer);
if (res_map) {
util_copy_rect((ubyte*)map, pres->format, res->dt_stride, 0, 0,
transfer->box.width, transfer->box.height,
(const ubyte*)res_map, transfer->stride, 0, 0);
pipe_texture_unmap(pcontext, transfer);
/* need to get the actual zink_context, not the threaded context */
if (screen->threaded)
pctx = threaded_context_unwrap_sync(pctx);
pctx = trace_get_possibly_threaded_context(pctx);
ctx = zink_context(pctx);
if (ctx->batch.swapchain) {
pctx->flush(pctx, NULL, 0);
if (ctx->last_fence && screen->threaded) {
struct zink_batch_state *bs = zink_batch_state(ctx->last_fence);
util_queue_fence_wait(&bs->flush_completed);
}
winsys->displaytarget_unmap(winsys, res->dt);
}
winsys->displaytarget_display(winsys, res->dt, winsys_drawable_handle, sub_box);
if (res->obj->acquired)
zink_kopper_present_queue(screen, res);
else {
assert(res->obj->last_dt_idx != UINT32_MAX);
if (!zink_kopper_last_present_eq(res->obj->dt, res->obj->last_dt_idx)) {
zink_kopper_acquire_readback(ctx, res);
zink_kopper_present_readback(ctx, res);
}
}
}
bool
@ -1619,23 +1633,6 @@ zink_internal_setup_moltenvk(struct zink_screen *screen)
return true;
}
static void
check_device_needs_mesa_wsi(struct zink_screen *screen)
{
if (
/* Raspberry Pi 4 V3DV driver */
(screen->info.props.vendorID == 0x14E4 &&
screen->info.props.deviceID == 42) ||
/* RADV */
screen->info.driver_props.driverID == VK_DRIVER_ID_MESA_RADV_KHR
) {
screen->needs_mesa_wsi = true;
} else if (screen->info.driver_props.driverID == VK_DRIVER_ID_INTEL_OPEN_SOURCE_MESA_KHR ||
screen->info.driver_props.driverID == VK_DRIVER_ID_MESA_VENUS)
screen->needs_mesa_flush_wsi = true;
}
static void
populate_format_props(struct zink_screen *screen)
{
@ -2150,11 +2147,6 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
if (screen->threaded)
util_queue_init(&screen->flush_queue, "zfq", 8, 1, UTIL_QUEUE_INIT_RESIZE_IF_FULL, screen);
/* Some Vulkan implementations have special requirements for WSI
* allocations.
*/
check_device_needs_mesa_wsi(screen);
zink_internal_setup_moltenvk(screen);
screen->dev = zink_create_logical_device(screen);
@ -2293,6 +2285,8 @@ zink_internal_create_screen(const struct pipe_screen_config *config)
_mesa_hash_table_init(&screen->framebuffer_cache, screen, hash_framebuffer_state, equals_framebuffer_state);
}
simple_mtx_init(&screen->dt_lock, mtx_plain);
zink_screen_init_descriptor_funcs(screen, false);
util_idalloc_mt_init_tc(&screen->buffer_ids);
@ -2312,12 +2306,12 @@ fail:
}
struct pipe_screen *
zink_create_screen(struct sw_winsys *winsys)
zink_create_screen(struct sw_winsys *winsys, const struct pipe_screen_config *config)
{
struct zink_screen *ret = zink_internal_create_screen(NULL);
struct zink_screen *ret = zink_internal_create_screen(config);
if (ret) {
ret->winsys = winsys;
ret->drm_fd = -1;
ret->sw_winsys = winsys;
}
return &ret->base;

View File

@ -40,6 +40,9 @@
#include "util/u_vertex_state_cache.h"
#include "pipebuffer/pb_cache.h"
#include "pipebuffer/pb_slab.h"
#include "frontend/sw_winsys.h"
#include "kopper_interface.h"
#include <vulkan/vulkan.h>
extern uint32_t zink_debug;
@ -87,9 +90,14 @@ struct zink_screen {
unsigned buffer_rebind_counter;
struct hash_table dts;
simple_mtx_t dt_lock;
bool device_lost;
struct sw_winsys *winsys;
int drm_fd;
struct sw_winsys winsys;
struct sw_winsys *sw_winsys; // wrapped
__DRIkopperLoaderExtension *loader;
struct hash_table framebuffer_cache;
simple_mtx_t framebuffer_mtx;
@ -145,9 +153,6 @@ struct zink_screen {
uint32_t cur_custom_border_color_samplers;
bool needs_mesa_wsi;
bool needs_mesa_flush_wsi;
struct vk_dispatch_table vk;
bool (*descriptor_program_init)(struct zink_context *ctx, struct zink_program *pg);
@ -184,7 +189,6 @@ struct zink_screen {
} driver_workarounds;
};
/* update last_finished to account for batch_id wrapping */
static inline void
zink_screen_update_last_finished(struct zink_screen *screen, uint32_t batch_id)

View File

@ -26,6 +26,7 @@
#include "zink_resource.h"
#include "zink_screen.h"
#include "zink_surface.h"
#include "zink_kopper.h"
#include "util/format/u_format.h"
#include "util/u_inlines.h"
@ -114,7 +115,12 @@ init_surface_info(struct zink_surface *surface, struct zink_resource *res, VkIma
surface->info.width = surface->base.width;
surface->info.height = surface->base.height;
surface->info.layerCount = ivci->subresourceRange.layerCount;
surface->info.format = ivci->format;
surface->info.format[0] = ivci->format;
if (res->obj->dt) {
struct kopper_displaytarget *cdt = res->obj->dt;
if (zink_kopper_has_srgb(cdt))
surface->info.format[1] = ivci->format == cdt->formats[0] ? cdt->formats[1] : cdt->formats[0];
}
surface->info_hash = _mesa_hash_data(&surface->info, sizeof(surface->info));
}
@ -249,7 +255,16 @@ zink_create_surface(struct pipe_context *pctx,
VkImageViewCreateInfo ivci = create_ivci(zink_screen(pctx->screen), res, templ,
pres->target == PIPE_TEXTURE_3D ? target_2d[is_array] : pres->target);
struct pipe_surface *psurf = zink_get_surface(zink_context(pctx), pres, templ, &ivci);
struct pipe_surface *psurf = NULL;
if (res->obj->dt) {
/* don't cache swapchain surfaces. that's weird. */
struct zink_surface *surface = do_create_surface(pctx, pres, templ, &ivci, 0, false);
if (surface) {
surface->is_swapchain = true;
psurf = &surface->base;
}
} else
psurf = zink_get_surface(zink_context(pctx), pres, templ, &ivci);
if (!psurf)
return NULL;
@ -308,7 +323,7 @@ zink_destroy_surface(struct zink_screen *screen, struct pipe_surface *psurface)
{
struct zink_surface *surface = zink_surface(psurface);
struct zink_resource *res = zink_resource(psurface->texture);
if (!psurface->nr_samples) {
if (!psurface->nr_samples && !surface->is_swapchain) {
simple_mtx_lock(&res->surface_mtx);
if (psurface->reference.count) {
/* got a cache hit during deletion */
@ -325,10 +340,17 @@ zink_destroy_surface(struct zink_screen *screen, struct pipe_surface *psurface)
surface_clear_fb_refs(screen, psurface);
zink_descriptor_set_refs_clear(&surface->desc_set_refs, surface);
util_dynarray_fini(&surface->framebuffer_refs);
pipe_resource_reference(&psurface->texture, NULL);
if (surface->simage_view)
VKSCR(DestroyImageView)(screen->dev, surface->simage_view, NULL);
VKSCR(DestroyImageView)(screen->dev, surface->image_view, NULL);
if (surface->is_swapchain) {
for (unsigned i = 0; i < surface->old_swapchain_size; i++)
VKSCR(DestroyImageView)(screen->dev, surface->old_swapchain[i], NULL);
for (unsigned i = 0; i < surface->swapchain_size; i++)
VKSCR(DestroyImageView)(screen->dev, surface->swapchain[i], NULL);
free(surface->swapchain);
} else
VKSCR(DestroyImageView)(screen->dev, surface->image_view, NULL);
pipe_resource_reference(&psurface->texture, NULL);
FREE(surface);
}
@ -350,6 +372,7 @@ zink_rebind_surface(struct zink_context *ctx, struct pipe_surface **psurface)
struct zink_screen *screen = zink_screen(ctx->base.screen);
if (surface->simage_view)
return false;
assert(!res->obj->dt);
VkImageViewCreateInfo ivci = create_ivci(screen,
zink_resource((*psurface)->texture), (*psurface), surface->base.texture->target);
uint32_t hash = hash_ivci(&ivci);
@ -425,3 +448,29 @@ zink_context_surface_init(struct pipe_context *context)
context->create_surface = zink_create_surface;
context->surface_destroy = zink_surface_destroy;
}
void
zink_surface_swapchain_update(struct zink_context *ctx, struct zink_surface *surface)
{
struct zink_screen *screen = zink_screen(ctx->base.screen);
struct zink_resource *res = zink_resource(surface->base.texture);
struct kopper_displaytarget *cdt = res->obj->dt;
if (res->obj->dt != surface->dt) {
/* new swapchain: clear out previous old_swapchain and move current swapchain there */
for (unsigned i = 0; i < surface->old_swapchain_size; i++)
util_dynarray_append(&ctx->batch.state->dead_swapchains, VkImageView, surface->old_swapchain[i]);
free(surface->old_swapchain);
surface->old_swapchain = surface->swapchain;
surface->old_swapchain_size = surface->swapchain_size;
surface->swapchain_size = cdt->swapchain->num_images;
surface->swapchain = calloc(surface->swapchain_size, sizeof(VkImageView));
init_surface_info(surface, res, &surface->ivci);
}
if (!surface->swapchain[res->obj->dt_idx]) {
assert(res->obj->image && cdt->swapchain->images[res->obj->dt_idx] == res->obj->image);
surface->ivci.image = res->obj->image;
assert(surface->ivci.image);
VKSCR(CreateImageView)(screen->dev, &surface->ivci, NULL, &surface->swapchain[res->obj->dt_idx]);
}
surface->image_view = surface->swapchain[res->obj->dt_idx];
}

View File

@ -36,7 +36,7 @@ struct zink_surface_info {
uint32_t width;
uint32_t height;
uint32_t layerCount;
VkFormat format;
VkFormat format[2];
};
struct zink_surface {
@ -44,7 +44,13 @@ struct zink_surface {
VkImageViewCreateInfo ivci;
struct zink_surface_info info; //TODO: union with fb refs
uint32_t info_hash;
bool is_swapchain;
VkImageView image_view;
void *dt;
VkImageView *swapchain;
unsigned swapchain_size;
VkImageView *old_swapchain;
unsigned old_swapchain_size;
VkImageView simage_view;//old iview after storage replacement/rebind
void *obj; //backing resource object
uint32_t hash;
@ -141,4 +147,7 @@ zink_rebind_ctx_surface(struct zink_context *ctx, struct pipe_surface **psurface
struct pipe_surface *
zink_surface_create_null(struct zink_context *ctx, enum pipe_texture_target target, unsigned width, unsigned height, unsigned samples);
void
zink_surface_swapchain_update(struct zink_context *ctx, struct zink_surface *surface);
#endif

View File

@ -346,11 +346,9 @@ kopper_update_drawable_info(struct dri_drawable *drawable)
drawable->textures[ST_ATTACHMENT_BACK_LEFT] :
drawable->textures[ST_ATTACHMENT_FRONT_LEFT];
#if 0
if (is_window && ptex && kscreen->base.fd == -1)
zink_kopper_update(screen, ptex, &dPriv->w, &dPriv->h);
else
#endif
get_drawable_info(dPriv, &x, &y, &dPriv->w, &dPriv->h);
}

View File

@ -97,7 +97,7 @@ wgl_screen_create_by_name(HDC hDC, const char* driver, struct sw_winsys *winsys)
#endif
#ifdef GALLIUM_ZINK
if (strcmp(driver, "zink") == 0) {
screen = zink_create_screen(winsys);
screen = zink_create_screen(winsys, NULL);
if (screen)
use_zink = TRUE;
}