Mesa (main): panfrost: Flip point coords in hardware
GitLab Mirror
gitlab-mirror at kemper.freedesktop.org
Mon May 2 14:14:35 UTC 2022
Module: Mesa
Branch: main
Commit: 3641dfe4367e37b3bbe125c9b18044a07e35e502
URL: http://cgit.freedesktop.org/mesa/mesa/commit/?id=3641dfe4367e37b3bbe125c9b18044a07e35e502
Author: Alyssa Rosenzweig <alyssa at collabora.com>
Date: Mon May 2 09:19:41 2022 -0400
panfrost: Flip point coords in hardware
On Bifrost, this is very easy: there's an RSD bit to Y-flip gl_PointCoord. It
should map perfectly to the Gallium bit. With this change, we no longer use
lower_pntc_ytransform on Bifrost, saving a bit of ALU when reading point
coordinates.
On Valhall, this is quite hard: the bit is in the framebuffer descriptor now!
That means it can't be changed in a batch. This is expected to be ok: on GLES
and VK, the origin is controlled only by the framebuffer orientation. It's a
bigger problem on big GL, where GL_POINT_SPRITE_COORD_ORIGIN can be set freely.
To cope, a tri-state data structure is used for the state tracking. This has a
failure case on Valhall: every draw toggling the coord origin. However, the
intention of the ORIGIN state bit is smoothing over coordinate system
differences; it should never /actually/ change once set. Until we see an app
doing something so stupid, I don't think we should worry about.
We need all the Valhall tri-state infrastructure for handling provoking vertices
on big GL anyway.
Signed-off-by: Alyssa Rosenzweig <alyssa at collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16173>
---
src/gallium/drivers/panfrost/pan_cmdstream.c | 34 ++++++++++++++-----
src/gallium/drivers/panfrost/pan_job.c | 1 +
src/gallium/drivers/panfrost/pan_job.h | 51 ++++++++++++++++++++++++++++
src/panfrost/bifrost/bifrost_compile.h | 1 -
src/panfrost/lib/pan_cs.c | 4 +++
src/panfrost/lib/pan_cs.h | 3 ++
6 files changed, 85 insertions(+), 9 deletions(-)
diff --git a/src/gallium/drivers/panfrost/pan_cmdstream.c b/src/gallium/drivers/panfrost/pan_cmdstream.c
index 1823144db6f..82e57afd027 100644
--- a/src/gallium/drivers/panfrost/pan_cmdstream.c
+++ b/src/gallium/drivers/panfrost/pan_cmdstream.c
@@ -573,6 +573,13 @@ panfrost_prepare_fs_state(struct panfrost_context *ctx,
cfg.multisample_misc.evaluate_per_sample = true;
cfg.preload.fragment.sample_mask_id = true;
}
+
+ /* Flip gl_PointCoord (and point sprites) depending on API
+ * setting on framebuffer orientation. We do not use
+ * lower_wpos_pntc on Bifrost.
+ */
+ cfg.properties.point_sprite_coord_origin_max_y =
+ (rast->sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT);
#endif
cfg.stencil_mask_misc.alpha_to_coverage = alpha_to_coverage;
@@ -3780,6 +3787,21 @@ panfrost_indirect_draw(struct panfrost_batch *batch,
}
#endif
+static bool
+panfrost_compatible_batch_state(struct panfrost_batch *batch)
+{
+ /* Only applies on Valhall */
+ if (PAN_ARCH < 9)
+ return true;
+
+ struct panfrost_context *ctx = batch->ctx;
+ struct pipe_rasterizer_state *rast = &ctx->rasterizer->base;
+
+ bool coord = (rast->sprite_coord_mode == PIPE_SPRITE_COORD_LOWER_LEFT);
+
+ return pan_tristate_set(&batch->sprite_coord_origin, coord);
+}
+
static void
panfrost_draw_vbo(struct pipe_context *pipe,
const struct pipe_draw_info *info,
@@ -3810,6 +3832,9 @@ panfrost_draw_vbo(struct pipe_context *pipe,
if (unlikely(batch->scoreboard.job_index > 10000))
batch = panfrost_get_fresh_batch_for_fbo(ctx, "Too many draws");
+ if (unlikely(!panfrost_compatible_batch_state(batch)))
+ batch = panfrost_get_fresh_batch_for_fbo(ctx, "State change");
+
/* panfrost_batch_skip_rasterization reads
* batch->scissor_culls_everything, which is set by
* panfrost_emit_viewport, so call that first.
@@ -4371,14 +4396,7 @@ prepare_shader(struct panfrost_shader_state *state,
pan_pack(out, RENDERER_STATE, cfg) {
pan_shader_prepare_rsd(&state->info, state->bin.gpu, &cfg);
-#if PAN_ARCH >= 6
- /* Match the mesa/st convention. If this needs to be flipped,
- * nir_lower_pntc_ytransform will do so.
- */
- if (state->info.stage == MESA_SHADER_FRAGMENT)
- cfg.properties.point_sprite_coord_origin_max_y = true;
-#endif
- }
+ }
#else
assert(upload);
diff --git a/src/gallium/drivers/panfrost/pan_job.c b/src/gallium/drivers/panfrost/pan_job.c
index 25d634baf8b..6e051fd892d 100644
--- a/src/gallium/drivers/panfrost/pan_job.c
+++ b/src/gallium/drivers/panfrost/pan_job.c
@@ -435,6 +435,7 @@ panfrost_batch_to_fb_info(const struct panfrost_batch *batch,
fb->extent.maxy = batch->maxy - 1;
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);
static const unsigned char id_swz[] = {
PIPE_SWIZZLE_X, PIPE_SWIZZLE_Y, PIPE_SWIZZLE_Z, PIPE_SWIZZLE_W,
diff --git a/src/gallium/drivers/panfrost/pan_job.h b/src/gallium/drivers/panfrost/pan_job.h
index a905ec028f6..94635b3cc90 100644
--- a/src/gallium/drivers/panfrost/pan_job.h
+++ b/src/gallium/drivers/panfrost/pan_job.h
@@ -33,6 +33,52 @@
#include "pan_resource.h"
#include "pan_scoreboard.h"
+/* Simple tri-state data structure. In the default "don't care" state, the value
+ * may be set to true or false. However, once the value is set, it must not be
+ * changed. Declared inside of a struct to prevent casting to bool, which is an
+ * error. The getter needs to be used instead.
+ */
+struct pan_tristate {
+ enum {
+ PAN_TRISTATE_DONTCARE,
+ PAN_TRISTATE_FALSE,
+ PAN_TRISTATE_TRUE,
+ } v;
+};
+
+/*
+ * Try to set a tristate value to a desired boolean value. Returns whether the
+ * operation is successful.
+ */
+static bool
+pan_tristate_set(struct pan_tristate *state, bool value)
+{
+ switch (state->v) {
+ case PAN_TRISTATE_DONTCARE:
+ state->v = value ? PAN_TRISTATE_TRUE : PAN_TRISTATE_FALSE;
+ return true;
+
+ case PAN_TRISTATE_FALSE:
+ return (value == false);
+
+ case PAN_TRISTATE_TRUE:
+ return (value == true);
+
+ default:
+ unreachable("Invalid tristate value");
+ }
+}
+
+/*
+ * Read the boolean value of a tristate. Return value undefined in the don't
+ * care state.
+ */
+static bool
+pan_tristate_get(struct pan_tristate state)
+{
+ return (state.v == PAN_TRISTATE_TRUE);
+}
+
/* A panfrost_batch corresponds to a bound FBO we're rendering to,
* collecting over multiple draws. */
@@ -141,6 +187,11 @@ struct panfrost_batch {
*/
mali_ptr images[PIPE_SHADER_TYPES];
+ /* On Valhall, these are properties of the batch. On Bifrost, they are
+ * per draw.
+ */
+ struct pan_tristate sprite_coord_origin;
+
/* Referenced resources */
struct set *resources;
};
diff --git a/src/panfrost/bifrost/bifrost_compile.h b/src/panfrost/bifrost/bifrost_compile.h
index 7a8d24c03f5..746a32ce7d0 100644
--- a/src/panfrost/bifrost/bifrost_compile.h
+++ b/src/panfrost/bifrost/bifrost_compile.h
@@ -48,7 +48,6 @@ static const nir_shader_compiler_options bifrost_nir_options = {
.lower_fdph = true,
.lower_fsqrt = true,
- .lower_wpos_pntc = true,
.lower_fsign = true,
.lower_bitfield_insert_to_shifts = true,
diff --git a/src/panfrost/lib/pan_cs.c b/src/panfrost/lib/pan_cs.c
index e0f451c3f9e..4ca908dbcbb 100644
--- a/src/panfrost/lib/pan_cs.c
+++ b/src/panfrost/lib/pan_cs.c
@@ -690,6 +690,10 @@ GENX(pan_emit_fbd)(const struct panfrost_device *dev,
*valid |= full;
}
+
+#if PAN_ARCH >= 9
+ cfg.point_sprite_coord_origin_max_y = fb->sprite_coord_origin;
+#endif
}
#if PAN_ARCH >= 6
diff --git a/src/panfrost/lib/pan_cs.h b/src/panfrost/lib/pan_cs.h
index 27d030efdf2..6e134d76556 100644
--- a/src/panfrost/lib/pan_cs.h
+++ b/src/panfrost/lib/pan_cs.h
@@ -117,6 +117,9 @@ struct pan_fb_info {
union {
struct pan_fb_bifrost_info bifrost;
};
+
+ /* Only used on Valhall */
+ bool sprite_coord_origin;
};
static inline unsigned
More information about the mesa-commit
mailing list