}
}
+/* 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)
{
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)
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) {