tc: add resolve resource to rp info
this allows non-winsys resolves to be optimized out Acked-by: Marek Olšák <marek.olsak@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35477>
This commit is contained in:
@@ -232,17 +232,21 @@ tc_batch_increment_renderpass_info(struct threaded_context *tc, unsigned batch_i
|
|||||||
/* copy the previous data in its entirety: this is still the same renderpass */
|
/* copy the previous data in its entirety: this is still the same renderpass */
|
||||||
if (tc->renderpass_info_recording) {
|
if (tc->renderpass_info_recording) {
|
||||||
tc_info[batch->renderpass_info_idx].info.data = tc->renderpass_info_recording->data;
|
tc_info[batch->renderpass_info_idx].info.data = tc->renderpass_info_recording->data;
|
||||||
|
tc_info[batch->renderpass_info_idx].info.resolve = tc->renderpass_info_recording->resolve;
|
||||||
|
tc->renderpass_info_recording->resolve = NULL;
|
||||||
tc_batch_rp_info(tc->renderpass_info_recording)->next = &tc_info[batch->renderpass_info_idx];
|
tc_batch_rp_info(tc->renderpass_info_recording)->next = &tc_info[batch->renderpass_info_idx];
|
||||||
tc_info[batch->renderpass_info_idx].prev = tc_batch_rp_info(tc->renderpass_info_recording);
|
tc_info[batch->renderpass_info_idx].prev = tc_batch_rp_info(tc->renderpass_info_recording);
|
||||||
/* guard against deadlock scenario */
|
/* guard against deadlock scenario */
|
||||||
assert(&tc_batch_rp_info(tc->renderpass_info_recording)->next->info != tc->renderpass_info_recording);
|
assert(&tc_batch_rp_info(tc->renderpass_info_recording)->next->info != tc->renderpass_info_recording);
|
||||||
} else {
|
} else {
|
||||||
tc_info[batch->renderpass_info_idx].info.data = 0;
|
tc_info[batch->renderpass_info_idx].info.data = 0;
|
||||||
|
pipe_resource_reference(&tc_info[batch->renderpass_info_idx].info.resolve, NULL);
|
||||||
tc_info[batch->renderpass_info_idx].prev = NULL;
|
tc_info[batch->renderpass_info_idx].prev = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* selectively copy: only the CSO metadata is copied, and a new framebuffer state will be added later */
|
/* selectively copy: only the CSO metadata is copied, and a new framebuffer state will be added later */
|
||||||
tc_info[batch->renderpass_info_idx].info.data = 0;
|
tc_info[batch->renderpass_info_idx].info.data = 0;
|
||||||
|
pipe_resource_reference(&tc_info[batch->renderpass_info_idx].info.resolve, NULL);
|
||||||
if (tc->renderpass_info_recording) {
|
if (tc->renderpass_info_recording) {
|
||||||
tc_info[batch->renderpass_info_idx].info.data16[2] = tc->renderpass_info_recording->data16[2];
|
tc_info[batch->renderpass_info_idx].info.data16[2] = tc->renderpass_info_recording->data16[2];
|
||||||
tc_batch_rp_info(tc->renderpass_info_recording)->next = NULL;
|
tc_batch_rp_info(tc->renderpass_info_recording)->next = NULL;
|
||||||
@@ -1477,6 +1481,9 @@ tc_set_framebuffer_state(struct pipe_context *_pipe,
|
|||||||
tc_set_resource_batch_usage_persistent(tc, tc->fb_resources[i], true);
|
tc_set_resource_batch_usage_persistent(tc, tc->fb_resources[i], true);
|
||||||
}
|
}
|
||||||
tc->nr_cbufs = nr_cbufs;
|
tc->nr_cbufs = nr_cbufs;
|
||||||
|
tc->fb_layers = util_framebuffer_get_num_layers(fb);
|
||||||
|
tc->fb_width = fb->width;
|
||||||
|
tc->fb_height = fb->height;
|
||||||
if (tc->options.parse_renderpass_info) {
|
if (tc->options.parse_renderpass_info) {
|
||||||
/* store existing zsbuf data for possible persistence */
|
/* store existing zsbuf data for possible persistence */
|
||||||
uint8_t zsbuf = tc->renderpass_info_recording->has_draw ?
|
uint8_t zsbuf = tc->renderpass_info_recording->has_draw ?
|
||||||
@@ -1500,7 +1507,9 @@ tc_set_framebuffer_state(struct pipe_context *_pipe,
|
|||||||
* just increment the index and keep using the existing info for recording
|
* just increment the index and keep using the existing info for recording
|
||||||
*/
|
*/
|
||||||
tc->batch_slots[tc->next].renderpass_info_idx = 0;
|
tc->batch_slots[tc->next].renderpass_info_idx = 0;
|
||||||
|
tc->renderpass_info_recording->has_resolve = false;
|
||||||
}
|
}
|
||||||
|
assert(!tc->renderpass_info_recording->resolve);
|
||||||
tc->seen_fb_state = true;
|
tc->seen_fb_state = true;
|
||||||
}
|
}
|
||||||
/* ref for cmd */
|
/* ref for cmd */
|
||||||
@@ -4498,7 +4507,13 @@ tc_call_blit(struct pipe_context *pipe, void *call)
|
|||||||
return call_size(tc_blit_call);
|
return call_size(tc_blit_call);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static uint16_t ALWAYS_INLINE
|
||||||
|
tc_call_resolve(struct pipe_context *pipe, void *call)
|
||||||
|
{
|
||||||
|
return tc_call_blit(pipe, call);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct tc_blit_call *
|
||||||
tc_blit_enqueue(struct threaded_context *tc, const struct pipe_blit_info *info)
|
tc_blit_enqueue(struct threaded_context *tc, const struct pipe_blit_info *info)
|
||||||
{
|
{
|
||||||
struct tc_blit_call *blit = tc_add_call(tc, TC_CALL_blit, tc_blit_call);
|
struct tc_blit_call *blit = tc_add_call(tc, TC_CALL_blit, tc_blit_call);
|
||||||
@@ -4508,6 +4523,7 @@ tc_blit_enqueue(struct threaded_context *tc, const struct pipe_blit_info *info)
|
|||||||
tc_set_resource_batch_usage(tc, info->src.resource);
|
tc_set_resource_batch_usage(tc, info->src.resource);
|
||||||
tc_set_resource_reference(&blit->info.src.resource, info->src.resource);
|
tc_set_resource_reference(&blit->info.src.resource, info->src.resource);
|
||||||
memcpy(&blit->info, info, sizeof(*info));
|
memcpy(&blit->info, info, sizeof(*info));
|
||||||
|
return blit;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@@ -4518,29 +4534,62 @@ tc_blit(struct pipe_context *_pipe, const struct pipe_blit_info *info)
|
|||||||
/* filter out untracked non-resolves */
|
/* filter out untracked non-resolves */
|
||||||
if (!tc->options.parse_renderpass_info ||
|
if (!tc->options.parse_renderpass_info ||
|
||||||
info->src.resource->nr_samples <= 1 ||
|
info->src.resource->nr_samples <= 1 ||
|
||||||
info->dst.resource->nr_samples > 1) {
|
info->dst.resource->nr_samples > 1 ||
|
||||||
|
info->scissor_enable ||
|
||||||
|
info->swizzle_enable ||
|
||||||
|
info->alpha_blend ||
|
||||||
|
info->src.resource->format != info->src.format ||
|
||||||
|
info->dst.resource->format != info->dst.format ||
|
||||||
|
info->src.format != info->dst.format ||
|
||||||
|
info->src.box.width < 0 ||
|
||||||
|
info->src.box.height < 0 ||
|
||||||
|
info->src.box.depth < 0 ||
|
||||||
|
info->dst.box.width < 0 ||
|
||||||
|
info->dst.box.height < 0 ||
|
||||||
|
info->dst.box.depth < 0 ||
|
||||||
|
info->src.box.x != info->dst.box.x ||
|
||||||
|
info->src.box.y != info->dst.box.y ||
|
||||||
|
info->src.box.z != info->dst.box.z ||
|
||||||
|
info->src.box.width != info->dst.box.width ||
|
||||||
|
info->src.box.height != info->dst.box.height ||
|
||||||
|
info->src.box.depth != info->dst.box.depth ||
|
||||||
|
info->src.box.width != tc->fb_width ||
|
||||||
|
info->src.box.height != tc->fb_height ||
|
||||||
|
tc->renderpass_info_recording->ended ||
|
||||||
|
(info->dst.resource->array_size && info->dst.resource->array_size != tc->fb_layers) ||
|
||||||
|
(!tc->renderpass_info_recording->has_draw && !tc->renderpass_info_recording->cbuf_clear && !tc->renderpass_info_recording->zsbuf_clear)) {
|
||||||
if (tc->options.parse_renderpass_info && tc->in_renderpass)
|
if (tc->options.parse_renderpass_info && tc->in_renderpass)
|
||||||
tc_check_fb_access(tc, info->src.resource, info->dst.resource);
|
tc_check_fb_access(tc, info->src.resource, info->dst.resource);
|
||||||
tc_blit_enqueue(tc, info);
|
tc_blit_enqueue(tc, info);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct pipe_resource *src = tc->nr_cbufs ? tc->fb_resources[0] : tc->fb_resources[PIPE_MAX_COLOR_BUFS];
|
||||||
if (tc->fb_resolve == info->dst.resource) {
|
if (tc->fb_resolve == info->dst.resource) {
|
||||||
|
#if TC_DEBUG >= 3
|
||||||
|
tc_printf("WSI RESOLVE MERGE");
|
||||||
|
#endif
|
||||||
/* optimize out this blit entirely */
|
/* optimize out this blit entirely */
|
||||||
tc->renderpass_info_recording->has_resolve = true;
|
tc->renderpass_info_recording->has_resolve = true;
|
||||||
tc->renderpass_info_recording->ended = true;
|
tc->renderpass_info_recording->ended = true;
|
||||||
tc_signal_renderpass_info_ready(tc);
|
tc_signal_renderpass_info_ready(tc);
|
||||||
return;
|
} else if (src == info->src.resource &&
|
||||||
}
|
(!tc->renderpass_info_recording->has_resolve ||
|
||||||
for (unsigned i = 0; i < PIPE_MAX_COLOR_BUFS; i++) {
|
tc->renderpass_info_recording->resolve == info->dst.resource)) {
|
||||||
if (tc->fb_resources[i] == info->src.resource) {
|
#if TC_DEBUG >= 3
|
||||||
tc->renderpass_info_recording->has_resolve = true;
|
tc_printf("RESOLVE MERGE");
|
||||||
break;
|
#endif
|
||||||
}
|
/* can only optimize out the first resolve */
|
||||||
}
|
tc->renderpass_info_recording->has_resolve = true;
|
||||||
if (tc->options.parse_renderpass_info && tc->in_renderpass)
|
pipe_resource_reference(&tc->renderpass_info_recording->resolve, info->dst.resource);
|
||||||
|
tc_set_resource_batch_usage(tc, info->dst.resource);
|
||||||
|
tc->renderpass_info_recording->ended = true;
|
||||||
|
tc_signal_renderpass_info_ready(tc);
|
||||||
|
} else if (tc->in_renderpass) {
|
||||||
tc_check_fb_access(tc, info->src.resource, info->dst.resource);
|
tc_check_fb_access(tc, info->src.resource, info->dst.resource);
|
||||||
tc_blit_enqueue(tc, info);
|
}
|
||||||
|
struct tc_blit_call *blit = tc_blit_enqueue(tc, info);
|
||||||
|
blit->base.call_id = TC_CALL_resolve;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct tc_generate_mipmap {
|
struct tc_generate_mipmap {
|
||||||
|
|||||||
@@ -440,7 +440,7 @@ struct tc_renderpass_info {
|
|||||||
bool zsbuf_invalidate : 1;
|
bool zsbuf_invalidate : 1;
|
||||||
/* whether a draw occurs */
|
/* whether a draw occurs */
|
||||||
bool has_draw : 1;
|
bool has_draw : 1;
|
||||||
/* whether a framebuffer resolve occurs on cbuf[0] */
|
/* whether a framebuffer resolve occurs on cbuf[0] or zsbuf */
|
||||||
bool has_resolve : 1;
|
bool has_resolve : 1;
|
||||||
/* whether queries are ended during this renderpass */
|
/* whether queries are ended during this renderpass */
|
||||||
bool has_query_ends : 1;
|
bool has_query_ends : 1;
|
||||||
@@ -468,6 +468,8 @@ struct tc_renderpass_info {
|
|||||||
/* zsbuf fb info is in data8[3] & BITFIELD_MASK(4) */
|
/* zsbuf fb info is in data8[3] & BITFIELD_MASK(4) */
|
||||||
uint8_t data8[8];
|
uint8_t data8[8];
|
||||||
};
|
};
|
||||||
|
/* only valid if has_resolve is true and the resolve member of pipe_framebuffer_state is NULL */
|
||||||
|
struct pipe_resource *resolve;
|
||||||
};
|
};
|
||||||
|
|
||||||
static inline bool
|
static inline bool
|
||||||
@@ -640,6 +642,9 @@ struct threaded_context {
|
|||||||
unsigned max_images;
|
unsigned max_images;
|
||||||
unsigned max_samplers;
|
unsigned max_samplers;
|
||||||
unsigned nr_cbufs;
|
unsigned nr_cbufs;
|
||||||
|
unsigned fb_layers;
|
||||||
|
uint16_t fb_width;
|
||||||
|
uint16_t fb_height;
|
||||||
|
|
||||||
unsigned last, next, next_buf_list;
|
unsigned last, next, next_buf_list;
|
||||||
|
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ CALL(draw_vstate_single)
|
|||||||
CALL(draw_vstate_multi)
|
CALL(draw_vstate_multi)
|
||||||
CALL(launch_grid)
|
CALL(launch_grid)
|
||||||
CALL(blit)
|
CALL(blit)
|
||||||
|
CALL(resolve)
|
||||||
CALL(generate_mipmap)
|
CALL(generate_mipmap)
|
||||||
CALL(invalidate_resource)
|
CALL(invalidate_resource)
|
||||||
CALL(clear_render_target)
|
CALL(clear_render_target)
|
||||||
|
|||||||
@@ -330,6 +330,18 @@ zink_blit(struct pipe_context *pctx,
|
|||||||
struct zink_resource *use_src = src;
|
struct zink_resource *use_src = src;
|
||||||
struct zink_resource *dst = zink_resource(info->dst.resource);
|
struct zink_resource *dst = zink_resource(info->dst.resource);
|
||||||
bool needs_present_readback = false;
|
bool needs_present_readback = false;
|
||||||
|
|
||||||
|
if (ctx->awaiting_resolve && ctx->in_rp && ctx->dynamic_fb.tc_info.has_resolve) {
|
||||||
|
struct pipe_resource *resolve = ctx->fb_state.resolve;
|
||||||
|
if (!resolve)
|
||||||
|
resolve = ctx->dynamic_fb.tc_info.resolve;
|
||||||
|
if (resolve == info->dst.resource) {
|
||||||
|
zink_batch_no_rp_safe(ctx);
|
||||||
|
ctx->awaiting_resolve = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (zink_is_swapchain(dst)) {
|
if (zink_is_swapchain(dst)) {
|
||||||
if (!zink_kopper_acquire(ctx, dst, UINT64_MAX))
|
if (!zink_kopper_acquire(ctx, dst, UINT64_MAX))
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -72,6 +72,8 @@ update_tc_info(struct zink_context *ctx)
|
|||||||
const struct tc_renderpass_info *info = threaded_context_get_renderpass_info(ctx->tc);
|
const struct tc_renderpass_info *info = threaded_context_get_renderpass_info(ctx->tc);
|
||||||
ctx->rp_changed |= ctx->dynamic_fb.tc_info.data != info->data;
|
ctx->rp_changed |= ctx->dynamic_fb.tc_info.data != info->data;
|
||||||
ctx->dynamic_fb.tc_info.data = info->data;
|
ctx->dynamic_fb.tc_info.data = info->data;
|
||||||
|
ctx->dynamic_fb.tc_info.resolve = info->resolve;
|
||||||
|
ctx->awaiting_resolve = ctx->dynamic_fb.tc_info.has_resolve;
|
||||||
} else {
|
} else {
|
||||||
struct tc_renderpass_info info = ctx->dynamic_fb.tc_info;
|
struct tc_renderpass_info info = ctx->dynamic_fb.tc_info;
|
||||||
bool zsbuf_used = !ctx->zsbuf_unused;
|
bool zsbuf_used = !ctx->zsbuf_unused;
|
||||||
@@ -3204,22 +3206,37 @@ begin_rendering(struct zink_context *ctx, bool check_msaa_expand)
|
|||||||
ctx->dynamic_fb.attachments[PIPE_MAX_COLOR_BUFS + 1].resolveMode = 0;
|
ctx->dynamic_fb.attachments[PIPE_MAX_COLOR_BUFS + 1].resolveMode = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ctx->fb_state.resolve && use_tc_info && ctx->dynamic_fb.tc_info.has_resolve) {
|
if (use_tc_info && ctx->dynamic_fb.tc_info.has_resolve) {
|
||||||
struct zink_resource *res = zink_resource(ctx->fb_state.resolve);
|
struct zink_resource *res = zink_resource(ctx->fb_state.resolve);
|
||||||
zink_surface_resolve_init(screen, res, ctx->fb_state.resolve->format);
|
if (!res)
|
||||||
|
res = zink_resource(ctx->dynamic_fb.tc_info.resolve);
|
||||||
|
assert(res);
|
||||||
|
zink_batch_resource_usage_set(ctx->bs, res, true, false);
|
||||||
|
bool is_depth = util_format_is_depth_or_stencil(res->base.b.format);
|
||||||
|
enum pipe_format format = res->base.b.format;
|
||||||
|
if (!ctx->fb_state.resolve)
|
||||||
|
format = is_depth ? ctx->fb_state.zsbuf.format : ctx->fb_state.cbufs[0].format;
|
||||||
|
zink_surface_resolve_init(screen, res, format);
|
||||||
struct zink_surface *surf = zink_surface(res->surface);
|
struct zink_surface *surf = zink_surface(res->surface);
|
||||||
if (zink_is_swapchain(res)) {
|
if (zink_is_swapchain(res)) {
|
||||||
if (!zink_kopper_acquire(ctx, res, UINT64_MAX))
|
if (!zink_kopper_acquire(ctx, res, UINT64_MAX))
|
||||||
return 0;
|
return 0;
|
||||||
zink_surface_swapchain_update(ctx, surf);
|
zink_surface_swapchain_update(ctx, surf);
|
||||||
}
|
}
|
||||||
zink_batch_resource_usage_set(ctx->bs, res, true, false);
|
VkImageLayout layout = is_depth ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
||||||
VkImageLayout layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
|
if (screen->driver_workarounds.general_layout)
|
||||||
|
layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||||
|
unsigned idx = util_format_is_depth_or_stencil(res->base.b.format) ? PIPE_MAX_COLOR_BUFS : 0;
|
||||||
screen->image_barrier(ctx, res, layout, 0, 0);
|
screen->image_barrier(ctx, res, layout, 0, 0);
|
||||||
res->obj->unordered_read = res->obj->unordered_write = false;
|
res->obj->unordered_read = res->obj->unordered_write = false;
|
||||||
ctx->dynamic_fb.attachments[0].resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
|
ctx->dynamic_fb.attachments[idx].resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
|
||||||
ctx->dynamic_fb.attachments[0].resolveImageLayout = zink_resource(surf->base.texture)->layout;
|
ctx->dynamic_fb.attachments[idx].resolveImageLayout = zink_resource(surf->base.texture)->layout;
|
||||||
ctx->dynamic_fb.attachments[0].resolveImageView = surf->image_view;
|
ctx->dynamic_fb.attachments[idx].resolveImageView = surf->image_view;
|
||||||
|
if (idx == PIPE_MAX_COLOR_BUFS) {
|
||||||
|
ctx->dynamic_fb.attachments[idx + 1].resolveMode = VK_RESOLVE_MODE_AVERAGE_BIT;
|
||||||
|
ctx->dynamic_fb.attachments[idx + 1].resolveImageLayout = zink_resource(surf->base.texture)->layout;
|
||||||
|
ctx->dynamic_fb.attachments[idx + 1].resolveImageView = surf->image_view;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
ctx->zsbuf_unused = !zsbuf_used;
|
ctx->zsbuf_unused = !zsbuf_used;
|
||||||
assert(ctx->fb_state.width >= ctx->dynamic_fb.info.renderArea.extent.width);
|
assert(ctx->fb_state.width >= ctx->dynamic_fb.info.renderArea.extent.width);
|
||||||
|
|||||||
@@ -1768,6 +1768,7 @@ struct zink_context {
|
|||||||
struct set rendering_state_cache[6]; //[util_logbase2_ceil(msrtss samplecount)]
|
struct set rendering_state_cache[6]; //[util_logbase2_ceil(msrtss samplecount)]
|
||||||
struct zink_resource *swapchain;
|
struct zink_resource *swapchain;
|
||||||
VkExtent2D swapchain_size;
|
VkExtent2D swapchain_size;
|
||||||
|
bool awaiting_resolve; //from tc info
|
||||||
bool in_rp; //renderpass is currently active
|
bool in_rp; //renderpass is currently active
|
||||||
bool rp_changed; //force renderpass restart
|
bool rp_changed; //force renderpass restart
|
||||||
bool rp_layout_changed; //renderpass changed, maybe restart
|
bool rp_layout_changed; //renderpass changed, maybe restart
|
||||||
|
|||||||
Reference in New Issue
Block a user