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