[virglrenderer-devel] [PATCH 1/8] shader: add image support to shader parsing. (v3)

Gert Wollny gert.wollny at collabora.com
Mon Jul 30 11:18:34 UTC 2018


The array stuff likes a lot friendlier now :)
Just one more nit, apart from that 
  Reviewed-by: Gert Wollny <gert.wollny at collabora.com>

Am Montag, den 30.07.2018, 14:56 +1000 schrieb Dave Airlie:
> From: Dave Airlie <airlied at redhat.com>
> 
> This converts the image related opcodes, and tracks the used
> images.
> 
> Images need some extensions for extra features:
> ES_3_1_compatability is needed for r32f image support
> shader_image_size for image size support
> 
> v2: image: fix missing emit for atomic,
> use a shader req for images extension
> extend cas_str - we overflowed this
> v2.1: drop extra breaks, use decl last for range check (Tomeu)
> v3: add indirect support,
>     drop pointless debug print (Gert)
> ---
>  src/vrend_renderer.c |   1 +
>  src/vrend_shader.c   | 435
> ++++++++++++++++++++++++++++++++++++++++++++++++---
>  src/vrend_shader.h   |   9 ++
>  3 files changed, 427 insertions(+), 18 deletions(-)
> 
> diff --git a/src/vrend_renderer.c b/src/vrend_renderer.c
> index 16013cc..0c53348 100644
> --- a/src/vrend_renderer.c
> +++ b/src/vrend_renderer.c
> @@ -749,6 +749,7 @@ static void vrend_destroy_shader_selector(struct
> vrend_shader_selector *sel)
>     free(sel->sinfo.so_names);
>     free(sel->sinfo.interpinfo);
>     free(sel->sinfo.sampler_arrays);
> +   free(sel->sinfo.image_arrays);
>     free(sel->tokens);
>     free(sel);
>  }
> diff --git a/src/vrend_shader.c b/src/vrend_shader.c
> index ca4e18e..1fd062b 100644
> --- a/src/vrend_shader.c
> +++ b/src/vrend_shader.c
> @@ -56,6 +56,9 @@ extern int vrend_dump_shaders;
>  #define SHADER_REQ_GPU_SHADER5        (1 << 12)
>  #define SHADER_REQ_DERIVATIVE_CONTROL (1 << 13)
>  #define SHADER_REQ_FP64               (1 << 14)
> +#define SHADER_REQ_IMAGE_LOAD_STORE   (1 << 15)
> +#define SHADER_REQ_ES31_COMPAT        (1 << 16)
> +#define SHADER_REQ_IMAGE_SIZE         (1 << 17)
>  
>  struct vrend_shader_io {
>     unsigned                name;
> @@ -86,6 +89,12 @@ struct vrend_shader_table {
>     const char *string;
>  };
>  
> +struct vrend_shader_image {
> +   struct tgsi_declaration_image decl;
> +   enum tgsi_return_type image_return;
> +   bool vflag;
> +};
> +
>  #define MAX_IMMEDIATE 1024
>  struct immed {
>     int type;
> @@ -143,6 +152,12 @@ struct dump_ctx {
>     uint32_t ssbo_array_base;
>     uint32_t ssbo_atomic_array_base;
>  
> +   struct vrend_shader_image images[32];
> +   uint32_t images_used_mask;
> +
> +   struct vrend_image_array *image_arrays;
> +   uint32_t num_image_arrays;
> +
>     struct vrend_sampler_array *sampler_arrays;
>     uint32_t num_sampler_arrays;
>     int last_sampler_array_idx;
> @@ -210,6 +225,9 @@ static const struct vrend_shader_table
> shader_req_table[] = {
>      { SHADER_REQ_GPU_SHADER5, "GL_ARB_gpu_shader5" },
>      { SHADER_REQ_DERIVATIVE_CONTROL, "GL_ARB_derivative_control" },
>      { SHADER_REQ_FP64, "GL_ARB_gpu_shader_fp64" },
> +    { SHADER_REQ_IMAGE_LOAD_STORE, "GL_ARB_shader_image_load_store"
> },
> +    { SHADER_REQ_ES31_COMPAT, "GL_ARB_ES3_1_compatibility" },
> +    { SHADER_REQ_IMAGE_SIZE, "GL_ARB_shader_image_size" },
>  };
>  
>  enum vrend_type_qualifier {
> @@ -301,6 +319,8 @@ static inline const char *get_wm_string(unsigned
> wm)
>     }
>  }
>  
> +const char *get_internalformat_string(int virgl_format, enum
> tgsi_return_type *stype);
> +
>  static inline const char *tgsi_proc_to_prefix(int shader_type)
>  {
>     switch (shader_type) {
> @@ -488,6 +508,53 @@ static struct vrend_temp_range
> *find_temp_range(struct dump_ctx *ctx, int index)
>     return NULL;
>  }
>  
> +static int add_images(struct dump_ctx *ctx, int first, int last,
> +                      struct tgsi_declaration_image *img_decl)
> +{
> +   int i;
> +
> +   for (i = first; i <= last; i++) {
> +      ctx->images[i].decl = *img_decl;
> +      ctx->images[i].vflag = false;
> +      ctx->images_used_mask |= (1 << i);
> +
> +      if (ctx->images[i].decl.Resource == TGSI_TEXTURE_CUBE_ARRAY)
> +         ctx->shader_req_bits |= SHADER_REQ_CUBE_ARRAY;
> +      else if (ctx->images[i].decl.Resource == TGSI_TEXTURE_2D_MSAA
> ||
> +          ctx->images[i].decl.Resource ==
> TGSI_TEXTURE_2D_ARRAY_MSAA)
> +         ctx->shader_req_bits |= SHADER_REQ_SAMPLER_MS;
> +      else if (ctx->images[i].decl.Resource == TGSI_TEXTURE_BUFFER)
> +         ctx->uses_sampler_buf = true;
> +      else if (ctx->images[i].decl.Resource == TGSI_TEXTURE_RECT)
> +         ctx->shader_req_bits |= SHADER_REQ_SAMPLER_RECT;
> +   }
> +
> +   if (ctx->info.indirect_files & (1 << TGSI_FILE_IMAGE)) {
> +      if (ctx->num_image_arrays) {
> +         struct vrend_image_array *last_array = &ctx-
> >image_arrays[ctx->num_image_arrays - 1];
> +         /*
> +          * If this set of images is consecutive to the last array,
> +          * and has compatible return and decls, then increase the
> array size.
> +          */
> +         if ((last_array->first + last_array->array_size == first)
> &&
> +             !memcmp(&ctx->images[last_array->first].decl, &ctx-
> >images[first].decl, sizeof(ctx->images[first].decl)) &&
> +             ctx->images[last_array->first].image_return == ctx-
> >images[first].image_return) {
> +            last_array->array_size += last - first + 1;
> +            return 0;
> +         }
> +      }
> +
> +      /* allocate a new image array for this range of images */
> +      ctx->num_image_arrays++;
> +      ctx->image_arrays = realloc(ctx->image_arrays, sizeof(struct
> vrend_image_array) * ctx->num_image_arrays);
> +      if (!ctx->image_arrays)
> +         return -1;
> +      ctx->image_arrays[ctx->num_image_arrays - 1].first = first;
> +      ctx->image_arrays[ctx->num_image_arrays - 1].array_size = last
> - first + 1;
> +   }
> +   return 0;
> +}
> +
>  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;
> @@ -546,6 +613,18 @@ static bool ctx_indirect_outputs(struct dump_ctx
> *ctx)
>     return false;
>  }
>  
> +static int lookup_image_array(struct dump_ctx *ctx, int index)
> +{
> +   uint32_t i;
> +   for (i = 0; i < ctx->num_image_arrays; i++) {
> +      if (index >= ctx->image_arrays[i].first &&
> +          index <= ctx->image_arrays[i].first + ctx-
> >image_arrays[i].array_size - 1) {
> +         return ctx->image_arrays[i].first;
> +      }
> +   }
> +   return -1;
> +}
> +
>  static boolean
>  iter_declaration(struct tgsi_iterate_context *iter,
>                   struct tgsi_full_declaration *decl )
> @@ -1049,6 +1128,18 @@ iter_declaration(struct tgsi_iterate_context
> *iter,
>           }
>        }
>        break;
> +   case TGSI_FILE_IMAGE: {
> +      int ret;
> +      ctx->shader_req_bits |= SHADER_REQ_IMAGE_LOAD_STORE;
> +      if (decl->Range.Last >= ARRAY_SIZE(ctx->images)) {
> +         fprintf(stderr, "Image view exceeded, max is %lu\n",
> ARRAY_SIZE(ctx->images));
> +         return FALSE;
> +      }
> +      ret = add_images(ctx, decl->Range.First, decl->Range.Last,
> &decl->Image);
> +      if (ret == -1)
> +         return FALSE;
> +      break;
> +   }
>     case TGSI_FILE_BUFFER:
>        if (decl->Range.First >= 32) {
>           fprintf(stderr, "Buffer view exceeded, max is 32\n");
> @@ -2144,6 +2235,32 @@ create_swizzled_clipdist(struct dump_ctx *ctx,
>     snprintf(result, 255, "%s(vec4(%s,%s,%s,%s))", stypeprefix,
> clipdistvec[0], clipdistvec[1], clipdistvec[2], clipdistvec[3]);
>  }
>  
> +static enum vrend_type_qualifier get_coord_prefix(int resource, bool
> *is_ms)
> +{
> +   switch(resource) {
> +   case TGSI_TEXTURE_1D:
> +   case TGSI_TEXTURE_BUFFER:
> +      return INT;
> +   case TGSI_TEXTURE_2D:
> +   case TGSI_TEXTURE_RECT:
> +   case TGSI_TEXTURE_1D_ARRAY:
> +      return IVEC2;
> +   case TGSI_TEXTURE_3D:
> +   case TGSI_TEXTURE_CUBE:
> +   case TGSI_TEXTURE_2D_ARRAY:
> +   case TGSI_TEXTURE_CUBE_ARRAY:
> +      return IVEC3;
> +   case TGSI_TEXTURE_2D_MSAA:
> +      *is_ms = true;
> +      return IVEC2;
> +   case TGSI_TEXTURE_2D_ARRAY_MSAA:
> +      *is_ms = true;
> +      return IVEC3;
> +   default:
> +      return TYPE_CONVERSION_NONE;
> +   }
> +}
> +
>  static int
>  translate_store(struct dump_ctx *ctx,
>                  struct tgsi_full_instruction *inst,
> @@ -2153,7 +2270,29 @@ translate_store(struct dump_ctx *ctx,
>     const struct tgsi_full_dst_register *dst = &inst->Dst[0];
>     char buf[512];
>  
> -   if (dst->Register.File == TGSI_FILE_BUFFER) {
> +   if (dst->Register.File == TGSI_FILE_IMAGE) {
> +      bool is_ms = false;
> +      enum vrend_type_qualifier coord_prefix = get_coord_prefix(ctx-
> >images[dst->Register.Index].decl.Resource, &is_ms);
> +      enum tgsi_return_type itype;
> +      char ms_str[32] = {};
> +      enum vrend_type_qualifier stypeprefix = TYPE_CONVERSION_NONE;
> +      get_internalformat_string(inst->Memory.Format, &itype);
> +      if (is_ms) {
> +         snprintf(ms_str, 32, "int(%s.w),", srcs[0]);
> +      }
> +      switch (itype) {
> +      case TGSI_RETURN_TYPE_UINT:
> +         stypeprefix = FLOAT_BITS_TO_UINT;
> +         break;
> +      case TGSI_RETURN_TYPE_SINT:
> +         stypeprefix = FLOAT_BITS_TO_INT;
> +         break;
> +      default:
> +         break;
> +      }
> +      snprintf(buf, 512,
> "imageStore(%s,%s(floatBitsToInt(%s)),%s%s(%s));\n", dsts[0],
> get_string(coord_prefix), srcs[0], ms_str, get_string(stypeprefix),
> srcs[1]);
> +      EMIT_BUF_WITH_RET(ctx, buf);
> +   } else if (dst->Register.File == TGSI_FILE_BUFFER) {
>        const char *conversion = get_string(FLOAT_BITS_TO_UINT);
>        if (inst->Dst[0].Register.WriteMask & 0x1) {
>           snprintf(buf, 255, "%s[uint(floatBitsToUint(%s))>>2] =
> %s(%s).x;\n", dsts[0], srcs[0], conversion, srcs[1]);
> @@ -2178,13 +2317,38 @@ translate_store(struct dump_ctx *ctx,
>  static int
>  translate_load(struct dump_ctx *ctx,
>                 struct tgsi_full_instruction *inst,
> +               struct source_info *sinfo,
> +               struct dest_info *dinfo,
>                 char srcs[4][255],
> -               char dsts[3][255])
> +               char dsts[3][255],
> +               const char *writemask)
>  {
>     char buf[512];
>     const struct tgsi_full_src_register *src = &inst->Src[0];
> -
> -   if (src->Register.File == TGSI_FILE_BUFFER) {
> +   if (src->Register.File == TGSI_FILE_IMAGE) {
> +      bool is_ms = false;
> +      enum vrend_type_qualifier coord_prefix = get_coord_prefix(ctx-
> >images[sinfo->sreg_index].decl.Resource, &is_ms);
> +      enum vrend_type_qualifier dtypeprefix = TYPE_CONVERSION_NONE;
> +      enum tgsi_return_type itype;
> +      get_internalformat_string(ctx->images[sinfo-
> >sreg_index].decl.Format, &itype);
> +      char ms_str[32] = {};
> +      const char *wm = dinfo->dst_override_no_wm[0] ? "" :
> writemask;
> +      if (is_ms) {
> +         snprintf(ms_str, 32, ", int(%s.w)", srcs[1]);
> +      }
> +      switch (itype) {
> +      case TGSI_RETURN_TYPE_UINT:
> +         dtypeprefix = UINT_BITS_TO_FLOAT;
> +         break;
> +      case TGSI_RETURN_TYPE_SINT:
> +         dtypeprefix = INT_BITS_TO_FLOAT;
> +         break;
> +      default:
> +         break;
> +      }
> +      snprintf(buf, 255, "%s = %s(imageLoad(%s,
> %s(floatBitsToInt(%s))%s)%s);\n", dsts[0], get_string(dtypeprefix),
> srcs[0], get_string(coord_prefix), srcs[1], ms_str, wm);
> +      EMIT_BUF_WITH_RET(ctx, buf);
> +   } else if (src->Register.File == TGSI_FILE_BUFFER) {
>        char mydst[255], atomic_op[9], atomic_src[10];
>        strcpy(mydst, dsts[0]);
>        char *wmp = strchr(mydst, '.');
> @@ -2270,7 +2434,11 @@ translate_resq(struct dump_ctx *ctx, struct
> tgsi_full_instruction *inst,
>     char buf[512];
>     const struct tgsi_full_src_register *src = &inst->Src[0];
>  
> -   if (src->Register.File == TGSI_FILE_BUFFER) {
> +   if (src->Register.File == TGSI_FILE_IMAGE) {
> +      ctx->shader_req_bits |= SHADER_REQ_IMAGE_SIZE;
> +      snprintf(buf, 255, "%s = %s(imageSize(%s));\n", dsts[0],
> get_string(INT_BITS_TO_FLOAT), srcs[0]);
> +      EMIT_BUF_WITH_RET(ctx, buf);
> +   } else if (src->Register.File == TGSI_FILE_BUFFER) {
>        snprintf(buf, 255, "%s = %s(int(%s.length()) << 2);\n",
> dsts[0], get_string(INT_BITS_TO_FLOAT), srcs[0]);
In store you use 512, maybe also here, just to be on the save side (the
buffer is 512)? 

also I'm wondering whether the code common to  translate_load and
translate_store could be factored out. 


>        EMIT_BUF_WITH_RET(ctx, buf);
>     }
> @@ -2281,29 +2449,62 @@ translate_resq(struct dump_ctx *ctx, struct
> tgsi_full_instruction *inst,
>  static int
>  translate_atomic(struct dump_ctx *ctx,
>                   struct tgsi_full_instruction *inst,
> +                 struct source_info *sinfo,
>                   char srcs[4][255],
>                   char dsts[3][255])
>  {
>     char buf[512];
>     const struct tgsi_full_src_register *src = &inst->Src[0];
>     const char *opname;
> -   enum vrend_type_qualifier stypeprefix;
> -   enum vrend_type_qualifier dtypeprefix;
> -   enum vrend_type_qualifier stypecast;
> +   enum vrend_type_qualifier stypeprefix = TYPE_CONVERSION_NONE;
> +   enum vrend_type_qualifier dtypeprefix = TYPE_CONVERSION_NONE;
> +   enum vrend_type_qualifier stypecast = TYPE_CONVERSION_NONE;
>     bool is_cas;
> -   char cas_str[64] = {};
> -
> -   stypeprefix = FLOAT_BITS_TO_UINT;
> -   dtypeprefix = UINT_BITS_TO_FLOAT;
> -   stypecast = UINT;
> +   char cas_str[128] = {};
> +
> +   if (src->Register.File == TGSI_FILE_IMAGE) {
> +     enum tgsi_return_type itype;
> +     get_internalformat_string(ctx->images[sinfo-
> >sreg_index].decl.Format, &itype);
> +     switch (itype) {
> +     default:
> +     case TGSI_RETURN_TYPE_UINT:
> +        stypeprefix = FLOAT_BITS_TO_UINT;
> +        dtypeprefix = UINT_BITS_TO_FLOAT;
> +        stypecast = UINT;
> +        break;
> +     case TGSI_RETURN_TYPE_SINT:
> +        stypeprefix = FLOAT_BITS_TO_INT;
> +        dtypeprefix = INT_BITS_TO_FLOAT;
> +        stypecast = INT;
> +        break;
> +     case TGSI_RETURN_TYPE_FLOAT:
> +        ctx->shader_req_bits |= SHADER_REQ_ES31_COMPAT;
> +        stypecast = FLOAT;
> +        break;
> +     }
> +   } else {
> +     stypeprefix = FLOAT_BITS_TO_UINT;
> +     dtypeprefix = UINT_BITS_TO_FLOAT;
> +     stypecast = UINT;
> +   }
>  
>     opname = get_atomic_opname(inst->Instruction.Opcode, &is_cas);
>     if (!opname)
>        return -1;
>  
>     if (is_cas)
> -      snprintf(cas_str, 64, ", %s(%s(%s))", get_string(stypecast),
> get_string(stypeprefix), srcs[3]);
> -
> +      snprintf(cas_str, 128, ", %s(%s(%s))", get_string(stypecast),
> get_string(stypeprefix), srcs[3]);
> +
> +   if (src->Register.File == TGSI_FILE_IMAGE) {
> +      bool is_ms = false;
> +      enum vrend_type_qualifier coord_prefix = get_coord_prefix(ctx-
> >images[sinfo->sreg_index].decl.Resource, &is_ms);
> +      char ms_str[32] = {};
> +      if (is_ms) {
> +         snprintf(ms_str, 32, ", int(%s.w)", srcs[1]);
> +      }
> +      snprintf(buf, 512, "%s = %s(imageAtomic%s(%s,
> %s(floatBitsToInt(%s))%s, %s(%s(%s))%s));\n", dsts[0],
> get_string(dtypeprefix), opname, srcs[0], get_string(coord_prefix),
> srcs[1], ms_str, get_string(stypecast), get_string(stypeprefix),
> srcs[2], cas_str);
> +      EMIT_BUF_WITH_RET(ctx, buf);
> +   }
>     if (src->Register.File == TGSI_FILE_BUFFER) {
>        snprintf(buf, 512, "%s =
> %s(atomic%s(%s[int(floatBitsToInt(%s)) >> 2], uint(%s(%s).x)%s));\n",
> dsts[0], get_string(dtypeprefix), opname, srcs[0], srcs[1],
> get_string(stypeprefix), srcs[2], cas_str);
>        EMIT_BUF_WITH_RET(ctx, buf);
> @@ -2472,6 +2673,18 @@ get_destination_info(struct dump_ctx *ctx,
>              snprintf(dsts[i], 255, "temp%d[addr0 + %d]%s", range-
> >first, dst_reg->Register.Index - range->first, writemask);
>           } else
>              snprintf(dsts[i], 255, "temp%d[%d]%s", range->first,
> dst_reg->Register.Index - range->first, writemask);
> +      }
> +      else if (dst_reg->Register.File == TGSI_FILE_IMAGE) {
> +         const char *cname = tgsi_proc_to_prefix(ctx->prog_type);
> +	 if (ctx->info.indirect_files & (1 << TGSI_FILE_IMAGE)) {
> +            int basearrayidx = lookup_image_array(ctx, dst_reg-
> >Register.Index);
> +            if (dst_reg->Register.Indirect) {
> +               assert(dst_reg->Indirect.File == TGSI_FILE_ADDRESS);
> +               snprintf(dsts[i], 255, "%simg%d[addr%d + %d]", cname,
> basearrayidx, dst_reg->Indirect.Index, dst_reg->Register.Index -
> basearrayidx);
> +            } else
> +               snprintf(dsts[i], 255, "%simg%d[%d]", cname,
> basearrayidx, dst_reg->Register.Index - basearrayidx);
> +         } else
> +            snprintf(dsts[i], 255, "%simg%d", cname, dst_reg-
> >Register.Index);
>        } else if (dst_reg->Register.File == TGSI_FILE_BUFFER) {
>           const char *cname = tgsi_proc_to_prefix(ctx->prog_type);
>           if (ctx->info.indirect_files & (1 << TGSI_FILE_BUFFER)) {
> @@ -2740,6 +2953,18 @@ get_source_info(struct dump_ctx *ctx,
>              snprintf(srcs[i], 255, "%ssamp%d%s", cname, src-
> >Register.Index, swizzle);
>           }
>           sinfo->sreg_index = src->Register.Index;
> +      } else if (src->Register.File == TGSI_FILE_IMAGE) {
> +         const char *cname = tgsi_proc_to_prefix(ctx->prog_type);
> +         if (ctx->info.indirect_files & (1 << TGSI_FILE_IMAGE)) {
> +            int basearrayidx = lookup_image_array(ctx, src-
> >Register.Index);
> +            if (src->Register.Indirect) {
> +               assert(src->Indirect.File == TGSI_FILE_ADDRESS);
> +               snprintf(srcs[i], 255, "%simg%d[addr%d + %d]", cname,
> basearrayidx, src->Indirect.Index, src->Register.Index -
> basearrayidx);
> +            } else
> +               snprintf(srcs[i], 255, "%simg%d[%d]", cname,
> basearrayidx, src->Register.Index - basearrayidx);
> +         } else
> +            snprintf(srcs[i], 255, "%simg%d%s", cname, src-
> >Register.Index, swizzle);
> +         sinfo->sreg_index = src->Register.Index;
>        } else if (src->Register.File == TGSI_FILE_BUFFER) {
>           const char *cname = tgsi_proc_to_prefix(ctx->prog_type);
>           if (ctx->info.indirect_files & (1 << TGSI_FILE_BUFFER)) {
> @@ -3526,7 +3751,7 @@ iter_instruction(struct tgsi_iterate_context
> *iter,
>           return FALSE;
>        break;
>     case TGSI_OPCODE_LOAD:
> -      ret = translate_load(ctx, inst, srcs, dsts);
> +      ret = translate_load(ctx, inst, &sinfo, &dinfo, srcs, dsts,
> writemask);
>        if (ret)
>           return FALSE;
>        break;
> @@ -3540,7 +3765,7 @@ iter_instruction(struct tgsi_iterate_context
> *iter,
>     case TGSI_OPCODE_ATOMUMAX:
>     case TGSI_OPCODE_ATOMIMIN:
>     case TGSI_OPCODE_ATOMIMAX:
> -      ret = translate_atomic(ctx, inst, srcs, dsts);
> +      ret = translate_atomic(ctx, inst, &sinfo, srcs, dsts);
>        if (ret)
>           return FALSE;
>        break;
> @@ -3751,6 +3976,136 @@ static void *emit_sampler_decl(struct
> dump_ctx *ctx, char *glsl_hdr, uint32_t i,
>     return glsl_hdr;
>  }
>  
> +const char *get_internalformat_string(int virgl_format, enum
> tgsi_return_type *stype)
> +{
> +   switch (virgl_format) {
> +   case PIPE_FORMAT_R11G11B10_FLOAT:
> +      *stype = TGSI_RETURN_TYPE_FLOAT;
> +      return "layout(r11f_g11f_b10f) ";
> +   case PIPE_FORMAT_R10G10B10A2_UNORM:
> +      *stype = TGSI_RETURN_TYPE_UNORM;
> +      return "layout(rgb10_a2) ";
> +   case PIPE_FORMAT_R10G10B10A2_UINT:
> +      *stype = TGSI_RETURN_TYPE_UINT;
> +      return "layout(rgb10_a2ui) ";
> +   case PIPE_FORMAT_R8_UNORM:
> +      *stype = TGSI_RETURN_TYPE_UNORM;
> +      return "layout(r8) ";
> +   case PIPE_FORMAT_R8_SNORM:
> +      *stype = TGSI_RETURN_TYPE_SNORM;
> +      return "layout(r8_snorm) ";
> +   case PIPE_FORMAT_R8_UINT:
> +      *stype = TGSI_RETURN_TYPE_UINT;
> +      return "layout(r8ui) ";
> +   case PIPE_FORMAT_R8_SINT:
> +      *stype = TGSI_RETURN_TYPE_SINT;
> +      return "layout(r8i) ";
> +   case PIPE_FORMAT_R8G8_UNORM:
> +      *stype = TGSI_RETURN_TYPE_UNORM;
> +      return "layout(rg8) ";
> +   case PIPE_FORMAT_R8G8_SNORM:
> +      *stype = TGSI_RETURN_TYPE_SNORM;
> +      return "layout(rg8_snorm) ";
> +   case PIPE_FORMAT_R8G8_UINT:
> +      *stype = TGSI_RETURN_TYPE_UINT;
> +      return "layout(rg8ui) ";
> +   case PIPE_FORMAT_R8G8_SINT:
> +      *stype = TGSI_RETURN_TYPE_SINT;
> +      return "layout(rg8i) ";
> +   case PIPE_FORMAT_R8G8B8A8_UNORM:
> +      *stype = TGSI_RETURN_TYPE_UNORM;
> +      return "layout(rgba8) ";
> +   case PIPE_FORMAT_R8G8B8A8_SNORM:
> +      *stype = TGSI_RETURN_TYPE_SNORM;
> +      return "layout(rgba8_snorm) ";
> +   case PIPE_FORMAT_R8G8B8A8_UINT:
> +      *stype = TGSI_RETURN_TYPE_UINT;
> +      return "layout(rgba8ui) ";
> +   case PIPE_FORMAT_R8G8B8A8_SINT:
> +      *stype = TGSI_RETURN_TYPE_SINT;
> +      return "layout(rgba8i) ";
> +   case PIPE_FORMAT_R16_UNORM:
> +      *stype = TGSI_RETURN_TYPE_UNORM;
> +      return "layout(r16) ";
> +   case PIPE_FORMAT_R16_SNORM:
> +      *stype = TGSI_RETURN_TYPE_SNORM;
> +      return "layout(r16_snorm) ";
> +   case PIPE_FORMAT_R16_UINT:
> +      *stype = TGSI_RETURN_TYPE_UINT;
> +      return "layout(r16ui) ";
> +   case PIPE_FORMAT_R16_SINT:
> +      *stype = TGSI_RETURN_TYPE_SINT;
> +      return "layout(r16i) ";
> +   case PIPE_FORMAT_R16_FLOAT:
> +      *stype = TGSI_RETURN_TYPE_FLOAT;
> +      return "layout(r16f) ";
> +   case PIPE_FORMAT_R16G16_UNORM:
> +      *stype = TGSI_RETURN_TYPE_UNORM;
> +      return "layout(rg16) ";
> +   case PIPE_FORMAT_R16G16_SNORM:
> +      *stype = TGSI_RETURN_TYPE_SNORM;
> +      return "layout(rg16_snorm) ";
> +   case PIPE_FORMAT_R16G16_UINT:
> +      *stype = TGSI_RETURN_TYPE_UINT;
> +      return "layout(rg16ui) ";
> +   case PIPE_FORMAT_R16G16_SINT:
> +      *stype = TGSI_RETURN_TYPE_SINT;
> +      return "layout(rg16i) ";
> +   case PIPE_FORMAT_R16G16_FLOAT:
> +      *stype = TGSI_RETURN_TYPE_FLOAT;
> +      return "layout(rg16f) ";
> +   case PIPE_FORMAT_R16G16B16A16_UNORM:
> +      *stype = TGSI_RETURN_TYPE_UNORM;
> +      return "layout(rgba16) ";
> +   case PIPE_FORMAT_R16G16B16A16_SNORM:
> +      *stype = TGSI_RETURN_TYPE_SNORM;
> +      return "layout(rgba16_snorm) ";
> +   case PIPE_FORMAT_R16G16B16A16_FLOAT:
> +      *stype = TGSI_RETURN_TYPE_FLOAT;
> +      return "layout(rgba16f) ";
> +   case PIPE_FORMAT_R32_FLOAT:
> +      *stype = TGSI_RETURN_TYPE_FLOAT;
> +      return "layout(r32f) ";
> +   case PIPE_FORMAT_R32_UINT:
> +      *stype = TGSI_RETURN_TYPE_UINT;
> +      return "layout(r32ui) ";
> +   case PIPE_FORMAT_R32_SINT:
> +      *stype = TGSI_RETURN_TYPE_SINT;
> +      return "layout(r32i) ";
> +   case PIPE_FORMAT_R32G32_FLOAT:
> +      *stype = TGSI_RETURN_TYPE_FLOAT;
> +      return "layout(rg32f) ";
> +   case PIPE_FORMAT_R32G32_UINT:
> +      *stype = TGSI_RETURN_TYPE_UINT;
> +      return "layout(rg32ui) ";
> +   case PIPE_FORMAT_R32G32_SINT:
> +      *stype = TGSI_RETURN_TYPE_SINT;
> +      return "layout(rg32i) ";
> +   case PIPE_FORMAT_R32G32B32A32_FLOAT:
> +      *stype = TGSI_RETURN_TYPE_FLOAT;
> +      return "layout(rgba32f) ";
> +   case PIPE_FORMAT_R32G32B32A32_UINT:
> +      *stype = TGSI_RETURN_TYPE_UINT;
> +      return "layout(rgba32ui) ";
> +   case PIPE_FORMAT_R16G16B16A16_UINT:
> +      *stype = TGSI_RETURN_TYPE_UINT;
> +      return "layout(rgba16ui) ";
> +   case PIPE_FORMAT_R16G16B16A16_SINT:
> +      *stype = TGSI_RETURN_TYPE_SINT;
> +      return "layout(rgba16i) ";
> +   case PIPE_FORMAT_R32G32B32A32_SINT:
> +      *stype = TGSI_RETURN_TYPE_SINT;
> +      return "layout(rgba32i) ";
> +   case PIPE_FORMAT_NONE:
> +      *stype = TGSI_RETURN_TYPE_UNORM;
> +      return "";
> +   default:
> +      *stype = TGSI_RETURN_TYPE_UNORM;
> +      fprintf(stderr, "illegal format %d\n", virgl_format);
> +      return "";
> +   }
> +}
> +
>  static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
>  {
>     uint32_t i;
> @@ -4166,6 +4521,44 @@ static char *emit_ios(struct dump_ctx *ctx,
> char *glsl_hdr)
>        }
>     }
>  
> +   if (ctx->info.indirect_files & (1 << TGSI_FILE_IMAGE)) {
> +      for (i = 0; i < ctx->num_image_arrays; i++) {
> +         int idx = ctx->image_arrays[i].first;
> +         int is_shad = 0;
> +         const char *stc;
> +         char ptc;
> +         const char *volatile_str = (ctx->images[idx].vflag) ?
> "volatile " : "";
> +         const char *writeonly = (ctx->images[idx].decl.Format) ? ""
> : "writeonly ";
> +         const char *formatstr;
> +         enum tgsi_return_type itype;
> +         formatstr = get_internalformat_string(ctx-
> >images[idx].decl.Format, &itype);
> +         ptc = vrend_shader_samplerreturnconv(itype);
> +         sname = tgsi_proc_to_prefix(ctx->prog_type);
> +         stc = vrend_shader_samplertypeconv(ctx-
> >images[i].decl.Resource, &is_shad);
> +         snprintf(buf, 255, "%s%s%suniform %cimage%s
> %simg%d[%d];\n", formatstr, writeonly, volatile_str, ptc, stc, sname,
> idx, ctx->image_arrays[i].array_size);
> +         STRCAT_WITH_RET(glsl_hdr, buf);
> +      }
> +   } else {
> +      uint32_t mask = ctx->images_used_mask;
> +      while (mask) {
> +         int is_shad = 0;
> +         const char *stc;
> +         char ptc;
> +
> +         i = u_bit_scan(&mask);
> +         const char *volatile_str = (ctx->images[i].vflag) ?
> "volatile " : "";
> +         const char *writeonly = (ctx->images[i].decl.Format) ? "" :
> "writeonly ";
> +         const char *formatstr;
> +         enum tgsi_return_type itype;
> +         formatstr = get_internalformat_string(ctx-
> >images[i].decl.Format, &itype);
> +         ptc = vrend_shader_samplerreturnconv(itype);
> +         sname = tgsi_proc_to_prefix(ctx->prog_type);
> +         stc = vrend_shader_samplertypeconv(ctx-
> >images[i].decl.Resource, &is_shad);
> +         snprintf(buf, 255, "%s%s%suniform %cimage%s %simg%d;\n",
> formatstr, writeonly, volatile_str, ptc, stc, sname, i);
> +         STRCAT_WITH_RET(glsl_hdr, buf);
> +      }
> +   }
> +
>     if (ctx->info.indirect_files & (1 << TGSI_FILE_BUFFER)) {
>        uint32_t mask = ctx->ssbo_used_mask;
>        while (mask) {
> @@ -4262,6 +4655,8 @@ char *vrend_convert_shader(struct
> vrend_shader_cfg *cfg,
>     ctx.key = key;
>     ctx.cfg = cfg;
>     ctx.prog_type = -1;
> +   ctx.num_image_arrays = 0;
> +   ctx.image_arrays = NULL;
>     ctx.num_sampler_arrays = 0;
>     ctx.sampler_arrays = NULL;
>     ctx.last_sampler_array_idx = -1;
> @@ -4284,7 +4679,8 @@ char *vrend_convert_shader(struct
> vrend_shader_cfg *cfg,
>     if (ctx.info.dimension_indirect_files & (1 <<
> TGSI_FILE_CONSTANT))
>        require_glsl_ver(&ctx, 150);
>  
> -   if (ctx.info.indirect_files & (1 << TGSI_FILE_BUFFER)) {
> +   if (ctx.info.indirect_files & (1 << TGSI_FILE_BUFFER) ||
> +       ctx.info.indirect_files & (1 << TGSI_FILE_IMAGE)) {
>        require_glsl_ver(&ctx, 150);
>        ctx.shader_req_bits |= SHADER_REQ_GPU_SHADER5;
>     }
> @@ -4336,6 +4732,7 @@ char *vrend_convert_shader(struct
> vrend_shader_cfg *cfg,
>     sinfo->num_clip_out = has_prop ? ctx.num_clip_dist_prop :
> (ctx.num_clip_dist ? ctx.num_clip_dist : 8);
>     sinfo->num_cull_out = has_prop ? ctx.num_cull_dist_prop : 0;
>     sinfo->samplers_used_mask = ctx.samplers_used;
> +   sinfo->images_used_mask = ctx.images_used_mask;
>     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));
> @@ -4368,6 +4765,8 @@ char *vrend_convert_shader(struct
> vrend_shader_cfg *cfg,
>     sinfo->attrib_input_mask = ctx.attrib_input_mask;
>     sinfo->sampler_arrays = ctx.sampler_arrays;
>     sinfo->num_sampler_arrays = ctx.num_sampler_arrays;
> +   sinfo->image_arrays = ctx.image_arrays;
> +   sinfo->num_image_arrays = ctx.num_image_arrays;
>     return glsl_final;
>   fail:
>     free(ctx.glsl_main);
> diff --git a/src/vrend_shader.h b/src/vrend_shader.h
> index a19da20..6bb671b 100644
> --- a/src/vrend_shader.h
> +++ b/src/vrend_shader.h
> @@ -44,8 +44,14 @@ struct vrend_sampler_array {
>     int sview_rtype;
>  };
>  
> +struct vrend_image_array {
> +   int first;
> +   int array_size;
> +};
> +
>  struct vrend_shader_info {
>     uint32_t samplers_used_mask;
> +   uint32_t images_used_mask;
>     uint32_t ssbo_used_mask;
>     int num_consts;
>     int num_inputs;
> @@ -73,6 +79,9 @@ struct vrend_shader_info {
>     struct vrend_sampler_array *sampler_arrays;
>     int num_sampler_arrays;
>  
> +   struct vrend_image_array *image_arrays;
> +   int num_image_arrays;
> +
>     struct pipe_stream_output_info so_info;
>  
>     struct vrend_interp_info *interpinfo;


More information about the virglrenderer-devel mailing list