Path: blob/21.2-virgl/src/compiler/spirv/nir_lower_libclc.c
4545 views
/*1* Copyright © 2019 Red Hat2*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*/2324/* Pass to find libclc functions from a clc library shader and inline25* them into a user shader.26* This pass should only be called once, but it also has to iterate27* itself to make sure all instances are lowered, before validation.28*/29#include "nir.h"30#include "nir_builder.h"31#include "nir_spirv.h"3233static bool34lower_clc_call_instr(nir_instr *instr, nir_builder *b,35const nir_shader *clc_shader,36struct hash_table *copy_vars)37{38nir_call_instr *call = nir_instr_as_call(instr);39nir_function *func = NULL;40nir_foreach_function(function, clc_shader) {41if (strcmp(function->name, call->callee->name) == 0) {42func = function;43break;44}45}46if (!func || !func->impl) {47return false;48}4950nir_ssa_def **params = rzalloc_array(b->shader, nir_ssa_def*, call->num_params);5152for (unsigned i = 0; i < call->num_params; i++) {53params[i] = nir_ssa_for_src(b, call->params[i],54call->callee->params[i].num_components);55}5657b->cursor = nir_instr_remove(&call->instr);58nir_inline_function_impl(b, func->impl, params, copy_vars);5960ralloc_free(params);6162return true;63}6465static bool66nir_lower_libclc_impl(nir_function_impl *impl,67const nir_shader *clc_shader,68struct hash_table *copy_vars)69{70nir_builder b;71nir_builder_init(&b, impl);7273bool progress = false;74nir_foreach_block_safe(block, impl) {75nir_foreach_instr_safe(instr, block) {76if (instr->type == nir_instr_type_call)77progress |= lower_clc_call_instr(instr, &b, clc_shader, copy_vars);78}79}8081if (progress) {82nir_index_ssa_defs(impl);83nir_index_local_regs(impl);84nir_metadata_preserve(impl, nir_metadata_none);85} else {86nir_metadata_preserve(impl, nir_metadata_all);87}8889return progress;90}9192bool93nir_lower_libclc(nir_shader *shader,94const nir_shader *clc_shader)95{96void *ra_ctx = ralloc_context(NULL);97struct hash_table *copy_vars = _mesa_pointer_hash_table_create(ra_ctx);98bool progress = false, overall_progress = false;99100/* do progress passes inside the pass */101do {102progress = false;103nir_foreach_function(function, shader) {104if (function->impl)105progress |= nir_lower_libclc_impl(function->impl, clc_shader, copy_vars);106}107overall_progress |= progress;108} while (progress);109110ralloc_free(ra_ctx);111112return overall_progress;113}114115116