Path: blob/21.2-virgl/src/compiler/nir/nir_inline_uniforms.c
4546 views
/*1* Copyright © 2020 Advanced Micro Devices, Inc.2*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, sublicense,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 the next11* paragraph) shall be included in all copies or substantial portions of the12* 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 NONINFRINGEMENT. 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 OTHER DEALINGS20* IN THE SOFTWARE.21*/2223/* These passes enable converting uniforms to literals when it's profitable,24* effectively inlining uniform values in the IR. The main benefit is register25* usage decrease leading to better SMT (hyperthreading). It's accomplished26* by targetting uniforms that determine whether a conditional branch is27* taken.28*29* Only uniforms used in if conditions are analyzed.30*31* nir_find_inlinable_uniforms finds uniforms that can be inlined and stores32* that information in shader_info.33*34* nir_inline_uniforms inlines uniform values.35*36* (uniforms must be lowered to load_ubo before calling this)37*/3839#include "compiler/nir/nir_builder.h"4041/* Maximum value in shader_info::inlinable_uniform_dw_offsets[] */42#define MAX_OFFSET (UINT16_MAX * 4)4344static bool45src_only_uses_uniforms(const nir_src *src, struct set **uni_offsets)46{47if (!src->is_ssa)48return false;4950nir_instr *instr = src->ssa->parent_instr;5152switch (instr->type) {53case nir_instr_type_alu: {54/* Return true if all sources return true. */55/* TODO: Swizzles are ignored, so vectors can prevent inlining. */56nir_alu_instr *alu = nir_instr_as_alu(instr);57for (unsigned i = 0; i < nir_op_infos[alu->op].num_inputs; i++) {58if (!src_only_uses_uniforms(&alu->src[i].src, uni_offsets))59return false;60}61return true;62}6364case nir_instr_type_intrinsic: {65nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);66/* Return true if the intrinsic loads from UBO 0 with a constant67* offset.68*/69if (intr->intrinsic == nir_intrinsic_load_ubo &&70nir_src_is_const(intr->src[0]) &&71nir_src_as_uint(intr->src[0]) == 0 &&72nir_src_is_const(intr->src[1]) &&73nir_src_as_uint(intr->src[1]) <= MAX_OFFSET &&74/* TODO: Can't handle vectors and other bit sizes for now. */75/* UBO loads should be scalarized. */76intr->dest.ssa.num_components == 1 &&77intr->dest.ssa.bit_size == 32) {78/* Record the uniform offset. */79if (!*uni_offsets)80*uni_offsets = _mesa_set_create_u32_keys(NULL);8182/* Add 1 because the set doesn't allow NULL keys. */83_mesa_set_add(*uni_offsets,84(void*)(uintptr_t)(nir_src_as_uint(intr->src[1]) + 1));85return true;86}87return false;88}8990case nir_instr_type_load_const:91/* Always return true for constants. */92return true;9394default:95return false;96}97}9899void100nir_find_inlinable_uniforms(nir_shader *shader)101{102struct set *uni_offsets = NULL;103104nir_foreach_function(function, shader) {105if (function->impl) {106foreach_list_typed(nir_cf_node, node, node, &function->impl->body) {107switch (node->type) {108case nir_cf_node_if: {109const nir_src *cond = &nir_cf_node_as_if(node)->condition;110struct set *found_offsets = NULL;111112if (src_only_uses_uniforms(cond, &found_offsets) &&113found_offsets) {114/* All uniforms are lowerable. Save uniform offsets. */115set_foreach(found_offsets, entry) {116if (!uni_offsets)117uni_offsets = _mesa_set_create_u32_keys(NULL);118119_mesa_set_add(uni_offsets, entry->key);120}121}122if (found_offsets)123_mesa_set_destroy(found_offsets, NULL);124break;125}126127case nir_cf_node_loop:128/* TODO: handle loops if we want to unroll them at draw time */129break;130131default:132break;133}134}135}136}137138if (uni_offsets) {139unsigned num = 0;140141set_foreach(uni_offsets, entry) {142/* Subtract 1 because all keys are + 1. */143uint32_t offset = (uintptr_t)entry->key - 1;144assert(offset < MAX_OFFSET);145146if (num < MAX_INLINABLE_UNIFORMS)147shader->info.inlinable_uniform_dw_offsets[num++] = offset / 4;148}149shader->info.num_inlinable_uniforms = num;150_mesa_set_destroy(uni_offsets, NULL);151}152}153154void155nir_inline_uniforms(nir_shader *shader, unsigned num_uniforms,156const uint32_t *uniform_values,157const uint16_t *uniform_dw_offsets)158{159if (!num_uniforms)160return;161162nir_foreach_function(function, shader) {163if (function->impl) {164nir_builder b;165nir_builder_init(&b, function->impl);166nir_foreach_block(block, function->impl) {167nir_foreach_instr_safe(instr, block) {168if (instr->type != nir_instr_type_intrinsic)169continue;170171nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);172173/* Only replace UBO 0 with constant offsets. */174if (intr->intrinsic == nir_intrinsic_load_ubo &&175nir_src_is_const(intr->src[0]) &&176nir_src_as_uint(intr->src[0]) == 0 &&177nir_src_is_const(intr->src[1]) &&178/* TODO: Can't handle vectors and other bit sizes for now. */179/* UBO loads should be scalarized. */180intr->dest.ssa.num_components == 1 &&181intr->dest.ssa.bit_size == 32) {182uint64_t offset = nir_src_as_uint(intr->src[1]);183184for (unsigned i = 0; i < num_uniforms; i++) {185if (offset == uniform_dw_offsets[i] * 4) {186b.cursor = nir_before_instr(&intr->instr);187nir_ssa_def *def = nir_imm_int(&b, uniform_values[i]);188nir_ssa_def_rewrite_uses(&intr->dest.ssa, def);189nir_instr_remove(&intr->instr);190break;191}192}193}194}195}196197nir_metadata_preserve(function->impl, nir_metadata_block_index |198nir_metadata_dominance);199}200}201}202203204