About Social Code
aboutsummaryrefslogtreecommitdiff
path: root/src/compiler/nir/nir_fixup_is_exported.c
blob: ed21b88481cd28b2f348797ed1301ae6ccfc0324 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/*
 * Copyright 2024 Valve Corporation
 * SPDX-License-Identifier: MIT
 */

#include "nir.h"

/*
 * After going through the clang -> LLVM -> SPIR-V translator -> vtn pipes,
 * OpenCL kernel's end up translated to 2 nir_functions:
 *
 * - a "wrapper" function that is_entrypoint but not is_exported
 * - the "real" function that is_exported
 *
 * Confusingly, both functions have the same name.
 *
 * Also, workgroup size information is on the wrapper function only, so we can't
 * just ignore the wrappers. But inlining and removing non-exported would delete
 * the whole shader and lose that information.
 *
 * This pass is a silly solution to the silly problem: it looks for shadowed
 * function names, which can only come from these wrappers. It then exports the
 * wrappers and unexports the inner functions. After inlining and removing
 * non-exported functions, we're left with a single function per kernel with
 * workgroup size information preserved.
 *
 * While we're at it, we unexport _prefixed functions. This is an escape hatch
 * to allow defining `kernel`s that are not intended for export, to workaround
 * OpenCL limitations around `static kernel`s and shared local memory outside
 * `kernel`s.
 */
void
nir_fixup_is_exported(nir_shader *nir)
{
   struct set *seen =
      _mesa_set_create(NULL, _mesa_hash_string, _mesa_key_string_equal);
   struct set *shadowed =
      _mesa_set_create(NULL, _mesa_hash_string, _mesa_key_string_equal);

   nir_foreach_function(func, nir) {
      if (_mesa_set_search(seen, func->name)) {
         _mesa_set_add(shadowed, func->name);
      } else {
         _mesa_set_add(seen, func->name);
      }
   }

   nir_foreach_function(func, nir) {
      if (_mesa_set_search(shadowed, func->name)) {
         func->is_exported = func->is_entrypoint;
      }

      if (func->name[0] == '_') {
         func->is_exported = func->is_entrypoint = false;
      }
   }

   _mesa_set_destroy(seen, NULL);
   _mesa_set_destroy(shadowed, NULL);
}