xref: /aosp_15_r20/external/mesa3d/src/asahi/vulkan/hk_nir_passthrough_gs.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2024 Valve Corporation
3  * Copyright 2024 Alyssa Rosenzweig
4  * Copyright 2022 Collabora Ltd.
5  * SPDX-License-Identifier: MIT
6  */
7 
8 #include "util/bitscan.h"
9 #include "hk_shader.h"
10 #include "nir.h"
11 #include "nir_builder.h"
12 #include "nir_xfb_info.h"
13 #include "shader_enums.h"
14 
15 void
hk_nir_passthrough_gs(nir_builder * b,const void * key_)16 hk_nir_passthrough_gs(nir_builder *b, const void *key_)
17 {
18    nir_shader *s = b->shader;
19    const struct hk_passthrough_gs_key *key = key_;
20    assert(key->prim == u_decomposed_prim(key->prim));
21    assert(key->prim != MESA_PRIM_PATCHES && "tessellation consumes patches");
22 
23    enum mesa_prim out;
24    if (key->prim == MESA_PRIM_POINTS)
25       out = MESA_PRIM_POINTS;
26    else if (u_reduced_prim(key->prim) == MESA_PRIM_LINES)
27       out = MESA_PRIM_LINE_STRIP;
28    else
29       out = MESA_PRIM_TRIANGLE_STRIP;
30 
31 #if 0
32    assert((key->outputs &
33            (VARYING_BIT_BOUNDING_BOX0 | VARYING_BIT_BOUNDING_BOX1)) == 0 &&
34           "cull distance lowering not run yet");
35 #endif
36    /* XXX: need rework of preprocess_nir */
37    uint64_t outputs =
38       key->outputs & ~(VARYING_BIT_BOUNDING_BOX0 | VARYING_BIT_BOUNDING_BOX1);
39 
40    s->info.outputs_written = s->info.inputs_read = outputs;
41    s->info.clip_distance_array_size = key->clip_distance_array_size;
42    s->info.cull_distance_array_size = key->cull_distance_array_size;
43    s->info.stage = MESA_SHADER_GEOMETRY;
44    s->info.gs.input_primitive = key->prim;
45    s->info.gs.output_primitive = out;
46    s->info.gs.vertices_in = mesa_vertices_per_prim(key->prim);
47    s->info.gs.vertices_out = mesa_vertices_per_prim(out);
48    s->info.gs.invocations = 1;
49    s->info.gs.active_stream_mask = 1;
50 
51    if (key->xfb_info.output_count) {
52       size_t size = nir_xfb_info_size(key->xfb_info.output_count);
53       s->xfb_info = ralloc_memdup(s, &key->xfb_info, size);
54       s->info.has_transform_feedback_varyings = true;
55       memcpy(s->info.xfb_stride, key->xfb_stride, sizeof(key->xfb_stride));
56    }
57 
58    unsigned int start_vert = key->prim == MESA_PRIM_LINES_ADJACENCY ? 1 : 0;
59    unsigned int step = key->prim == MESA_PRIM_TRIANGLES_ADJACENCY ? 2 : 1;
60 
61    nir_def *zero = nir_imm_int(b, 0);
62    nir_def *one = nir_imm_int(b, 1);
63 
64    for (unsigned i = 0; i < s->info.gs.vertices_out; ++i) {
65       nir_def *vertex = nir_imm_int(b, start_vert + (i * step));
66 
67       /* Copy inputs to outputs. */
68       u_foreach_bit64(loc, outputs) {
69          unsigned adjusted_loc = loc;
70          nir_def *offset = zero;
71          unsigned num_slots = 1;
72 
73          bool scalar = loc == VARYING_SLOT_LAYER ||
74                        loc == VARYING_SLOT_VIEW_INDEX ||
75                        loc == VARYING_SLOT_VIEWPORT || loc == VARYING_SLOT_PSIZ;
76          unsigned comps = scalar ? 1 : 4;
77 
78          /* We use combined, compact clip/cull */
79          if (loc == VARYING_SLOT_CLIP_DIST1 || loc == VARYING_SLOT_CULL_DIST1) {
80             adjusted_loc--;
81             offset = one;
82          }
83 
84          if (adjusted_loc == VARYING_SLOT_CLIP_DIST0 ||
85              adjusted_loc == VARYING_SLOT_CULL_DIST0) {
86             num_slots =
87                key->cull_distance_array_size + key->clip_distance_array_size;
88 
89             if (loc > adjusted_loc)
90                comps = num_slots - 4;
91             else
92                comps = MIN2(num_slots, 4);
93          }
94 
95          nir_io_semantics sem = {
96             .location = adjusted_loc,
97             .num_slots = num_slots,
98          };
99 
100          nir_def *val = nir_load_per_vertex_input(b, comps, 32, vertex, offset,
101                                                   .io_semantics = sem);
102 
103          for (unsigned c = 0; c < comps; ++c) {
104             nir_store_output(b, nir_channel(b, val, c), offset,
105                              .io_semantics = sem, .src_type = nir_type_uint32,
106                              .component = c);
107          }
108       }
109 
110       nir_emit_vertex(b, 0);
111    }
112 }
113