radeonsi: link ES-GS just like LS-HS
authorMarek Olšák <marek.olsak@amd.com>
Thu, 15 Oct 2015 21:29:00 +0000 (23:29 +0200)
committerMarek Olšák <marek.olsak@amd.com>
Fri, 13 Nov 2015 18:54:42 +0000 (19:54 +0100)
This reduces the shader key for ES.

Use a fixed attrib location based on (semantic name,  index).

The ESGS item size is determined by the physical index of the highest ES
output, so it's almost always larger than before, but I think that
shouldn't matter as long as the ESGS ring buffer is large enough.

Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
src/gallium/drivers/radeonsi/si_shader.c
src/gallium/drivers/radeonsi/si_shader.h
src/gallium/drivers/radeonsi/si_state_shaders.c

index a119cbdc16ca12b9e52faec41c1e8b895c66f713..56b05cef1a30a86590094daa180b8ece2deec9e3 100644 (file)
@@ -775,6 +775,7 @@ static LLVMValueRef fetch_input_gs(
        struct tgsi_shader_info *info = &shader->selector->info;
        unsigned semantic_name = info->input_semantic_name[reg->Register.Index];
        unsigned semantic_index = info->input_semantic_index[reg->Register.Index];
+       unsigned param;
 
        if (swizzle != ~0 && semantic_name == TGSI_SEMANTIC_PRIMID)
                return get_primitive_id(bld_base, swizzle);
@@ -805,12 +806,10 @@ static LLVMValueRef fetch_input_gs(
                                                   vtx_offset_param),
                                      4);
 
+       param = si_shader_io_get_unique_index(semantic_name, semantic_index);
        args[0] = si_shader_ctx->esgs_ring;
        args[1] = vtx_offset;
-       args[2] = lp_build_const_int32(gallivm,
-                                      (get_param_index(semantic_name, semantic_index,
-                                                       shader->selector->inputs_read) * 4 +
-                                       swizzle) * 256);
+       args[2] = lp_build_const_int32(gallivm, (param * 4 + swizzle) * 256);
        args[3] = uint->zero;
        args[4] = uint->one;  /* OFFEN */
        args[5] = uint->zero; /* IDXEN */
@@ -2016,9 +2015,6 @@ static void si_llvm_emit_es_epilogue(struct lp_build_tgsi_context * bld_base)
        LLVMTypeRef i32 = LLVMInt32TypeInContext(gallivm->context);
        LLVMValueRef soffset = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn,
                                            si_shader_ctx->param_es2gs_offset);
-       uint64_t enabled_outputs = si_shader_ctx->type == TGSI_PROCESSOR_TESS_EVAL ?
-                                          es->key.tes.es_enabled_outputs :
-                                          es->key.vs.es_enabled_outputs;
        unsigned chan;
        int i;
 
@@ -2031,11 +2027,8 @@ static void si_llvm_emit_es_epilogue(struct lp_build_tgsi_context * bld_base)
                    info->output_semantic_name[i] == TGSI_SEMANTIC_LAYER)
                        continue;
 
-               param_index = get_param_index(info->output_semantic_name[i],
-                                             info->output_semantic_index[i],
-                                             enabled_outputs);
-               if (param_index < 0)
-                       continue;
+               param_index = si_shader_io_get_unique_index(info->output_semantic_name[i],
+                                                           info->output_semantic_index[i]);
 
                for (chan = 0; chan < 4; chan++) {
                        LLVMValueRef out_val = LLVMBuildLoad(gallivm->builder, out_ptr[chan], "");
@@ -4023,10 +4016,6 @@ void si_dump_shader_key(unsigned shader, union si_shader_key *key, FILE *f)
                        fprintf(f, !i ? "%u" : ", %u",
                                key->vs.instance_divisors[i]);
                fprintf(f, "}\n");
-
-               if (key->vs.as_es)
-                       fprintf(f, "  es_enabled_outputs = 0x%"PRIx64"\n",
-                               key->vs.es_enabled_outputs);
                fprintf(f, "  as_es = %u\n", key->vs.as_es);
                fprintf(f, "  as_ls = %u\n", key->vs.as_ls);
                fprintf(f, "  export_prim_id = %u\n", key->vs.export_prim_id);
@@ -4037,9 +4026,6 @@ void si_dump_shader_key(unsigned shader, union si_shader_key *key, FILE *f)
                break;
 
        case PIPE_SHADER_TESS_EVAL:
-               if (key->tes.as_es)
-                       fprintf(f, "  es_enabled_outputs = 0x%"PRIx64"\n",
-                               key->tes.es_enabled_outputs);
                fprintf(f, "  as_es = %u\n", key->tes.as_es);
                fprintf(f, "  export_prim_id = %u\n", key->tes.export_prim_id);
                break;
index d815ce27e6a36f457e0394f2c642c9befa4da9ee..de69a273ab4a00b0168852472e0dc59d078cba82 100644 (file)
  *      Christian König <christian.koenig@amd.com>
  */
 
-/* How linking tessellation shader inputs and outputs works.
+/* How linking shader inputs and outputs between vertex, tessellation, and
+ * geometry shaders works.
  *
  * Inputs and outputs between shaders are stored in a buffer. This buffer
  * lives in LDS (typical case for tessellation), but it can also live
- * in memory. Each input or output has a fixed location within a vertex.
+ * in memory (ESGS). Each input or output has a fixed location within a vertex.
  * The highest used input or output determines the stride between vertices.
  *
- * Since tessellation is only enabled in the OpenGL core profile,
+ * Since GS and tessellation are only possible in the OpenGL core profile,
  * only these semantics are valid for per-vertex data:
  *
  *   Name             Location
  * That's how independent shaders agree on input and output locations.
  * The si_shader_io_get_unique_index function assigns the locations.
  *
- * Other required information for calculating the input and output addresses
- * like the vertex stride, the patch stride, and the offsets where per-vertex
- * and per-patch data start, is passed to the shader via user data SGPRs.
- * The offsets and strides are calculated at draw time and aren't available
- * at compile time.
- *
- * The same approach should be used for linking ES->GS in the future.
+ * For tessellation, other required information for calculating the input and
+ * output addresses like the vertex stride, the patch stride, and the offsets
+ * where per-vertex and per-patch data start, is passed to the shader via
+ * user data SGPRs. The offsets and strides are calculated at draw time and
+ * aren't available at compile time.
  */
 
 #ifndef SI_SHADER_H
@@ -245,7 +244,6 @@ union si_shader_key {
                /* Mask of "get_unique_index" bits - which outputs are read
                 * by the next stage (needed by ES).
                 * This describes how outputs are laid out in memory. */
-               uint64_t        es_enabled_outputs;
                unsigned        as_es:1; /* export shader */
                unsigned        as_ls:1; /* local shader */
                unsigned        export_prim_id:1; /* when PS needs it and GS is disabled */
@@ -257,7 +255,6 @@ union si_shader_key {
                /* Mask of "get_unique_index" bits - which outputs are read
                 * by the next stage (needed by ES).
                 * This describes how outputs are laid out in memory. */
-               uint64_t        es_enabled_outputs;
                unsigned        as_es:1; /* export shader */
                unsigned        export_prim_id:1; /* when PS needs it and GS is disabled */
        } tes; /* tessellation evaluation shader */
index 007a0ecb47628472a43be7b95270c011ea39e71f..3bf130d8a36f5ec81038e8208c3b787960ec00a7 100644 (file)
@@ -195,6 +195,8 @@ static void si_shader_es(struct si_shader *shader)
        }
        assert(num_sgprs <= 104);
 
+       si_pm4_set_reg(pm4, R_028AAC_VGT_ESGS_RING_ITEMSIZE,
+                      shader->selector->esgs_itemsize / 4);
        si_pm4_set_reg(pm4, R_00B320_SPI_SHADER_PGM_LO_ES, va >> 8);
        si_pm4_set_reg(pm4, R_00B324_SPI_SHADER_PGM_HI_ES, va >> 40);
        si_pm4_set_reg(pm4, R_00B328_SPI_SHADER_PGM_RSRC1_ES,
@@ -251,8 +253,6 @@ static void si_shader_gs(struct si_shader *shader)
        si_pm4_set_reg(pm4, R_028A64_VGT_GSVS_RING_OFFSET_2, gsvs_itemsize * ((max_stream >= 2) ? 2 : 1));
        si_pm4_set_reg(pm4, R_028A68_VGT_GSVS_RING_OFFSET_3, gsvs_itemsize * ((max_stream >= 3) ? 3 : 1));
 
-       si_pm4_set_reg(pm4, R_028AAC_VGT_ESGS_RING_ITEMSIZE,
-                      shader->selector->esgs_itemsize / 4);
        si_pm4_set_reg(pm4, R_028AB0_VGT_GSVS_RING_ITEMSIZE, gsvs_itemsize * (max_stream + 1));
 
        si_pm4_set_reg(pm4, R_028B38_VGT_GS_MAX_VERT_OUT, gs_max_vert_out);
@@ -515,10 +515,8 @@ static inline void si_shader_selector_key(struct pipe_context *ctx,
 
                if (sctx->tes_shader.cso)
                        key->vs.as_ls = 1;
-               else if (sctx->gs_shader.cso) {
+               else if (sctx->gs_shader.cso)
                        key->vs.as_es = 1;
-                       key->vs.es_enabled_outputs = sctx->gs_shader.cso->inputs_read;
-               }
 
                if (!sctx->gs_shader.cso && sctx->ps_shader.cso &&
                    sctx->ps_shader.cso->info.uses_primid)
@@ -529,10 +527,9 @@ static inline void si_shader_selector_key(struct pipe_context *ctx,
                        sctx->tes_shader.cso->info.properties[TGSI_PROPERTY_TES_PRIM_MODE];
                break;
        case PIPE_SHADER_TESS_EVAL:
-               if (sctx->gs_shader.cso) {
+               if (sctx->gs_shader.cso)
                        key->tes.as_es = 1;
-                       key->tes.es_enabled_outputs = sctx->gs_shader.cso->inputs_read;
-               } else if (sctx->ps_shader.cso && sctx->ps_shader.cso->info.uses_primid)
+               else if (sctx->ps_shader.cso && sctx->ps_shader.cso->info.uses_primid)
                        key->tes.export_prim_id = 1;
                break;
        case PIPE_SHADER_GEOMETRY: