Path: blob/21.2-virgl/src/compiler/glsl/gl_nir_lower_atomics.c
4545 views
/*1* Copyright © 2014 Intel Corporation2*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*22* Authors:23* Connor Abbott ([email protected])24*25*/2627#include "compiler/nir/nir.h"28#include "compiler/nir/nir_builder.h"29#include "gl_nir.h"30#include "ir_uniform.h"31#include "main/config.h"32#include "main/mtypes.h"33#include <assert.h>3435/*36* replace atomic counter intrinsics that use a variable with intrinsics37* that directly store the buffer index and byte offset38*/3940static bool41lower_deref_instr(nir_builder *b, nir_intrinsic_instr *instr,42const struct gl_shader_program *shader_program,43nir_shader *shader, bool use_binding_as_idx)44{45nir_intrinsic_op op;46switch (instr->intrinsic) {47case nir_intrinsic_atomic_counter_read_deref:48op = nir_intrinsic_atomic_counter_read;49break;5051case nir_intrinsic_atomic_counter_inc_deref:52op = nir_intrinsic_atomic_counter_inc;53break;5455case nir_intrinsic_atomic_counter_pre_dec_deref:56op = nir_intrinsic_atomic_counter_pre_dec;57break;5859case nir_intrinsic_atomic_counter_post_dec_deref:60op = nir_intrinsic_atomic_counter_post_dec;61break;6263case nir_intrinsic_atomic_counter_add_deref:64op = nir_intrinsic_atomic_counter_add;65break;6667case nir_intrinsic_atomic_counter_min_deref:68op = nir_intrinsic_atomic_counter_min;69break;7071case nir_intrinsic_atomic_counter_max_deref:72op = nir_intrinsic_atomic_counter_max;73break;7475case nir_intrinsic_atomic_counter_and_deref:76op = nir_intrinsic_atomic_counter_and;77break;7879case nir_intrinsic_atomic_counter_or_deref:80op = nir_intrinsic_atomic_counter_or;81break;8283case nir_intrinsic_atomic_counter_xor_deref:84op = nir_intrinsic_atomic_counter_xor;85break;8687case nir_intrinsic_atomic_counter_exchange_deref:88op = nir_intrinsic_atomic_counter_exchange;89break;9091case nir_intrinsic_atomic_counter_comp_swap_deref:92op = nir_intrinsic_atomic_counter_comp_swap;93break;9495default:96return false;97}9899nir_deref_instr *deref = nir_src_as_deref(instr->src[0]);100nir_variable *var = nir_deref_instr_get_variable(deref);101102if (var->data.mode != nir_var_uniform &&103var->data.mode != nir_var_mem_ssbo &&104var->data.mode != nir_var_mem_shared)105return false; /* atomics passed as function arguments can't be lowered */106107const unsigned uniform_loc = var->data.location;108const unsigned idx = use_binding_as_idx ? var->data.binding :109shader_program->data->UniformStorage[uniform_loc].opaque[shader->info.stage].index;110111b->cursor = nir_before_instr(&instr->instr);112113nir_ssa_def *offset = nir_imm_int(b, var->data.offset);114for (nir_deref_instr *d = deref; d->deref_type != nir_deref_type_var;115d = nir_deref_instr_parent(d)) {116assert(d->deref_type == nir_deref_type_array);117assert(d->arr.index.is_ssa);118119unsigned array_stride = ATOMIC_COUNTER_SIZE;120if (glsl_type_is_array(d->type))121array_stride *= glsl_get_aoa_size(d->type);122123offset = nir_iadd(b, offset, nir_imul(b, d->arr.index.ssa,124nir_imm_int(b, array_stride)));125}126127/* Since the first source is a deref and the first source in the lowered128* instruction is the offset, we can just swap it out and change the129* opcode.130*/131instr->intrinsic = op;132nir_instr_rewrite_src(&instr->instr, &instr->src[0],133nir_src_for_ssa(offset));134nir_intrinsic_set_base(instr, idx);135136nir_deref_instr_remove_if_unused(deref);137138return true;139}140141bool142gl_nir_lower_atomics(nir_shader *shader,143const struct gl_shader_program *shader_program,144bool use_binding_as_idx)145{146bool progress = false;147148nir_foreach_function(function, shader) {149if (!function->impl)150continue;151152bool impl_progress = false;153154nir_builder build;155nir_builder_init(&build, function->impl);156157nir_foreach_block(block, function->impl) {158nir_foreach_instr_safe(instr, block) {159if (instr->type != nir_instr_type_intrinsic)160continue;161162impl_progress |= lower_deref_instr(&build,163nir_instr_as_intrinsic(instr),164shader_program, shader,165use_binding_as_idx);166}167}168169if (impl_progress) {170nir_metadata_preserve(function->impl, nir_metadata_block_index |171nir_metadata_dominance);172progress = true;173}174}175176return progress;177}178179180