|
|
|
@@ -47,8 +47,6 @@ FragmentShaderFromNir::FragmentShaderFromNir(const nir_shader& nir,
|
|
|
|
|
m_need_back_color(false),
|
|
|
|
|
m_front_face_loaded(false),
|
|
|
|
|
m_depth_exports(0),
|
|
|
|
|
m_enable_centroid_interpolators(false),
|
|
|
|
|
m_enable_sample_interpolators(false),
|
|
|
|
|
m_apply_sample_mask(key.ps.apply_sample_id_mask),
|
|
|
|
|
m_dual_source_blend(key.ps.dual_source_blend)
|
|
|
|
|
{
|
|
|
|
@@ -111,11 +109,168 @@ bool FragmentShaderFromNir::do_process_inputs(nir_variable *input)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
unsigned barycentric_ij_index(nir_intrinsic_instr *instr)
|
|
|
|
|
{
|
|
|
|
|
unsigned index = 0;
|
|
|
|
|
switch (instr->intrinsic) {
|
|
|
|
|
case nir_intrinsic_load_barycentric_sample:
|
|
|
|
|
index = 0;
|
|
|
|
|
break;
|
|
|
|
|
case nir_intrinsic_load_barycentric_at_sample:
|
|
|
|
|
case nir_intrinsic_load_barycentric_at_offset:
|
|
|
|
|
case nir_intrinsic_load_barycentric_pixel:
|
|
|
|
|
index = 1;
|
|
|
|
|
break;
|
|
|
|
|
case nir_intrinsic_load_barycentric_centroid:
|
|
|
|
|
index = 2;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
unreachable("Unknown interpolator intrinsic");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (nir_intrinsic_interp_mode(instr)) {
|
|
|
|
|
case INTERP_MODE_NONE:
|
|
|
|
|
case INTERP_MODE_SMOOTH:
|
|
|
|
|
case INTERP_MODE_COLOR:
|
|
|
|
|
return index;
|
|
|
|
|
break;
|
|
|
|
|
case INTERP_MODE_NOPERSPECTIVE:
|
|
|
|
|
return index + 3;
|
|
|
|
|
break;
|
|
|
|
|
case INTERP_MODE_FLAT:
|
|
|
|
|
case INTERP_MODE_EXPLICIT:
|
|
|
|
|
default:
|
|
|
|
|
assert(0 && "unknown/unsupported mode for load_interpolated");
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FragmentShaderFromNir::process_load_input(nir_intrinsic_instr *instr,
|
|
|
|
|
bool interpolated)
|
|
|
|
|
{
|
|
|
|
|
sfn_log << SfnLog::io << "Parse " << instr->instr
|
|
|
|
|
<< "\n";
|
|
|
|
|
|
|
|
|
|
auto index = nir_src_as_const_value(instr->src[interpolated ? 1 : 0]);
|
|
|
|
|
assert(index);
|
|
|
|
|
|
|
|
|
|
unsigned location = nir_intrinsic_io_semantics(instr).location + index->u32;
|
|
|
|
|
auto semantic = r600_get_varying_semantic(location);
|
|
|
|
|
tgsi_semantic name = (tgsi_semantic)semantic.first;
|
|
|
|
|
unsigned sid = semantic.second;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (location == VARYING_SLOT_POS) {
|
|
|
|
|
m_sv_values.set(es_pos);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (location == VARYING_SLOT_FACE) {
|
|
|
|
|
m_sv_values.set(es_face);
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tgsi_interpolate_mode tgsi_interpolate = TGSI_INTERPOLATE_CONSTANT;
|
|
|
|
|
tgsi_interpolate_loc tgsi_loc = TGSI_INTERPOLATE_LOC_CENTER;
|
|
|
|
|
|
|
|
|
|
bool uses_interpol_at_centroid = false;
|
|
|
|
|
|
|
|
|
|
if (interpolated) {
|
|
|
|
|
|
|
|
|
|
glsl_interp_mode mode = INTERP_MODE_NONE;
|
|
|
|
|
auto parent = nir_instr_as_intrinsic(instr->src[0].ssa->parent_instr);
|
|
|
|
|
mode = (glsl_interp_mode)nir_intrinsic_interp_mode(parent);
|
|
|
|
|
switch (parent->intrinsic) {
|
|
|
|
|
case nir_intrinsic_load_barycentric_sample:
|
|
|
|
|
tgsi_loc = TGSI_INTERPOLATE_LOC_SAMPLE;
|
|
|
|
|
break;
|
|
|
|
|
case nir_intrinsic_load_barycentric_at_sample:
|
|
|
|
|
case nir_intrinsic_load_barycentric_at_offset:
|
|
|
|
|
case nir_intrinsic_load_barycentric_pixel:
|
|
|
|
|
tgsi_loc = TGSI_INTERPOLATE_LOC_CENTER;
|
|
|
|
|
break;
|
|
|
|
|
case nir_intrinsic_load_barycentric_centroid:
|
|
|
|
|
tgsi_loc = TGSI_INTERPOLATE_LOC_CENTROID;
|
|
|
|
|
uses_interpol_at_centroid = true;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
std::cerr << "Instruction " << nir_intrinsic_infos[parent->intrinsic].name << " as parent of "
|
|
|
|
|
<< nir_intrinsic_infos[instr->intrinsic].name
|
|
|
|
|
<< " interpolator?\n";
|
|
|
|
|
assert(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (mode) {
|
|
|
|
|
case INTERP_MODE_NONE:
|
|
|
|
|
if (name == TGSI_SEMANTIC_COLOR) {
|
|
|
|
|
tgsi_interpolate = TGSI_INTERPOLATE_COLOR;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
/* fallthrough */
|
|
|
|
|
case INTERP_MODE_SMOOTH:
|
|
|
|
|
tgsi_interpolate = TGSI_INTERPOLATE_PERSPECTIVE;
|
|
|
|
|
break;
|
|
|
|
|
case INTERP_MODE_NOPERSPECTIVE:
|
|
|
|
|
tgsi_interpolate = TGSI_INTERPOLATE_LINEAR;
|
|
|
|
|
break;
|
|
|
|
|
case INTERP_MODE_FLAT:
|
|
|
|
|
break;
|
|
|
|
|
case INTERP_MODE_COLOR:
|
|
|
|
|
tgsi_interpolate = TGSI_INTERPOLATE_COLOR;
|
|
|
|
|
break;
|
|
|
|
|
case INTERP_MODE_EXPLICIT:
|
|
|
|
|
default:
|
|
|
|
|
assert(0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
m_interpolators_used.set(barycentric_ij_index(parent));
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
switch (name) {
|
|
|
|
|
case TGSI_SEMANTIC_COLOR: {
|
|
|
|
|
m_shaderio.add_input(new ShaderInputColor(name, sid,
|
|
|
|
|
nir_intrinsic_base(instr) + index->u32,
|
|
|
|
|
nir_intrinsic_component(instr),
|
|
|
|
|
nir_dest_num_components(instr->dest),
|
|
|
|
|
tgsi_interpolate, tgsi_loc));
|
|
|
|
|
m_need_back_color = m_two_sided_color;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
case TGSI_SEMANTIC_PRIMID:
|
|
|
|
|
sh_info().gs_prim_id_input = true;
|
|
|
|
|
sh_info().ps_prim_id_input = m_shaderio.inputs().size();
|
|
|
|
|
/* fallthrough */
|
|
|
|
|
case TGSI_SEMANTIC_FOG:
|
|
|
|
|
case TGSI_SEMANTIC_GENERIC:
|
|
|
|
|
case TGSI_SEMANTIC_TEXCOORD:
|
|
|
|
|
case TGSI_SEMANTIC_LAYER:
|
|
|
|
|
case TGSI_SEMANTIC_PCOORD:
|
|
|
|
|
case TGSI_SEMANTIC_VIEWPORT_INDEX:
|
|
|
|
|
case TGSI_SEMANTIC_CLIPDIST: {
|
|
|
|
|
auto varying = m_shaderio.find_varying(name, sid, nir_intrinsic_component(instr));
|
|
|
|
|
if (!varying) {
|
|
|
|
|
m_shaderio.add_input(new ShaderInputVarying(name, sid, nir_intrinsic_base(instr) + index->u32,
|
|
|
|
|
nir_intrinsic_component(instr),
|
|
|
|
|
nir_dest_num_components(instr->dest),
|
|
|
|
|
tgsi_interpolate, tgsi_loc));
|
|
|
|
|
} else if (uses_interpol_at_centroid)
|
|
|
|
|
varying->set_uses_interpolate_at_centroid();
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool FragmentShaderFromNir::scan_sysvalue_access(nir_instr *instr)
|
|
|
|
|
{
|
|
|
|
|
switch (instr->type) {
|
|
|
|
|
case nir_instr_type_intrinsic: {
|
|
|
|
|
nir_intrinsic_instr *ii = nir_instr_as_intrinsic(instr);
|
|
|
|
|
|
|
|
|
|
switch (ii->intrinsic) {
|
|
|
|
|
case nir_intrinsic_load_front_face:
|
|
|
|
|
m_sv_values.set(es_face);
|
|
|
|
@@ -129,16 +284,14 @@ bool FragmentShaderFromNir::scan_sysvalue_access(nir_instr *instr)
|
|
|
|
|
case nir_intrinsic_load_sample_id:
|
|
|
|
|
m_sv_values.set(es_sample_id);
|
|
|
|
|
break;
|
|
|
|
|
case nir_intrinsic_interp_deref_at_centroid:
|
|
|
|
|
/* This is not a sysvalue, should go elsewhere */
|
|
|
|
|
m_enable_centroid_interpolators = true;
|
|
|
|
|
break;
|
|
|
|
|
case nir_intrinsic_interp_deref_at_sample:
|
|
|
|
|
m_enable_sample_interpolators = true;
|
|
|
|
|
break;
|
|
|
|
|
case nir_intrinsic_load_helper_invocation:
|
|
|
|
|
m_sv_values.set(es_helper_invocation);
|
|
|
|
|
break;
|
|
|
|
|
case nir_intrinsic_load_input:
|
|
|
|
|
return process_load_input(ii, false);
|
|
|
|
|
case nir_intrinsic_load_interpolated_input: {
|
|
|
|
|
return process_load_input(ii, true);
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
@@ -156,23 +309,13 @@ bool FragmentShaderFromNir::do_allocate_reserved_registers()
|
|
|
|
|
int face_reg_index = -1;
|
|
|
|
|
int sample_id_index = -1;
|
|
|
|
|
// enabled interpolators based on inputs
|
|
|
|
|
for (auto& i: m_shaderio.inputs()) {
|
|
|
|
|
int ij = i->ij_index();
|
|
|
|
|
if (ij >= 0) {
|
|
|
|
|
m_interpolator[ij].enabled = true;
|
|
|
|
|
for (unsigned i = 0; i < s_max_interpolators; ++i) {
|
|
|
|
|
if (m_interpolators_used.test(i)) {
|
|
|
|
|
sfn_log << SfnLog::io << "Interpolator " << i << " test enabled\n";
|
|
|
|
|
m_interpolator[i].enabled = true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Lazy, enable both possible interpolators,
|
|
|
|
|
* TODO: check which ones are really needed */
|
|
|
|
|
if (m_enable_centroid_interpolators) {
|
|
|
|
|
m_interpolator[2].enabled = true; /* perspective */
|
|
|
|
|
m_interpolator[5].enabled = true; /* linear */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (m_enable_sample_interpolators)
|
|
|
|
|
m_interpolator[1].enabled = true; /* perspective */
|
|
|
|
|
|
|
|
|
|
// sort the varying inputs
|
|
|
|
|
m_shaderio.sort_varying_inputs();
|
|
|
|
|
|
|
|
|
@@ -180,7 +323,7 @@ bool FragmentShaderFromNir::do_allocate_reserved_registers()
|
|
|
|
|
int num_baryc = 0;
|
|
|
|
|
for (int i = 0; i < 6; ++i) {
|
|
|
|
|
if (m_interpolator[i].enabled) {
|
|
|
|
|
sfn_log << SfnLog::io << "Interpolator " << i << " is enabled\n";
|
|
|
|
|
sfn_log << SfnLog::io << "Interpolator " << i << " is enabled with ij=" << num_baryc <<" \n";
|
|
|
|
|
|
|
|
|
|
m_interpolator[i].ij_index = num_baryc;
|
|
|
|
|
|
|
|
|
@@ -400,11 +543,248 @@ bool FragmentShaderFromNir::emit_intrinsic_instruction_override(nir_intrinsic_in
|
|
|
|
|
return emit_load_sample_pos(instr);
|
|
|
|
|
case nir_intrinsic_load_helper_invocation:
|
|
|
|
|
return load_preloaded_value(instr->dest, 0, m_helper_invocation);
|
|
|
|
|
case nir_intrinsic_load_input:
|
|
|
|
|
return emit_load_input(instr);
|
|
|
|
|
case nir_intrinsic_load_barycentric_sample:
|
|
|
|
|
case nir_intrinsic_load_barycentric_pixel:
|
|
|
|
|
case nir_intrinsic_load_barycentric_centroid: {
|
|
|
|
|
unsigned ij = barycentric_ij_index(instr);
|
|
|
|
|
return load_preloaded_value(instr->dest, 0, m_interpolator[ij].i) &&
|
|
|
|
|
load_preloaded_value(instr->dest, 1, m_interpolator[ij].j);
|
|
|
|
|
}
|
|
|
|
|
case nir_intrinsic_load_barycentric_at_offset:
|
|
|
|
|
return load_barycentric_at_offset(instr);
|
|
|
|
|
case nir_intrinsic_load_barycentric_at_sample:
|
|
|
|
|
return load_barycentric_at_sample(instr);
|
|
|
|
|
|
|
|
|
|
case nir_intrinsic_load_interpolated_input: {
|
|
|
|
|
return emit_load_interpolated_input(instr);
|
|
|
|
|
}
|
|
|
|
|
default:
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FragmentShaderFromNir::emit_load_interpolated_input(nir_intrinsic_instr* instr)
|
|
|
|
|
{
|
|
|
|
|
unsigned loc = nir_intrinsic_io_semantics(instr).location;
|
|
|
|
|
switch (loc) {
|
|
|
|
|
case VARYING_SLOT_POS:
|
|
|
|
|
for (unsigned i = 0; i < nir_dest_num_components(instr->dest); ++i) {
|
|
|
|
|
load_preloaded_value(instr->dest, i, m_frag_pos[i]);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
case VARYING_SLOT_FACE:
|
|
|
|
|
return load_preloaded_value(instr->dest, 0, m_front_face_reg);
|
|
|
|
|
default:
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto param = nir_src_as_const_value(instr->src[1]);
|
|
|
|
|
assert(param && "Indirect PS inputs not (yet) supported");
|
|
|
|
|
|
|
|
|
|
auto& io = m_shaderio.input(param->u32 + nir_intrinsic_base(instr), nir_intrinsic_component(instr));
|
|
|
|
|
auto dst = nir_intrinsic_component(instr) ? get_temp_vec4() : vec_from_nir(instr->dest, 4);
|
|
|
|
|
|
|
|
|
|
io.set_gpr(dst.sel());
|
|
|
|
|
|
|
|
|
|
Interpolator ip = {true, 0, from_nir(instr->src[0], 0), from_nir(instr->src[0], 1)};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (!load_interpolated(dst, io, ip, nir_dest_num_components(instr->dest),
|
|
|
|
|
nir_intrinsic_component(instr)))
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
if (m_need_back_color && io.name() == TGSI_SEMANTIC_COLOR) {
|
|
|
|
|
|
|
|
|
|
auto & color_input = static_cast<ShaderInputColor&> (io);
|
|
|
|
|
auto& bgio = m_shaderio.input(color_input.back_color_input_index());
|
|
|
|
|
|
|
|
|
|
bgio.set_gpr(allocate_temp_register());
|
|
|
|
|
|
|
|
|
|
GPRVector bgcol(bgio.gpr(), {0,1,2,3});
|
|
|
|
|
load_interpolated(bgcol, bgio, ip, nir_dest_num_components(instr->dest), 0);
|
|
|
|
|
|
|
|
|
|
load_front_face();
|
|
|
|
|
|
|
|
|
|
AluInstruction *ir = nullptr;
|
|
|
|
|
for (unsigned i = 0; i < 4 ; ++i) {
|
|
|
|
|
ir = new AluInstruction(op3_cnde, dst[i], m_front_face_reg, bgcol[i], dst[i], {alu_write});
|
|
|
|
|
emit_instruction(ir);
|
|
|
|
|
}
|
|
|
|
|
if (ir)
|
|
|
|
|
ir->set_flag(alu_last_instr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
AluInstruction *ir = nullptr;
|
|
|
|
|
if (nir_intrinsic_component(instr) != 0) {
|
|
|
|
|
std::cerr << "move in right pos \n";
|
|
|
|
|
for (unsigned i = 0; i < nir_dest_num_components(instr->dest); ++i) {
|
|
|
|
|
ir = new AluInstruction(op1_mov, from_nir(instr->dest, i), dst[i + nir_intrinsic_component(instr)], {alu_write});
|
|
|
|
|
emit_instruction(ir);
|
|
|
|
|
}
|
|
|
|
|
if (ir)
|
|
|
|
|
ir->set_flag(alu_last_instr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FragmentShaderFromNir::load_barycentric_at_offset(nir_intrinsic_instr* instr)
|
|
|
|
|
{
|
|
|
|
|
auto interpolator = m_interpolator[barycentric_ij_index(instr)];
|
|
|
|
|
PValue dummy(new GPRValue(interpolator.i->sel(), 0));
|
|
|
|
|
|
|
|
|
|
GPRVector help = get_temp_vec4();
|
|
|
|
|
GPRVector interp({interpolator.j, interpolator.i, dummy, dummy});
|
|
|
|
|
|
|
|
|
|
auto getgradh = new TexInstruction(TexInstruction::get_gradient_h, help, interp, 0, 0, PValue());
|
|
|
|
|
getgradh->set_dest_swizzle({0,1,7,7});
|
|
|
|
|
getgradh->set_flag(TexInstruction::x_unnormalized);
|
|
|
|
|
getgradh->set_flag(TexInstruction::y_unnormalized);
|
|
|
|
|
getgradh->set_flag(TexInstruction::z_unnormalized);
|
|
|
|
|
getgradh->set_flag(TexInstruction::w_unnormalized);
|
|
|
|
|
getgradh->set_flag(TexInstruction::grad_fine);
|
|
|
|
|
emit_instruction(getgradh);
|
|
|
|
|
|
|
|
|
|
auto getgradv = new TexInstruction(TexInstruction::get_gradient_v, help, interp, 0, 0, PValue());
|
|
|
|
|
getgradv->set_dest_swizzle({7,7,0,1});
|
|
|
|
|
getgradv->set_flag(TexInstruction::x_unnormalized);
|
|
|
|
|
getgradv->set_flag(TexInstruction::y_unnormalized);
|
|
|
|
|
getgradv->set_flag(TexInstruction::z_unnormalized);
|
|
|
|
|
getgradv->set_flag(TexInstruction::w_unnormalized);
|
|
|
|
|
getgradv->set_flag(TexInstruction::grad_fine);
|
|
|
|
|
emit_instruction(getgradv);
|
|
|
|
|
|
|
|
|
|
PValue ofs_x = from_nir(instr->src[0], 0);
|
|
|
|
|
PValue ofs_y = from_nir(instr->src[0], 1);
|
|
|
|
|
emit_instruction(new AluInstruction(op3_muladd, help.reg_i(0), help.reg_i(0), ofs_x, interpolator.j, {alu_write}));
|
|
|
|
|
emit_instruction(new AluInstruction(op3_muladd, help.reg_i(1), help.reg_i(1), ofs_x, interpolator.i, {alu_write, alu_last_instr}));
|
|
|
|
|
emit_instruction(new AluInstruction(op3_muladd, from_nir(instr->dest, 0), help.reg_i(3), ofs_y, help.reg_i(1), {alu_write}));
|
|
|
|
|
emit_instruction(new AluInstruction(op3_muladd, from_nir(instr->dest, 1), help.reg_i(2), ofs_y, help.reg_i(0), {alu_write, alu_last_instr}));
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FragmentShaderFromNir::load_barycentric_at_sample(nir_intrinsic_instr* instr)
|
|
|
|
|
{
|
|
|
|
|
GPRVector slope = get_temp_vec4();
|
|
|
|
|
|
|
|
|
|
auto fetch = new FetchInstruction(vc_fetch, no_index_offset, slope,
|
|
|
|
|
from_nir_with_fetch_constant(instr->src[0], 0),
|
|
|
|
|
0, R600_BUFFER_INFO_CONST_BUFFER, PValue(), bim_none);
|
|
|
|
|
fetch->set_flag(vtx_srf_mode);
|
|
|
|
|
emit_instruction(fetch);
|
|
|
|
|
|
|
|
|
|
GPRVector grad = get_temp_vec4();
|
|
|
|
|
|
|
|
|
|
auto interpolator = m_interpolator[barycentric_ij_index(instr)];
|
|
|
|
|
assert(interpolator.enabled);
|
|
|
|
|
PValue dummy(new GPRValue(interpolator.i->sel(), 0));
|
|
|
|
|
|
|
|
|
|
GPRVector src({interpolator.j, interpolator.i, dummy, dummy});
|
|
|
|
|
|
|
|
|
|
auto tex = new TexInstruction(TexInstruction::get_gradient_h, grad, src, 0, 0, PValue());
|
|
|
|
|
tex->set_flag(TexInstruction::grad_fine);
|
|
|
|
|
tex->set_flag(TexInstruction::x_unnormalized);
|
|
|
|
|
tex->set_flag(TexInstruction::y_unnormalized);
|
|
|
|
|
tex->set_flag(TexInstruction::z_unnormalized);
|
|
|
|
|
tex->set_flag(TexInstruction::w_unnormalized);
|
|
|
|
|
tex->set_dest_swizzle({0,1,7,7});
|
|
|
|
|
emit_instruction(tex);
|
|
|
|
|
|
|
|
|
|
tex = new TexInstruction(TexInstruction::get_gradient_v, grad, src, 0, 0, PValue());
|
|
|
|
|
tex->set_flag(TexInstruction::x_unnormalized);
|
|
|
|
|
tex->set_flag(TexInstruction::y_unnormalized);
|
|
|
|
|
tex->set_flag(TexInstruction::z_unnormalized);
|
|
|
|
|
tex->set_flag(TexInstruction::w_unnormalized);
|
|
|
|
|
tex->set_flag(TexInstruction::grad_fine);
|
|
|
|
|
tex->set_dest_swizzle({7,7,0,1});
|
|
|
|
|
emit_instruction(tex);
|
|
|
|
|
|
|
|
|
|
emit_instruction(new AluInstruction(op3_muladd, slope.reg_i(0), {grad.reg_i(0), slope.reg_i(2), interpolator.j}, {alu_write}));
|
|
|
|
|
emit_instruction(new AluInstruction(op3_muladd, slope.reg_i(1), {grad.reg_i(1), slope.reg_i(2), interpolator.i}, {alu_write, alu_last_instr}));
|
|
|
|
|
|
|
|
|
|
emit_instruction(new AluInstruction(op3_muladd, from_nir(instr->dest, 0), {grad.reg_i(3), slope.reg_i(3), slope.reg_i(1)}, {alu_write}));
|
|
|
|
|
emit_instruction(new AluInstruction(op3_muladd, from_nir(instr->dest, 1), {grad.reg_i(2), slope.reg_i(3), slope.reg_i(0)}, {alu_write, alu_last_instr}));
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool FragmentShaderFromNir::emit_load_input(nir_intrinsic_instr* instr)
|
|
|
|
|
{
|
|
|
|
|
unsigned loc = nir_intrinsic_io_semantics(instr).location;
|
|
|
|
|
auto param = nir_src_as_const_value(instr->src[0]);
|
|
|
|
|
assert(param && "Indirect PS inputs not (yet) supported");
|
|
|
|
|
|
|
|
|
|
auto& io = m_shaderio.input(param->u32 + nir_intrinsic_base(instr), nir_intrinsic_component(instr));
|
|
|
|
|
|
|
|
|
|
assert(nir_intrinsic_io_semantics(instr).num_slots == 1);
|
|
|
|
|
|
|
|
|
|
unsigned num_components = nir_dest_num_components(instr->dest);
|
|
|
|
|
|
|
|
|
|
switch (loc) {
|
|
|
|
|
case VARYING_SLOT_POS:
|
|
|
|
|
for (unsigned i = 0; i < num_components; ++i) {
|
|
|
|
|
load_preloaded_value(instr->dest, i, m_frag_pos[i]);
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
case VARYING_SLOT_FACE:
|
|
|
|
|
return load_preloaded_value(instr->dest, 0, m_front_face_reg);
|
|
|
|
|
default:
|
|
|
|
|
;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto dst = nir_intrinsic_component(instr) ? get_temp_vec4() : vec_from_nir(instr->dest, 4);
|
|
|
|
|
|
|
|
|
|
AluInstruction *ir = nullptr;
|
|
|
|
|
for (unsigned i = 0; i < 4 ; ++i) {
|
|
|
|
|
ir = new AluInstruction(op1_interp_load_p0, dst[i],
|
|
|
|
|
PValue(new InlineConstValue(ALU_SRC_PARAM_BASE +
|
|
|
|
|
io.lds_pos(), i)),
|
|
|
|
|
EmitInstruction::write);
|
|
|
|
|
emit_instruction(ir);
|
|
|
|
|
}
|
|
|
|
|
ir->set_flag(alu_last_instr);
|
|
|
|
|
|
|
|
|
|
/* TODO: back color */
|
|
|
|
|
if (m_need_back_color && io.name() == TGSI_SEMANTIC_COLOR) {
|
|
|
|
|
Interpolator ip = {false, 0, NULL, NULL};
|
|
|
|
|
|
|
|
|
|
auto & color_input = static_cast<ShaderInputColor&> (io);
|
|
|
|
|
auto& bgio = m_shaderio.input(color_input.back_color_input_index());
|
|
|
|
|
|
|
|
|
|
bgio.set_gpr(allocate_temp_register());
|
|
|
|
|
|
|
|
|
|
GPRVector bgcol(bgio.gpr(), {0,1,2,3});
|
|
|
|
|
load_interpolated(bgcol, bgio, ip, num_components, 0);
|
|
|
|
|
|
|
|
|
|
load_front_face();
|
|
|
|
|
|
|
|
|
|
AluInstruction *ir = nullptr;
|
|
|
|
|
for (unsigned i = 0; i < 4 ; ++i) {
|
|
|
|
|
ir = new AluInstruction(op3_cnde, dst[i], m_front_face_reg, bgcol[i], dst[i], {alu_write});
|
|
|
|
|
emit_instruction(ir);
|
|
|
|
|
}
|
|
|
|
|
if (ir)
|
|
|
|
|
ir->set_flag(alu_last_instr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (nir_intrinsic_component(instr) != 0) {
|
|
|
|
|
std::cerr << "move in right pos \n";
|
|
|
|
|
for (unsigned i = 0; i < nir_dest_num_components(instr->dest); ++i) {
|
|
|
|
|
ir = new AluInstruction(op1_mov, from_nir(instr->dest, i), dst[i + nir_intrinsic_component(instr)], {alu_write});
|
|
|
|
|
emit_instruction(ir);
|
|
|
|
|
}
|
|
|
|
|
if (ir)
|
|
|
|
|
ir->set_flag(alu_last_instr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void FragmentShaderFromNir::load_front_face()
|
|
|
|
|
{
|
|
|
|
|
assert(m_front_face_reg);
|
|
|
|
@@ -656,7 +1036,7 @@ bool FragmentShaderFromNir::load_interpolated(GPRVector &dest,
|
|
|
|
|
// replace io with ShaderInputVarying
|
|
|
|
|
if (io.interpolate() > 0) {
|
|
|
|
|
|
|
|
|
|
sfn_log << SfnLog::io << "Using Interpolator " << io.ij_index() << "\n";
|
|
|
|
|
sfn_log << SfnLog::io << "Using Interpolator (" << *ip.j << ", " << *ip.i << ")" << "\n";
|
|
|
|
|
|
|
|
|
|
if (num_components == 1) {
|
|
|
|
|
switch (start_comp) {
|
|
|
|
@@ -727,6 +1107,8 @@ bool FragmentShaderFromNir::load_interpolated_two_comp(GPRVector &dest, ShaderIn
|
|
|
|
|
const Interpolator& ip, EAluOp op, int writemask)
|
|
|
|
|
{
|
|
|
|
|
AluInstruction *ir = nullptr;
|
|
|
|
|
assert(ip.j);
|
|
|
|
|
assert(ip.i);
|
|
|
|
|
for (unsigned i = 0; i < 4 ; ++i) {
|
|
|
|
|
ir = new AluInstruction(op, dest[i], i & 1 ? ip.j : ip.i, PValue(new InlineConstValue(ALU_SRC_PARAM_BASE + io.lds_pos(), i)),
|
|
|
|
|
(writemask & (1 << i)) ? EmitInstruction::write : EmitInstruction::empty);
|
|
|
|
|