aco: add emit_mimg() helper

Some fossil-db noise from slightly different order of instructions.

fossil-db (GFX10.3):
Totals from 73 (0.05% of 139391) affected shaders:
SGPRs: 3424 -> 3440 (+0.47%)
CodeSize: 199076 -> 199064 (-0.01%); split: -0.01%, +0.00%
Instrs: 37303 -> 37300 (-0.01%); split: -0.01%, +0.00%
Cycles: 786328 -> 786316 (-0.00%); split: -0.00%, +0.00%
VMEM: 19448 -> 19454 (+0.03%); split: +0.04%, -0.01%
SMEM: 5241 -> 5305 (+1.22%); split: +1.70%, -0.48%
SClause: 1282 -> 1281 (-0.08%)

Signed-off-by: Rhys Perry <pendingchaos02@gmail.com>
Reviewed-by: Daniel Schürmann <daniel@schuermann.dev>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8523>
This commit is contained in:
Rhys Perry
2021-01-14 17:33:43 +00:00
committed by Marge Bot
parent 9890dabb1b
commit cd29210fce
+83 -97
View File
@@ -5837,6 +5837,49 @@ static int image_type_to_components_count(enum glsl_sampler_dim dim, bool array)
}
static MIMG_instruction *emit_mimg(Builder& bld, aco_opcode op,
Definition dst,
Temp rsrc,
Operand samp,
const std::vector<Temp>& coords,
unsigned num_wqm_coords=0,
Operand vdata=Operand(v1))
{
Temp coord = coords[0];
if (coords.size() > 1) {
coord = bld.tmp(RegType::vgpr, coords.size());
aco_ptr<Pseudo_instruction> vec{create_instruction<Pseudo_instruction>(aco_opcode::p_create_vector, Format::PSEUDO, coords.size(), 1)};
for (unsigned i = 0; i < coords.size(); i++)
vec->operands[i] = Operand(coords[i]);
vec->definitions[0] = Definition(coord);
bld.insert(std::move(vec));
} else if (coord.type() == RegType::sgpr) {
coord = bld.copy(bld.def(v1), coord);
}
if (num_wqm_coords) {
/* We don't need the bias, sample index, compare value or offset to be
* computed in WQM but if the p_create_vector copies the coordinates, then it
* needs to be in WQM. */
coord = emit_wqm(bld, coord, bld.tmp(coord.regClass()), true);
}
aco_ptr<MIMG_instruction> mimg{create_instruction<MIMG_instruction>(
op, Format::MIMG, 3 + !vdata.isUndefined(), dst.isTemp())};
if (dst.isTemp())
mimg->definitions[0] = dst;
mimg->operands[0] = Operand(rsrc);
mimg->operands[1] = samp;
mimg->operands[2] = Operand(coord);
if (!vdata.isUndefined())
mimg->operands[3] = vdata;
MIMG_instruction *res = mimg.get();
bld.insert(std::move(mimg));
return res;
}
/* Adjust the sample index according to FMASK.
*
* For uncompressed MSAA surfaces, FMASK should return 0x76543210,
@@ -5859,20 +5902,15 @@ static Temp adjust_sample_index_using_fmask(isel_context *ctx, bool da, std::vec
? ac_get_sampler_dim(ctx->options->chip_class, GLSL_SAMPLER_DIM_2D, da)
: 0;
Temp coord = da ? bld.pseudo(aco_opcode::p_create_vector, bld.def(v3), coords[0], coords[1], coords[2]) :
bld.pseudo(aco_opcode::p_create_vector, bld.def(v2), coords[0], coords[1]);
aco_ptr<MIMG_instruction> load{create_instruction<MIMG_instruction>(aco_opcode::image_load, Format::MIMG, 3, 1)};
load->operands[0] = Operand(fmask_desc_ptr);
load->operands[1] = Operand(s4); /* no sampler */
load->operands[2] = Operand(coord);
load->definitions[0] = Definition(fmask);
MIMG_instruction *load = emit_mimg(bld, aco_opcode::image_load,
Definition(fmask), fmask_desc_ptr,
Operand(s4), coords);
load->glc = false;
load->dlc = false;
load->dmask = 0x1;
load->unrm = true;
load->da = da;
load->dim = dim;
ctx->block->instructions.emplace_back(std::move(load));
Operand sample_index4;
if (sample_index.isConstant()) {
@@ -5909,7 +5947,7 @@ static Temp adjust_sample_index_using_fmask(isel_context *ctx, bool da, std::vec
return bld.vop2(aco_opcode::v_cndmask_b32, bld.def(v1), sample_index_v, final_sample, compare);
}
static Temp get_image_coords(isel_context *ctx, const nir_intrinsic_instr *instr, const struct glsl_type *type)
static std::vector<Temp> get_image_coords(isel_context *ctx, const nir_intrinsic_instr *instr, const struct glsl_type *type)
{
Temp src0 = get_ssa_temp(ctx, instr->src[1].ssa);
@@ -5963,13 +6001,7 @@ static Temp get_image_coords(isel_context *ctx, const nir_intrinsic_instr *instr
coords.emplace_back(get_ssa_temp(ctx, instr->src[lod_index].ssa));
}
aco_ptr<Pseudo_instruction> vec{create_instruction<Pseudo_instruction>(aco_opcode::p_create_vector, Format::PSEUDO, coords.size(), 1)};
for (unsigned i = 0; i < coords.size(); i++)
vec->operands[i] = Operand(coords[i]);
Temp res = ctx->program->allocateTmp(RegClass(RegType::vgpr, coords.size()));
vec->definitions[0] = Definition(res);
ctx->block->instructions.emplace_back(std::move(vec));
return res;
return coords;
}
@@ -6081,16 +6113,14 @@ void visit_image_load(isel_context *ctx, nir_intrinsic_instr *instr)
load->operands[3] = emit_tfe_init(bld, tmp);
ctx->block->instructions.emplace_back(std::move(load));
} else {
Temp coords = get_image_coords(ctx, instr, type);
std::vector<Temp> coords = get_image_coords(ctx, instr, type);
bool level_zero = nir_src_is_const(instr->src[3]) && nir_src_as_uint(instr->src[3]) == 0;
aco_opcode opcode = level_zero ? aco_opcode::image_load : aco_opcode::image_load_mip;
aco_ptr<MIMG_instruction> load{create_instruction<MIMG_instruction>(opcode, Format::MIMG, 3 + is_sparse, 1)};
load->operands[0] = Operand(resource);
load->operands[1] = Operand(s4); /* no sampler */
load->operands[2] = Operand(coords);
load->definitions[0] = Definition(tmp);
Operand vdata = is_sparse ? emit_tfe_init(bld, tmp) : Operand(v1);
MIMG_instruction *load = emit_mimg(bld, opcode, Definition(tmp), resource,
Operand(s4), coords, 0, vdata);
load->glc = access & (ACCESS_VOLATILE | ACCESS_COHERENT) ? 1 : 0;
load->dlc = load->glc && ctx->options->chip_class >= GFX10;
load->dim = ac_get_image_dim(ctx->options->chip_class, dim, is_array);
@@ -6099,9 +6129,6 @@ void visit_image_load(isel_context *ctx, nir_intrinsic_instr *instr)
load->da = should_declare_array(ctx, dim, glsl_sampler_type_is_array(type));
load->sync = sync;
load->tfe = is_sparse;
if (load->tfe)
load->operands[3] = emit_tfe_init(bld, tmp);
ctx->block->instructions.emplace_back(std::move(load));
}
if (is_sparse && instr->dest.ssa.bit_size == 64) {
@@ -6167,17 +6194,15 @@ void visit_image_store(isel_context *ctx, nir_intrinsic_instr *instr)
}
assert(data.type() == RegType::vgpr);
Temp coords = get_image_coords(ctx, instr, type);
std::vector<Temp> coords = get_image_coords(ctx, instr, type);
Temp resource = get_sampler_desc(ctx, nir_instr_as_deref(instr->src[0].ssa->parent_instr), ACO_DESC_IMAGE, nullptr, true, true);
bool level_zero = nir_src_is_const(instr->src[4]) && nir_src_as_uint(instr->src[4]) == 0;
aco_opcode opcode = level_zero ? aco_opcode::image_store : aco_opcode::image_store_mip;
aco_ptr<MIMG_instruction> store{create_instruction<MIMG_instruction>(opcode, Format::MIMG, 4, 0)};
store->operands[0] = Operand(resource);
store->operands[1] = Operand(s4); /* no sampler */
store->operands[2] = Operand(coords);
store->operands[3] = Operand(data);
Builder bld(ctx->program, ctx->block);
MIMG_instruction *store = emit_mimg(bld, opcode, Definition(), resource,
Operand(s4), coords, 0, Operand(data));
store->glc = glc;
store->dlc = false;
store->dim = ac_get_image_dim(ctx->options->chip_class, dim, is_array);
@@ -6187,7 +6212,6 @@ void visit_image_store(isel_context *ctx, nir_intrinsic_instr *instr)
store->disable_wqm = true;
store->sync = sync;
ctx->program->needs_exact = true;
ctx->block->instructions.emplace_back(std::move(store));
return;
}
@@ -6299,15 +6323,11 @@ void visit_image_atomic(isel_context *ctx, nir_intrinsic_instr *instr)
return;
}
Temp coords = get_image_coords(ctx, instr, type);
std::vector<Temp> coords = get_image_coords(ctx, instr, type);
Temp resource = get_sampler_desc(ctx, nir_instr_as_deref(instr->src[0].ssa->parent_instr), ACO_DESC_IMAGE, nullptr, true, true);
aco_ptr<MIMG_instruction> mimg{create_instruction<MIMG_instruction>(image_op, Format::MIMG, 4, return_previous ? 1 : 0)};
mimg->operands[0] = Operand(resource);
mimg->operands[1] = Operand(s4); /* no sampler */
mimg->operands[2] = Operand(coords);
mimg->operands[3] = Operand(data);
if (return_previous)
mimg->definitions[0] = Definition(dst);
Definition def = return_previous ? Definition(dst) : Definition();
MIMG_instruction *mimg = emit_mimg(bld, image_op, def, resource,
Operand(s4), coords, 0, Operand(data));
mimg->glc = return_previous;
mimg->dlc = false; /* Not needed for atomics */
mimg->dim = ac_get_image_dim(ctx->options->chip_class, dim, is_array);
@@ -6317,7 +6337,6 @@ void visit_image_atomic(isel_context *ctx, nir_intrinsic_instr *instr)
mimg->disable_wqm = true;
mimg->sync = sync;
ctx->program->needs_exact = true;
ctx->block->instructions.emplace_back(std::move(mimg));
return;
}
@@ -6365,30 +6384,26 @@ void visit_image_size(isel_context *ctx, nir_intrinsic_instr *instr)
/* LOD */
assert(nir_src_as_uint(instr->src[1]) == 0);
Temp lod = bld.copy(bld.def(v1), Operand(0u));
std::vector<Temp> lod{bld.copy(bld.def(v1), Operand(0u))};
/* Resource */
Temp resource = get_sampler_desc(ctx, nir_instr_as_deref(instr->src[0].ssa->parent_instr), ACO_DESC_IMAGE, NULL, true, false);
Temp dst = get_ssa_temp(ctx, &instr->dest.ssa);
aco_ptr<MIMG_instruction> mimg{create_instruction<MIMG_instruction>(aco_opcode::image_get_resinfo, Format::MIMG, 3, 1)};
mimg->operands[0] = Operand(resource);
mimg->operands[1] = Operand(s4); /* no sampler */
mimg->operands[2] = Operand(lod);
MIMG_instruction *mimg = emit_mimg(bld, aco_opcode::image_get_resinfo,
Definition(dst), resource, Operand(s4), lod);
uint8_t& dmask = mimg->dmask;
mimg->dim = ac_get_image_dim(ctx->options->chip_class, dim, is_array);
mimg->dmask = (1 << instr->dest.ssa.num_components) - 1;
mimg->da = glsl_sampler_type_is_array(type);
Definition& def = mimg->definitions[0];
ctx->block->instructions.emplace_back(std::move(mimg));
if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_CUBE &&
glsl_sampler_type_is_array(type)) {
assert(instr->dest.ssa.num_components == 3);
Temp tmp = ctx->program->allocateTmp(v3);
def = Definition(tmp);
mimg->definitions[0] = Definition(tmp);
emit_split_vector(ctx, tmp, 3);
/* divide 3rd value by 6 by multiplying with magic number */
@@ -6404,10 +6419,7 @@ void visit_image_size(isel_context *ctx, nir_intrinsic_instr *instr)
glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_1D &&
glsl_sampler_type_is_array(type)) {
assert(instr->dest.ssa.num_components == 2);
def = Definition(dst);
dmask = 0x5;
} else {
def = Definition(dst);
}
emit_split_vector(ctx, dst, instr->dest.ssa.num_components);
@@ -9145,7 +9157,6 @@ void visit_tex(isel_context *ctx, nir_tex_instr *instr)
tmp_dst = bld.tmp(RegClass(RegType::vgpr, util_bitcount(dmask)));
}
aco_ptr<MIMG_instruction> tex;
if (instr->op == nir_texop_txs || instr->op == nir_texop_query_levels) {
if (!has_lod)
lod = bld.copy(bld.def(v1), Operand(0u));
@@ -9157,10 +9168,9 @@ void visit_tex(isel_context *ctx, nir_tex_instr *instr)
if (tmp_dst.id() == dst.id() && div_by_6)
tmp_dst = bld.tmp(tmp_dst.regClass());
tex.reset(create_instruction<MIMG_instruction>(aco_opcode::image_get_resinfo, Format::MIMG, 3, 1));
tex->operands[0] = Operand(resource);
tex->operands[1] = Operand(s4); /* no sampler */
tex->operands[2] = Operand(as_vgpr(ctx,lod));
MIMG_instruction *tex = emit_mimg(bld, aco_opcode::image_get_resinfo,
Definition(tmp_dst), resource, Operand(s4),
std::vector<Temp>{lod});
if (ctx->options->chip_class == GFX9 &&
instr->op == nir_texop_txs &&
instr->sampler_dim == GLSL_SAMPLER_DIM_1D &&
@@ -9172,9 +9182,7 @@ void visit_tex(isel_context *ctx, nir_tex_instr *instr)
tex->dmask = dmask;
}
tex->da = da;
tex->definitions[0] = Definition(tmp_dst);
tex->dim = dim;
ctx->block->instructions.emplace_back(std::move(tex));
if (div_by_6) {
/* divide 3rd value by 6 by multiplying with magic number */
@@ -9197,16 +9205,14 @@ void visit_tex(isel_context *ctx, nir_tex_instr *instr)
Temp tg4_compare_cube_wa64 = Temp();
if (tg4_integer_workarounds) {
tex.reset(create_instruction<MIMG_instruction>(aco_opcode::image_get_resinfo, Format::MIMG, 3, 1));
tex->operands[0] = Operand(resource);
tex->operands[1] = Operand(s4); /* no sampler */
tex->operands[2] = bld.copy(bld.def(v1), Operand(0u));
Temp tg4_lod = bld.copy(bld.def(v1), Operand(0u));
Temp size = bld.tmp(v2);
MIMG_instruction *tex = emit_mimg(bld, aco_opcode::image_get_resinfo,
Definition(size), resource, Operand(s4),
std::vector<Temp>{tg4_lod});
tex->dim = dim;
tex->dmask = 0x3;
tex->da = da;
Temp size = bld.tmp(v2);
tex->definitions[0] = Definition(size);
ctx->block->instructions.emplace_back(std::move(tex));
emit_split_vector(ctx, size, size.size());
Temp half_texel[2];
@@ -9329,13 +9335,6 @@ void visit_tex(isel_context *ctx, nir_tex_instr *instr)
if (has_clamped_lod)
args.emplace_back(clamped_lod);
Temp arg = bld.tmp(RegClass(RegType::vgpr, args.size()));
aco_ptr<Instruction> vec{create_instruction<Pseudo_instruction>(aco_opcode::p_create_vector, Format::PSEUDO, args.size(), 1)};
vec->definitions[0] = Definition(arg);
for (unsigned i = 0; i < args.size(); i++)
vec->operands[i] = Operand(args[i]);
ctx->block->instructions.emplace_back(std::move(vec));
if (instr->op == nir_texop_txf ||
instr->op == nir_texop_txf_ms ||
@@ -9343,19 +9342,14 @@ void visit_tex(isel_context *ctx, nir_tex_instr *instr)
instr->op == nir_texop_fragment_fetch ||
instr->op == nir_texop_fragment_mask_fetch) {
aco_opcode op = level_zero || instr->sampler_dim == GLSL_SAMPLER_DIM_MS || instr->sampler_dim == GLSL_SAMPLER_DIM_SUBPASS_MS ? aco_opcode::image_load : aco_opcode::image_load_mip;
tex.reset(create_instruction<MIMG_instruction>(op, Format::MIMG, 3 + instr->is_sparse, 1));
tex->operands[0] = Operand(resource);
tex->operands[1] = Operand(s4); /* no sampler */
tex->operands[2] = Operand(arg);
Operand vdata = instr->is_sparse ? emit_tfe_init(bld, tmp_dst) : Operand(v1);
MIMG_instruction *tex = emit_mimg(bld, op, Definition(tmp_dst), resource,
Operand(s4), args, 0, vdata);
tex->dim = dim;
tex->dmask = dmask & 0xf;
tex->unrm = true;
tex->da = da;
tex->tfe = instr->is_sparse;
tex->definitions[0] = Definition(tmp_dst);
if (tex->tfe)
tex->operands[3] = emit_tfe_init(bld, tmp_dst);
ctx->block->instructions.emplace_back(std::move(tex));
if (instr->op == nir_texop_samples_identical) {
assert(dmask == 1 && dst.regClass() == bld.lm);
@@ -9478,27 +9472,19 @@ void visit_tex(isel_context *ctx, nir_tex_instr *instr)
opcode = aco_opcode::image_get_lod;
}
/* we don't need the bias, sample index, compare value or offset to be
* computed in WQM but if the p_create_vector copies the coordinates, then it
* needs to be in WQM */
if (ctx->stage == fragment_fs &&
!has_derivs && !has_lod && !level_zero &&
instr->sampler_dim != GLSL_SAMPLER_DIM_MS &&
instr->sampler_dim != GLSL_SAMPLER_DIM_SUBPASS_MS)
arg = emit_wqm(bld, arg, bld.tmp(arg.regClass()), true);
bool implicit_derivs = bld.program->stage == fragment_fs &&
!has_derivs && !has_lod && !level_zero &&
instr->sampler_dim != GLSL_SAMPLER_DIM_MS &&
instr->sampler_dim != GLSL_SAMPLER_DIM_SUBPASS_MS;
tex.reset(create_instruction<MIMG_instruction>(opcode, Format::MIMG, 3 + instr->is_sparse, 1));
tex->operands[0] = Operand(resource);
tex->operands[1] = Operand(sampler);
tex->operands[2] = Operand(arg);
Operand vdata = instr->is_sparse ? emit_tfe_init(bld, tmp_dst) : Operand(v1);
unsigned num_wqm_coords = implicit_derivs ? args.size() : 0;
MIMG_instruction *tex = emit_mimg(bld, opcode, Definition(tmp_dst), resource,
Operand(sampler), args, num_wqm_coords, vdata);
tex->dim = dim;
tex->dmask = dmask & 0xf;
tex->da = da;
tex->tfe = instr->is_sparse;
tex->definitions[0] = Definition(tmp_dst);
if (tex->tfe)
tex->operands[3] = emit_tfe_init(bld, tmp_dst);
ctx->block->instructions.emplace_back(std::move(tex));
if (tg4_integer_cube_workaround) {
assert(tmp_dst.id() != dst.id());