Path: blob/21.2-virgl/src/gallium/drivers/lima/ir/gp/nir.c
4574 views
/*1* Copyright (c) 2017 Lima Project2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* the rights to use, copy, modify, merge, publish, distribute, sub license,7* and/or sell copies of the Software, and to permit persons to whom the8* Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the11* next paragraph) shall be included in all copies or substantial portions12* of the Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER18* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING19* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER20* DEALINGS IN THE SOFTWARE.21*22*/2324#include "util/ralloc.h"25#include "compiler/nir/nir.h"26#include "pipe/p_state.h"272829#include "gpir.h"30#include "lima_context.h"3132gpir_reg *gpir_create_reg(gpir_compiler *comp)33{34gpir_reg *reg = ralloc(comp, gpir_reg);35reg->index = comp->cur_reg++;36list_addtail(®->list, &comp->reg_list);37return reg;38}3940static gpir_reg *reg_for_nir_reg(gpir_compiler *comp, nir_register *nir_reg)41{42unsigned index = nir_reg->index;43gpir_reg *reg = comp->reg_for_reg[index];44if (reg)45return reg;46reg = gpir_create_reg(comp);47comp->reg_for_reg[index] = reg;48return reg;49}5051static void register_node_ssa(gpir_block *block, gpir_node *node, nir_ssa_def *ssa)52{53block->comp->node_for_ssa[ssa->index] = node;54snprintf(node->name, sizeof(node->name), "ssa%d", ssa->index);5556/* If any uses are outside the current block, we'll need to create a57* register and store to it.58*/59bool needs_register = false;60nir_foreach_use(use, ssa) {61if (use->parent_instr->block != ssa->parent_instr->block) {62needs_register = true;63break;64}65}6667if (!needs_register) {68nir_foreach_if_use(use, ssa) {69if (nir_cf_node_prev(&use->parent_if->cf_node) !=70&ssa->parent_instr->block->cf_node) {71needs_register = true;72break;73}74}75}7677if (needs_register) {78gpir_store_node *store = gpir_node_create(block, gpir_op_store_reg);79store->child = node;80store->reg = gpir_create_reg(block->comp);81gpir_node_add_dep(&store->node, node, GPIR_DEP_INPUT);82list_addtail(&store->node.list, &block->node_list);83block->comp->reg_for_ssa[ssa->index] = store->reg;84}85}8687static void register_node_reg(gpir_block *block, gpir_node *node, nir_reg_dest *nir_reg)88{89block->comp->node_for_reg[nir_reg->reg->index] = node;90gpir_store_node *store = gpir_node_create(block, gpir_op_store_reg);9192snprintf(node->name, sizeof(node->name), "reg%d", nir_reg->reg->index);9394store->child = node;95store->reg = reg_for_nir_reg(block->comp, nir_reg->reg);96gpir_node_add_dep(&store->node, node, GPIR_DEP_INPUT);9798list_addtail(&store->node.list, &block->node_list);99}100101/* Register the given gpir_node as providing the given NIR destination, so102* that gpir_node_find() will return it. Also insert any stores necessary if103* the destination will be used after the end of this basic block. The node104* must already be inserted.105*/106static void register_node(gpir_block *block, gpir_node *node, nir_dest *dest)107{108if (dest->is_ssa)109register_node_ssa(block, node, &dest->ssa);110else111register_node_reg(block, node, &dest->reg);112}113114static gpir_node *gpir_node_find(gpir_block *block, nir_src *src,115int channel)116{117gpir_reg *reg = NULL;118gpir_node *pred = NULL;119if (src->is_ssa) {120if (src->ssa->num_components > 1) {121for (int i = 0; i < GPIR_VECTOR_SSA_NUM; i++) {122if (block->comp->vector_ssa[i].ssa == src->ssa->index) {123return block->comp->vector_ssa[i].nodes[channel];124}125}126} else {127gpir_node *pred = block->comp->node_for_ssa[src->ssa->index];128if (pred->block == block)129return pred;130reg = block->comp->reg_for_ssa[src->ssa->index];131}132} else {133pred = block->comp->node_for_reg[src->reg.reg->index];134if (pred && pred->block == block)135return pred;136reg = reg_for_nir_reg(block->comp, src->reg.reg);137}138139assert(reg);140pred = gpir_node_create(block, gpir_op_load_reg);141gpir_load_node *load = gpir_node_to_load(pred);142load->reg = reg;143list_addtail(&pred->list, &block->node_list);144145return pred;146}147148static int nir_to_gpir_opcodes[nir_num_opcodes] = {149/* not supported */150[0 ... nir_last_opcode] = -1,151152[nir_op_fmul] = gpir_op_mul,153[nir_op_fadd] = gpir_op_add,154[nir_op_fneg] = gpir_op_neg,155[nir_op_fmin] = gpir_op_min,156[nir_op_fmax] = gpir_op_max,157[nir_op_frcp] = gpir_op_rcp,158[nir_op_frsq] = gpir_op_rsqrt,159[nir_op_fexp2] = gpir_op_exp2,160[nir_op_flog2] = gpir_op_log2,161[nir_op_slt] = gpir_op_lt,162[nir_op_sge] = gpir_op_ge,163[nir_op_fcsel] = gpir_op_select,164[nir_op_ffloor] = gpir_op_floor,165[nir_op_fsign] = gpir_op_sign,166[nir_op_seq] = gpir_op_eq,167[nir_op_sne] = gpir_op_ne,168[nir_op_fabs] = gpir_op_abs,169};170171static bool gpir_emit_alu(gpir_block *block, nir_instr *ni)172{173nir_alu_instr *instr = nir_instr_as_alu(ni);174175/* gpir_op_mov is useless before the final scheduler, and the scheduler176* currently doesn't expect us to emit it. Just register the destination of177* this instruction with its source. This will also emit any necessary178* register loads/stores for things like "r0 = mov ssa_0" or179* "ssa_0 = mov r0".180*/181if (instr->op == nir_op_mov) {182gpir_node *child = gpir_node_find(block, &instr->src[0].src,183instr->src[0].swizzle[0]);184register_node(block, child, &instr->dest.dest);185return true;186}187188int op = nir_to_gpir_opcodes[instr->op];189190if (op < 0) {191gpir_error("unsupported nir_op: %s\n", nir_op_infos[instr->op].name);192return false;193}194195gpir_alu_node *node = gpir_node_create(block, op);196if (unlikely(!node))197return false;198199unsigned num_child = nir_op_infos[instr->op].num_inputs;200assert(num_child <= ARRAY_SIZE(node->children));201node->num_child = num_child;202203for (int i = 0; i < num_child; i++) {204nir_alu_src *src = instr->src + i;205node->children_negate[i] = src->negate;206207gpir_node *child = gpir_node_find(block, &src->src, src->swizzle[0]);208node->children[i] = child;209210gpir_node_add_dep(&node->node, child, GPIR_DEP_INPUT);211}212213list_addtail(&node->node.list, &block->node_list);214register_node(block, &node->node, &instr->dest.dest);215216return true;217}218219static gpir_node *gpir_create_load(gpir_block *block, nir_dest *dest,220int op, int index, int component)221{222gpir_load_node *load = gpir_node_create(block, op);223if (unlikely(!load))224return NULL;225226load->index = index;227load->component = component;228list_addtail(&load->node.list, &block->node_list);229register_node(block, &load->node, dest);230return &load->node;231}232233static bool gpir_create_vector_load(gpir_block *block, nir_dest *dest, int index)234{235assert(dest->is_ssa);236assert(index < GPIR_VECTOR_SSA_NUM);237238block->comp->vector_ssa[index].ssa = dest->ssa.index;239240for (int i = 0; i < dest->ssa.num_components; i++) {241gpir_node *node = gpir_create_load(block, dest, gpir_op_load_uniform,242block->comp->constant_base + index, i);243if (!node)244return false;245246block->comp->vector_ssa[index].nodes[i] = node;247snprintf(node->name, sizeof(node->name), "ssa%d.%c", dest->ssa.index, "xyzw"[i]);248}249250return true;251}252253static bool gpir_emit_intrinsic(gpir_block *block, nir_instr *ni)254{255nir_intrinsic_instr *instr = nir_instr_as_intrinsic(ni);256257switch (instr->intrinsic) {258case nir_intrinsic_load_input:259return gpir_create_load(block, &instr->dest,260gpir_op_load_attribute,261nir_intrinsic_base(instr),262nir_intrinsic_component(instr)) != NULL;263case nir_intrinsic_load_uniform:264{265int offset = nir_intrinsic_base(instr);266offset += (int)nir_src_as_float(instr->src[0]);267268return gpir_create_load(block, &instr->dest,269gpir_op_load_uniform,270offset / 4, offset % 4) != NULL;271}272case nir_intrinsic_load_viewport_scale:273return gpir_create_vector_load(block, &instr->dest, GPIR_VECTOR_SSA_VIEWPORT_SCALE);274case nir_intrinsic_load_viewport_offset:275return gpir_create_vector_load(block, &instr->dest, GPIR_VECTOR_SSA_VIEWPORT_OFFSET);276case nir_intrinsic_store_output:277{278gpir_store_node *store = gpir_node_create(block, gpir_op_store_varying);279if (unlikely(!store))280return false;281gpir_node *child = gpir_node_find(block, instr->src, 0);282store->child = child;283store->index = nir_intrinsic_base(instr);284store->component = nir_intrinsic_component(instr);285286gpir_node_add_dep(&store->node, child, GPIR_DEP_INPUT);287list_addtail(&store->node.list, &block->node_list);288289return true;290}291default:292gpir_error("unsupported nir_intrinsic_instr %s\n",293nir_intrinsic_infos[instr->intrinsic].name);294return false;295}296}297298static bool gpir_emit_load_const(gpir_block *block, nir_instr *ni)299{300nir_load_const_instr *instr = nir_instr_as_load_const(ni);301gpir_const_node *node = gpir_node_create(block, gpir_op_const);302if (unlikely(!node))303return false;304305assert(instr->def.bit_size == 32);306assert(instr->def.num_components == 1);307308node->value.i = instr->value[0].i32;309310list_addtail(&node->node.list, &block->node_list);311register_node_ssa(block, &node->node, &instr->def);312return true;313}314315static bool gpir_emit_ssa_undef(gpir_block *block, nir_instr *ni)316{317gpir_error("nir_ssa_undef_instr not support\n");318return false;319}320321static bool gpir_emit_tex(gpir_block *block, nir_instr *ni)322{323gpir_error("nir_jump_instr not support\n");324return false;325}326327static bool gpir_emit_jump(gpir_block *block, nir_instr *ni)328{329/* Jumps are emitted at the end of the basic block, so do nothing. */330return true;331}332333static bool (*gpir_emit_instr[nir_instr_type_phi])(gpir_block *, nir_instr *) = {334[nir_instr_type_alu] = gpir_emit_alu,335[nir_instr_type_intrinsic] = gpir_emit_intrinsic,336[nir_instr_type_load_const] = gpir_emit_load_const,337[nir_instr_type_ssa_undef] = gpir_emit_ssa_undef,338[nir_instr_type_tex] = gpir_emit_tex,339[nir_instr_type_jump] = gpir_emit_jump,340};341342static bool gpir_emit_function(gpir_compiler *comp, nir_function_impl *impl)343{344nir_index_blocks(impl);345comp->blocks = ralloc_array(comp, gpir_block *, impl->num_blocks);346347nir_foreach_block(block_nir, impl) {348gpir_block *block = ralloc(comp, gpir_block);349if (!block)350return false;351352list_inithead(&block->node_list);353list_inithead(&block->instr_list);354355list_addtail(&block->list, &comp->block_list);356block->comp = comp;357comp->blocks[block_nir->index] = block;358}359360nir_foreach_block(block_nir, impl) {361gpir_block *block = comp->blocks[block_nir->index];362nir_foreach_instr(instr, block_nir) {363assert(instr->type < nir_instr_type_phi);364if (!gpir_emit_instr[instr->type](block, instr))365return false;366}367368if (block_nir->successors[0] == impl->end_block)369block->successors[0] = NULL;370else371block->successors[0] = comp->blocks[block_nir->successors[0]->index];372block->successors[1] = NULL;373374if (block_nir->successors[1] != NULL) {375nir_if *nif = nir_cf_node_as_if(nir_cf_node_next(&block_nir->cf_node));376gpir_alu_node *cond = gpir_node_create(block, gpir_op_not);377cond->children[0] = gpir_node_find(block, &nif->condition, 0);378379gpir_node_add_dep(&cond->node, cond->children[0], GPIR_DEP_INPUT);380list_addtail(&cond->node.list, &block->node_list);381382gpir_branch_node *branch = gpir_node_create(block, gpir_op_branch_cond);383list_addtail(&branch->node.list, &block->node_list);384385branch->dest = comp->blocks[block_nir->successors[1]->index];386block->successors[1] = branch->dest;387388branch->cond = &cond->node;389gpir_node_add_dep(&branch->node, &cond->node, GPIR_DEP_INPUT);390391assert(block_nir->successors[0]->index == block_nir->index + 1);392} else if (block_nir->successors[0]->index != block_nir->index + 1) {393gpir_branch_node *branch = gpir_node_create(block, gpir_op_branch_uncond);394list_addtail(&branch->node.list, &block->node_list);395396branch->dest = comp->blocks[block_nir->successors[0]->index];397}398}399400return true;401}402403static gpir_compiler *gpir_compiler_create(void *prog, unsigned num_reg, unsigned num_ssa)404{405gpir_compiler *comp = rzalloc(prog, gpir_compiler);406407list_inithead(&comp->block_list);408list_inithead(&comp->reg_list);409410for (int i = 0; i < GPIR_VECTOR_SSA_NUM; i++)411comp->vector_ssa[i].ssa = -1;412413comp->node_for_ssa = rzalloc_array(comp, gpir_node *, num_ssa);414comp->node_for_reg = rzalloc_array(comp, gpir_node *, num_reg);415comp->reg_for_ssa = rzalloc_array(comp, gpir_reg *, num_ssa);416comp->reg_for_reg = rzalloc_array(comp, gpir_reg *, num_reg);417comp->prog = prog;418return comp;419}420421static int gpir_glsl_type_size(enum glsl_base_type type)422{423/* only support GLSL_TYPE_FLOAT */424assert(type == GLSL_TYPE_FLOAT);425return 4;426}427428static void gpir_print_shader_db(struct nir_shader *nir, gpir_compiler *comp,429struct pipe_debug_callback *debug)430{431const struct shader_info *info = &nir->info;432char *shaderdb;433ASSERTED int ret = asprintf(&shaderdb,434"%s shader: %d inst, %d loops, %d:%d spills:fills\n",435gl_shader_stage_name(info->stage),436comp->num_instr,437comp->num_loops,438comp->num_spills,439comp->num_fills);440assert(ret >= 0);441442if (lima_debug & LIMA_DEBUG_SHADERDB)443fprintf(stderr, "SHADER-DB: %s\n", shaderdb);444445pipe_debug_message(debug, SHADER_INFO, "%s", shaderdb);446free(shaderdb);447}448449bool gpir_compile_nir(struct lima_vs_compiled_shader *prog, struct nir_shader *nir,450struct pipe_debug_callback *debug)451{452nir_function_impl *func = nir_shader_get_entrypoint(nir);453gpir_compiler *comp = gpir_compiler_create(prog, func->reg_alloc, func->ssa_alloc);454if (!comp)455return false;456457comp->constant_base = nir->num_uniforms;458prog->state.uniform_size = nir->num_uniforms * 16;459prog->state.gl_pos_idx = 0;460prog->state.point_size_idx = -1;461462if (!gpir_emit_function(comp, func))463goto err_out0;464465gpir_node_print_prog_seq(comp);466gpir_node_print_prog_dep(comp);467468/* increase for viewport uniforms */469comp->constant_base += GPIR_VECTOR_SSA_NUM;470471if (!gpir_optimize(comp))472goto err_out0;473474if (!gpir_pre_rsched_lower_prog(comp))475goto err_out0;476477if (!gpir_reduce_reg_pressure_schedule_prog(comp))478goto err_out0;479480if (!gpir_regalloc_prog(comp))481goto err_out0;482483if (!gpir_schedule_prog(comp))484goto err_out0;485486if (!gpir_codegen_prog(comp))487goto err_out0;488489/* initialize to support accumulating below */490nir_foreach_shader_out_variable(var, nir) {491struct lima_varying_info *v = prog->state.varying + var->data.driver_location;492v->components = 0;493}494495nir_foreach_shader_out_variable(var, nir) {496bool varying = true;497switch (var->data.location) {498case VARYING_SLOT_POS:499prog->state.gl_pos_idx = var->data.driver_location;500varying = false;501break;502case VARYING_SLOT_PSIZ:503prog->state.point_size_idx = var->data.driver_location;504varying = false;505break;506}507508struct lima_varying_info *v = prog->state.varying + var->data.driver_location;509if (!v->components) {510v->component_size = gpir_glsl_type_size(glsl_get_base_type(var->type));511prog->state.num_outputs++;512if (varying)513prog->state.num_varyings++;514}515516v->components += glsl_get_components(var->type);517}518519gpir_print_shader_db(nir, comp, debug);520521ralloc_free(comp);522return true;523524err_out0:525ralloc_free(comp);526return false;527}528529530531