radeonsi: implement texture fetching for compressed MSAA textures (v2)

v2: use resource slots 16..31 for FMASK textures

Reviewed-by: Michel Dänzer <michel.daenzer@amd.com>
This commit is contained in:
Marek Olšák 2013-08-06 15:08:54 +02:00
parent f671dfa8aa
commit 4855acd461
1 changed files with 116 additions and 5 deletions

View File

@ -915,6 +915,12 @@ handle_semantic:
/* ctx->shader->output[i].spi_sid = r600_spi_sid(&ctx->shader->output[i]);*/
}
static const struct lp_build_tgsi_action txf_action;
static void build_tex_intrinsic(const struct lp_build_tgsi_action * action,
struct lp_build_tgsi_context * bld_base,
struct lp_build_emit_data * emit_data);
static void tex_fetch_args(
struct lp_build_tgsi_context * bld_base,
struct lp_build_emit_data * emit_data)
@ -924,9 +930,11 @@ static void tex_fetch_args(
const struct tgsi_full_instruction * inst = emit_data->inst;
unsigned opcode = inst->Instruction.Opcode;
unsigned target = inst->Texture.Texture;
unsigned sampler_src;
unsigned sampler_src, sampler_index;
LLVMValueRef coords[4];
LLVMValueRef address[16];
LLVMValueRef sample_index_rewrite = NULL;
LLVMValueRef sample_chan = NULL;
int ref_pos;
unsigned num_coords = tgsi_util_get_texture_coord_dim(target, &ref_pos);
unsigned count = 0;
@ -1021,9 +1029,99 @@ static void tex_fetch_args(
}
sampler_src = emit_data->inst->Instruction.NumSrcRegs - 1;
sampler_index = emit_data->inst->Src[sampler_src].Register.Index;
/* 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 (target == TGSI_TEXTURE_2D_MSAA ||
target == TGSI_TEXTURE_2D_ARRAY_MSAA) {
struct lp_build_context *uint_bld = &bld_base->uint_bld;
struct lp_build_emit_data txf_emit_data = *emit_data;
LLVMValueRef txf_address[16];
unsigned txf_count = count;
memcpy(txf_address, address, sizeof(address));
/* Pad to a power-of-two size. */
while (txf_count < util_next_power_of_two(txf_count))
txf_address[txf_count++] = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context));
/* Read FMASK using TXF. */
txf_emit_data.chan = 0;
txf_emit_data.dst_type = LLVMVectorType(
LLVMInt32TypeInContext(bld_base->base.gallivm->context), 4);
txf_emit_data.args[0] = lp_build_gather_values(gallivm, txf_address, txf_count);
txf_emit_data.args[1] = si_shader_ctx->resources[FMASK_TEX_OFFSET + sampler_index];
txf_emit_data.args[2] = lp_build_const_int32(bld_base->base.gallivm, target);
txf_emit_data.arg_count = 3;
build_tex_intrinsic(&txf_action, bld_base, &txf_emit_data);
/* Initialize some constants. */
if (target == TGSI_TEXTURE_2D_MSAA) {
sample_chan = LLVMConstInt(uint_bld->elem_type, 2, 0);
} else {
sample_chan = LLVMConstInt(uint_bld->elem_type, 3, 0);
}
LLVMValueRef four = LLVMConstInt(uint_bld->elem_type, 4, 0);
LLVMValueRef F = LLVMConstInt(uint_bld->elem_type, 0xF, 0);
/* Apply the formula. */
LLVMValueRef fmask =
LLVMBuildExtractElement(gallivm->builder,
txf_emit_data.output[0],
uint_bld->zero, "");
LLVMValueRef sample_index =
LLVMBuildExtractElement(gallivm->builder,
txf_emit_data.args[0],
sample_chan, "");
LLVMValueRef sample_index4 =
LLVMBuildMul(gallivm->builder, sample_index, four, "");
LLVMValueRef shifted_fmask =
LLVMBuildLShr(gallivm->builder, fmask, sample_index4, "");
LLVMValueRef final_sample =
LLVMBuildAnd(gallivm->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(gallivm->builder,
si_shader_ctx->resources[FMASK_TEX_OFFSET + sampler_index],
LLVMVectorType(uint_bld->elem_type, 8), "");
LLVMValueRef fmask_word1 =
LLVMBuildExtractElement(gallivm->builder, fmask_desc,
uint_bld->one, "");
LLVMValueRef word1_is_nonzero =
LLVMBuildICmp(gallivm->builder, LLVMIntNE,
fmask_word1, uint_bld->zero, "");
sample_index_rewrite =
LLVMBuildSelect(gallivm->builder, word1_is_nonzero,
final_sample, sample_index, "");
}
/* Resource */
emit_data->args[1] = si_shader_ctx->resources[emit_data->inst->Src[sampler_src].Register.Index];
emit_data->args[1] = si_shader_ctx->resources[sampler_index];
if (opcode == TGSI_OPCODE_TXF) {
/* add tex offsets */
@ -1054,7 +1152,7 @@ static void tex_fetch_args(
emit_data->arg_count = 3;
} else {
/* Sampler */
emit_data->args[2] = si_shader_ctx->samplers[emit_data->inst->Src[sampler_src].Register.Index];
emit_data->args[2] = si_shader_ctx->samplers[sampler_index];
emit_data->dst_type = LLVMVectorType(
LLVMFloatTypeInContext(bld_base->base.gallivm->context),
@ -1072,6 +1170,13 @@ static void tex_fetch_args(
address[count++] = LLVMGetUndef(LLVMInt32TypeInContext(gallivm->context));
emit_data->args[0] = lp_build_gather_values(gallivm, address, count);
/* Replace the MSAA sample index if needed. */
if (sample_index_rewrite) {
emit_data->args[0] =
LLVMBuildInsertElement(gallivm->builder, emit_data->args[0],
sample_index_rewrite, sample_chan, "");
}
}
static void build_tex_intrinsic(const struct lp_build_tgsi_action * action,
@ -1352,7 +1457,7 @@ static void preload_samplers(struct si_shader_context *si_shader_ctx)
return;
/* Allocate space for the values */
si_shader_ctx->resources = CALLOC(num_samplers, sizeof(LLVMValueRef));
si_shader_ctx->resources = CALLOC(NUM_SAMPLER_VIEWS, sizeof(LLVMValueRef));
si_shader_ctx->samplers = CALLOC(num_samplers, sizeof(LLVMValueRef));
res_ptr = LLVMGetParam(si_shader_ctx->radeon_bld.main_fn, SI_PARAM_RESOURCE);
@ -1360,7 +1465,6 @@ static void preload_samplers(struct si_shader_context *si_shader_ctx)
/* Load the resources and samplers, we rely on the code sinking to do the rest */
for (i = 0; i < num_samplers; ++i) {
/* Resource */
offset = lp_build_const_int32(gallivm, i);
si_shader_ctx->resources[i] = build_indexed_load(si_shader_ctx, res_ptr, offset);
@ -1368,6 +1472,13 @@ static void preload_samplers(struct si_shader_context *si_shader_ctx)
/* Sampler */
offset = lp_build_const_int32(gallivm, i);
si_shader_ctx->samplers[i] = build_indexed_load(si_shader_ctx, samp_ptr, offset);
/* FMASK resource */
if (info->is_msaa_sampler[i]) {
offset = lp_build_const_int32(gallivm, FMASK_TEX_OFFSET + i);
si_shader_ctx->resources[FMASK_TEX_OFFSET + i] =
build_indexed_load(si_shader_ctx, res_ptr, offset);
}
}
}