[virglrenderer-devel] [PATCH 17/19] tessellation: handle tessellation shader indirect input/outputs

Dave Airlie airlied at gmail.com
Fri Jun 8 05:14:21 UTC 2018


From: Dave Airlie <airlied at redhat.com>

---
 src/vrend_shader.c | 180 ++++++++++++++++++++++++++++++++++++++++++++++++++++-
 src/vrend_shader.h |   8 +++
 2 files changed, 186 insertions(+), 2 deletions(-)

diff --git a/src/vrend_shader.c b/src/vrend_shader.c
index f18d252..d367e41 100644
--- a/src/vrend_shader.c
+++ b/src/vrend_shader.c
@@ -100,6 +100,13 @@ struct vrend_temp_range {
    int array_id;
 };
 
+struct vrend_io_range {
+   int first;
+   int last;
+   int array_id;
+   bool used;
+};
+
 struct dump_ctx {
    struct tgsi_iterate_context iter;
    struct vrend_shader_cfg *cfg;
@@ -117,7 +124,10 @@ struct dump_ctx {
    struct vrend_shader_io outputs[64];
    int num_system_values;
    struct vrend_shader_io system_values[32];
-
+   struct vrend_io_range generic_input_range;
+   struct vrend_io_range patch_input_range;
+   struct vrend_io_range generic_output_range;
+   struct vrend_io_range patch_output_range;
    int num_temp_ranges;
    struct vrend_temp_range *temp_ranges;
 
@@ -488,6 +498,24 @@ int shader_lookup_sampler_array(struct vrend_shader_info *sinfo, int index)
    return -1;
 }
 
+static bool ctx_indirect_inputs(struct dump_ctx *ctx)
+{
+   if (ctx->info.indirect_files & (1 << TGSI_FILE_INPUT))
+      return true;
+   if (ctx->key->num_indirect_generic_inputs || ctx->key->num_indirect_patch_inputs)
+      return true;
+   return false;
+}
+
+static bool ctx_indirect_outputs(struct dump_ctx *ctx)
+{
+   if (ctx->info.indirect_files & (1 << TGSI_FILE_OUTPUT))
+      return true;
+   if (ctx->key->num_indirect_generic_outputs || ctx->key->num_indirect_patch_outputs)
+      return true;
+   return false;
+}
+
 static boolean
 iter_declaration(struct tgsi_iterate_context *iter,
                  struct tgsi_full_declaration *decl )
@@ -497,10 +525,12 @@ iter_declaration(struct tgsi_iterate_context *iter,
    int color_offset = 0;
    const char *name_prefix = "";
    bool add_two_side = false;
+   bool indirect = false;
 
    switch (decl->Declaration.File) {
    case TGSI_FILE_INPUT:
       i = ctx->num_inputs++;
+      indirect = ctx_indirect_inputs(ctx);
       if (ctx->num_inputs > ARRAY_SIZE(ctx->inputs)) {
          fprintf(stderr, "Number of inputs exceeded, max is %lu\n", ARRAY_SIZE(ctx->inputs));
          return FALSE;
@@ -663,6 +693,17 @@ iter_declaration(struct tgsi_iterate_context *iter,
             break;
          }
       case TGSI_SEMANTIC_PATCH:
+	 if (indirect && ctx->inputs[i].name == TGSI_SEMANTIC_PATCH) {
+            ctx->inputs[i].glsl_predefined_no_emit = true;
+	    if (ctx->inputs[i].sid < ctx->patch_input_range.first || ctx->patch_input_range.used == false) {
+	       ctx->patch_input_range.first = ctx->inputs[i].sid;
+	       ctx->patch_input_range.array_id = i;
+	       ctx->patch_input_range.used = true;
+	    }
+	    if (ctx->inputs[i].sid > ctx->patch_input_range.last)
+               ctx->patch_input_range.last = ctx->inputs[i].sid;
+         }
+
       case TGSI_SEMANTIC_GENERIC:
          if (iter->processor.Processor == TGSI_PROCESSOR_FRAGMENT) {
             if (ctx->key->coord_replace & (1 << ctx->inputs[i].sid)) {
@@ -675,6 +716,16 @@ iter_declaration(struct tgsi_iterate_context *iter,
                break;
             }
          }
+         if (indirect && ctx->inputs[i].name == TGSI_SEMANTIC_GENERIC) {
+            ctx->inputs[i].glsl_predefined_no_emit = true;
+            if (ctx->inputs[i].sid < ctx->generic_input_range.first || ctx->generic_input_range.used == false) {
+               ctx->generic_input_range.first = ctx->inputs[i].sid;
+               ctx->generic_input_range.array_id = i;
+               ctx->generic_input_range.used = true;
+            }
+            if (ctx->inputs[i].sid > ctx->generic_input_range.last)
+               ctx->generic_input_range.last = ctx->inputs[i].sid;
+         }
       default:
          name_prefix = get_stage_input_name_prefix(ctx, iter->processor.Processor);
          break;
@@ -704,6 +755,7 @@ iter_declaration(struct tgsi_iterate_context *iter,
       break;
    case TGSI_FILE_OUTPUT:
       i = ctx->num_outputs++;
+      indirect = ctx_indirect_outputs(ctx);
       if (ctx->num_outputs > ARRAY_SIZE(ctx->outputs)) {
          fprintf(stderr, "Number of outputs exceeded, max is %lu\n", ARRAY_SIZE(ctx->outputs));
          return FALSE;
@@ -868,7 +920,29 @@ iter_declaration(struct tgsi_iterate_context *iter,
          if (iter->processor.Processor == TGSI_PROCESSOR_VERTEX)
             if (ctx->outputs[i].name == TGSI_SEMANTIC_GENERIC)
                color_offset = -1;
+         if (indirect && ctx->outputs[i].name == TGSI_SEMANTIC_GENERIC) {
+            ctx->outputs[i].glsl_predefined_no_emit = true;
+            ctx->glsl_ver_required = 150;
+            if (ctx->outputs[i].sid < ctx->generic_output_range.first || ctx->generic_output_range.used == false) {
+               ctx->generic_output_range.array_id = i;
+               ctx->generic_output_range.first = ctx->outputs[i].sid;
+               ctx->generic_output_range.used = true;
+            }
+            if (ctx->outputs[i].sid > ctx->generic_output_range.last)
+               ctx->generic_output_range.last = ctx->outputs[i].sid;
+         }
       case TGSI_SEMANTIC_PATCH:
+         if (indirect && ctx->outputs[i].name == TGSI_SEMANTIC_PATCH) {
+            ctx->outputs[i].glsl_predefined_no_emit = true;
+            ctx->glsl_ver_required = 150;
+            if (ctx->outputs[i].sid < ctx->patch_output_range.first || ctx->patch_output_range.used == false) {
+               ctx->patch_output_range.array_id = i;
+               ctx->patch_output_range.first = ctx->outputs[i].sid;
+               ctx->patch_output_range.used = true;
+            }
+            if (ctx->outputs[i].sid > ctx->patch_output_range.last)
+               ctx->patch_output_range.last = ctx->outputs[i].sid;
+         }
       default:
          name_prefix = get_stage_output_name_prefix(iter->processor.Processor);
          break;
@@ -2052,7 +2126,26 @@ get_destination_info(struct dump_ctx *ctx,
                               ctx->outputs[j].glsl_name,
                               ctx->outputs[j].override_no_wm ? "" : writemask);
                   } else if (ctx->prog_type == TGSI_PROCESSOR_TESS_CTRL && ctx->outputs[j].name != TGSI_SEMANTIC_PATCH) {
-                     snprintf(dsts[i], 255, "%s[gl_InvocationID]%s", ctx->outputs[j].glsl_name, ctx->outputs[j].override_no_wm ? "" : writemask);
+                     if (ctx_indirect_outputs(ctx)) {
+                        if (dst_reg->Register.Indirect)
+                           snprintf(dsts[i], 255, "oblk[gl_InvocationID].%s%d[addr%d + %d]%s", get_stage_output_name_prefix(ctx->prog_type), ctx->generic_output_range.first, dst_reg->Indirect.Index, dst_reg->Register.Index - ctx->generic_output_range.array_id, ctx->outputs[j].override_no_wm ? "" : writemask);
+                        else
+                           snprintf(dsts[i], 255, "oblk[gl_InvocationID].%s%d[%d]%s", get_stage_output_name_prefix(ctx->prog_type), ctx->generic_output_range.first, dst_reg->Register.Index - ctx->generic_output_range.array_id, ctx->outputs[j].override_no_wm ? "" : writemask);
+
+                     } else
+                        snprintf(dsts[i], 255, "%s[gl_InvocationID]%s", ctx->outputs[j].glsl_name, ctx->outputs[j].override_no_wm ? "" : writemask);
+                  } else if (ctx_indirect_outputs(ctx) && ctx->outputs[j].name == TGSI_SEMANTIC_GENERIC) {
+                     if (dst_reg->Register.Indirect)
+                        snprintf(dsts[i], 255, "oblk.%s%d[addr%d + %d]%s", get_stage_output_name_prefix(ctx->prog_type), ctx->generic_output_range.first, dst_reg->Indirect.Index, dst_reg->Register.Index - ctx->generic_output_range.array_id, ctx->outputs[j].override_no_wm ? "" : writemask);
+                     else
+                        snprintf(dsts[i], 255, "oblk.%s%d[%d]%s", get_stage_output_name_prefix(ctx->prog_type), ctx->generic_output_range.first, dst_reg->Register.Index - ctx->generic_output_range.array_id, ctx->outputs[j].override_no_wm ? "" : writemask);
+                     dinfo->dst_override_no_wm[i] = ctx->outputs[j].override_no_wm;
+                  } else if (ctx_indirect_outputs(ctx) && ctx->outputs[j].name == TGSI_SEMANTIC_PATCH) {
+                     if (dst_reg->Register.Indirect)
+                        snprintf(dsts[i], 255, "%sp%d[addr%d + %d]%s", get_stage_output_name_prefix(ctx->prog_type), ctx->patch_output_range.first, dst_reg->Indirect.Index, dst_reg->Register.Index - ctx->patch_output_range.array_id, ctx->outputs[j].override_no_wm ? "" : writemask);
+                     else
+                        snprintf(dsts[i], 255, "%sp%d[%d]%s", get_stage_output_name_prefix(ctx->prog_type), ctx->patch_output_range.first, dst_reg->Register.Index - ctx->patch_output_range.array_id, ctx->outputs[j].override_no_wm ? "" : writemask);
+                     dinfo->dst_override_no_wm[i] = ctx->outputs[j].override_no_wm;
                   } else {
                      snprintf(dsts[i], 255, "%s%s", ctx->outputs[j].glsl_name, ctx->outputs[j].override_no_wm ? "" : writemask);
                      dinfo->dst_override_no_wm[i] = ctx->outputs[j].override_no_wm;
@@ -2185,6 +2278,19 @@ get_source_info(struct dump_ctx *ctx,
 
                   if (inst->Instruction.Opcode == TGSI_OPCODE_INTERP_SAMPLE && i == 1) {
                      snprintf(srcs[i], 255, "floatBitsToInt(%s%s%s%s)", prefix, ctx->inputs[j].glsl_name, arrayname, swizzle);
+                  } else if (ctx->inputs[j].name == TGSI_SEMANTIC_GENERIC &&
+                             ctx_indirect_inputs(ctx)) {
+                     const char *blkarray = ctx->prog_type == TGSI_PROCESSOR_TESS_CTRL ? "[gl_InvocationID]" : "[0]";
+                     if (src->Register.Indirect)
+                        snprintf(srcs[i], 255, "%s(%sblk%s.%s%d[addr%d + %d]%s)", get_string(srcstypeprefix), prefix, blkarray, get_stage_input_name_prefix(ctx, ctx->prog_type), ctx->generic_input_range.first, src->Indirect.Index, src->Register.Index - ctx->generic_input_range.array_id, ctx->inputs[j].is_int ? "" : swizzle);
+                     else
+                        snprintf(srcs[i], 255, "%s(%sblk%s.%s%d[%d]%s)", get_string(srcstypeprefix), prefix, blkarray, get_stage_input_name_prefix(ctx, ctx->prog_type), ctx->generic_input_range.first, src->Register.Index - ctx->generic_input_range.array_id, ctx->inputs[j].is_int ? "" : swizzle);
+                  } else if (ctx->inputs[j].name == TGSI_SEMANTIC_PATCH &&
+                             ctx_indirect_inputs(ctx)) {
+                     if (src->Register.Indirect)
+                        snprintf(srcs[i], 255, "%s(%s%sp%d[addr%d + %d]%s)", get_string(srcstypeprefix), prefix, get_stage_input_name_prefix(ctx, ctx->prog_type), ctx->patch_input_range.first, src->Indirect.Index, src->Register.Index - ctx->patch_input_range.array_id, ctx->inputs[j].is_int ? "" : swizzle);
+                     else
+                        snprintf(srcs[i], 255, "%s(%s%sp%d[%d]%s)", get_string(srcstypeprefix), prefix, get_stage_input_name_prefix(ctx, ctx->prog_type), ctx->patch_input_range.first, src->Register.Index - ctx->patch_input_range.array_id, ctx->inputs[j].is_int ? "" : swizzle);
                   } else
                      snprintf(srcs[i], 255, "%s(%s%s%s%s)", get_string(srcstypeprefix), prefix, ctx->inputs[j].glsl_name, arrayname, ctx->inputs[j].is_int ? "" : swizzle);
                }
@@ -2209,6 +2315,19 @@ get_source_info(struct dump_ctx *ctx,
                   if (ctx->outputs[j].name == TGSI_SEMANTIC_CLIPDIST) {
                      create_swizzled_clipdist(ctx, srcs[i], src, ctx->outputs[j].sid, 1, get_string(stypeprefix), prefix, arrayname);
                   }
+               } else if (ctx->outputs[j].name == TGSI_SEMANTIC_GENERIC &&
+                          ctx_indirect_outputs(ctx)) {
+                  const char *blkarray = ctx->prog_type == TGSI_PROCESSOR_TESS_CTRL ? "[gl_InvocationID]" : "[0]";
+                  if (src->Register.Indirect)
+                     snprintf(srcs[i], 255, "%s(%soblk%s.%s%d[addr%d + %d]%s)", get_string(srcstypeprefix), prefix, blkarray, get_stage_output_name_prefix(ctx->prog_type), ctx->generic_output_range.first, src->Indirect.Index, src->Register.Index - ctx->generic_output_range.array_id, ctx->outputs[j].is_int ? "" : swizzle);
+                  else
+                     snprintf(srcs[i], 255, "%s(%sblk%s.%s%d[%d]%s)", get_string(srcstypeprefix), prefix, blkarray, get_stage_output_name_prefix(ctx->prog_type), ctx->generic_output_range.first, src->Register.Index - ctx->generic_output_range.array_id, ctx->outputs[j].is_int ? "" : swizzle);
+               } else if (ctx->outputs[j].name == TGSI_SEMANTIC_PATCH &&
+                          ctx_indirect_outputs(ctx)) {
+                  if (src->Register.Indirect)
+                     snprintf(srcs[i], 255, "%s(%s%sp%d[addr%d + %d]%s)", get_string(srcstypeprefix), prefix, get_stage_output_name_prefix(ctx->prog_type), ctx->patch_output_range.first, src->Indirect.Index, src->Register.Index - ctx->patch_output_range.array_id, ctx->outputs[j].is_int ? "" : swizzle);
+                  else
+                     snprintf(srcs[i], 255, "%s(%s%sp%d[%d]%s)", get_string(srcstypeprefix), prefix, get_stage_output_name_prefix(ctx->prog_type), ctx->patch_output_range.first, src->Register.Index - ctx->patch_output_range.array_id, ctx->outputs[j].is_int ? "" : swizzle);
                } else {
                   snprintf(srcs[i], 255, "%s(%s%s%s%s)", get_string(srcstypeprefix), prefix, ctx->outputs[j].glsl_name, arrayname, ctx->outputs[j].is_int ? "" : swizzle);
                }
@@ -3112,6 +3231,30 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
       snprintf(buf, 255, "layout(%s, max_vertices = %d) out;\n", prim_to_name(ctx->gs_out_prim), ctx->gs_max_out_verts);
       STRCAT_WITH_RET(glsl_hdr, buf);
    }
+
+   if (ctx_indirect_inputs(ctx)) {
+      const char *name_prefix = get_stage_input_name_prefix(ctx, ctx->prog_type);
+      if (ctx->prog_type == TGSI_PROCESSOR_TESS_EVAL) {
+         if (ctx->patch_input_range.used) {
+            int size = ctx->patch_input_range.last - ctx->patch_input_range.first + 1;
+            if (size < ctx->key->num_indirect_patch_inputs)
+               size = ctx->key->num_indirect_patch_inputs;
+            snprintf(buf, 255, "patch in vec4 %sp%d[%d];\n", name_prefix, ctx->patch_input_range.first, size);
+            STRCAT_WITH_RET(glsl_hdr, buf);
+         }
+      }
+
+      if (ctx->prog_type == TGSI_PROCESSOR_TESS_CTRL ||
+          ctx->prog_type == TGSI_PROCESSOR_TESS_EVAL) {
+         if (ctx->generic_input_range.used) {
+            int size = ctx->generic_input_range.last - ctx->generic_input_range.first + 1;
+            if (size < ctx->key->num_indirect_generic_inputs)
+               size = ctx->key->num_indirect_generic_inputs;
+            snprintf(buf, 255, "in block { vec4 %s%d[%d]; } blk[];\n", name_prefix, ctx->generic_input_range.first, size);
+            STRCAT_WITH_RET(glsl_hdr, buf);
+         }
+      }
+   }
    for (i = 0; i < ctx->num_inputs; i++) {
       if (!ctx->inputs[i].glsl_predefined_no_emit) {
          if (ctx->prog_type == TGSI_PROCESSOR_VERTEX && ctx->cfg->use_explicit_locations) {
@@ -3154,6 +3297,26 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
       STRCAT_WITH_RET(glsl_hdr, buf);
    }
 
+   if (ctx_indirect_outputs(ctx)) {
+      const char *name_prefix = get_stage_output_name_prefix(ctx->prog_type);
+      if (ctx->prog_type == TGSI_PROCESSOR_VERTEX) {
+         if (ctx->generic_output_range.used) {
+            snprintf(buf, 255, "out block { vec4 %s%d[%d]; } oblk;\n", name_prefix, ctx->generic_output_range.first, ctx->generic_output_range.last - ctx->generic_output_range.first + 1);
+            STRCAT_WITH_RET(glsl_hdr, buf);
+         }
+      }
+      if (ctx->prog_type == TGSI_PROCESSOR_TESS_CTRL) {
+         if (ctx->generic_output_range.used) {
+            snprintf(buf, 255, "out block { vec4 %s%d[%d]; } oblk[];\n", name_prefix, ctx->generic_output_range.first, ctx->generic_output_range.last - ctx->generic_output_range.first + 1);
+            STRCAT_WITH_RET(glsl_hdr, buf);
+         }
+         if (ctx->patch_output_range.used) {
+            snprintf(buf, 255, "patch out vec4 %sp%d[%d];\n", name_prefix, ctx->patch_output_range.first, ctx->patch_output_range.last - ctx->patch_output_range.first + 1);
+            STRCAT_WITH_RET(glsl_hdr, buf);
+         }
+      }
+   }
+
    if (ctx->write_all_cbufs) {
       for (i = 0; i < 8; i++) {
          if (ctx->cfg->use_gles)
@@ -3596,6 +3759,19 @@ char *vrend_convert_shader(struct vrend_shader_cfg *cfg,
    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);
+   if (ctx_indirect_inputs(&ctx)) {
+      if (ctx.generic_input_range.used)
+         sinfo->num_indirect_generic_inputs = ctx.generic_input_range.last - ctx.generic_input_range.first + 1;
+      if (ctx.patch_input_range.used)
+         sinfo->num_indirect_patch_inputs = ctx.patch_input_range.last - ctx.patch_input_range.first + 1;
+   }
+   if (ctx_indirect_outputs(&ctx)) {
+      if (ctx.generic_output_range.used)
+         sinfo->num_indirect_generic_outputs = ctx.generic_output_range.last - ctx.generic_output_range.first + 1;
+      if (ctx.patch_output_range.used)
+         sinfo->num_indirect_patch_outputs = ctx.patch_output_range.last - ctx.patch_output_range.first + 1;
+   }
+
    sinfo->num_inputs = ctx.num_inputs;
    sinfo->num_interps = ctx.num_interps;
    sinfo->num_outputs = ctx.num_outputs;
diff --git a/src/vrend_shader.h b/src/vrend_shader.h
index 2fe9f28..9dc6e1d 100644
--- a/src/vrend_shader.h
+++ b/src/vrend_shader.h
@@ -53,6 +53,10 @@ struct vrend_shader_info {
    int num_ubos;
    int ubo_idx[32];
    bool ubo_indirect;
+   uint8_t num_indirect_generic_outputs;
+   uint8_t num_indirect_patch_outputs;
+   uint8_t num_indirect_generic_inputs;
+   uint8_t num_indirect_patch_inputs;
    int num_ucp;
    int glsl_ver;
    bool has_pervertex_out;
@@ -88,6 +92,10 @@ struct vrend_shader_key {
    uint8_t prev_stage_num_cull_out;
    float alpha_ref_val;
    uint32_t cbufs_are_a8_bitmask;
+   uint8_t num_indirect_generic_outputs;
+   uint8_t num_indirect_patch_outputs;
+   uint8_t num_indirect_generic_inputs;
+   uint8_t num_indirect_patch_inputs;
 };
 
 struct vrend_shader_cfg {
-- 
2.14.3



More information about the virglrenderer-devel mailing list