• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2024 Valve Corporation
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "nir.h"
7 
8 /*
9  * After going through the clang -> LLVM -> SPIR-V translator -> vtn pipes,
10  * OpenCL kernel's end up translated to 2 nir_functions:
11  *
12  * - a "wrapper" function that is_entrypoint but not is_exported
13  * - the "real" function that is_exported
14  *
15  * Confusingly, both functions have the same name.
16  *
17  * Also, workgroup size information is on the wrapper function only, so we can't
18  * just ignore the wrappers. But inlining and removing non-exported would delete
19  * the whole shader and lose that information.
20  *
21  * This pass is a silly solution to the silly problem: it looks for shadowed
22  * function names, which can only come from these wrappers. It then exports the
23  * wrappers and unexports the inner functions. After inlining and removing
24  * non-exported functions, we're left with a single function per kernel with
25  * workgroup size information preserved.
26  *
27  * While we're at it, we unexport _prefixed functions. This is an escape hatch
28  * to allow defining `kernel`s that are not intended for export, to workaround
29  * OpenCL limitations around `static kernel`s and shared local memory outside
30  * `kernel`s.
31  */
32 void
nir_fixup_is_exported(nir_shader * nir)33 nir_fixup_is_exported(nir_shader *nir)
34 {
35    struct set *seen =
36       _mesa_set_create(NULL, _mesa_hash_string, _mesa_key_string_equal);
37    struct set *shadowed =
38       _mesa_set_create(NULL, _mesa_hash_string, _mesa_key_string_equal);
39 
40    nir_foreach_function(func, nir) {
41       if (_mesa_set_search(seen, func->name)) {
42          _mesa_set_add(shadowed, func->name);
43       } else {
44          _mesa_set_add(seen, func->name);
45       }
46    }
47 
48    nir_foreach_function(func, nir) {
49       if (_mesa_set_search(shadowed, func->name)) {
50          func->is_exported = func->is_entrypoint;
51       }
52 
53       if (func->name[0] == '_') {
54          func->is_exported = func->is_entrypoint = false;
55       }
56    }
57 
58    _mesa_set_destroy(seen, NULL);
59    _mesa_set_destroy(shadowed, NULL);
60 }
61