#include "sfn_shader_tcs.h" #include "sfn_instruction_gds.h" #include "tgsi/tgsi_from_mesa.h" namespace r600 { TcsShaderFromNir::TcsShaderFromNir(r600_pipe_shader *sh, r600_pipe_shader_selector& sel, const r600_shader_key& key, enum chip_class chip_class): ShaderFromNirProcessor (PIPE_SHADER_TESS_CTRL, sel, sh->shader, sh->scratch_space_needed, chip_class, key.tcs.first_atomic_counter), m_reserved_registers(0) { sh_info().tcs_prim_mode = key.tcs.prim_mode; } bool TcsShaderFromNir::scan_sysvalue_access(nir_instr *instr) { if (instr->type != nir_instr_type_intrinsic) return true; auto intr = nir_instr_as_intrinsic(instr); switch (intr->intrinsic) { case nir_intrinsic_load_primitive_id: m_sv_values.set(es_primitive_id); break; case nir_intrinsic_load_invocation_id: m_sv_values.set(es_invocation_id); break; case nir_intrinsic_load_tcs_rel_patch_id_r600: m_sv_values.set(es_rel_patch_id); break; case nir_intrinsic_load_tcs_tess_factor_base_r600: m_sv_values.set(es_tess_factor_base); break; default: ; } return true; } bool TcsShaderFromNir::do_allocate_reserved_registers() { if (m_sv_values.test(es_primitive_id)) { m_reserved_registers = 1; auto gpr = new GPRValue(0,0); gpr->set_as_input(); m_primitive_id.reset(gpr); } if (m_sv_values.test(es_invocation_id)) { m_reserved_registers = 1; auto gpr = new GPRValue(0,2); gpr->set_as_input(); m_invocation_id.reset(gpr); } if (m_sv_values.test(es_rel_patch_id)) { m_reserved_registers = 1; auto gpr = new GPRValue(0,1); gpr->set_as_input(); m_rel_patch_id.reset(gpr); } if (m_sv_values.test(es_tess_factor_base)) { m_reserved_registers = 1; auto gpr = new GPRValue(0,3); gpr->set_as_input(); m_tess_factor_base.reset(gpr); } set_reserved_registers(m_reserved_registers); return true; } bool TcsShaderFromNir::emit_intrinsic_instruction_override(nir_intrinsic_instr* instr) { switch (instr->intrinsic) { case nir_intrinsic_load_tcs_rel_patch_id_r600: return load_preloaded_value(instr->dest, 0, m_rel_patch_id); case nir_intrinsic_load_invocation_id: return load_preloaded_value(instr->dest, 0, m_invocation_id); case nir_intrinsic_load_primitive_id: return load_preloaded_value(instr->dest, 0, m_primitive_id); case nir_intrinsic_load_tcs_tess_factor_base_r600: return load_preloaded_value(instr->dest, 0, m_tess_factor_base); case nir_intrinsic_store_tf_r600: return store_tess_factor(instr); default: return false; } } bool TcsShaderFromNir::store_tess_factor(nir_intrinsic_instr* instr) { const GPRVector::Swizzle& swizzle = (instr->src[0].ssa->num_components == 4) ? GPRVector::Swizzle({0, 1, 2, 3}) : GPRVector::Swizzle({0, 1, 7, 7}); auto val = vec_from_nir_with_fetch_constant(instr->src[0], (1 << instr->src[0].ssa->num_components) - 1, swizzle); emit_instruction(new GDSStoreTessFactor(val)); return true; } }