[3/3] shader: Add support for TGSI_FILE_HW_ATOMIC

Submitted by Tomeu Vizoso on July 19, 2018, 1:41 p.m.

Details

Message ID 20180719134142.21407-4-tomeu.vizoso@collabora.com
State New
Headers show
Series "TGSI_FILE_HW_ATOMIC support" ( rev: 1 ) in Virgil 3D

Not browsing as part of any series.

Commit Message

Tomeu Vizoso July 19, 2018, 1:41 p.m.
Add support for TGSI's HW atomic counters, implemented here with
atomic_uint.

Signed-off-by: Tomeu Vizoso <tomeu.vizoso@collabora.com>
---
 src/vrend_shader.c | 54 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 53 insertions(+), 1 deletion(-)

Patch hide | download patch | download mbox

diff --git a/src/vrend_shader.c b/src/vrend_shader.c
index f6247c26aa2a..f5f8eb726188 100644
--- a/src/vrend_shader.c
+++ b/src/vrend_shader.c
@@ -180,6 +180,11 @@  struct dump_ctx {
    uint32_t images_used;
    bool iviews_used;
 
+   uint32_t num_abo;
+   int abo_idx[32];
+   int abo_sizes[32];
+   int abo_offsets[32];
+
    uint32_t num_ssbo;
    struct vrend_ssbo ssbos[32];
 
@@ -276,6 +281,7 @@  struct source_info {
    bool tg4_has_component;
    bool override_no_wm[3];
    bool override_no_cast[3];
+   bool has_minus_one;
 };
 
 static const struct vrend_shader_table conversion_table[] =
@@ -1218,6 +1224,16 @@  iter_declaration(struct tgsi_iterate_context *iter,
       break;
    case TGSI_FILE_MEMORY:
       break;
+   case TGSI_FILE_HW_ATOMIC:
+         if (ctx->num_abo >= ARRAY_SIZE(ctx->abo_idx)) {
+            fprintf(stderr, "Number of atomic counter buffers exceeded, max is %lu\n", ARRAY_SIZE(ctx->abo_idx));
+            return FALSE;
+         }
+         ctx->abo_idx[ctx->num_abo] = decl->Dim.Index2D;
+         ctx->abo_sizes[ctx->num_abo] = decl->Range.Last - decl->Range.First + 1;
+         ctx->abo_offsets[ctx->num_abo] = decl->Range.First;
+         ctx->num_abo++;
+      break;
    default:
       fprintf(stderr,"unsupported file %d declaration\n", decl->Declaration.File);
       break;
@@ -2445,6 +2461,9 @@  translate_load(struct dump_ctx *ctx,
 	 snprintf(buf, 255, "%s.w = (uintBitsToFloat((%s[(uint(floatBitsToUint(%s)) >> 2)+3u])));\n", mydst, srcs[0], srcs[1]);
 	 EMIT_BUF_WITH_RET(ctx, buf);
       }
+   } else if (src->Register.File == TGSI_FILE_HW_ATOMIC) {
+      snprintf(buf, 255, "%s = uintBitsToFloat(atomicCounter(%s));\n", dsts[0], srcs[0]);
+      EMIT_BUF_WITH_RET(ctx, buf);
    }
 
    return 0;
@@ -2563,7 +2582,12 @@  translate_atomic(struct dump_ctx *ctx,
    const char *conversion = sinfo->override_no_cast[1] ? "" : get_string(FLOAT_BITS_TO_UINT);
    if (src->Register.File == TGSI_FILE_IMAGE)
       snprintf(buf, 512, "%s = %s(imageAtomic%s(%s, %s(%s(%s))%s, %s(%s(%s))%s));\n", dsts[0], get_string(dtypeprefix), opname, srcs[0], get_string(coord_prefix), conversion, srcs[1], ms_str, get_string(stypecast), get_string(stypeprefix), srcs[2], cas_str);
-   else
+   else if(src->Register.File == TGSI_FILE_HW_ATOMIC) {
+      if (sinfo->has_minus_one)
+         snprintf(buf, 512, "%s = uintBitsToFloat(atomicCounterDecrement(%s) + 1u);\n", dsts[0], srcs[0]);
+      else
+         snprintf(buf, 512, "%s = uintBitsToFloat(atomicCounterIncrement(%s));\n", dsts[0], srcs[0]);
+   } else
      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);
    return 0;
@@ -3093,6 +3117,8 @@  get_source_info(struct dump_ctx *ctx,
                break;
             case TGSI_IMM_INT32:
                snprintf(temp, 25, "%d", imd->val[idx].i);
+               if (imd->val[idx].i == -1)
+                  sinfo->has_minus_one = true;
                break;
             case TGSI_IMM_FLOAT64:
                snprintf(temp, 48, "%uU", imd->val[idx].ui);
@@ -3160,6 +3186,21 @@  get_source_info(struct dump_ctx *ctx,
                sinfo->override_no_wm[i] = ctx->system_values[j].override_no_wm;
                break;
             }
+      } else if (src->Register.File == TGSI_FILE_HW_ATOMIC) {
+         for (uint32_t j = 0; j < ctx->num_abo; j++) {
+            if (src->Dimension.Index == ctx->abo_idx[j] &&
+                src->Register.Index >= ctx->abo_offsets[j] &&
+                src->Register.Index < ctx->abo_offsets[j] + ctx->abo_sizes[j]) {
+               if (ctx->abo_sizes[j] > 1) {
+                  if (ctx->info.indirect_files & (1 << TGSI_FILE_HW_ATOMIC))
+                     snprintf(srcs[i], 255, "ac%d[addr%d]", j, src->Indirect.Index);
+                  else
+                     snprintf(srcs[i], 255, "ac%d[%d]", j, src->Register.Index);
+               } else
+                  snprintf(srcs[i], 255, "ac%d", j);
+            }
+         }
+         sinfo->sreg_index = src->Register.Index;
       }
 
       if (stype == TGSI_TYPE_DOUBLE) {
@@ -3888,6 +3929,9 @@  static char *emit_header(struct dump_ctx *ctx, char *glsl_hdr)
       if (ctx->num_ssbo)
          STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_shader_storage_buffer_object : require\n");
 
+      if (ctx->num_abo)
+         STRCAT_WITH_RET(glsl_hdr, "#extension GL_ARB_shader_atomic_counters : 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;
@@ -4591,6 +4635,14 @@  static char *emit_ios(struct dump_ctx *ctx, char *glsl_hdr)
       }
    }
 
+   for (i = 0; i < ctx->num_abo; i++){
+      if (ctx->abo_sizes[i] > 1)
+         snprintf(buf, 255, "layout (binding = %d, offset = %d) uniform atomic_uint ac%d[%d];\n", ctx->abo_idx[i], ctx->abo_offsets[i] * 4, i, ctx->abo_sizes[i]);
+      else
+         snprintf(buf, 255, "layout (binding = %d, offset = %d) uniform atomic_uint ac%d;\n", ctx->abo_idx[i], ctx->abo_offsets[i] * 4, i);
+      STRCAT_WITH_RET(glsl_hdr, buf);
+   }
+
    if (ctx->info.indirect_files & (1 << TGSI_FILE_BUFFER)) {
 
    } else {