[virglrenderer-devel] [PATCH 11/12] arb_gpu_shader5: add support for indirect ubo/samplers

Dave Airlie airlied at gmail.com
Tue May 15 04:38:09 UTC 2018


From: Dave Airlie <airlied at redhat.com>

---
 src/vrend_renderer.c |  15 +++-
 src/vrend_shader.c   | 189 ++++++++++++++++++++++++++++++++++++++++++++-------
 src/vrend_shader.h   |  15 ++++
 3 files changed, 190 insertions(+), 29 deletions(-)

diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
index 1f677ed..4cfeb6b 100644
--- a/src/vrend_renderer.c
+++ b/src/vrend_renderer.c
@@ -627,6 +627,7 @@ static void vrend_destroy_shader_selector(struct vrend_shader_selector *sel)
    free(sel->tmp_buf);
    free(sel->sinfo.so_names);
    free(sel->sinfo.interpinfo);
+   free(sel->sinfo.sampler_arrays);
    free(sel->tokens);
    free(sel);
 }
@@ -871,7 +872,7 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_conte
                                                               struct vrend_shader *gs)
 {
    struct vrend_linked_shader_program *sprog = CALLOC_STRUCT(vrend_linked_shader_program);
-   char name[32];
+   char name[64];
    int i;
    GLuint prog_id;
    GLint lret;
@@ -994,7 +995,11 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_conte
             index = 0;
             while(mask) {
                i = u_bit_scan(&mask);
-               snprintf(name, 32, "%ssamp%d", prefix, i);
+               if (sprog->ss[id]->sel->sinfo.num_sampler_arrays) {
+                  int arr_idx = shader_lookup_sampler_array(&sprog->ss[id]->sel->sinfo, i);
+                  snprintf(name, 32, "%ssamp%d[%d]", prefix, arr_idx, i - sprog->ss[id]->sel->sinfo.sampler_arrays[arr_idx].first);
+               } else
+                  snprintf(name, 32, "%ssamp%d", prefix, i);
                sprog->samp_locs[id][index] = glGetUniformLocation(prog_id, name);
                if (sprog->ss[id]->sel->sinfo.shadow_samp_mask & (1 << i)) {
                   snprintf(name, 32, "%sshadmask%d", prefix, i);
@@ -1048,7 +1053,11 @@ static struct vrend_linked_shader_program *add_shader_program(struct vrend_conte
          sprog->ubo_locs[id] = calloc(sprog->ss[id]->sel->sinfo.num_ubos, sizeof(uint32_t));
          for (i = 0; i < sprog->ss[id]->sel->sinfo.num_ubos; i++) {
             int ubo_idx = sprog->ss[id]->sel->sinfo.ubo_idx[i];
-            snprintf(name, 32, "%subo%d", prefix, ubo_idx);
+            if (sprog->ss[id]->sel->sinfo.ubo_indirect)
+               snprintf(name, 32, "%subo[%d]", prefix, ubo_idx - 1);
+            else
+               snprintf(name, 32, "%subo%d", prefix, ubo_idx);
+
             sprog->ubo_locs[id][i] = glGetUniformBlockIndex(prog_id, name);
          }
       } else
diff --git a/src/vrend_shader.c b/src/vrend_shader.c
index 6e7ca2f..78c929b 100644
--- a/src/vrend_shader.c
+++ b/src/vrend_shader.c
@@ -102,8 +102,13 @@ struct dump_ctx {
 
    struct vrend_shader_sampler samplers[32];
    uint32_t samplers_used;
-   int num_consts;
+   bool sviews_used;
+
+   struct vrend_sampler_array *sampler_arrays;
+   int num_sampler_arrays;
+   int last_sampler_array_idx;
 
+   int num_consts;
    int num_imm;
    struct immed imm[MAX_IMMEDIATE];
    unsigned fragcoord_input;
@@ -250,6 +255,46 @@ static struct vrend_temp_range *find_temp_range(struct dump_ctx *ctx, int index)
    return NULL;
 }
 
+static int add_sampler_array(struct dump_ctx *ctx, int first, int last, int sview_type, int sview_rtype)
+{
+   int idx = ctx->num_sampler_arrays;
+   ctx->num_sampler_arrays++;
+   ctx->sampler_arrays = realloc(ctx->sampler_arrays, sizeof(struct vrend_sampler_array) * ctx->num_sampler_arrays);
+   if (!ctx->sampler_arrays)
+      return -1;
+
+   ctx->sampler_arrays[idx].first = first;
+   ctx->sampler_arrays[idx].last = last;
+   ctx->sampler_arrays[idx].idx = idx;
+   ctx->sampler_arrays[idx].sview_type = sview_type;
+   ctx->sampler_arrays[idx].sview_rtype = sview_rtype;
+   return idx;
+}
+
+int lookup_sampler_array(struct dump_ctx *ctx, int index)
+{
+   int i;
+   for (i = 0; i < ctx->num_sampler_arrays; i++) {
+      if (index >= ctx->sampler_arrays[i].first &&
+          index <= ctx->sampler_arrays[i].last) {
+         return ctx->sampler_arrays[i].idx;
+      }
+   }
+   return -1;
+}
+
+int shader_lookup_sampler_array(struct vrend_shader_info *sinfo, int index)
+{
+   int i;
+   for (i = 0; i < sinfo->num_sampler_arrays; i++) {
+      if (index >= sinfo->sampler_arrays[i].first &&
+          index <= sinfo->sampler_arrays[i].last) {
+         return sinfo->sampler_arrays[i].idx;
+      }
+   }
+   return -1;
+}
+
 static boolean
 iter_declaration(struct tgsi_iterate_context *iter,
                  struct tgsi_full_declaration *decl )
@@ -663,6 +708,19 @@ iter_declaration(struct tgsi_iterate_context *iter,
          return FALSE;
       }
       ctx->samplers[decl->Range.First].tgsi_sampler_return = decl->SamplerView.ReturnTypeX;
+      if (ctx->info.indirect_files & (1 << TGSI_FILE_SAMPLER)) {
+         if (ctx->last_sampler_array_idx != -1) {
+            if (ctx->sampler_arrays[ctx->last_sampler_array_idx].sview_type == decl->SamplerView.Resource &&
+                ctx->sampler_arrays[ctx->last_sampler_array_idx].sview_rtype == decl->SamplerView.ReturnTypeX) {
+               ctx->sampler_arrays[ctx->last_sampler_array_idx].last = decl->Range.Last + 1;
+            } else {
+               ctx->last_sampler_array_idx = add_sampler_array(ctx, decl->Range.First, decl->Range.Last + 1, decl->SamplerView.Resource, decl->SamplerView.ReturnTypeX);
+            }
+         } else {
+            ctx->last_sampler_array_idx = add_sampler_array(ctx, decl->Range.First, decl->Range.Last + 1, decl->SamplerView.Resource, decl->SamplerView.ReturnTypeX);
+         }
+      } else
+      ctx->sviews_used = true;
       break;
    case TGSI_FILE_CONSTANT:
       if (decl->Declaration.Dimension) {
@@ -682,7 +740,7 @@ iter_declaration(struct tgsi_iterate_context *iter,
       }
       break;
    case TGSI_FILE_ADDRESS:
-      ctx->num_address = 1;
+      ctx->num_address = decl->Range.Last + 1;
       break;
    case TGSI_FILE_SYSTEM_VALUE:
       i = ctx->num_system_values++;
@@ -1771,10 +1829,14 @@ iter_instruction(struct tgsi_iterate_context *iter,
          if (!range)
             return FALSE;
          if (dst->Register.Indirect) {
-            snprintf(dsts[i], 255, "temp%d[addr0 + %d]%s", range->first, dst->Register.Index - range->first, writemask);
+            assert(dst->Indirect.File == TGSI_FILE_ADDRESS);
+            snprintf(dsts[i], 255, "temp%d[addr%d + %d]%s", range->first, dst->Indirect.Index, dst->Register.Index - range->first, writemask);
          } else
             snprintf(dsts[i], 255, "temp%d[%d]%s", range->first, dst->Register.Index - range->first, writemask);
       }
+      else if (dst->Register.File == TGSI_FILE_ADDRESS) {
+         snprintf(dsts[i], 255, "addr%d", dst->Register.Index);
+      }
    }
 
    for (i = 0; i < inst->Instruction.NumSrcRegs; i++) {
@@ -1794,8 +1856,13 @@ iter_instruction(struct tgsi_iterate_context *iter,
       if (isabsolute)
          strcpy(&prefix[pre_idx++], "abs(");
 
-      if (src->Register.Dimension)
-         sprintf(arrayname, "[%d]", src->Dimension.Index);
+      if (src->Register.Dimension) {
+         if (src->Dimension.Indirect) {
+            assert(src->DimIndirect.File == TGSI_FILE_ADDRESS);
+            sprintf(arrayname, "[addr%d]", src->DimIndirect.Index);
+         } else
+            sprintf(arrayname, "[%d]", src->Dimension.Index);
+      }
 
       if (src->Register.SwizzleX != TGSI_SWIZZLE_X ||
           src->Register.SwizzleY != TGSI_SWIZZLE_Y ||
@@ -1858,7 +1925,8 @@ iter_instruction(struct tgsi_iterate_context *iter,
          }
 
          if (src->Register.Indirect) {
-            snprintf(srcs[i], 255, "%s%c%stemp%d[addr0 + %d]%s%c", stypeprefix, stprefix ? '(' : ' ', prefix, range->first, src->Register.Index - range->first, swizzle, stprefix ? ')' : ' ');
+            assert(src->Indirect.File == TGSI_FILE_ADDRESS);
+            snprintf(srcs[i], 255, "%s%c%stemp%d[addr%d + %d]%s%c", stypeprefix, stprefix ? '(' : ' ', prefix, range->first, src->Indirect.Index, src->Register.Index - range->first, swizzle, stprefix ? ')' : ' ');
          } else
             snprintf(srcs[i], 255, "%s%c%stemp%d[%d]%s%c", stypeprefix, stprefix ? '(' : ' ', prefix, range->first, src->Register.Index - range->first, swizzle, stprefix ? ')' : ' ');
       } else if (src->Register.File == TGSI_FILE_CONSTANT) {
@@ -1866,10 +1934,27 @@ iter_instruction(struct tgsi_iterate_context *iter,
          int dim = 0;
          if (src->Register.Dimension) {
             dim = src->Dimension.Index;
-            if (src->Register.Indirect) {
-               snprintf(srcs[i], 255, "%s(%s%subo%dcontents[addr0 + %d]%s)", stypeprefix, prefix, cname, dim, src->Register.Index, swizzle);
-            } else
-               snprintf(srcs[i], 255, "%s(%s%subo%dcontents[%d]%s)", stypeprefix, prefix, cname, dim, src->Register.Index, swizzle);
+            if (src->Dimension.Indirect) {
+               assert(src->DimIndirect.File == TGSI_FILE_ADDRESS);
+               ctx->uses_gpu_shader5 = true;
+               if (src->Register.Indirect) {
+                  assert(src->Indirect.File == TGSI_FILE_ADDRESS);
+                  snprintf(srcs[i], 255, "%s(%s%suboarr[addr%d].ubocontents[addr%d + %d]%s)", stypeprefix, prefix, cname, src->DimIndirect.Index, src->Indirect.Index, src->Register.Index, swizzle);
+               } else
+                  snprintf(srcs[i], 255, "%s(%s%suboarr[addr%d].ubocontents[%d]%s)", stypeprefix, prefix, cname, src->DimIndirect.Index, src->Register.Index, swizzle);
+            } else {
+               if (ctx->info.dimension_indirect_files & (1 << TGSI_FILE_CONSTANT)) {
+                  if (src->Register.Indirect) {
+                     snprintf(srcs[i], 255, "%s(%s%suboarr[%d].ubocontents[addr%d + %d]%s)", stypeprefix, prefix, cname, dim, src->Indirect.Index, src->Register.Index, swizzle);
+                  } else
+                     snprintf(srcs[i], 255, "%s(%s%suboarr[%d].ubocontents[%d]%s)", stypeprefix, prefix, cname, dim, src->Register.Index, swizzle);
+               } else {
+                  if (src->Register.Indirect) {
+                     snprintf(srcs[i], 255, "%s(%s%subo%dcontents[addr0 + %d]%s)", stypeprefix, prefix, cname, dim, src->Register.Index, swizzle);
+                  } else
+                     snprintf(srcs[i], 255, "%s(%s%subo%dcontents[%d]%s)", stypeprefix, prefix, cname, dim, src->Register.Index, swizzle);
+               }
+            }
          } else {
             const char *csp;
             ctx->has_ints = true;
@@ -1889,7 +1974,17 @@ iter_instruction(struct tgsi_iterate_context *iter,
          }
       } else if (src->Register.File == TGSI_FILE_SAMPLER) {
          const char *cname = tgsi_proc_to_prefix(ctx->prog_type);
-         snprintf(srcs[i], 255, "%ssamp%d%s", cname, src->Register.Index, swizzle);
+         if (ctx->info.indirect_files & (1 << TGSI_FILE_SAMPLER)) {
+            int arr_idx = lookup_sampler_array(ctx, src->Register.Index);
+            if (src->Register.Indirect) {
+
+               snprintf(srcs[i], 255, "%ssamp%d[addr%d+%d]%s", cname, arr_idx, src->Indirect.Index, src->Register.Index - ctx->sampler_arrays[arr_idx].first, swizzle);
+            } else {
+               snprintf(srcs[i], 255, "%ssamp%d[%d]%s", cname, arr_idx, src->Register.Index - ctx->sampler_arrays[arr_idx].first, swizzle);
+            }
+         } else {
+            snprintf(srcs[i], 255, "%ssamp%d%s", cname, src->Register.Index, swizzle);
+         }
          sreg_index = src->Register.Index;
       } else if (src->Register.File == TGSI_FILE_IMMEDIATE) {
          if (src->Register.Index >= ARRAY_SIZE(ctx->imm)) {
@@ -2326,11 +2421,11 @@ iter_instruction(struct tgsi_iterate_context *iter,
       EMIT_BUF_WITH_RET(ctx, "return;\n");
       break;
    case TGSI_OPCODE_ARL:
-      snprintf(buf, 255, "addr0 = int(floor(%s)%s);\n", srcs[0], writemask);
+      snprintf(buf, 255, "%s = int(floor(%s)%s);\n", dsts[0], srcs[0], writemask);
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
    case TGSI_OPCODE_UARL:
-      snprintf(buf, 255, "addr0 = int(%s);\n", srcs[0]);
+      snprintf(buf, 255, "%s = int(%s);\n", dsts[0], srcs[0]);
       EMIT_BUF_WITH_RET(ctx, buf);
       break;
    case TGSI_OPCODE_XPD:
@@ -2607,6 +2702,15 @@ static const char *get_aux_string(struct vrend_shader_cfg *cfg, bool centroid)
    return centroid ? "centroid " : "";
 }
 
+static const char get_return_type_prefix(enum tgsi_return_type type)
+{
+   if (type == TGSI_RETURN_TYPE_SINT)
+      return 'i';
+   if (type == TGSI_RETURN_TYPE_UINT)
+      return 'u';
+   return ' ';
+}
+
 static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
 {
    int i;
@@ -2870,27 +2974,49 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
       }
    }
    if (ctx->num_ubo) {
-      for (i = 0; i < ctx->num_ubo; i++) {
-         const char *cname = tgsi_proc_to_prefix(ctx->prog_type);
-         snprintf(buf, 255, "uniform %subo%d { vec4 %subo%dcontents[%d]; };\n", cname, ctx->ubo_idx[i], cname, ctx->ubo_idx[i], ctx->ubo_sizes[i]);
+      const char *cname = tgsi_proc_to_prefix(ctx->prog_type);
+
+      if (ctx->info.dimension_indirect_files & (1 << TGSI_FILE_CONSTANT)) {
+         ctx->glsl_ver_required = 150;
+         snprintf(buf, 255, "uniform %subo { vec4 ubocontents[%d]; } %suboarr[%d];\n", cname, ctx->ubo_sizes[0], cname, ctx->num_ubo);
          STRCAT_WITH_RET(glsl_hdr, buf);
+      } else {
+         for (i = 0; i < ctx->num_ubo; i++) {
+            snprintf(buf, 255, "uniform %subo%d { vec4 %subo%dcontents[%d]; };\n", cname, ctx->ubo_idx[i], cname, ctx->ubo_idx[i], ctx->ubo_sizes[i]);
+            STRCAT_WITH_RET(glsl_hdr, buf);
+         }
       }
    }
-   for (i = 0; i < 32; i++) {
-      int is_shad = 0;
-      const char *stc;
-      char ptc;
 
-      if ((ctx->samplers_used & (1 << i)) == 0)
-         continue;
+   if (ctx->info.indirect_files & (1 << TGSI_FILE_SAMPLER)) {
+      for (i = 0; i < ctx->num_sampler_arrays; i++) {
+         int is_shad = 0;
+         const char *stc;
+         stc = vrend_shader_samplertypeconv(ctx->sampler_arrays[i].sview_type, &is_shad);
+         if (!stc)
+            continue;
+         snprintf(buf, 255, "uniform %csampler%s %ssamp%d[%d];\n",
+                  get_return_type_prefix(ctx->sampler_arrays[i].sview_rtype),
+                  stc, sname, ctx->sampler_arrays[i].idx,
+                  ctx->sampler_arrays[i].last - ctx->sampler_arrays[i].first);
+         STRCAT_WITH_RET(glsl_hdr, buf);
+      }
+   } else {
+      nsamp = util_last_bit(ctx->samplers_used);
+      for (i = 0; i < nsamp; i++) {
+         int is_shad = 0;
+         const char *stc;
+         char ptc;
 
-      ptc = vrend_shader_samplerreturnconv(ctx->samplers[i].tgsi_sampler_return);
-      stc = vrend_shader_samplertypeconv(ctx->samplers[i].tgsi_sampler_type, &is_shad);
+         if ((ctx->samplers_used & (1 << i)) == 0)
+            continue;
 
-      if (stc) {
          const char *sname;
          const char *precision;
 
+         ptc = vrend_shader_samplerreturnconv(ctx->samplers[i].tgsi_sampler_return);
+         stc = vrend_shader_samplertypeconv(ctx->samplers[i].tgsi_sampler_type, &is_shad);
+
          sname = tgsi_proc_to_prefix(ctx->prog_type);
 
          if (ctx->cfg->use_gles) {
@@ -2994,7 +3120,9 @@ char *vrend_convert_shader(struct vrend_shader_cfg *cfg,
    ctx.key = key;
    ctx.cfg = cfg;
    ctx.prog_type = -1;
-
+   ctx.num_sampler_arrays = 0;
+   ctx.sampler_arrays = NULL;
+   ctx.last_sampler_array_idx = -1;
    tgsi_scan_shader(tokens, &ctx.info);
    /* if we are in core profile mode we should use GLSL 1.40 */
    if (cfg->use_core_profile && cfg->glsl_version >= 140)
@@ -3008,6 +3136,12 @@ char *vrend_convert_shader(struct vrend_shader_cfg *cfg,
    } else
       ctx.so_names = NULL;
 
+   if (ctx.info.dimension_indirect_files & (1 << TGSI_FILE_CONSTANT))
+      ctx.glsl_ver_required = 150;
+
+   if (ctx.info.indirect_files & (1 << TGSI_FILE_SAMPLER))
+      ctx.uses_gpu_shader5 = true;
+
    ctx.glsl_main = malloc(4096);
    if (!ctx.glsl_main)
       goto fail;
@@ -3055,6 +3189,7 @@ char *vrend_convert_shader(struct vrend_shader_cfg *cfg,
    sinfo->num_consts = ctx.num_consts;
    sinfo->num_ubos = ctx.num_ubo;
    memcpy(sinfo->ubo_idx, ctx.ubo_idx, ctx.num_ubo * sizeof(*ctx.ubo_idx));
+   sinfo->ubo_indirect = ctx.info.dimension_indirect_files & (1 << TGSI_FILE_CONSTANT);
    sinfo->num_inputs = ctx.num_inputs;
    sinfo->num_interps = ctx.num_interps;
    sinfo->num_outputs = ctx.num_outputs;
@@ -3063,6 +3198,8 @@ char *vrend_convert_shader(struct vrend_shader_cfg *cfg,
    sinfo->gs_out_prim = ctx.gs_out_prim;
    sinfo->so_names = ctx.so_names;
    sinfo->attrib_input_mask = ctx.attrib_input_mask;
+   sinfo->sampler_arrays = ctx.sampler_arrays;
+   sinfo->num_sampler_arrays = ctx.num_sampler_arrays;
    return glsl_final;
  fail:
    free(ctx.glsl_main);
diff --git a/src/vrend_shader.h b/src/vrend_shader.h
index 230a3c1..897d750 100644
--- a/src/vrend_shader.h
+++ b/src/vrend_shader.h
@@ -35,6 +35,14 @@ struct vrend_interp_info {
    bool centroid;
 };
 
+struct vrend_sampler_array {
+   int first;
+   int last;
+   int idx;
+   int sview_type;
+   int sview_rtype;
+};
+
 struct vrend_shader_info {
    uint32_t samplers_used_mask;
    int num_consts;
@@ -43,6 +51,7 @@ struct vrend_shader_info {
    int num_outputs;
    int num_ubos;
    int ubo_idx[32];
+   bool ubo_indirect;
    int num_ucp;
    int glsl_ver;
    bool has_pervertex_out;
@@ -51,6 +60,10 @@ struct vrend_shader_info {
    uint32_t shadow_samp_mask;
    int gs_out_prim;
    uint32_t attrib_input_mask;
+
+   struct vrend_sampler_array *sampler_arrays;
+   int num_sampler_arrays;
+
    struct pipe_stream_output_info so_info;
 
    struct vrend_interp_info *interpinfo;
@@ -92,4 +105,6 @@ char *vrend_convert_shader(struct vrend_shader_cfg *cfg,
                            struct vrend_shader_key *key,
                            struct vrend_shader_info *sinfo);
 const char *vrend_shader_samplertypeconv(int sampler_type, int *is_shad);
+
+int shader_lookup_sampler_array(struct vrend_shader_info *sinfo, int index);
 #endif
-- 
2.14.3



More information about the virglrenderer-devel mailing list