Mesa (main): gallium: add a pipe cap to rewrite index buffers for draws using a non-fixed restart index

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Wed Jun 23 03:52:35 UTC 2021


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

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Fri May 21 07:00:52 2021 -0400

gallium: add a pipe cap to rewrite index buffers for draws using a non-fixed restart index

for drivers that set it, this now automatically handles restart index rewriting
by running draws through primconvert when necessary

Reviewed-by: Marek Olšák <marek.olsak at amd.com>
Reviewed-by: Rob Clark <robdclark at chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/10973>

---

 docs/gallium/screen.rst                        |  1 +
 src/gallium/auxiliary/util/u_screen.c          |  3 +++
 src/gallium/auxiliary/util/u_vbuf.c            | 32 ++++++++++++++++++++++++--
 src/gallium/auxiliary/util/u_vbuf.h            |  1 +
 src/gallium/drivers/nouveau/nv30/nv30_screen.c |  1 +
 src/gallium/drivers/nouveau/nv50/nv50_screen.c |  1 +
 src/gallium/drivers/nouveau/nvc0/nvc0_screen.c |  1 +
 src/gallium/include/pipe/p_defines.h           |  1 +
 8 files changed, 39 insertions(+), 2 deletions(-)

diff --git a/docs/gallium/screen.rst b/docs/gallium/screen.rst
index 328b3e3e2f2..4714c0417f5 100644
--- a/docs/gallium/screen.rst
+++ b/docs/gallium/screen.rst
@@ -615,6 +615,7 @@ The integer capabilities:
 * ``PIPE_CAP_TEXRECT``: Driver supports rectangle textures.  Required for OpenGL on `!prefers_nir` drivers.  If this cap is not present, st/mesa will lower the NIR to use normal 2D texture sampling by using either `txs` or `nir_intrinsic_load_texture_scaling` to normalize the texture coordinates.
 * ``PIPE_CAP_SAMPLER_REDUCTION_MINMAX``: Driver supports EXT min/max sampler reduction.
 * ``PIPE_CAP_SAMPLER_REDUCTION_MINMAX_ARB``: Driver supports ARB min/max sampler reduction with format queries.
+* ``PIPE_CAP_EMULATE_NONFIXED_PRIMITIVE_RESTART``: Driver requests all draws using a non-fixed restart index to be rewritten to use a fixed restart index.
 
 .. _pipe_capf:
 
diff --git a/src/gallium/auxiliary/util/u_screen.c b/src/gallium/auxiliary/util/u_screen.c
index 32a35c1a8e9..f185282a961 100644
--- a/src/gallium/auxiliary/util/u_screen.c
+++ b/src/gallium/auxiliary/util/u_screen.c
@@ -466,6 +466,9 @@ u_pipe_screen_get_param_defaults(struct pipe_screen *pscreen,
    case PIPE_CAP_ALLOW_DYNAMIC_VAO_FASTPATH:
       return 1;
 
+   case PIPE_CAP_EMULATE_NONFIXED_PRIMITIVE_RESTART:
+      return 0;
+
    default:
       unreachable("bad PIPE_CAP_*");
    }
diff --git a/src/gallium/auxiliary/util/u_vbuf.c b/src/gallium/auxiliary/util/u_vbuf.c
index 9e5f2e2366e..2d00c16c5e9 100644
--- a/src/gallium/auxiliary/util/u_vbuf.c
+++ b/src/gallium/auxiliary/util/u_vbuf.c
@@ -91,6 +91,8 @@
 #include "util/format/u_format.h"
 #include "util/u_inlines.h"
 #include "util/u_memory.h"
+#include "indices/u_primconvert.h"
+#include "util/u_prim_restart.h"
 #include "util/u_screen.h"
 #include "util/u_upload_mgr.h"
 #include "translate/translate.h"
@@ -152,6 +154,7 @@ struct u_vbuf {
    struct translate_cache *translate_cache;
    struct cso_cache cso_cache;
 
+   struct primconvert_context *pc;
    bool flatshade_first;
 
    /* This is what was set in set_vertex_buffers.
@@ -302,6 +305,12 @@ void u_vbuf_get_caps(struct pipe_screen *screen, struct u_vbuf_caps *caps,
    caps->max_vertex_buffers =
       screen->get_param(screen, PIPE_CAP_MAX_VERTEX_BUFFERS);
 
+   if (screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART) ||
+       screen->get_param(screen, PIPE_CAP_PRIMITIVE_RESTART_FIXED_INDEX)) {
+      caps->rewrite_restart_index = screen->get_param(screen, PIPE_CAP_EMULATE_NONFIXED_PRIMITIVE_RESTART);
+      caps->fallback_always |= caps->rewrite_restart_index;
+   }
+
    /* OpenGL 2.0 requires a minimum of 16 vertex buffers */
    if (caps->max_vertex_buffers < 16)
       caps->fallback_always = true;
@@ -322,6 +331,13 @@ u_vbuf_create(struct pipe_context *pipe, struct u_vbuf_caps *caps)
 
    mgr->caps = *caps;
    mgr->pipe = pipe;
+   if (caps->rewrite_restart_index) {
+      struct primconvert_config cfg;
+      cfg.fixed_prim_restart = caps->rewrite_restart_index;
+      cfg.primtypes_mask = 0xff;
+      cfg.restart_primtypes_mask = 0xff;
+      mgr->pc = util_primconvert_create_config(pipe, &cfg);
+   }
    mgr->translate_cache = translate_cache_create();
    memset(mgr->fallback_vbs, ~0, sizeof(mgr->fallback_vbs));
    mgr->allowed_vb_mask = u_bit_consecutive(0, mgr->caps.max_vertex_buffers);
@@ -405,6 +421,9 @@ void u_vbuf_destroy(struct u_vbuf *mgr)
    for (i = 0; i < PIPE_MAX_ATTRIBS; i++)
       pipe_vertex_buffer_unreference(&mgr->real_vertex_buffer[i]);
 
+   if (mgr->pc)
+      util_primconvert_destroy(mgr->pc);
+
    translate_cache_destroy(mgr->translate_cache);
    cso_cache_delete(&mgr->cso_cache);
    FREE(mgr);
@@ -1356,11 +1375,15 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info,
       mgr->incompatible_vb_mask & used_vb_mask;
    struct pipe_draw_info new_info;
    struct pipe_draw_start_count_bias new_draw;
+   unsigned fixed_restart_index = info->index_size ? util_prim_restart_index_from_size(info->index_size) : 0;
 
    /* Normal draw. No fallback and no user buffers. */
    if (!incompatible_vb_mask &&
        !mgr->ve->incompatible_elem_mask &&
-       !user_vb_mask) {
+       !user_vb_mask &&
+       (!info->primitive_restart ||
+        info->restart_index == fixed_restart_index ||
+        !mgr->caps.rewrite_restart_index)) {
 
       /* Set vertex buffers if needed. */
       if (mgr->dirty_real_vb_mask & used_vb_mask) {
@@ -1639,7 +1662,12 @@ void u_vbuf_draw_vbo(struct u_vbuf *mgr, const struct pipe_draw_info *info,
    if (mgr->dirty_real_vb_mask)
       u_vbuf_set_driver_vertex_buffers(mgr);
 
-   pipe->draw_vbo(pipe, &new_info, drawid_offset, indirect, &new_draw, 1);
+   if (new_info.primitive_restart &&
+       (new_info.restart_index != fixed_restart_index && mgr->caps.rewrite_restart_index)) {
+      util_primconvert_save_flatshade_first(mgr->pc, mgr->flatshade_first);
+      util_primconvert_draw_vbo(mgr->pc, &new_info, drawid_offset, indirect, &new_draw, 1);
+   } else
+      pipe->draw_vbo(pipe, &new_info, drawid_offset, indirect, &new_draw, 1);
 
    if (mgr->using_translate) {
       u_vbuf_translate_end(mgr);
diff --git a/src/gallium/auxiliary/util/u_vbuf.h b/src/gallium/auxiliary/util/u_vbuf.h
index 3ec93e662a7..a7360be3fc9 100644
--- a/src/gallium/auxiliary/util/u_vbuf.h
+++ b/src/gallium/auxiliary/util/u_vbuf.h
@@ -59,6 +59,7 @@ struct u_vbuf_caps {
 
    bool fallback_always;
    bool fallback_only_for_user_vbuffers;
+   bool rewrite_restart_index;
 };
 
 
diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c
index cc2859384f7..45a75ebdd0e 100644
--- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c
+++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c
@@ -115,6 +115,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_PRIMITIVE_RESTART_FIXED_INDEX:
       return (eng3d->oclass >= NV40_3D_CLASS) ? 1 : 0;
    /* unsupported */
+   case PIPE_CAP_EMULATE_NONFIXED_PRIMITIVE_RESTART:
    case PIPE_CAP_DEPTH_CLIP_DISABLE_SEPARATE:
    case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS:
    case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD:
diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
index cd9946baed6..c88942765f6 100644
--- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c
+++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c
@@ -275,6 +275,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
       return class_3d >= NVA3_3D_CLASS;
 
    /* unsupported caps */
+   case PIPE_CAP_EMULATE_NONFIXED_PRIMITIVE_RESTART:
    case PIPE_CAP_DEPTH_CLIP_DISABLE_SEPARATE:
    case PIPE_CAP_SEAMLESS_CUBE_MAP_PER_TEXTURE:
    case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
index d1e901c4820..84cae860ba6 100644
--- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
+++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c
@@ -350,6 +350,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
       return 0;
 
    /* unsupported caps */
+   case PIPE_CAP_EMULATE_NONFIXED_PRIMITIVE_RESTART:
    case PIPE_CAP_DEPTH_CLIP_DISABLE_SEPARATE:
    case PIPE_CAP_TGSI_FS_COORD_ORIGIN_LOWER_LEFT:
    case PIPE_CAP_TGSI_FS_COORD_PIXEL_CENTER_INTEGER:
diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h
index 4523c405555..4747ef7953a 100644
--- a/src/gallium/include/pipe/p_defines.h
+++ b/src/gallium/include/pipe/p_defines.h
@@ -989,6 +989,7 @@ enum pipe_cap
    PIPE_CAP_SAMPLER_REDUCTION_MINMAX,
    PIPE_CAP_SAMPLER_REDUCTION_MINMAX_ARB,
    PIPE_CAP_ALLOW_DYNAMIC_VAO_FASTPATH,
+   PIPE_CAP_EMULATE_NONFIXED_PRIMITIVE_RESTART,
 
    PIPE_CAP_LAST,
    /* XXX do not add caps after PIPE_CAP_LAST! */



More information about the mesa-commit mailing list