Mesa (master): turnip: Emit geometry shader obj and related consts

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Apr 7 14:48:15 UTC 2020


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

Author: Brian Ho <brian at brkho.com>
Date:   Wed Apr  1 11:09:48 2020 -0700

turnip: Emit geometry shader obj and related consts

Like with other shader types, we need to emit the geometry shader
object and the consts it uses. In addition, we need to emit
additional geometry-specific consts that link primitive/vertex stride
between the vs and gs. In conjunction with the gsheader, these are
used by the vs to determine where to stlw outputs and used by the gs
to determine where to ldlw those outputs from.

FD emits these consts in the draw call because in GL, you can mix
and match shaders in different programs. In Vulkan, however, we
compile and link the shaders at pipeline creation, so we can emit
these in the pipeline IB instead.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/4436>

---

 src/freedreno/vulkan/tu_pipeline.c | 50 +++++++++++++++++++++++++++++++++++++-
 1 file changed, 49 insertions(+), 1 deletion(-)

diff --git a/src/freedreno/vulkan/tu_pipeline.c b/src/freedreno/vulkan/tu_pipeline.c
index 63fb616b73a..b004b7e5bc2 100644
--- a/src/freedreno/vulkan/tu_pipeline.c
+++ b/src/freedreno/vulkan/tu_pipeline.c
@@ -666,6 +666,26 @@ tu6_setup_streamout(const struct ir3_shader_variant *v,
                COND(tf->ncomp[3] > 0, A6XX_VPC_SO_BUF_CNTL_BUF3);
 }
 
+static void
+tu6_emit_const(struct tu_cs *cs, uint32_t opcode, uint32_t base,
+               enum a6xx_state_block block, uint32_t offset,
+               uint32_t size, uint32_t *dwords) {
+   assert(size % 4 == 0);
+
+   tu_cs_emit_pkt7(cs, opcode, 3 + size);
+   tu_cs_emit(cs, CP_LOAD_STATE6_0_DST_OFF(base) |
+         CP_LOAD_STATE6_0_STATE_TYPE(ST6_CONSTANTS) |
+         CP_LOAD_STATE6_0_STATE_SRC(SS6_DIRECT) |
+         CP_LOAD_STATE6_0_STATE_BLOCK(block) |
+         CP_LOAD_STATE6_0_NUM_UNIT(size / 4));
+
+   tu_cs_emit(cs, CP_LOAD_STATE6_1_EXT_SRC_ADDR(0));
+   tu_cs_emit(cs, CP_LOAD_STATE6_2_EXT_SRC_ADDR_HI(0));
+   dwords = (uint32_t *)&((uint8_t *)dwords)[offset];
+
+   tu_cs_emit_array(cs, dwords, size);
+}
+
 static void
 tu6_emit_vpc(struct tu_cs *cs,
              const struct ir3_shader_variant *vs,
@@ -1138,6 +1158,27 @@ tu6_emit_immediates(struct tu_cs *cs, const struct ir3_shader_variant *v,
    }
 }
 
+static void
+tu6_emit_geometry_consts(struct tu_cs *cs,
+                         const struct ir3_shader_variant *vs,
+                         const struct ir3_shader_variant *gs) {
+   unsigned num_vertices = gs->shader->nir->info.gs.vertices_in;
+
+   uint32_t params[4] = {
+      vs->shader->output_size * num_vertices * 4,  /* primitive stride */
+      vs->shader->output_size * 4,                 /* vertex stride */
+      0,
+      0,
+   };
+   uint32_t vs_base = vs->shader->const_state.offsets.primitive_param;
+   tu6_emit_const(cs, CP_LOAD_STATE6_GEOM, vs_base, SB6_VS_SHADER, 0,
+                  ARRAY_SIZE(params), params);
+
+   uint32_t gs_base = gs->shader->const_state.offsets.primitive_param;
+   tu6_emit_const(cs, CP_LOAD_STATE6_GEOM, gs_base, SB6_GS_SHADER, 0,
+                  ARRAY_SIZE(params), params);
+}
+
 static void
 tu6_emit_program(struct tu_cs *cs,
                  const struct tu_pipeline_builder *builder,
@@ -1167,6 +1208,7 @@ tu6_emit_program(struct tu_cs *cs,
       builder->shaders[MESA_SHADER_FRAGMENT]
          ? &builder->shaders[MESA_SHADER_FRAGMENT]->variants[0]
          : &dummy_variant;
+   bool has_gs = gs->type != MESA_SHADER_NONE;
 
    if (binning_pass) {
       /* if we have streamout, use full VS in binning pass, as the
@@ -1192,11 +1234,17 @@ tu6_emit_program(struct tu_cs *cs,
 
    tu6_emit_shader_object(cs, MESA_SHADER_VERTEX, vs, binary_bo,
       binning_pass ? builder->binning_vs_offset : builder->shader_offsets[MESA_SHADER_VERTEX]);
-
+   if (has_gs)
+      tu6_emit_shader_object(cs, MESA_SHADER_GEOMETRY, gs, binary_bo,
+                             builder->shader_offsets[MESA_SHADER_GEOMETRY]);
    tu6_emit_shader_object(cs, MESA_SHADER_FRAGMENT, fs, binary_bo,
                           builder->shader_offsets[MESA_SHADER_FRAGMENT]);
 
    tu6_emit_immediates(cs, vs, CP_LOAD_STATE6_GEOM, SB6_VS_SHADER);
+   if (has_gs) {
+      tu6_emit_immediates(cs, gs, CP_LOAD_STATE6_GEOM, SB6_GS_SHADER);
+      tu6_emit_geometry_consts(cs, vs, gs);
+   }
    if (!binning_pass)
       tu6_emit_immediates(cs, fs, CP_LOAD_STATE6_FRAG, SB6_FS_SHADER);
 }



More information about the mesa-commit mailing list