spirv_to_dxil: Add support for non-zero vertex and instance indices
authorEnrico Galli <enrico.galli@intel.com>
Thu, 2 Sep 2021 20:22:57 +0000 (13:22 -0700)
committerMarge Bot <eric+marge@anholt.net>
Fri, 3 Sep 2021 16:21:03 +0000 (16:21 +0000)
Since DXIL does not have a way to get the base/first vertex and base
instance as well as using a zero-based vertex index, these values need
to be passed in via a constant buffer.

Reviewed-by: Jesse Natalie <jenatali@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12707>

src/microsoft/spirv_to_dxil/spirv_to_dxil.c
src/microsoft/spirv_to_dxil/spirv_to_dxil.h

index 1fadf30eef94ef7bb4c9e2e0fcde38e66bbd2ea9..1c392e2d3eac0f63ac77217a6ded050ea88ee519 100644 (file)
@@ -45,10 +45,14 @@ shared_var_info(const struct glsl_type* type, unsigned* size, unsigned* align)
 static nir_variable *
 add_runtime_data_var(nir_shader *nir, unsigned desc_set, unsigned binding)
 {
-   const struct glsl_type *array_type = glsl_array_type(
-      glsl_uint_type(),
-      sizeof(struct dxil_spirv_compute_runtime_data) / sizeof(unsigned),
-      sizeof(unsigned));
+   unsigned runtime_data_size =
+      nir->info.stage == MESA_SHADER_COMPUTE
+         ? sizeof(struct dxil_spirv_compute_runtime_data)
+         : sizeof(struct dxil_spirv_vertex_runtime_data);
+
+   const struct glsl_type *array_type =
+      glsl_array_type(glsl_uint_type(), runtime_data_size / sizeof(unsigned),
+                      sizeof(unsigned));
    const struct glsl_struct_field field = {array_type, "arr"};
    nir_variable *var = nir_variable_create(
       nir, nir_var_mem_ubo,
@@ -89,6 +93,16 @@ lower_shader_system_values(struct nir_builder *builder, nir_instr *instr,
       offset =
          offsetof(struct dxil_spirv_compute_runtime_data, group_count_x);
       break;
+   case nir_intrinsic_load_first_vertex:
+      offset = offsetof(struct dxil_spirv_vertex_runtime_data, first_vertex);
+      break;
+   case nir_intrinsic_load_is_indexed_draw:
+      offset =
+         offsetof(struct dxil_spirv_vertex_runtime_data, is_indexed_draw);
+      break;
+   case nir_intrinsic_load_base_instance:
+      offset = offsetof(struct dxil_spirv_vertex_runtime_data, base_instance);
+      break;
    default:
       return false;
    }
@@ -164,8 +178,9 @@ spirv_to_dxil(const uint32_t *words, size_t word_count,
    glsl_type_singleton_init_or_ref();
 
    struct nir_shader_compiler_options nir_options = *dxil_get_nir_compiler_options();
-   // We will manually handle base_vertex
-   nir_options.lower_base_vertex = false;
+   // We will manually handle base_vertex when vertex_id and instance_id have
+   // have been already converted to zero-base.
+   nir_options.lower_base_vertex = !conf->zero_based_vertex_instance_id;
 
    nir_shader *nir = spirv_to_nir(
       words, word_count, (struct nir_spirv_specialization *)specializations,
@@ -181,15 +196,16 @@ spirv_to_dxil(const uint32_t *words, size_t word_count,
 
    NIR_PASS_V(nir, nir_lower_system_values);
 
-   // vertex_id and instance_id should have already been transformed to base
-   //  zero before spirv_to_dxil was called. Also, WebGPU does not support
-   //  base/firstVertex/Instance.
-   gl_system_value system_values[] = {
-      SYSTEM_VALUE_FIRST_VERTEX,
-      SYSTEM_VALUE_BASE_VERTEX,
-      SYSTEM_VALUE_BASE_INSTANCE
-   };
-   NIR_PASS_V(nir, dxil_nir_lower_system_values_to_zero, system_values, ARRAY_SIZE(system_values));
+   if (conf->zero_based_vertex_instance_id) {
+      // vertex_id and instance_id should have already been transformed to
+      // base zero before spirv_to_dxil was called. Therefore, we can zero out
+      // base/firstVertex/Instance.
+      gl_system_value system_values[] = {SYSTEM_VALUE_FIRST_VERTEX,
+                                         SYSTEM_VALUE_BASE_VERTEX,
+                                         SYSTEM_VALUE_BASE_INSTANCE};
+      NIR_PASS_V(nir, dxil_nir_lower_system_values_to_zero, system_values,
+                 ARRAY_SIZE(system_values));
+   }
 
    bool requires_runtime_data = false;
    NIR_PASS(requires_runtime_data, nir,
index 7e16288d7988abcd6927ffeb44601bb76c3567e5..4bf7c3e3870f2c096827229eb434f6522e0942b2 100644 (file)
@@ -90,11 +90,23 @@ struct dxil_spirv_compute_runtime_data {
    uint32_t group_count_z;
 };
 
+/* This struct describes the layout of data expected in the CB bound to
+ * runtime_data_cbv during vertex stages */
+struct dxil_spirv_vertex_runtime_data {
+   uint32_t first_vertex;
+   uint32_t base_instance;
+   bool is_indexed_draw;
+};
+
 struct dxil_spirv_runtime_conf {
    struct {
       uint32_t register_space;
       uint32_t base_shader_register;
    } runtime_data_cbv;
+
+   // Set true if vertex and instance ids have already been converted to
+   // zero-based. Otherwise, runtime_data will be required to lower them.
+   bool zero_based_vertex_instance_id;
 };
 
 /**