[Mesa-dev] [PATCH 15/28] nir/linker/i965: Lower vulkan_resource_index during linking

Alejandro Piñeiro apinheiro at igalia.com
Mon Oct 22 12:24:37 UTC 2018


From: Neil Roberts <nroberts at igalia.com>

When linking a program using ARB_gl_spirv it now lowers the
vulkan_resource_index intrinsic as an extra pass on the nir shader.
Unlike Vulkan this can be done without waiting for the extra state
from the pipeline layout.

It also adds the call to this lowering on the i965 driver, to avoid a
new two-liner patch.
---
 src/compiler/Makefile.sources                      |   1 +
 src/compiler/glsl/gl_nir.h                         |   4 +
 .../glsl/gl_nir_lower_vulkan_resource_index.c      | 120 +++++++++++++++++++++
 src/compiler/glsl/meson.build                      |   1 +
 src/mesa/drivers/dri/i965/brw_link.cpp             |   2 +
 5 files changed, 128 insertions(+)
 create mode 100644 src/compiler/glsl/gl_nir_lower_vulkan_resource_index.c

diff --git a/src/compiler/Makefile.sources b/src/compiler/Makefile.sources
index b65bb9b80b9..3021bede6cf 100644
--- a/src/compiler/Makefile.sources
+++ b/src/compiler/Makefile.sources
@@ -28,6 +28,7 @@ LIBGLSL_FILES = \
 	glsl/gl_nir_lower_atomics.c \
 	glsl/gl_nir_lower_samplers.c \
 	glsl/gl_nir_lower_samplers_as_deref.c \
+	glsl/gl_nir_lower_vulkan_resource_index.c \
 	glsl/gl_nir_link_atomics.c \
 	glsl/gl_nir_link_uniform_initializers.c \
 	glsl/gl_nir_link_uniforms.c \
diff --git a/src/compiler/glsl/gl_nir.h b/src/compiler/glsl/gl_nir.h
index 59d5f65e659..80f56039952 100644
--- a/src/compiler/glsl/gl_nir.h
+++ b/src/compiler/glsl/gl_nir.h
@@ -30,6 +30,7 @@ extern "C" {
 
 struct nir_shader;
 struct gl_shader_program;
+struct gl_linked_shader;
 
 bool gl_nir_lower_atomics(nir_shader *shader,
                           const struct gl_shader_program *shader_program,
@@ -40,6 +41,9 @@ bool gl_nir_lower_samplers(nir_shader *shader,
 bool gl_nir_lower_samplers_as_deref(nir_shader *shader,
                                     const struct gl_shader_program *shader_program);
 
+bool gl_nir_lower_vulkan_resource_index(nir_shader *shader,
+                                        struct gl_linked_shader *linked_shader);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/src/compiler/glsl/gl_nir_lower_vulkan_resource_index.c b/src/compiler/glsl/gl_nir_lower_vulkan_resource_index.c
new file mode 100644
index 00000000000..92ee3dd707a
--- /dev/null
+++ b/src/compiler/glsl/gl_nir_lower_vulkan_resource_index.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright © 2018 Intel Corporation
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
+ * IN THE SOFTWARE.
+ *
+ * Authors:
+ *    Neil Roberts (nroberts at igalia.com)
+ *
+ */
+
+#include "nir.h"
+#include "gl_nir.h"
+#include "nir_builder.h"
+#include "main/mtypes.h"
+
+/*
+ * This pass lowers the vulkan_resource_index intrinsic to a surface index. It
+ * is intended to be used with GL_ARB_gl_spirv. Unlike Vulkan, in that case it
+ * is not necessary to wait for the complete pipeline state to lower it.
+ */
+
+static unsigned
+find_block_by_binding(struct gl_linked_shader *linked_shader,
+                      unsigned binding)
+{
+   unsigned num_blocks = linked_shader->Program->info.num_ubos;
+   struct gl_uniform_block **blocks = linked_shader->Program->sh.UniformBlocks;
+
+   for (unsigned i = 0; i < num_blocks; i++) {
+      if (blocks[i]->Binding == binding)
+         return i;
+   }
+
+   unreachable("No block found with the given binding");
+}
+
+static bool
+convert_block(nir_block *block,
+              struct gl_linked_shader *linked_shader,
+              nir_builder *b)
+{
+   bool progress = false;
+
+   nir_foreach_instr_safe(instr, block) {
+      if (instr->type != nir_instr_type_intrinsic)
+         continue;
+
+      nir_intrinsic_instr *res_index = nir_instr_as_intrinsic(instr);
+
+      if (res_index->intrinsic != nir_intrinsic_vulkan_resource_index)
+         continue;
+
+      b->cursor = nir_after_instr(instr);
+
+      /* The descriptor set should always be zero for GL */
+      assert(nir_intrinsic_desc_set(res_index) == 0);
+
+      unsigned binding = nir_intrinsic_binding(res_index);
+      unsigned block = find_block_by_binding(linked_shader, binding);
+      nir_ssa_def *surface =
+         nir_iadd(b,
+                  nir_imm_int(b, block),
+                  nir_ssa_for_src(b, res_index->src[0], 1));
+
+      nir_ssa_def_rewrite_uses(&res_index->dest.ssa, nir_src_for_ssa(surface));
+      nir_instr_remove(instr);
+
+      progress = true;
+   }
+
+   return progress;
+}
+
+static bool
+convert_impl(nir_function_impl *impl,
+             struct gl_linked_shader *linked_shader)
+{
+   bool progress = false;
+   nir_builder builder;
+   nir_builder_init(&builder, impl);
+
+   nir_foreach_block(block, impl) {
+      progress |= convert_block(block, linked_shader, &builder);
+   }
+
+   nir_metadata_preserve(impl, nir_metadata_block_index |
+                               nir_metadata_dominance);
+   return progress;
+}
+
+bool
+gl_nir_lower_vulkan_resource_index(nir_shader *shader,
+                                   struct gl_linked_shader *linked_shader)
+{
+   bool progress = false;
+
+   nir_foreach_function(function, shader) {
+      if (function->impl)
+         progress = convert_impl(function->impl, linked_shader) || progress;
+   }
+
+   return progress;
+}
diff --git a/src/compiler/glsl/meson.build b/src/compiler/glsl/meson.build
index 71b4c42e4d7..df43dccd345 100644
--- a/src/compiler/glsl/meson.build
+++ b/src/compiler/glsl/meson.build
@@ -69,6 +69,7 @@ files_libglsl = files(
   'gl_nir_lower_atomics.c',
   'gl_nir_lower_samplers.c',
   'gl_nir_lower_samplers_as_deref.c',
+  'gl_nir_lower_vulkan_resource_index.c',
   'gl_nir_link_atomics.c',
   'gl_nir_link_uniform_initializers.c',
   'gl_nir_link_uniforms.c',
diff --git a/src/mesa/drivers/dri/i965/brw_link.cpp b/src/mesa/drivers/dri/i965/brw_link.cpp
index 2cbb1e0b879..37b775637b4 100644
--- a/src/mesa/drivers/dri/i965/brw_link.cpp
+++ b/src/mesa/drivers/dri/i965/brw_link.cpp
@@ -327,6 +327,8 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg)
       NIR_PASS_V(prog->nir, gl_nir_lower_atomics, shProg, false);
       NIR_PASS_V(prog->nir, nir_lower_atomics_to_ssbo,
                  prog->nir->info.num_abos);
+      if (shProg->data->spirv)
+         NIR_PASS_V(prog->nir, gl_nir_lower_vulkan_resource_index, shader);
 
       nir_sweep(prog->nir);
 
-- 
2.14.1



More information about the mesa-dev mailing list