Mesa (master): nv50: fake enough resume support pre-nva0 to pass gles3 requirements

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Jan 8 19:20:17 UTC 2021


Module: Mesa
Branch: master
Commit: c0171c4626319ae6822f9c490d9118d5caf43246
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=c0171c4626319ae6822f9c490d9118d5caf43246

Author: Ilia Mirkin <imirkin at alum.mit.edu>
Date:   Wed Jan  6 00:48:23 2021 -0500

nv50: fake enough resume support pre-nva0 to pass gles3 requirements

GLES3 supports pause/resume of xfb. However since there's no geometry
shader support in ES3, it's a lot easier to figure out the offsets to
use. This makes it work for the dEQP tests at least.

Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
Reviewed-by: Karol Herbst <kherbst at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8346>

---

 src/gallium/drivers/nouveau/nv50/nv50_context.h      |  5 +++++
 src/gallium/drivers/nouveau/nv50/nv50_shader_state.c | 17 ++++++++++++-----
 src/gallium/drivers/nouveau/nv50/nv50_state.c        |  4 +++-
 src/gallium/drivers/nouveau/nv50/nv50_vbo.c          | 13 +++++++++++++
 4 files changed, 33 insertions(+), 6 deletions(-)

diff --git a/src/gallium/drivers/nouveau/nv50/nv50_context.h b/src/gallium/drivers/nouveau/nv50/nv50_context.h
index 57b8599483f..eda5a6fd58d 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_context.h
+++ b/src/gallium/drivers/nouveau/nv50/nv50_context.h
@@ -161,6 +161,11 @@ struct nv50_context {
    uint8_t num_so_targets;
    uint8_t so_targets_dirty;
    struct pipe_stream_output_target *so_target[4];
+   /* keeps track of how much of an SO is used. normally this doesn't work in
+    * the presence of GS, but this only needs to work for ES 3.0 which doesn't
+    * have GS or any other oddities. only used pre-NVA0.
+    */
+   uint32_t so_used[4];
 
    struct pipe_framebuffer_state framebuffer;
    struct pipe_blend_color blend_colour;
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c b/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c
index ae32a1345da..6a910d7f819 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_shader_state.c
@@ -696,11 +696,17 @@ nv50_stream_output_validate(struct nv50_context *nv50)
 
       const unsigned n = nv50->screen->base.class_3d >= NVA0_3D_CLASS ? 4 : 3;
 
-      if (n == 4 && !targ->clean)
-         nv84_hw_query_fifo_wait(push, nv50_query(targ->pq));
+      uint32_t so_used = 0;
+
+      if (!targ->clean) {
+         if (n == 4)
+            nv84_hw_query_fifo_wait(push, nv50_query(targ->pq));
+         else
+            so_used = nv50->so_used[i];
+      }
       BEGIN_NV04(push, NV50_3D(STRMOUT_ADDRESS_HIGH(i)), n);
-      PUSH_DATAh(push, buf->address + targ->pipe.buffer_offset);
-      PUSH_DATA (push, buf->address + targ->pipe.buffer_offset);
+      PUSH_DATAh(push, buf->address + targ->pipe.buffer_offset + so_used);
+      PUSH_DATA (push, buf->address + targ->pipe.buffer_offset + so_used);
       PUSH_DATA (push, so->num_attribs[i]);
       if (n == 4) {
          PUSH_DATA(push, targ->pipe.buffer_size);
@@ -714,9 +720,10 @@ nv50_stream_output_validate(struct nv50_context *nv50)
             targ->clean = false;
          }
       } else {
-         const unsigned limit = targ->pipe.buffer_size /
+         const unsigned limit = (targ->pipe.buffer_size - so_used) /
             (so->stride[i] * nv50->state.prim_size);
          prims = MIN2(prims, limit);
+         targ->clean = false;
       }
       targ->stride = so->stride[i];
       BCTX_REFN(nv50->bufctx_3d, 3D_SO, buf, WR);
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_state.c b/src/gallium/drivers/nouveau/nv50/nv50_state.c
index adb694536ee..73299302f86 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_state.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_state.c
@@ -1207,8 +1207,10 @@ nv50_set_stream_output_targets(struct pipe_context *pipe,
          serialize = false;
       }
 
-      if (targets[i] && !append)
+      if (targets[i] && !append) {
          nv50_so_target(targets[i])->clean = true;
+         nv50->so_used[i] = 0;
+      }
 
       pipe_so_target_reference(&nv50->so_target[i], targets[i]);
    }
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c
index 26539b38fe6..74030db67e0 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_vbo.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_vbo.c
@@ -23,6 +23,7 @@
 #include "pipe/p_context.h"
 #include "pipe/p_state.h"
 #include "util/u_inlines.h"
+#include "util/u_prim.h"
 #include "util/format/u_format.h"
 #include "translate/translate.h"
 
@@ -845,6 +846,18 @@ nv50_draw_vbo(struct pipe_context *pipe, const struct pipe_draw_info *info,
       PUSH_DATA (push, 0x00010000 * !!nv50->state.mul_zero_wins);
    }
 
+   /* Make starting/pausing streamout work pre-NVA0 enough for ES3.0. This
+    * means counting vertices in a vertex shader when it has so outputs.
+    */
+   if (nv50->screen->base.class_3d < NVA0_3D_CLASS &&
+       nv50->vertprog->pipe.stream_output.num_outputs) {
+      for (int i = 0; i < nv50->num_so_targets; i++) {
+         nv50->so_used[i] += info->instance_count *
+            u_stream_outputs_for_vertices(info->mode, draws[0].count) *
+            nv50->vertprog->pipe.stream_output.stride[i] * 4;
+      }
+   }
+
    if (nv50->vbo_fifo) {
       nv50_push_vbo(nv50, info, indirect, &draws[0]);
       goto cleanup;



More information about the mesa-commit mailing list