mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-05 15:30:14 +01:00
asahi: Implement ARB_texture_barrier by decompression
Your perf goes not stonks, sorry. Passes KHR-GL40.texture_barrier_ARB.*. Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/27616>
This commit is contained in:
parent
589338e8fc
commit
b39de8bb4a
3 changed files with 72 additions and 0 deletions
|
|
@ -34,6 +34,7 @@ enum agx_dbg {
|
|||
AGX_DBG_VARYINGS = BITFIELD_BIT(17),
|
||||
AGX_DBG_SCRATCH = BITFIELD_BIT(18),
|
||||
AGX_DBG_COMPBLIT = BITFIELD_BIT(19),
|
||||
AGX_DBG_FEEDBACK = BITFIELD_BIT(20),
|
||||
};
|
||||
|
||||
/* Dummy partial declarations, pending real UAPI */
|
||||
|
|
|
|||
|
|
@ -75,6 +75,7 @@ static const struct debug_named_value agx_debug_options[] = {
|
|||
{"nowc", AGX_DBG_NOWC, "Disable write-combining"},
|
||||
{"synctvb", AGX_DBG_SYNCTVB, "Synchronous TVB growth"},
|
||||
{"smalltile", AGX_DBG_SMALLTILE,"Force 16x16 tiles"},
|
||||
{"feedback", AGX_DBG_FEEDBACK, "Debug feedback loops"},
|
||||
{"nomsaa", AGX_DBG_NOMSAA, "Force disable MSAA"},
|
||||
{"noshadow", AGX_DBG_NOSHADOW, "Force disable resource shadowing"},
|
||||
{"varyings", AGX_DBG_VARYINGS, "Validate varying linkage"},
|
||||
|
|
@ -1569,6 +1570,7 @@ agx_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
|
|||
case PIPE_CAP_PRIMITIVE_RESTART_FIXED_INDEX:
|
||||
case PIPE_CAP_ANISOTROPIC_FILTER:
|
||||
case PIPE_CAP_NATIVE_FENCE_FD:
|
||||
case PIPE_CAP_TEXTURE_BARRIER:
|
||||
return true;
|
||||
|
||||
case PIPE_CAP_TIMER_RESOLUTION:
|
||||
|
|
|
|||
|
|
@ -4810,6 +4810,73 @@ agx_draw_patches(struct agx_context *ctx, const struct pipe_draw_info *info,
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* From the ARB_texture_barrier spec:
|
||||
*
|
||||
* Specifically, the values of rendered fragments are undefined if any
|
||||
* shader stage fetches texels and the same texels are written via fragment
|
||||
* shader outputs, even if the reads and writes are not in the same Draw
|
||||
* call, unless any of the following exceptions apply:
|
||||
*
|
||||
* - The reads and writes are from/to disjoint sets of texels (after
|
||||
* accounting for texture filtering rules).
|
||||
*
|
||||
* - There is only a single read and write of each texel, and the read is in
|
||||
* the fragment shader invocation that writes the same texel (e.g. using
|
||||
* "texelFetch2D(sampler, ivec2(gl_FragCoord.xy), 0);").
|
||||
*
|
||||
* - If a texel has been written, then in order to safely read the result
|
||||
* a texel fetch must be in a subsequent Draw separated by the command
|
||||
*
|
||||
* void TextureBarrier(void);
|
||||
*
|
||||
* TextureBarrier() will guarantee that writes have completed and caches
|
||||
* have been invalidated before subsequent Draws are executed."
|
||||
*
|
||||
* The wording is subtle, but we are not required to flush implicitly for
|
||||
* feedback loops, even though we're a tiler. What we are required to do is
|
||||
* decompress framebuffers involved in feedback loops, because otherwise
|
||||
* the hardware will race itself with exception #1, where we have a disjoint
|
||||
* group texels that intersects a compressed tile being written out.
|
||||
*/
|
||||
static void
|
||||
agx_legalize_feedback_loops(struct agx_context *ctx)
|
||||
{
|
||||
/* Trust that u_blitter knows what it's doing */
|
||||
if (ctx->blitter->running)
|
||||
return;
|
||||
|
||||
for (unsigned stage = 0; stage < ARRAY_SIZE(ctx->stage); ++stage) {
|
||||
if (!(ctx->stage[stage].dirty & AGX_STAGE_DIRTY_IMAGE))
|
||||
continue;
|
||||
|
||||
for (unsigned i = 0; i < ctx->stage[stage].texture_count; ++i) {
|
||||
if (!ctx->stage[stage].textures[i])
|
||||
continue;
|
||||
|
||||
struct agx_resource *rsrc = ctx->stage[stage].textures[i]->rsrc;
|
||||
|
||||
for (unsigned cb = 0; cb < ctx->framebuffer.nr_cbufs; ++cb) {
|
||||
if (ctx->framebuffer.cbufs[cb] &&
|
||||
agx_resource(ctx->framebuffer.cbufs[cb]->texture) == rsrc) {
|
||||
|
||||
if (rsrc->layout.tiling == AIL_TILING_TWIDDLED_COMPRESSED) {
|
||||
/* Decompress if we can and shadow if we can't. */
|
||||
if (rsrc->base.bind & PIPE_BIND_SHARED)
|
||||
unreachable("TODO");
|
||||
else
|
||||
agx_decompress(ctx, rsrc, "Texture feedback loop");
|
||||
}
|
||||
|
||||
/* Not required by the spec, just for debug */
|
||||
if (agx_device(ctx->base.screen)->debug & AGX_DBG_FEEDBACK)
|
||||
agx_flush_writer(ctx, rsrc, "Feedback loop");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
agx_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
|
||||
unsigned drawid_offset,
|
||||
|
|
@ -4876,6 +4943,8 @@ agx_draw_vbo(struct pipe_context *pctx, const struct pipe_draw_info *info,
|
|||
return;
|
||||
}
|
||||
|
||||
agx_legalize_feedback_loops(ctx);
|
||||
|
||||
/* Only the rasterization stream counts */
|
||||
if (ctx->active_queries && ctx->prims_generated[0] &&
|
||||
!ctx->stage[PIPE_SHADER_GEOMETRY].shader) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue