i965: Use NIR to lower legacy userclipping.
[mesa.git] / src / mesa / drivers / dri / i965 / brw_nir_uniforms.cpp
index e5f97b647afc14573e8420b4cd524cead2e8b47a..2ea316e7420b329ee74f575af060a13f900083d8 100644 (file)
@@ -395,3 +395,59 @@ brw_nir_lower_gl_images(nir_shader *shader,
       }
    }
 }
+
+void
+brw_nir_lower_legacy_clipping(nir_shader *nir, int nr_userclip_plane_consts,
+                              struct brw_stage_prog_data *prog_data)
+{
+   if (nr_userclip_plane_consts == 0)
+      return;
+
+   nir_function_impl *impl = nir_shader_get_entrypoint(nir);
+
+   nir_lower_clip_vs(nir, (1 << nr_userclip_plane_consts) - 1, true);
+   nir_lower_io_to_temporaries(nir, impl, true, false);
+   nir_lower_global_vars_to_local(nir);
+   nir_lower_vars_to_ssa(nir);
+
+   const unsigned clip_plane_base = nir->num_uniforms;
+
+   assert(nir->num_uniforms == prog_data->nr_params * 4);
+   const unsigned num_clip_floats = 4 * nr_userclip_plane_consts;
+   uint32_t *clip_param =
+      brw_stage_prog_data_add_params(prog_data, num_clip_floats);
+   nir->num_uniforms += num_clip_floats * sizeof(float);
+   assert(nir->num_uniforms == prog_data->nr_params * 4);
+
+   for (unsigned i = 0; i < num_clip_floats; i++)
+      clip_param[i] = BRW_PARAM_BUILTIN_CLIP_PLANE(i / 4, i % 4);
+
+   nir_builder b;
+   nir_builder_init(&b, impl);
+   nir_foreach_block(block, impl) {
+      nir_foreach_instr_safe(instr, block) {
+         if (instr->type != nir_instr_type_intrinsic)
+            continue;
+
+         nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);
+         if (intrin->intrinsic != nir_intrinsic_load_user_clip_plane)
+            continue;
+
+         b.cursor = nir_before_instr(instr);
+
+         nir_intrinsic_instr *load =
+            nir_intrinsic_instr_create(nir, nir_intrinsic_load_uniform);
+         load->num_components = 4;
+         load->src[0] = nir_src_for_ssa(nir_imm_int(&b, 0));
+         nir_ssa_dest_init(&load->instr, &load->dest, 4, 32, NULL);
+         nir_intrinsic_set_base(load, clip_plane_base + 4 * sizeof(float) *
+                                      nir_intrinsic_ucp_id(intrin));
+         nir_intrinsic_set_range(load, 4 * sizeof(float));
+         nir_builder_instr_insert(&b, &load->instr);
+
+         nir_ssa_def_rewrite_uses(&intrin->dest.ssa,
+                                  nir_src_for_ssa(&load->dest.ssa));
+         nir_instr_remove(instr);
+      }
+   }
+}