r600/sfn: lower tg4 to backend in NIR

Signed-off-by: Gert Wollny <gert.wollny@collabora.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18619>
This commit is contained in:
Gert Wollny 2022-09-16 14:55:58 +02:00 committed by Marge Bot
parent 1dca2b8ae9
commit 10ddbf50bb
2 changed files with 112 additions and 117 deletions

View file

@ -350,8 +350,6 @@ bool TexInstr::from_nir(nir_tex_instr *tex, Shader& shader)
return emit_tex_lod(tex, src, shader);
case nir_texop_query_levels:
return emit_tex_txs(tex, src, {3,7,7,7}, shader);
case nir_texop_tg4:
return emit_tex_tg4(tex, src, shader);
case nir_texop_texture_samples:
return emit_tex_texture_samples(tex, src, shader);
default:
@ -401,6 +399,57 @@ get_sampler_id(int sampler_id, const nir_variable *deref)
return result;
}
void TexInstr::emit_set_gradients(nir_tex_instr* tex, int sampler_id,
Inputs& src, TexInstr *irt, Shader& shader)
{
TexInstr *grad[2] = {nullptr, nullptr};
RegisterVec4 empty_dst(0, false, {0,0,0,0}, pin_group);
grad[0] = new TexInstr(set_gradient_h, empty_dst, {7,7,7,7}, src.ddx,
sampler_id,
sampler_id + R600_MAX_CONST_BUFFERS,
src.sampler_offset);
grad[0]->set_rect_coordinate_flags(tex);
grad[0]->set_always_keep();
grad[1] = new TexInstr(set_gradient_v, empty_dst, {7,7,7,7}, src.ddy,
sampler_id, sampler_id + R600_MAX_CONST_BUFFERS,
src.sampler_offset);
grad[1]->set_rect_coordinate_flags(tex);
grad[1]->set_always_keep();
irt->add_prepare_instr(grad[0]);
irt->add_prepare_instr(grad[1]);
if (shader.last_txd())
irt->add_required_instr(shader.last_txd());
shader.set_last_txd(irt);
}
void TexInstr::emit_set_offsets(nir_tex_instr* tex, int sampler_id,
Inputs& src, TexInstr *irt, Shader& shader)
{
RegisterVec4::Swizzle swizzle = {4,4,4,4};
int src_components = tex->coord_components;
if (tex->is_array)
--src_components;
for (int i = 0; i < src_components; ++i)
swizzle[i] = i;
int noffsets = tex->coord_components;
if (tex->is_array)
--noffsets;
auto ofs = shader.value_factory().src_vec4(*src.offset, pin_group, swizzle);
RegisterVec4 empty_dst(0, false, {0,0,0,0}, pin_group);
auto set_ofs = new TexInstr(TexInstr::set_offsets, empty_dst, {7,7,7,7},
ofs, sampler_id,
sampler_id + R600_MAX_CONST_BUFFERS,
src.sampler_offset);
set_ofs->set_always_keep();
irt->add_prepare_instr(set_ofs);
}
bool TexInstr::emit_lowered_tex(nir_tex_instr* tex, Inputs& src, Shader& shader)
{
assert(src.backend1);
@ -418,8 +467,7 @@ bool TexInstr::emit_lowered_tex(nir_tex_instr* tex, Inputs& src, Shader& shader)
int32_t coord_mask = params[0].i32;
int32_t flags = params[1].i32;
int32_t inst_mode = params[2].i32;
TexInstr *grad[2] = {nullptr, nullptr};
uint32_t dst_swz_packed = params[3].u32;
auto dst = vf.dest_vec4(tex->dest, pin_group);
@ -429,29 +477,23 @@ bool TexInstr::emit_lowered_tex(nir_tex_instr* tex, Inputs& src, Shader& shader)
auto src_coord = vf.src_vec4(*src.backend1, pin_group, src_swizzle);
auto irt = new TexInstr(src.opcode, dst, {0,1,2,3}, src_coord, sampler.id,
RegisterVec4::Swizzle dst_swz = {0,1,2,3};
if (dst_swz_packed) {
for (int i = 0; i < 4; ++i) {
dst_swz[i] = (dst_swz_packed >> (8 * i)) & 0xff;
}
}
auto irt = new TexInstr(src.opcode, dst, dst_swz, src_coord, sampler.id,
sampler.id + R600_MAX_CONST_BUFFERS,
src.sampler_offset);
if (tex->op == nir_texop_txd) {
RegisterVec4 empty_dst(0, false, {0,0,0,0}, pin_group);
grad[0] = new TexInstr(set_gradient_h, empty_dst, {7,7,7,7}, src.ddx,
sampler.id,
sampler.id + R600_MAX_CONST_BUFFERS,
src.sampler_offset);
grad[0]->set_rect_coordinate_flags(tex);
grad[0]->set_always_keep();
if (tex->op == nir_texop_txd)
emit_set_gradients(tex, sampler.id, src, irt, shader);
grad[1] = new TexInstr(set_gradient_v, empty_dst, {7,7,7,7}, src.ddy,
sampler.id, sampler.id + R600_MAX_CONST_BUFFERS,
src.sampler_offset);
grad[1]->set_rect_coordinate_flags(tex);
grad[1]->set_always_keep();
irt->add_prepare_instr(grad[0]);
irt->add_prepare_instr(grad[1]);
if (shader.last_txd())
irt->add_required_instr(shader.last_txd());
shader.set_last_txd(irt);
if (!irt->set_coord_offsets(src.offset)) {
assert(tex->op == nir_texop_tg4);
emit_set_offsets(tex, sampler.id, src, irt, shader);
}
for (const auto f : TexFlags) {
@ -459,7 +501,7 @@ bool TexInstr::emit_lowered_tex(nir_tex_instr* tex, Inputs& src, Shader& shader)
irt->set_tex_flag(f);
}
irt->set_coord_offsets(src.offset);
irt->set_inst_mode(inst_mode);
shader.emit_instruction(irt);
@ -575,89 +617,6 @@ bool TexInstr::emit_tex_txs(nir_tex_instr *tex, Inputs& src,
return true;
}
bool TexInstr::emit_tex_tg4(nir_tex_instr* tex, Inputs& src , Shader& shader)
{
auto& vf = shader.value_factory();
r600::sfn_log << SfnLog::instr << "emit '"
<< *reinterpret_cast<nir_instr*>(tex)
<< "' (" << __func__ << ")\n";
TexInstr *set_ofs = nullptr;
auto src_coord = prepare_source(tex, src, shader);
r600::sfn_log << SfnLog::instr << "emit '"
<< *reinterpret_cast<nir_instr*>(tex)
<< "' (" << __func__ << ")\n";
auto dst = vf.dest_vec4(tex->dest, pin_group);
RegisterVec4 empty_dst(125, false, {7,7,7,7}, pin_group);
/* pre CAYMAN needs swizzle */
auto dest_swizzle = shader.chip_class() <= ISA_CC_EVERGREEN ?
RegisterVec4::Swizzle{1, 2, 0, 3} :
RegisterVec4::Swizzle{0, 1, 2, 3};
auto sampler = get_sampler_id(tex->sampler_index, src.sampler_deref);
assert(!sampler.indirect && "Indirect sampler selection not yet supported");
bool literal_offset = false;
if (src.offset) {
literal_offset = nir_src_as_const_value(*src.offset) != 0;
r600::sfn_log << SfnLog::tex << " really have offsets and they are " <<
(literal_offset ? "l" : "varying") <<
"\n";
if (!literal_offset) {
RegisterVec4::Swizzle swizzle = {4,4,4,4};
int src_components = tex->coord_components;
if (tex->is_array)
--src_components;
for (int i = 0; i < src_components; ++i)
swizzle[i] = i;
int noffsets = tex->coord_components;
if (tex->is_array)
--noffsets;
auto ofs = vf.src_vec4(*src.offset, pin_group, swizzle);
RegisterVec4 dummy(0, true, {7,7,7,7});
set_ofs = new TexInstr(TexInstr::set_offsets, dummy, {7,7,7,7},
ofs, sampler.id,
sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
} else {
src.opcode = src.opcode == gather4_o ? gather4 : gather4_c;
}
}
auto irt = new TexInstr(src.opcode, dst, dest_swizzle, src_coord, sampler.id,
sampler.id + R600_MAX_CONST_BUFFERS, src.sampler_offset);
irt->set_gather_comp(tex->component);
if (tex->is_array)
irt->set_tex_flag(z_unnormalized);
if (literal_offset) {
r600::sfn_log << SfnLog::tex << "emit literal offsets\n";
irt->set_coord_offsets(src.offset);
}
irt->set_rect_coordinate_flags(tex);
if (set_ofs) {
set_ofs->set_always_keep();
irt->add_prepare_instr(set_ofs);
}
shader.emit_instruction(irt);
return true;
}
auto TexInstr::prepare_source(nir_tex_instr *tex, const Inputs& inputs, Shader& shader) -> RegisterVec4
{
RegisterVec4::Swizzle target{7,7,7,7};
@ -806,11 +765,12 @@ auto TexInstr::Inputs::get_opcode(const nir_tex_instr& instr) -> Opcode
return get_resinfo;
case nir_texop_txd:
return instr.is_shadow ? sample_c_g : sample_g;
case nir_texop_tg4:
case nir_texop_tg4: {
auto var_offset = offset && nir_src_as_const_value(*offset) == nullptr;
return instr.is_shadow ?
(offset ? gather4_c_o : gather4_c) :
(offset ? gather4_o : gather4);
(var_offset ? gather4_c_o : gather4_c) :
(var_offset ? gather4_o : gather4);
}
case nir_texop_txf_ms:
return ld;
case nir_texop_query_levels:
@ -860,17 +820,21 @@ RegisterVec4::Swizzle TexInstr::Inputs::swizzle_from_ncomps(int comps) const
return swz;
}
void TexInstr::set_coord_offsets(nir_src *offset)
bool TexInstr::set_coord_offsets(nir_src *offset)
{
if (!offset)
return;
return true;
if (!offset->is_ssa)
return false;
assert(offset->is_ssa);
auto literal = nir_src_as_const_value(*offset);
assert(literal);
if (!literal)
return false;
for (int i = 0; i < offset->ssa->num_components; ++i)
set_offset(i, literal[i].i32);
return true;
}
void TexInstr::set_rect_coordinate_flags(nir_tex_instr* instr)
@ -890,6 +854,7 @@ private:
nir_ssa_def *lower_tex(nir_tex_instr *tex);
nir_ssa_def *lower_txf(nir_tex_instr *tex);
nir_ssa_def *lower_tg4(nir_tex_instr *tex);
nir_ssa_def *lower_txf_ms(nir_tex_instr *tex);
nir_ssa_def *lower_txf_ms_direct(nir_tex_instr *tex);
@ -931,6 +896,7 @@ bool LowerTexToBackend::filter(const nir_instr *instr) const
case nir_texop_txl:
case nir_texop_txf:
case nir_texop_txd:
case nir_texop_tg4:
case nir_texop_txf_ms:
break;
default:
@ -953,6 +919,8 @@ nir_ssa_def *LowerTexToBackend::lower(nir_instr *instr)
return lower_tex(tex);
case nir_texop_txf:
return lower_txf(tex);
case nir_texop_tg4:
return lower_tg4(tex);
case nir_texop_txf_ms:
if (m_chip_class < EVERGREEN)
return lower_txf_ms_direct(tex);
@ -998,6 +966,30 @@ nir_ssa_def *LowerTexToBackend::lower_txf(nir_tex_instr *tex)
return finalize(tex, backend1, backend2);
}
nir_ssa_def *LowerTexToBackend::lower_tg4(nir_tex_instr *tex)
{
std::array<nir_ssa_def *, 4> new_coord = {
nullptr,
nullptr,
nullptr,
nullptr
};
get_src_coords(tex, new_coord, false);
uint32_t dest_swizzle = m_chip_class <= EVERGREEN ?
1 | (2 << 8) | (0 << 16) | (3 << 24) : 0;
int used_coord_mask = 0;
int unnormalized_mask = 0;
nir_ssa_def *backend1 = prepare_coord(tex, unnormalized_mask, used_coord_mask);
nir_ssa_def *backend2 = nir_imm_ivec4(b, used_coord_mask,
unnormalized_mask,
tex->component,
dest_swizzle);
return finalize(tex, backend1, backend2);
}
nir_ssa_def *LowerTexToBackend::lower_txf_ms(nir_tex_instr *tex)
{
std::array<nir_ssa_def *, 4> new_coord = {

View file

@ -174,11 +174,14 @@ private:
static bool emit_tex_txs(nir_tex_instr *tex, Inputs& src,
RegisterVec4::Swizzle dest_swz, Shader& shader);
static bool emit_tex_lod(nir_tex_instr* tex, Inputs& src, Shader& shader);
static bool emit_tex_tg4(nir_tex_instr* instr, Inputs& src , Shader& shader);
static bool emit_tex_texture_samples(nir_tex_instr* instr, Inputs& src, Shader& shader);
static bool emit_lowered_tex(nir_tex_instr* instr, Inputs& src, Shader& shader);
static void emit_set_gradients(nir_tex_instr* tex, int sampler_id,
Inputs& src, TexInstr *irt, Shader& shader);
static void emit_set_offsets(nir_tex_instr* tex, int sampler_id,
Inputs& src, TexInstr *irt, Shader& shader);
void set_coord_offsets(nir_src *offset);
bool set_coord_offsets(nir_src *offset);
void set_rect_coordinate_flags(nir_tex_instr* instr);
void add_prepare_instr(TexInstr *ir) {m_prepare_instr.push_back(ir);};