asahi: Implement polygon offset
authorAlyssa Rosenzweig <alyssa@rosenzweig.io>
Sat, 2 Apr 2022 19:31:40 +0000 (15:31 -0400)
committerAlyssa Rosenzweig <alyssa@rosenzweig.io>
Sun, 22 May 2022 21:09:04 +0000 (17:09 -0400)
This is pretty simple now that the hardware is understood. The hardware
interfaces parallels that of scissors, so the scissor path is reused
with minor modifications to accommodate the new functionality.

Signed-off-by: Alyssa Rosenzweig <alyssa@rosenzweig.io>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/16512>

src/gallium/drivers/asahi/agx_pipe.c
src/gallium/drivers/asahi/agx_state.c
src/gallium/drivers/asahi/agx_state.h
src/gallium/drivers/asahi/magic.c
src/gallium/drivers/asahi/magic.h

index 39b187e..7de453b 100644 (file)
@@ -502,6 +502,7 @@ agx_flush(struct pipe_context *pctx,
 
    agx_batch_add_bo(batch, batch->encoder);
    agx_batch_add_bo(batch, batch->scissor.bo);
+   agx_batch_add_bo(batch, batch->depth_bias.bo);
    agx_batch_add_bo(batch, dev->internal.bo);
    agx_batch_add_bo(batch, dev->reload.bo);
 
@@ -552,6 +553,7 @@ agx_flush(struct pipe_context *pctx,
                ctx->batch->encoder->ptr.gpu,
                encoder_id,
                ctx->batch->scissor.bo->ptr.gpu,
+               ctx->batch->depth_bias.bo->ptr.gpu,
                pipeline_null.gpu,
                pipeline_clear,
                pipeline_store,
@@ -629,6 +631,7 @@ agx_create_context(struct pipe_screen *screen,
    ctx->batch->encoder = agx_bo_create(agx_device(screen), 0x80000, AGX_MEMORY_TYPE_FRAMEBUFFER);
    ctx->batch->encoder_current = ctx->batch->encoder->ptr.cpu;
    ctx->batch->scissor.bo = agx_bo_create(agx_device(screen), 0x80000, AGX_MEMORY_TYPE_FRAMEBUFFER);
+   ctx->batch->depth_bias.bo = agx_bo_create(agx_device(screen), 0x80000, AGX_MEMORY_TYPE_FRAMEBUFFER);
 
    /* Upload fixed shaders (TODO: compile them?) */
 
index a26de9a..117a824 100644 (file)
@@ -288,16 +288,17 @@ agx_bind_rasterizer_state(struct pipe_context *pctx, void *cso)
    struct agx_context *ctx = agx_context(pctx);
    struct agx_rasterizer *so = cso;
 
-   /* Check if scissor state has changed, since scissor enable is part of the
-    * rasterizer state but everything else needed for scissors is part of
-    * viewport/scissor states */
-   bool scissor_changed = (cso == NULL) || (ctx->rast == NULL) ||
-      (ctx->rast->base.scissor != so->base.scissor);
+   /* Check if scissor or depth bias state has changed, since scissor/depth bias
+    * enable is part of the rasterizer state but everything else needed for
+    * scissors and depth bias is part of the scissor/depth bias arrays */
+   bool scissor_zbias_changed = (cso == NULL) || (ctx->rast == NULL) ||
+      (ctx->rast->base.scissor != so->base.scissor) ||
+      (ctx->rast->base.offset_tri != so->base.offset_tri);
 
    ctx->rast = so;
 
-   if (scissor_changed)
-      ctx->dirty |= AGX_DIRTY_SCISSOR;
+   if (scissor_zbias_changed)
+      ctx->dirty |= AGX_DIRTY_SCISSOR_ZBIAS;
 }
 
 static enum agx_wrap
@@ -606,7 +607,7 @@ agx_set_scissor_states(struct pipe_context *pctx,
    assert(num_scissors == 1 && "no geometry shaders");
 
    ctx->scissor = *scissor;
-   ctx->dirty |= AGX_DIRTY_SCISSOR;
+   ctx->dirty |= AGX_DIRTY_SCISSOR_ZBIAS;
 }
 
 static void
@@ -706,6 +707,22 @@ agx_upload_viewport_scissor(struct agx_pool *pool,
    };
 }
 
+static uint16_t
+agx_upload_depth_bias(struct agx_batch *batch,
+                      const struct pipe_rasterizer_state *rast)
+{
+   struct agx_depth_bias_packed *ptr = batch->depth_bias.bo->ptr.cpu;
+   unsigned index = (batch->depth_bias.count++);
+
+   agx_pack(ptr + index, DEPTH_BIAS, cfg) {
+      cfg.depth_bias    = rast->offset_units;
+      cfg.slope_scale   = rast->offset_scale;
+      cfg.clamp         = rast->offset_clamp;
+   }
+
+   return index;
+}
+
 /* A framebuffer state can be reused across batches, so it doesn't make sense
  * to add surfaces to the BO list here. Instead we added them when flushing.
  */
@@ -1407,6 +1424,8 @@ demo_rasterizer(struct agx_context *ctx, struct agx_pool *pool, bool is_points)
        * optimize this out if the viewport is the default and the app does not
        * use the scissor test) */
       cfg.scissor_enable = true;
+
+      cfg.depth_bias_enable = rast->base.offset_tri;
    };
 
    /* Words 2-3: front */
@@ -1450,12 +1469,13 @@ demo_unk12(struct agx_pool *pool)
 }
 
 static uint64_t
-agx_set_index(struct agx_pool *pool, unsigned scissor)
+agx_set_index(struct agx_pool *pool, uint16_t scissor, uint16_t zbias)
 {
    struct agx_ptr T = agx_pool_alloc_aligned(pool, AGX_SET_INDEX_LENGTH, 64);
 
    agx_pack(T.cpu, SET_INDEX, cfg) {
       cfg.scissor = scissor;
+      cfg.depth_bias = zbias;
    };
 
    return T.gpu;
@@ -1502,13 +1522,20 @@ agx_encode_state(struct agx_context *ctx, uint8_t *out,
    agx_push_record(&out, 7, demo_rasterizer(ctx, pool, is_points));
    agx_push_record(&out, 5, demo_unk11(pool, is_lines, is_points, reads_tib, sample_mask_from_shader));
 
-   if (ctx->dirty & (AGX_DIRTY_VIEWPORT | AGX_DIRTY_SCISSOR)) {
+   unsigned zbias = 0;
+
+   if (ctx->rast->base.offset_tri) {
+      zbias = agx_upload_depth_bias(ctx->batch, &ctx->rast->base);
+      ctx->dirty |= AGX_DIRTY_SCISSOR_ZBIAS;
+   }
+
+   if (ctx->dirty & (AGX_DIRTY_VIEWPORT | AGX_DIRTY_SCISSOR_ZBIAS)) {
       struct agx_viewport_scissor vps = agx_upload_viewport_scissor(pool,
             ctx->batch, &ctx->viewport,
             ctx->rast->base.scissor ? &ctx->scissor : NULL);
 
       agx_push_record(&out, 10, vps.viewport);
-      agx_push_record(&out, 2, agx_set_index(pool, vps.scissor));
+      agx_push_record(&out, 2, agx_set_index(pool, vps.scissor, zbias));
    }
 
    agx_push_record(&out, 3, demo_unk12(pool));
index 2de160b..35c11c1 100644 (file)
@@ -88,8 +88,8 @@ struct agx_stage {
    unsigned sampler_count, texture_count;
 };
 
-/* Uploaded scissor descriptors */
-struct agx_scissors {
+/* Uploaded scissor or depth bias descriptors */
+struct agx_array {
       struct agx_bo *bo;
       unsigned count;
 };
@@ -114,7 +114,7 @@ struct agx_batch {
    struct agx_bo *encoder;
    uint8_t *encoder_current;
 
-   struct agx_scissors scissor;
+   struct agx_array scissor, depth_bias;
 };
 
 struct agx_zsa {
@@ -141,7 +141,7 @@ struct asahi_shader_key {
 enum agx_dirty {
    AGX_DIRTY_VERTEX   = BITFIELD_BIT(0),
    AGX_DIRTY_VIEWPORT = BITFIELD_BIT(1),
-   AGX_DIRTY_SCISSOR  = BITFIELD_BIT(2),
+   AGX_DIRTY_SCISSOR_ZBIAS  = BITFIELD_BIT(2),
 };
 
 struct agx_context {
index a0d1cfb..05f93bd 100644 (file)
@@ -162,6 +162,7 @@ demo_cmdbuf(uint64_t *buf, size_t size,
             uint64_t encoder_ptr,
             uint64_t encoder_id,
             uint64_t scissor_ptr,
+            uint64_t depth_bias_ptr,
             uint32_t pipeline_null,
             uint32_t pipeline_clear,
             uint32_t pipeline_store,
@@ -187,7 +188,7 @@ demo_cmdbuf(uint64_t *buf, size_t size,
       cfg.store_pipeline_bind = 0x12;
       cfg.store_pipeline = pipeline_store;
       cfg.scissor_array = scissor_ptr;
-      cfg.depth_bias_array = demo_zero(pool, 0x1000);
+      cfg.depth_bias_array = depth_bias_ptr;
 
       if (framebuffer->zsbuf) {
          struct pipe_surface *zsbuf = framebuffer->zsbuf;
index c405cbe..a90595b 100644 (file)
@@ -31,6 +31,7 @@ demo_cmdbuf(uint64_t *buf, size_t size,
             uint64_t encoder_ptr,
             uint64_t encoder_id,
             uint64_t scissor_ptr,
+            uint64_t depth_bias_ptr,
             uint32_t pipeline_null,
             uint32_t pipeline_clear,
             uint32_t pipeline_store,