xref: /aosp_15_r20/external/mesa3d/src/asahi/lib/agx_nir_lower_ia.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 /*
2  * Copyright 2023 Valve Corporation
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include "compiler/nir/nir_builder.h"
7 #include "shaders/geometry.h"
8 #include "agx_nir_lower_gs.h"
9 #include "libagx_shaders.h"
10 #include "nir.h"
11 
12 /*
13  * This file implements basic input assembly in software. It runs on software
14  * vertex shaders, as part of geometry/tessellation lowering. It does not apply
15  * the topology, which happens in the geometry shader.
16  */
17 static nir_def *
load_vertex_id(nir_builder * b,unsigned index_size_B)18 load_vertex_id(nir_builder *b, unsigned index_size_B)
19 {
20    nir_def *id = nir_channel(b, nir_load_global_invocation_id(b, 32), 0);
21 
22    /* If drawing with an index buffer, pull the vertex ID. Otherwise, the
23     * vertex ID is just the index as-is.
24     */
25    if (index_size_B) {
26       nir_def *ia = nir_load_input_assembly_buffer_agx(b);
27       id = libagx_load_index_buffer(b, ia, id, nir_imm_int(b, index_size_B));
28    }
29 
30    /* Add the "start", either an index bias or a base vertex. This must happen
31     * after indexing for proper index bias behaviour.
32     */
33    return nir_iadd(b, id, nir_load_first_vertex(b));
34 }
35 
36 static bool
lower(nir_builder * b,nir_intrinsic_instr * intr,void * data)37 lower(nir_builder *b, nir_intrinsic_instr *intr, void *data)
38 {
39    unsigned *index_size_B = data;
40    b->cursor = nir_before_instr(&intr->instr);
41 
42    if (intr->intrinsic == nir_intrinsic_load_vertex_id) {
43       nir_def_replace(&intr->def, load_vertex_id(b, *index_size_B));
44       return true;
45    } else if (intr->intrinsic == nir_intrinsic_load_instance_id) {
46       nir_def_replace(&intr->def,
47                       nir_channel(b, nir_load_global_invocation_id(b, 32), 1));
48       return true;
49    }
50 
51    return false;
52 }
53 
54 bool
agx_nir_lower_sw_vs(nir_shader * s,unsigned index_size_B)55 agx_nir_lower_sw_vs(nir_shader *s, unsigned index_size_B)
56 {
57    return nir_shader_intrinsics_pass(s, lower, nir_metadata_control_flow,
58                                      &index_size_B);
59 }
60