panfrost: Implement provoking vertices on Valhall

Starting with Valhall, the provoking vertex state is specified per-framebuffer
(batch) instead of per-draw. We use the pan_tristate infrastructure to translate
between desktop OpenGL's per-draw semantics to Valhall's per-framebuffer
semantic. This is notably not required for GLES or Vulkan.

If the provoking vertex is unset when the tiler context is generated, it could
be set (incompatibly) later in the batch, and the tiler context's provoking
vertex field would no longer match the framebuffer's. That would violate a
hardware invariant. To ensure that doesn't happen, we make sure to set provoking
vertexes *before* generating the tiler context so it can't change after.

Fixes arb-provoking-vertex-render on Valhall.

Signed-off-by: Alyssa Rosenzweig <alyssa@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17068>
This commit is contained in:
Alyssa Rosenzweig 2022-06-15 16:06:00 -04:00 committed by Marge Bot
parent 9cdd32257f
commit b6a30b72ab
5 changed files with 20 additions and 2 deletions

View file

@ -3101,9 +3101,17 @@ panfrost_batch_get_bifrost_tiler(struct panfrost_batch *batch, unsigned vertex_c
mali_ptr heap = t.gpu;
/* We emit this descriptor after the first draw. The provoking vertex
* for the batch should have already been set (on Valhall, where it is a
* property of the batch).
*/
if (PAN_ARCH >= 9)
assert(pan_tristate_is_defined(batch->first_provoking_vertex));
t = pan_pool_alloc_desc(&batch->pool.base, TILER_CONTEXT);
GENX(pan_emit_tiler_ctx)(dev, batch->key.width, batch->key.height,
util_framebuffer_get_num_samples(&batch->key),
pan_tristate_get(batch->first_provoking_vertex),
heap, t.cpu);
batch->tiler_ctx.bifrost = t.gpu;
@ -3975,8 +3983,10 @@ panfrost_compatible_batch_state(struct panfrost_batch *batch)
struct pipe_rasterizer_state *rast = &ctx->rasterizer->base;
bool coord = (rast->sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT);
bool first = rast->flatshade_first;
return pan_tristate_set(&batch->sprite_coord_origin, coord);
return pan_tristate_set(&batch->sprite_coord_origin, coord) &&
pan_tristate_set(&batch->first_provoking_vertex, first);
}
static void

View file

@ -448,6 +448,7 @@ panfrost_batch_to_fb_info(const struct panfrost_batch *batch,
fb->nr_samples = util_framebuffer_get_num_samples(&batch->key);
fb->rt_count = batch->key.nr_cbufs;
fb->sprite_coord_origin = pan_tristate_get(batch->sprite_coord_origin);
fb->first_provoking_vertex = pan_tristate_get(batch->first_provoking_vertex);
static const unsigned char id_swz[] = {
PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W,

View file

@ -200,6 +200,7 @@ struct panfrost_batch {
* per draw.
*/
struct pan_tristate sprite_coord_origin;
struct pan_tristate first_provoking_vertex;
/* Referenced resources */
struct set *resources;

View file

@ -764,6 +764,7 @@ GENX(pan_emit_fbd)(const struct panfrost_device *dev,
#if PAN_ARCH >= 9
cfg.point_sprite_coord_origin_max_y = fb->sprite_coord_origin;
cfg.first_provoking_vertex = fb->first_provoking_vertex;
#endif
}
@ -937,6 +938,7 @@ void
GENX(pan_emit_tiler_ctx)(const struct panfrost_device *dev,
unsigned fb_width, unsigned fb_height,
unsigned nr_samples,
bool first_provoking_vertex,
mali_ptr heap,
void *out)
{
@ -959,6 +961,9 @@ GENX(pan_emit_tiler_ctx)(const struct panfrost_device *dev,
tiler.fb_height = fb_height;
tiler.heap = heap;
tiler.sample_pattern = pan_sample_pattern(nr_samples);
#if PAN_ARCH >= 9
tiler.first_provoking_vertex = first_provoking_vertex;
#endif
}
}
#endif

View file

@ -120,6 +120,7 @@ struct pan_fb_info {
/* Only used on Valhall */
bool sprite_coord_origin;
bool first_provoking_vertex;
};
static inline unsigned
@ -169,7 +170,7 @@ GENX(pan_emit_tiler_heap)(const struct panfrost_device *dev,
void
GENX(pan_emit_tiler_ctx)(const struct panfrost_device *dev,
unsigned fb_width, unsigned fb_height,
unsigned nr_samples,
unsigned nr_samples, bool first_provoking_vertex,
mali_ptr heap,
void *out);
#endif