radv/ac: refactor our fmask sample index fixup.
authorDave Airlie <airlied@redhat.com>
Thu, 23 Feb 2017 02:20:25 +0000 (12:20 +1000)
committerDave Airlie <airlied@redhat.com>
Fri, 24 Feb 2017 00:31:49 +0000 (10:31 +1000)
This refactors out the sample index fixup between
txf and image load.

Reviewed-by: Bas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Signed-off-by: Dave Airlie <airlied@redhat.com>
src/amd/common/ac_nir_to_llvm.c

index 63583fafb4eb05103c4c58cda5d701e246d28334..602164736421c962fa33ede86141a510020f00ac 100644 (file)
@@ -2429,6 +2429,95 @@ static void get_image_intr_name(const char *base_name,
         }
 }
 
+/* Adjust the sample index according to FMASK.
+ *
+ * For uncompressed MSAA surfaces, FMASK should return 0x76543210,
+ * which is the identity mapping. Each nibble says which physical sample
+ * should be fetched to get that sample.
+ *
+ * For example, 0x11111100 means there are only 2 samples stored and
+ * the second sample covers 3/4 of the pixel. When reading samples 0
+ * and 1, return physical sample 0 (determined by the first two 0s
+ * in FMASK), otherwise return physical sample 1.
+ *
+ * The sample index should be adjusted as follows:
+ *   sample_index = (fmask >> (sample_index * 4)) & 0xF;
+ */
+static LLVMValueRef adjust_sample_index_using_fmask(struct nir_to_llvm_context *ctx,
+                                                   LLVMValueRef coord_x, LLVMValueRef coord_y,
+                                                   LLVMValueRef coord_z,
+                                                   LLVMValueRef sample_index,
+                                                   LLVMValueRef fmask_desc_ptr)
+{
+       LLVMValueRef fmask_load_address[4], params[7];
+       LLVMValueRef glc = LLVMConstInt(ctx->i1, 0, false);
+       LLVMValueRef slc = LLVMConstInt(ctx->i1, 0, false);
+       LLVMValueRef da = coord_z ? ctx->i32one : ctx->i32zero;
+       LLVMValueRef res;
+       char intrinsic_name[64];
+
+       fmask_load_address[0] = coord_x;
+       fmask_load_address[1] = coord_y;
+       if (coord_z) {
+               fmask_load_address[2] = coord_z;
+               fmask_load_address[3] = LLVMGetUndef(ctx->i32);
+       }
+
+       params[0] = ac_build_gather_values(&ctx->ac, fmask_load_address, coord_z ? 4 : 2);
+       params[1] = fmask_desc_ptr;
+       params[2] = LLVMConstInt(ctx->i32, 15, false); /* dmask */
+       LLVMValueRef lwe = LLVMConstInt(ctx->i1, 0, false);
+       params[3] = glc;
+       params[4] = slc;
+       params[5] = lwe;
+       params[6] = da;
+
+       get_image_intr_name("llvm.amdgcn.image.load",
+                           ctx->v4f32, /* vdata */
+                           LLVMTypeOf(params[0]), /* coords */
+                           LLVMTypeOf(params[1]), /* rsrc */
+                           intrinsic_name, sizeof(intrinsic_name));
+
+       res = ac_emit_llvm_intrinsic(&ctx->ac, intrinsic_name, ctx->v4f32,
+                                    params, 7, AC_FUNC_ATTR_READONLY);
+
+       res = to_integer(ctx, res);
+       LLVMValueRef four = LLVMConstInt(ctx->i32, 4, false);
+       LLVMValueRef F = LLVMConstInt(ctx->i32, 0xf, false);
+
+       LLVMValueRef fmask = LLVMBuildExtractElement(ctx->builder,
+                                                    res,
+                                                    ctx->i32zero, "");
+
+       LLVMValueRef sample_index4 =
+               LLVMBuildMul(ctx->builder, sample_index, four, "");
+       LLVMValueRef shifted_fmask =
+               LLVMBuildLShr(ctx->builder, fmask, sample_index4, "");
+       LLVMValueRef final_sample =
+               LLVMBuildAnd(ctx->builder, shifted_fmask, F, "");
+
+       /* Don't rewrite the sample index if WORD1.DATA_FORMAT of the FMASK
+        * resource descriptor is 0 (invalid),
+        */
+       LLVMValueRef fmask_desc =
+               LLVMBuildBitCast(ctx->builder, params[1],
+                                ctx->v8i32, "");
+
+       LLVMValueRef fmask_word1 =
+               LLVMBuildExtractElement(ctx->builder, fmask_desc,
+                                       ctx->i32one, "");
+
+       LLVMValueRef word1_is_nonzero =
+               LLVMBuildICmp(ctx->builder, LLVMIntNE,
+                             fmask_word1, ctx->i32zero, "");
+
+       /* Replace the MSAA sample index. */
+       sample_index =
+               LLVMBuildSelect(ctx->builder, word1_is_nonzero,
+                               final_sample, sample_index, "");
+       return sample_index;
+}
+
 static LLVMValueRef get_image_coords(struct nir_to_llvm_context *ctx,
                                     nir_intrinsic_instr *instr)
 {
@@ -2456,73 +2545,25 @@ static LLVMValueRef get_image_coords(struct nir_to_llvm_context *ctx,
                                               glsl_sampler_type_is_array(type));
 
        if (is_ms) {
-               LLVMValueRef fmask_load_address[4];
-               LLVMValueRef params[7];
-               LLVMValueRef glc = LLVMConstInt(ctx->i1, 0, false);
-               LLVMValueRef slc = LLVMConstInt(ctx->i1, 0, false);
-               LLVMValueRef da = ctx->i32zero;
-               char intrinsic_name[64];
+               LLVMValueRef fmask_load_address[3];
                int chan;
+
                fmask_load_address[0] = LLVMBuildExtractElement(ctx->builder, src0, masks[0], "");
                fmask_load_address[1] = LLVMBuildExtractElement(ctx->builder, src0, masks[1], "");
-               fmask_load_address[2] = LLVMGetUndef(ctx->i32);
-               fmask_load_address[3] = LLVMGetUndef(ctx->i32);
+               if (glsl_sampler_type_is_array(type))
+                       fmask_load_address[2] = LLVMBuildExtractElement(ctx->builder, src0, masks[2], "");
+               else
+                       fmask_load_address[2] = NULL;
                if (add_frag_pos) {
                        for (chan = 0; chan < 2; ++chan)
                                fmask_load_address[chan] = LLVMBuildAdd(ctx->builder, fmask_load_address[chan], LLVMBuildFPToUI(ctx->builder, ctx->frag_pos[chan], ctx->i32, ""), "");
                }
-               params[0] = ac_build_gather_values(&ctx->ac, fmask_load_address, 4);
-               params[1] = get_sampler_desc(ctx, instr->variables[0], DESC_FMASK);
-               params[2] = LLVMConstInt(ctx->i32, 15, false); /* dmask */
-               LLVMValueRef lwe = LLVMConstInt(ctx->i1, 0, false);
-               params[3] = glc;
-               params[4] = slc;
-               params[5] = lwe;
-               params[6] = da;
-               
-               get_image_intr_name("llvm.amdgcn.image.load",
-                                   ctx->v4f32, /* vdata */
-                                   LLVMTypeOf(params[0]), /* coords */
-                                   LLVMTypeOf(params[1]), /* rsrc */
-                                   intrinsic_name, sizeof(intrinsic_name));
-
-               res = ac_emit_llvm_intrinsic(&ctx->ac, intrinsic_name, ctx->v4f32,
-                                            params, 7, AC_FUNC_ATTR_READONLY);
-
-               res = to_integer(ctx, res);
-               LLVMValueRef four = LLVMConstInt(ctx->i32, 4, false);
-               LLVMValueRef F = LLVMConstInt(ctx->i32, 0xf, false);
-
-               LLVMValueRef fmask = LLVMBuildExtractElement(ctx->builder,
-                                                            res,
-                                                            ctx->i32zero, "");
-
-               LLVMValueRef sample_index4 =
-                       LLVMBuildMul(ctx->builder, sample_index, four, "");
-               LLVMValueRef shifted_fmask =
-                       LLVMBuildLShr(ctx->builder, fmask, sample_index4, "");
-               LLVMValueRef final_sample =
-                       LLVMBuildAnd(ctx->builder, shifted_fmask, F, "");
-
-               /* Don't rewrite the sample index if WORD1.DATA_FORMAT of the FMASK
-                * resource descriptor is 0 (invalid),
-                */
-               LLVMValueRef fmask_desc =
-                       LLVMBuildBitCast(ctx->builder, params[1],
-                                        ctx->v8i32, "");
-
-               LLVMValueRef fmask_word1 =
-                       LLVMBuildExtractElement(ctx->builder, fmask_desc,
-                                               ctx->i32one, "");
-
-               LLVMValueRef word1_is_nonzero =
-                       LLVMBuildICmp(ctx->builder, LLVMIntNE,
-                                     fmask_word1, ctx->i32zero, "");
-
-               /* Replace the MSAA sample index. */
-               sample_index =
-                       LLVMBuildSelect(ctx->builder, word1_is_nonzero,
-                                       final_sample, sample_index, "");
+               sample_index = adjust_sample_index_using_fmask(ctx,
+                                                              fmask_load_address[0],
+                                                              fmask_load_address[1],
+                                                              fmask_load_address[2],
+                                                              sample_index,
+                                                              get_sampler_desc(ctx, instr->variables[0], DESC_FMASK));
        }
        if (count == 1) {
                if (instr->src[0].ssa->num_components)
@@ -3707,71 +3748,15 @@ static void visit_tex(struct nir_to_llvm_context *ctx, nir_tex_instr *instr)
                goto write_result;
        }
 
-       /* Adjust the sample index according to FMASK.
-        *
-        * For uncompressed MSAA surfaces, FMASK should return 0x76543210,
-        * which is the identity mapping. Each nibble says which physical sample
-        * should be fetched to get that sample.
-        *
-        * For example, 0x11111100 means there are only 2 samples stored and
-        * the second sample covers 3/4 of the pixel. When reading samples 0
-        * and 1, return physical sample 0 (determined by the first two 0s
-        * in FMASK), otherwise return physical sample 1.
-        *
-        * The sample index should be adjusted as follows:
-        *   sample_index = (fmask >> (sample_index * 4)) & 0xF;
-        */
        if (instr->sampler_dim == GLSL_SAMPLER_DIM_MS &&
            instr->op != nir_texop_txs) {
-               LLVMValueRef txf_address[4];
-               struct ac_tex_info txf_info = { 0 };
-               unsigned txf_count = count;
-               memcpy(txf_address, address, sizeof(txf_address));
-
-               if (!instr->is_array)
-                       txf_address[2] = ctx->i32zero;
-               txf_address[3] = ctx->i32zero;
-
-               set_tex_fetch_args(ctx, &txf_info, instr, nir_texop_txf,
-                                  fmask_ptr, NULL,
-                                  txf_address, txf_count, 0xf);
-
-               result = build_tex_intrinsic(ctx, instr, &txf_info);
-               LLVMValueRef four = LLVMConstInt(ctx->i32, 4, false);
-               LLVMValueRef F = LLVMConstInt(ctx->i32, 0xf, false);
-
-               LLVMValueRef fmask = LLVMBuildExtractElement(ctx->builder,
-                                                            result,
-                                                            ctx->i32zero, "");
-
                unsigned sample_chan = instr->is_array ? 3 : 2;
-
-               LLVMValueRef sample_index4 =
-                       LLVMBuildMul(ctx->builder, address[sample_chan], four, "");
-               LLVMValueRef shifted_fmask =
-                       LLVMBuildLShr(ctx->builder, fmask, sample_index4, "");
-               LLVMValueRef final_sample =
-                       LLVMBuildAnd(ctx->builder, shifted_fmask, F, "");
-
-               /* Don't rewrite the sample index if WORD1.DATA_FORMAT of the FMASK
-                * resource descriptor is 0 (invalid),
-                */
-               LLVMValueRef fmask_desc =
-                       LLVMBuildBitCast(ctx->builder, fmask_ptr,
-                                        ctx->v8i32, "");
-
-               LLVMValueRef fmask_word1 =
-                       LLVMBuildExtractElement(ctx->builder, fmask_desc,
-                                               ctx->i32one, "");
-
-               LLVMValueRef word1_is_nonzero =
-                       LLVMBuildICmp(ctx->builder, LLVMIntNE,
-                                     fmask_word1, ctx->i32zero, "");
-
-               /* Replace the MSAA sample index. */
-               address[sample_chan] =
-                       LLVMBuildSelect(ctx->builder, word1_is_nonzero,
-                                       final_sample, address[sample_chan], "");
+               address[sample_chan] = adjust_sample_index_using_fmask(ctx,
+                                                                      address[0],
+                                                                      address[1],
+                                                                      instr->is_array ? address[2] : NULL,
+                                                                      address[sample_chan],
+                                                                      fmask_ptr);
        }
 
        if (offsets && instr->op == nir_texop_txf) {