#define XXH_INLINE_ALL
#include "util/xxhash.h"
+static void
+update_tc_info(struct zink_context *ctx, bool wait)
+{
+ if (ctx->tc) {
+ const struct tc_renderpass_info *info = threaded_context_get_renderpass_info(ctx->tc, wait);
+ if (info) {
+ ctx->rp_changed |= ctx->dynamic_fb.tc_info.data != info->data;
+ ctx->dynamic_fb.tc_info.data = info->data;
+ }
+ }
+}
+
void
debug_describe_zink_buffer_view(char *buf, const struct zink_buffer_view *ptr)
{
bool has_stencil = false;
bool changed_layout = false;
bool changed_size = false;
+ bool zsbuf_used = zink_is_zsbuf_used(ctx);
if (ctx->rp_changed || ctx->rp_layout_changed || ctx->rp_loadop_changed) {
/* init imageviews, base loadOp, formats */
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
ctx->dynamic_fb.attachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
else
ctx->dynamic_fb.attachments[i].loadOp = VK_ATTACHMENT_LOAD_OP_LOAD;
+ if (ctx->tc && zink_screen(ctx->base.screen)->driver_workarounds.track_renderpasses) {
+ if (ctx->dynamic_fb.tc_info.cbuf_invalidate & BITFIELD_BIT(i))
+ ctx->dynamic_fb.attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ else
+ ctx->dynamic_fb.attachments[i].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ }
ctx->gfx_pipeline_state.rendering_formats[i] = surf ? surf->info.format[0] : VK_FORMAT_R8G8B8A8_UNORM;
/* use dummy fb size of 1024 if no surf exists */
unsigned width = surf ? surf->base.texture->width0 : 1024;
ctx->dynamic_fb.info.pStencilAttachment = NULL;
ctx->gfx_pipeline_state.rendering_info.stencilAttachmentFormat = VK_FORMAT_UNDEFINED;
- if (ctx->fb_state.zsbuf) {
+ if (ctx->fb_state.zsbuf && zsbuf_used) {
struct zink_surface *surf = zink_csurface(ctx->fb_state.zsbuf);
has_depth = util_format_has_depth(util_format_description(ctx->fb_state.zsbuf->format));
has_stencil = util_format_has_stencil(util_format_description(ctx->fb_state.zsbuf->format));
else
ctx->dynamic_fb.attachments[PIPE_MAX_COLOR_BUFS].loadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
+ if (ctx->tc && zink_screen(ctx->base.screen)->driver_workarounds.track_renderpasses) {
+ if (ctx->dynamic_fb.tc_info.zsbuf_invalidate)
+ ctx->dynamic_fb.attachments[PIPE_MAX_COLOR_BUFS].storeOp = VK_ATTACHMENT_STORE_OP_DONT_CARE;
+ else
+ ctx->dynamic_fb.attachments[PIPE_MAX_COLOR_BUFS].storeOp = VK_ATTACHMENT_STORE_OP_STORE;
+ }
+
/* stencil may or may not be used but init it anyway */
ctx->dynamic_fb.attachments[PIPE_MAX_COLOR_BUFS+1].loadOp = ctx->dynamic_fb.attachments[PIPE_MAX_COLOR_BUFS].loadOp;
+ ctx->dynamic_fb.attachments[PIPE_MAX_COLOR_BUFS+1].storeOp = ctx->dynamic_fb.attachments[PIPE_MAX_COLOR_BUFS].storeOp;
if (has_depth) {
ctx->dynamic_fb.info.pDepthAttachment = &ctx->dynamic_fb.attachments[PIPE_MAX_COLOR_BUFS];
return 0;
ctx->dynamic_fb.attachments[i].imageView = iv;
}
- if (ctx->fb_state.zsbuf) {
+ if (ctx->fb_state.zsbuf && zsbuf_used) {
struct zink_surface *surf = zink_csurface(ctx->fb_state.zsbuf);
VkImageView iv = zink_prep_fb_attachment(ctx, surf, ctx->fb_state.nr_cbufs);
ctx->dynamic_fb.attachments[PIPE_MAX_COLOR_BUFS].imageView = iv;
ctx->base.clear(&ctx->base, ctx->void_clears, NULL, &color, 0, 0);
ctx->void_clears = 0;
}
+ update_tc_info(ctx, ctx->rp_tc_info_updated);
+ ctx->rp_tc_info_updated = false;
unsigned clear_buffers;
/* use renderpass for multisample-to-singlesample or fbfetch:
* - msrtss is TODO
zink_update_fbfetch(ctx);
}
VkImageLayout layout;
- if (ctx->gfx_pipeline_state.render_pass) {
- layout = zink_render_pass_attachment_get_barrier_info(&ctx->gfx_pipeline_state.render_pass->state.rts[i],
- i < ctx->fb_state.nr_cbufs, &pipeline, &access);
+ if (ctx->tc && zink_screen(ctx->base.screen)->driver_workarounds.track_renderpasses && !ctx->blitting) {
+ assert(threaded_context_get_renderpass_info(ctx->tc, false)->data == ctx->dynamic_fb.tc_info.data);
+ layout = zink_tc_renderpass_info_parse(ctx, &ctx->dynamic_fb.tc_info, i < ctx->fb_state.nr_cbufs ? i : PIPE_MAX_COLOR_BUFS, &pipeline, &access);
+ assert(i < ctx->fb_state.nr_cbufs || layout != VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL || !zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS));
+ if (i == ctx->fb_state.nr_cbufs && zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS))
+ assert(ctx->dynamic_fb.tc_info.zsbuf_clear || ctx->dynamic_fb.tc_info.zsbuf_clear_partial || ctx->dynamic_fb.tc_info.zsbuf_load);
} else {
- struct zink_rt_attrib rt;
- if (i < ctx->fb_state.nr_cbufs)
- zink_init_color_attachment(ctx, i, &rt);
- else
- zink_init_zs_attachment(ctx, &rt);
- layout = zink_render_pass_attachment_get_barrier_info(&rt, i < ctx->fb_state.nr_cbufs, &pipeline, &access);
+ if (ctx->gfx_pipeline_state.render_pass) {
+ layout = zink_render_pass_attachment_get_barrier_info(&ctx->gfx_pipeline_state.render_pass->state.rts[i],
+ i < ctx->fb_state.nr_cbufs, &pipeline, &access);
+ } else {
+ struct zink_rt_attrib rt;
+ if (i < ctx->fb_state.nr_cbufs)
+ zink_init_color_attachment(ctx, i, &rt);
+ else
+ zink_init_zs_attachment(ctx, &rt);
+ layout = zink_render_pass_attachment_get_barrier_info(&rt, i < ctx->fb_state.nr_cbufs, &pipeline, &access);
+ }
}
if (!zink_screen(ctx->base.screen)->info.have_EXT_attachment_feedback_loop_layout &&
layout == VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT)
flush_batch(ctx, false);
else
update_layered_rendering_state(ctx);
+
+ ctx->rp_tc_info_updated = !ctx->blitting;
}
static void
if (!(flags & (PIPE_FLUSH_DEFERRED | PIPE_FLUSH_ASYNC)))
sync_flush(ctx, zink_batch_state(fence));
}
+ update_tc_info(ctx, false);
}
void
zink_get_dummy_surface(struct zink_context *ctx, int samples_index)
{
return zink_csurface(zink_get_dummy_pipe_surface(ctx, samples_index));
+
+}
+
+static void
+zink_tc_parse_dsa(void *state, struct tc_renderpass_info *info)
+{
+ struct zink_depth_stencil_alpha_state *cso = state;
+ info->zsbuf_write_dsa |= (cso->hw_state.depth_write || cso->base.stencil[0].writemask || cso->base.stencil[1].writemask);
+ info->zsbuf_read_dsa |= (cso->hw_state.depth_test || cso->hw_state.stencil_test);
+ /* TODO: if zsbuf fbfetch is ever supported */
+}
+
+static void
+zink_tc_parse_fs(void *state, struct tc_renderpass_info *info)
+{
+ struct zink_shader *zs = state;
+ info->zsbuf_write_fs |= zs->nir->info.outputs_written & (BITFIELD64_BIT(FRAG_RESULT_DEPTH) | BITFIELD64_BIT(FRAG_RESULT_STENCIL));
+ /* TODO: if >1 fbfetch attachment is ever supported */
+ info->cbuf_fbfetch |= zs->nir->info.fs.uses_fbfetch_output ? BITFIELD_BIT(0) : 0;
}
struct pipe_context *
.is_resource_busy = zink_context_is_resource_busy,
.driver_calls_flush_notify = true,
.unsynchronized_get_device_reset_status = true,
+ .parse_renderpass_info = screen->driver_workarounds.track_renderpasses,
+ .dsa_parse = zink_tc_parse_dsa,
+ .fs_parse = zink_tc_parse_fs,
},
&ctx->tc);
(1 << MESA_SHADER_GEOMETRY))) >> 1;
}
+static inline bool
+zink_is_zsbuf_used(const struct zink_context *ctx)
+{
+ return !ctx->tc || ctx->blitting ||
+ !zink_screen(ctx->base.screen)->driver_workarounds.track_renderpasses ||
+ tc_renderpass_info_is_zsbuf_used(&ctx->dynamic_fb.tc_info);
+}
+
void
zink_fence_wait(struct pipe_context *ctx);
zink_get_framebuffer(struct zink_context *ctx)
{
assert(zink_screen(ctx->base.screen)->info.have_KHR_imageless_framebuffer);
+ bool have_zsbuf = ctx->fb_state.zsbuf && zink_is_zsbuf_used(ctx);
struct zink_framebuffer_state state;
state.num_attachments = ctx->fb_state.nr_cbufs;
- const unsigned cresolve_offset = ctx->fb_state.nr_cbufs + !!ctx->fb_state.zsbuf;
+ const unsigned cresolve_offset = ctx->fb_state.nr_cbufs + !!have_zsbuf;
unsigned num_resolves = 0;
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
struct pipe_surface *psurf = ctx->fb_state.cbufs[i];
}
const unsigned zsresolve_offset = cresolve_offset + num_resolves;
- if (ctx->fb_state.zsbuf) {
+ if (have_zsbuf) {
struct pipe_surface *psurf = ctx->fb_state.zsbuf;
struct zink_surface *surface = zink_csurface(psurf);
struct zink_surface *transient = zink_transient_surface(psurf);
return get_zs_rt_layout(rt);
}
+VkImageLayout
+zink_tc_renderpass_info_parse(struct zink_context *ctx, const struct tc_renderpass_info *info, unsigned idx, VkPipelineStageFlags *pipeline, VkAccessFlags *access)
+{
+ if (idx < PIPE_MAX_COLOR_BUFS) {
+ *pipeline = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
+ *access = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
+ if (info->cbuf_load & BITFIELD_BIT(idx))
+ *access |= VK_ACCESS_COLOR_ATTACHMENT_READ_BIT;
+ return (ctx->feedback_loops & BITFIELD_BIT(idx)) ? VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT :
+ (info->cbuf_fbfetch & BITFIELD_BIT(idx)) ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
+ } else {
+ *access = 0;
+ if (info->zsbuf_load || info->zsbuf_read_dsa)
+ *access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT;
+ if (info->zsbuf_clear | info->zsbuf_clear_partial | info->zsbuf_write_fs | info->zsbuf_write_dsa)
+ *access |= VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT;
+ assert(*access);
+ *pipeline = VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT;
+ if (ctx->feedback_loops & BITFIELD_BIT(PIPE_MAX_COLOR_BUFS))
+ return VK_IMAGE_LAYOUT_ATTACHMENT_FEEDBACK_LOOP_OPTIMAL_EXT;
+ return (info->zsbuf_clear | info->zsbuf_clear_partial | info->zsbuf_write_fs | info->zsbuf_write_dsa) ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_DEPTH_STENCIL_READ_ONLY_OPTIMAL;
+ }
+}
static size_t
rp_state_size(const struct zink_render_pass_pipeline_state *pstate)
}
void
+zink_tc_init_zs_attachment(struct zink_context *ctx, const struct tc_renderpass_info *info, struct zink_rt_attrib *rt)
+{
+ const struct pipe_framebuffer_state *fb = &ctx->fb_state;
+ struct zink_resource *zsbuf = zink_resource(fb->zsbuf->texture);
+ struct zink_framebuffer_clear *fb_clear = &ctx->fb_clears[PIPE_MAX_COLOR_BUFS];
+ struct zink_surface *transient = zink_transient_surface(fb->zsbuf);
+ rt->format = zsbuf->format;
+ rt->samples = MAX3(transient ? transient->base.nr_samples : 0, fb->zsbuf->texture->nr_samples, 1);
+ rt->clear_color = zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS) &&
+ !zink_fb_clear_first_needs_explicit(fb_clear) &&
+ (zink_fb_clear_element(fb_clear, 0)->zs.bits & PIPE_CLEAR_DEPTH);
+ rt->clear_stencil = zink_fb_clear_enabled(ctx, PIPE_MAX_COLOR_BUFS) &&
+ !zink_fb_clear_first_needs_explicit(fb_clear) &&
+ (zink_fb_clear_element(fb_clear, 0)->zs.bits & PIPE_CLEAR_STENCIL);
+ rt->needs_write = info->zsbuf_clear | info->zsbuf_clear_partial | info->zsbuf_write_fs | info->zsbuf_write_dsa;
+ rt->invalid = !zsbuf->valid;
+ rt->feedback_loop = (ctx->feedback_loops & BITFIELD_BIT(PIPE_MAX_COLOR_BUFS)) > 0;
+}
+
+void
zink_init_color_attachment(struct zink_context *ctx, unsigned i, struct zink_rt_attrib *rt)
{
const struct pipe_framebuffer_state *fb = &ctx->fb_state;
}
}
+void
+zink_tc_init_color_attachment(struct zink_context *ctx, const struct tc_renderpass_info *info, unsigned i, struct zink_rt_attrib *rt)
+{
+ const struct pipe_framebuffer_state *fb = &ctx->fb_state;
+ struct pipe_surface *psurf = fb->cbufs[i];
+ if (psurf && !zink_use_dummy_attachments(ctx)) {
+ struct zink_surface *surf = zink_csurface(psurf);
+ struct zink_surface *transient = zink_transient_surface(psurf);
+ rt->format = surf->info.format[0];
+ rt->samples = MAX3(transient ? transient->base.nr_samples : 0, psurf->texture->nr_samples, 1);
+ rt->clear_color = zink_fb_clear_enabled(ctx, i) && !zink_fb_clear_first_needs_explicit(&ctx->fb_clears[i]);
+ rt->invalid = !zink_resource(psurf->texture)->valid;
+ rt->fbfetch = (info->cbuf_fbfetch & BITFIELD_BIT(i)) > 0;
+ rt->feedback_loop = (ctx->feedback_loops & BITFIELD_BIT(i)) > 0;
+ } else {
+ memset(rt, 0, sizeof(struct zink_rt_attrib));
+ rt->format = VK_FORMAT_R8G8B8A8_UNORM;
+ rt->samples = fb->samples;
+ }
+}
+
static struct zink_render_pass *
get_render_pass(struct zink_context *ctx)
{
const struct pipe_framebuffer_state *fb = &ctx->fb_state;
struct zink_render_pass_state state = {0};
uint32_t clears = 0;
+ bool have_zsbuf = fb->zsbuf && zink_is_zsbuf_used(ctx);
state.samples = fb->samples > 0;
for (int i = 0; i < fb->nr_cbufs; i++) {
- zink_init_color_attachment(ctx, i, &state.rts[i]);
+ if (ctx->tc && screen->driver_workarounds.track_renderpasses)
+ zink_tc_init_color_attachment(ctx, &ctx->dynamic_fb.tc_info, i, &state.rts[i]);
+ else
+ zink_init_color_attachment(ctx, i, &state.rts[i]);
struct pipe_surface *surf = fb->cbufs[i];
if (surf && !zink_use_dummy_attachments(ctx)) {
clears |= !!state.rts[i].clear_color ? PIPE_CLEAR_COLOR0 << i : 0;
state.num_cbufs = fb->nr_cbufs;
assert(!state.num_cresolves || state.num_cbufs == state.num_cresolves);
- if (fb->zsbuf) {
- zink_init_zs_attachment(ctx, &state.rts[fb->nr_cbufs]);
+ if (have_zsbuf) {
+ if (ctx->tc && screen->driver_workarounds.track_renderpasses)
+ zink_tc_init_zs_attachment(ctx, &ctx->dynamic_fb.tc_info, &state.rts[fb->nr_cbufs]);
+ else
+ zink_init_zs_attachment(ctx, &state.rts[fb->nr_cbufs]);
struct zink_surface *transient = zink_transient_surface(fb->zsbuf);
if (transient) {
state.num_zsresolves = 1;
clears |= PIPE_CLEAR_STENCIL;
state.num_rts++;
}
- state.have_zsbuf = fb->zsbuf != NULL;
+ state.have_zsbuf = have_zsbuf;
if (zink_use_dummy_attachments(ctx))
assert(clears == (ctx->rp_clears_enabled & PIPE_CLEAR_DEPTHSTENCIL));
else
static bool
prep_fb_attachments(struct zink_context *ctx, VkImageView *att)
{
- const unsigned cresolve_offset = ctx->fb_state.nr_cbufs + !!ctx->fb_state.zsbuf;
+ bool have_zsbuf = ctx->fb_state.zsbuf && zink_is_zsbuf_used(ctx);
+ const unsigned cresolve_offset = ctx->fb_state.nr_cbufs + !!have_zsbuf;
unsigned num_resolves = 0;
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
struct zink_surface *surf = zink_csurface(ctx->fb_state.cbufs[i]);
return false;
}
}
- if (ctx->fb_state.zsbuf) {
+ if (have_zsbuf) {
struct zink_surface *surf = zink_csurface(ctx->fb_state.zsbuf);
struct zink_surface *transient = zink_transient_surface(ctx->fb_state.zsbuf);
if (transient) {
{
struct zink_batch *batch = &ctx->batch;
struct pipe_framebuffer_state *fb_state = &ctx->fb_state;
+ bool zsbuf_used = ctx->fb_state.zsbuf && zink_is_zsbuf_used(ctx);
VkRenderPassBeginInfo rpbi = {0};
rpbi.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
/* this can be set if fbfetch is activated */
ctx->rp_changed = false;
#ifndef NDEBUG
- const unsigned cresolve_offset = ctx->fb_state.nr_cbufs + !!ctx->fb_state.zsbuf;
+ const unsigned cresolve_offset = ctx->fb_state.nr_cbufs + !!zsbuf_used;
for (int i = 0; i < ctx->fb_state.nr_cbufs; i++) {
if (ctx->fb_state.cbufs[i]) {
struct zink_surface *surf = zink_csurface(ctx->fb_state.cbufs[i]);
}
}
}
- if (ctx->fb_state.zsbuf) {
+ if (ctx->gfx_pipeline_state.render_pass->state.have_zsbuf) {
struct zink_surface *surf = zink_csurface(ctx->fb_state.zsbuf);
struct zink_surface *transient = zink_transient_surface(ctx->fb_state.zsbuf);
if (transient) {
VkImageLayout
zink_render_pass_attachment_get_barrier_info(const struct zink_rt_attrib *rt, bool color, VkPipelineStageFlags *pipeline, VkAccessFlags *access);
-
+VkImageLayout
+zink_tc_renderpass_info_parse(struct zink_context *ctx, const struct tc_renderpass_info *info, unsigned idx, VkPipelineStageFlags *pipeline, VkAccessFlags *access);
bool
zink_init_render_pass(struct zink_context *ctx);
void
zink_init_zs_attachment(struct zink_context *ctx, struct zink_rt_attrib *rt);
void
zink_init_color_attachment(struct zink_context *ctx, unsigned i, struct zink_rt_attrib *rt);
+void
+zink_tc_init_zs_attachment(struct zink_context *ctx, const struct tc_renderpass_info *info, struct zink_rt_attrib *rt);
+void
+zink_tc_init_color_attachment(struct zink_context *ctx, const struct tc_renderpass_info *info, unsigned i, struct zink_rt_attrib *rt);
#endif
{ "noreorder", ZINK_DEBUG_NOREORDER, "Do not reorder command streams" },
{ "gpl", ZINK_DEBUG_GPL, "Force using Graphics Pipeline Library for all shaders" },
{ "shaderdb", ZINK_DEBUG_SHADERDB, "Do stuff to make shader-db work" },
+ { "rp", ZINK_DEBUG_RP, "Enable renderpass tracking/optimizations" },
DEBUG_NAMED_VALUE_END
};
screen->driver_workarounds.needs_sanitised_layer = false;
break;
}
+
+ /* once more testing has been done, use the #if 0 block */
+ if (zink_debug & ZINK_DEBUG_RP)
+ screen->driver_workarounds.track_renderpasses = true;
+#if 0
+ /* these drivers benefit from renderpass optimization */
+ switch (screen->info.driver_props.driverID) {
+ //* llvmpipe is broken: #7489
+ // case VK_DRIVER_ID_MESA_LLVMPIPE:
+ case VK_DRIVER_ID_MESA_TURNIP:
+ case VK_DRIVER_ID_MESA_PANVK:
+ case VK_DRIVER_ID_MESA_VENUS:
+ case VK_DRIVER_ID_MESA_V3DV:
+ case VK_DRIVER_ID_IMAGINATION_PROPRIETARY:
+ case VK_DRIVER_ID_QUALCOMM_PROPRIETARY:
+ case VK_DRIVER_ID_BROADCOM_PROPRIETARY:
+ case VK_DRIVER_ID_ARM_PROPRIETARY:
+ screen->driver_workarounds.track_renderpasses = true;
+ break;
+ default:
+ break;
+ }
+#endif
}
static struct zink_screen *
ZINK_DEBUG_NOREORDER = (1<<6),
ZINK_DEBUG_GPL = (1<<7),
ZINK_DEBUG_SHADERDB = (1<<8),
+ ZINK_DEBUG_RP = (1<<9),
};
bool always_feedback_loop;
bool always_feedback_loop_zs;
bool needs_sanitised_layer;
+ bool track_renderpasses;
unsigned z16_unscaled_bias;
unsigned z24_unscaled_bias;
} driver_workarounds;
struct {
VkRenderingAttachmentInfo attachments[PIPE_MAX_COLOR_BUFS + 2]; //+depth, +stencil
VkRenderingInfo info;
+ struct tc_renderpass_info tc_info;
} dynamic_fb;
uint32_t fb_layer_mismatch; //bitmask
unsigned depth_bias_scale_factor;
bool dsa_state_changed : 1;
bool stencil_ref_changed : 1;
bool rasterizer_discard_changed : 1;
+ bool rp_tc_info_updated : 1;
};
static inline struct zink_context *