From bcf50b75329891dcfe257c9ce7f2c912d14c6398 Mon Sep 17 00:00:00 2001 From: Jesse Natalie Date: Mon, 3 Apr 2023 15:17:45 -0700 Subject: [PATCH] dzn: Add a helper to generate triangle->point GS Part-of: --- src/microsoft/vulkan/dzn_nir.c | 151 +++++++++++++++++++++++++++++++++++++++++ src/microsoft/vulkan/dzn_nir.h | 3 + 2 files changed, 154 insertions(+) diff --git a/src/microsoft/vulkan/dzn_nir.c b/src/microsoft/vulkan/dzn_nir.c index 9c15262..0c2b316 100644 --- a/src/microsoft/vulkan/dzn_nir.c +++ b/src/microsoft/vulkan/dzn_nir.c @@ -26,6 +26,7 @@ #include "spirv_to_dxil.h" #include "nir_to_dxil.h" #include "nir_builder.h" +#include "nir_builtin_builder.h" #include "nir_vulkan.h" static nir_ssa_def * @@ -748,3 +749,153 @@ dzn_nir_blit_fs(const struct dzn_nir_blit_info *info) return b.shader; } + +static nir_ssa_def * +cull_face(nir_builder *b, nir_variable *vertices, bool ccw) +{ + nir_ssa_def *v0 = + nir_load_deref(b, nir_build_deref_array(b, nir_build_deref_var(b, vertices), nir_imm_int(b, 0))); + nir_ssa_def *v1 = + nir_load_deref(b, nir_build_deref_array(b, nir_build_deref_var(b, vertices), nir_imm_int(b, 1))); + nir_ssa_def *v2 = + nir_load_deref(b, nir_build_deref_array(b, nir_build_deref_var(b, vertices), nir_imm_int(b, 2))); + + nir_ssa_def *dir = nir_fdot(b, nir_cross4(b, nir_fsub(b, v1, v0), + nir_fsub(b, v2, v0)), + nir_imm_vec4(b, 0.0, 0.0, -1.0, 0.0)); + if (ccw) + return nir_fge(b, nir_imm_int(b, 0), dir); + else + return nir_flt(b, nir_imm_int(b, 0), dir); +} + +static void +copy_vars(nir_builder *b, nir_deref_instr *dst, nir_deref_instr *src) +{ + assert(glsl_get_bare_type(dst->type) == glsl_get_bare_type(src->type)); + if (glsl_type_is_struct(dst->type)) { + for (unsigned i = 0; i < glsl_get_length(dst->type); ++i) { + copy_vars(b, nir_build_deref_struct(b, dst, i), nir_build_deref_struct(b, src, i)); + } + } else if (glsl_type_is_array_or_matrix(dst->type)) { + copy_vars(b, nir_build_deref_array_wildcard(b, dst), nir_build_deref_array_wildcard(b, src)); + } else { + nir_copy_deref(b, dst, src); + } +} + +nir_shader * +dzn_nir_polygon_point_mode_gs(const nir_shader *previous_shader, unsigned cull_mode, bool front_ccw) +{ + nir_builder builder; + nir_builder *b = &builder; + nir_variable *pos_var = NULL; + + unsigned num_vars = 0; + nir_variable *in[VARYING_SLOT_MAX]; + nir_variable *out[VARYING_SLOT_MAX]; + + + builder = nir_builder_init_simple_shader(MESA_SHADER_GEOMETRY, + dxil_get_nir_compiler_options(), + "implicit_gs"); + + nir_shader *nir = b->shader; + nir->info.inputs_read = nir->info.outputs_written = previous_shader->info.outputs_written; + nir->info.outputs_written |= (1ull << VARYING_SLOT_VAR12); + nir->info.gs.input_primitive = PIPE_PRIM_TRIANGLES; + nir->info.gs.output_primitive = PIPE_PRIM_POINTS; + nir->info.gs.vertices_in = 3; + nir->info.gs.vertices_out = 3; + nir->info.gs.invocations = 1; + nir->info.gs.active_stream_mask = 1; + + nir_foreach_shader_out_variable(var, previous_shader) { + char tmp[100]; + snprintf(tmp, ARRAY_SIZE(tmp), "in_%d", num_vars); + in[num_vars] = nir_variable_create(nir, + nir_var_shader_in, + glsl_array_type(var->type, 3, 0), + tmp); + in[num_vars]->data = var->data; + in[num_vars]->data.mode = nir_var_shader_in; + + if (var->data.location == VARYING_SLOT_POS) + pos_var = in[num_vars]; + + snprintf(tmp, ARRAY_SIZE(tmp), "out_%d", num_vars); + out[num_vars] = nir_variable_create(nir, nir_var_shader_out, var->type, tmp); + out[num_vars]->data = var->data; + + num_vars++; + } + + nir_variable *front_facing_var = nir_variable_create(nir, + nir_var_shader_out, + glsl_uint_type(), + "gl_FrontFacing"); + front_facing_var->data.location = VARYING_SLOT_VAR12; + front_facing_var->data.driver_location = num_vars; + front_facing_var->data.interpolation = INTERP_MODE_FLAT; + + /* Temporary variable "loop_index" to loop over input vertices */ + nir_function_impl *impl = nir_shader_get_entrypoint(nir); + nir_variable *loop_index_var = + nir_local_variable_create(impl, glsl_uint_type(), "loop_index"); + nir_deref_instr *loop_index_deref = nir_build_deref_var(b, loop_index_var); + nir_store_deref(b, loop_index_deref, nir_imm_int(b, 0), 1); + + nir_ssa_def *cull_pass = nir_imm_bool(b, true); + nir_ssa_def *front_facing; + assert(cull_mode != VK_CULL_MODE_FRONT_AND_BACK); + if (cull_mode == VK_CULL_MODE_FRONT_BIT) { + cull_pass = cull_face(b, pos_var, front_ccw); + front_facing = nir_b2i32(b, cull_pass); + } else if (cull_mode == VK_CULL_MODE_BACK_BIT) { + cull_pass = cull_face(b, pos_var, !front_ccw); + front_facing = nir_inot(b, nir_b2i32(b, cull_pass)); + } else + front_facing = nir_i2i32(b, cull_face(b, pos_var, front_ccw)); + + /** + * if (cull_pass) { + * while { + * if (loop_index >= 3) + * break; + */ + nir_if *cull_check = nir_push_if(b, cull_pass); + nir_loop *loop = nir_push_loop(b); + + nir_ssa_def *loop_index = nir_load_deref(b, loop_index_deref); + nir_ssa_def *cmp = nir_ige(b, loop_index, + nir_imm_int(b, 3)); + nir_if *loop_check = nir_push_if(b, cmp); + nir_jump(b, nir_jump_break); + nir_pop_if(b, loop_check); + + /** + * [...] // Copy all variables + * EmitVertex(); + */ + for (unsigned i = 0; i < num_vars; ++i) { + nir_ssa_def *index = loop_index; + nir_deref_instr *in_value = nir_build_deref_array(b, nir_build_deref_var(b, in[i]), index); + copy_vars(b, nir_build_deref_var(b, out[i]), in_value); + } + nir_store_var(b, front_facing_var, front_facing, 0x1); + nir_emit_vertex(b, 0); + + /** + * loop_index++; + * } + * } + */ + nir_store_deref(b, loop_index_deref, nir_iadd_imm(b, loop_index, 1), 1); + nir_pop_loop(b, loop); + nir_pop_if(b, cull_check); + + nir_validate_shader(nir, "in dzn_nir_polygon_point_mode_gs"); + + NIR_PASS_V(nir, nir_lower_var_copies); + return b->shader; +} diff --git a/src/microsoft/vulkan/dzn_nir.h b/src/microsoft/vulkan/dzn_nir.h index a6e4383..881d8e1 100644 --- a/src/microsoft/vulkan/dzn_nir.h +++ b/src/microsoft/vulkan/dzn_nir.h @@ -158,4 +158,7 @@ dzn_nir_blit_vs(void); nir_shader * dzn_nir_blit_fs(const struct dzn_nir_blit_info *info); +nir_shader * +dzn_nir_polygon_point_mode_gs(const nir_shader *vs, unsigned cull_mode, bool front_ccw); + #endif -- 2.7.4