[virglrenderer-devel] [PATCH 3/7] shader: add image support to shader parsing.

Dave Airlie airlied at gmail.com
Fri Jul 20 00:05:10 UTC 2018


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
---
 src/vrend_shader.c | 387 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 src/vrend_shader.h |   1 +
 2 files changed, 374 insertions(+), 14 deletions(-)

diff --git a/src/vrend_shader.c b/src/vrend_shader.c
index 49e63eb..e991669 100644
--- a/src/vrend_shader.c
+++ b/src/vrend_shader.c
@@ -56,6 +56,8 @@ 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_ES31_COMPAT        (1 << 15)
+#define SHADER_REQ_IMAGE_SIZE         (1 << 16)
 
 struct vrend_shader_io {
    unsigned                name;
@@ -85,6 +87,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;
@@ -142,6 +150,9 @@ 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_sampler_array *sampler_arrays;
    uint32_t num_sampler_arrays;
    int last_sampler_array_idx;
@@ -210,6 +221,8 @@ 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_ES31_COMPAT, "GL_ARB_ES3_1_compatibility" },
+    { SHADER_REQ_IMAGE_SIZE, "GL_ARB_shader_image_size" },
 };
 
 enum vrend_type_qualifier {
@@ -301,6 +314,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 +503,29 @@ 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;
+   }
+   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;
@@ -1048,6 +1086,13 @@ iter_declaration(struct tgsi_iterate_context *iter,
          }
       }
       break;
+   case TGSI_FILE_IMAGE:
+      if (decl->Range.First >= ARRAY_SIZE(ctx->images)) {
+         fprintf(stderr, "Image view exceeded, max is %lu\n", ARRAY_SIZE(ctx->images));
+         return FALSE;
+      }
+      add_images(ctx, decl->Range.First, decl->Range.Last, &decl->Image);
+      break;
    case TGSI_FILE_BUFFER:
       if (decl->Range.First >= 32) {
          fprintf(stderr, "Buffer view exceeded, max is 32\n");
@@ -2147,6 +2192,36 @@ 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;
+      break;
+   case TGSI_TEXTURE_2D:
+   case TGSI_TEXTURE_RECT:
+   case TGSI_TEXTURE_1D_ARRAY:
+      return IVEC2;
+      break;
+   case TGSI_TEXTURE_3D:
+   case TGSI_TEXTURE_CUBE:
+   case TGSI_TEXTURE_2D_ARRAY:
+   case TGSI_TEXTURE_CUBE_ARRAY:
+      return IVEC3;
+      break;
+   case TGSI_TEXTURE_2D_MSAA:
+      *is_ms = true;
+      return IVEC2;
+   case TGSI_TEXTURE_2D_ARRAY_MSAA:
+      *is_ms = true;
+      return IVEC3;
+   default:
+      fprintf(stderr, "NON 2D IMAGE\n");
+      return TYPE_CONVERSION_NONE;
+   }
+}
+
 static int
 translate_store(struct dump_ctx *ctx,
                 struct tgsi_full_instruction *inst,
@@ -2156,7 +2231,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]);
@@ -2181,13 +2278,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, '.');
@@ -2273,7 +2395,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]);
       EMIT_BUF_WITH_RET(ctx, buf);
    }
@@ -2284,21 +2410,44 @@ 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;
+   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)
@@ -2307,6 +2456,15 @@ translate_atomic(struct dump_ctx *ctx,
    if (is_cas)
       snprintf(cas_str, 64, ", %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);
+   }
    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);
@@ -2469,6 +2627,14 @@ 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 (dst_reg->Register.Indirect) {
+            assert(dst_reg->Indirect.File == TGSI_FILE_ADDRESS);
+            snprintf(dsts[i], 255, "%simg[addr%d + %d]", cname, dst_reg->Indirect.Index, dst_reg->Register.Index);
+         } 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)) {
@@ -2737,6 +2903,14 @@ 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)) {
+            snprintf(srcs[i], 255, "%simg%d[addr%d + %d]", cname, 0, src->Indirect.Index, src->Register.Index);
+         } 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)) {
@@ -3487,7 +3661,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;
@@ -3501,7 +3675,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;
@@ -3593,6 +3767,9 @@ static char *emit_header(struct dump_ctx *ctx, char *glsl_hdr)
       if (ctx->ssbo_used_mask)
          STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_shader_storage_buffer_object : require\n");
 
+      if (ctx->images_used_mask)
+         STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_shader_image_load_store : require\n");
+
       for (uint32_t i = 0; i < ARRAY_SIZE(shader_req_table); i++) {
          if (shader_req_table[i].key == SHADER_REQ_SAMPLER_RECT && ctx->glsl_ver_required >= 140)
             continue;
@@ -3712,6 +3889,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;
@@ -4122,6 +4429,56 @@ static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
       }
    }
 
+   if (ctx->info.indirect_files & (1 << TGSI_FILE_IMAGE)) {
+      uint32_t mask = ctx->images_used_mask;
+      while (mask) {
+         int is_shad = 0;
+         const char *stc;
+         char ptc;
+         i = u_bit_scan(&mask);
+
+         unsigned array_size = 0;
+         for (uint32_t j = i; j < util_last_bit(ctx->images_used_mask); j++) {
+            if (!(ctx->images_used_mask & (1 << j)))
+               break;
+            if (!memcmp(&ctx->images[i].decl, &ctx->images[j].decl, sizeof(ctx->images[j].decl)) &&
+                ctx->images[i].image_return == ctx->images[j].image_return) {
+               mask &= ~(1 << j);
+               array_size++;
+            }
+         }
+         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[%d];\n", formatstr, writeonly, volatile_str, ptc, stc, sname, 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) {
@@ -4240,7 +4597,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;
    }
@@ -4292,6 +4650,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));
diff --git a/src/vrend_shader.h b/src/vrend_shader.h
index a19da20..4b0350a 100644
--- a/src/vrend_shader.h
+++ b/src/vrend_shader.h
@@ -46,6 +46,7 @@ struct vrend_sampler_array {
 
 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;
-- 
2.14.3



More information about the virglrenderer-devel mailing list