diff options
-rw-r--r-- | src/amd/common/ac_nir_to_llvm.c | 229 |
1 files changed, 107 insertions, 122 deletions
diff --git a/src/amd/common/ac_nir_to_llvm.c b/src/amd/common/ac_nir_to_llvm.c index 63583fafb4e..60216473642 100644 --- a/src/amd/common/ac_nir_to_llvm.c +++ b/src/amd/common/ac_nir_to_llvm.c @@ -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) { |