1 /*
2 * Copyright (C) 2024 Collabora, Ltd.
3 * SPDX-License-Identifier: MIT
4 */
5
6 #include "compiler/nir/nir_builder.h"
7 #include "pan_ir.h"
8
9 /*
10 * load_vertex_id_zero_base() is supposed to return the zero-based
11 * vertex ID, which is then offset by load_first_vertex() to get
12 * an absolute vertex ID. At the same time, when we're in a Vulkan
13 * environment, load_first_vertex() also encodes the vertexOffset
14 * passed to the indexed draw.
15 *
16 * Midgard/Bifrost have a sligtly different semantics, where
17 * load_first_vertex() returns vertexOffset + minVertexIdInIndexRange,
18 * and load_vertex_id_zero_base() returns an ID that needs to be offset
19 * by this vertexOffset + minVertexIdInIndexRange to get the absolute
20 * vertex ID. Everything works fine as long as all the load_first_vertex()
21 * and load_vertex_id_zero_base() calls are coming from the
22 * load_vertex_id() lowering. But as mentioned above, that's no longer
23 * the case in Vulkan, where gl_BaseVertexARB will be turned into
24 * load_first_vertex() and expect a value of vertexOffset in an
25 * indexed draw context.
26 *
27 * This pass is turning load_vertex_id() calls into
28 * load_raw_vertex_id_pan() + load_raw_vertex_offset_pan().
29 */
30
31 static bool
lower_load_vertex_id(nir_builder * b,nir_intrinsic_instr * intr,UNUSED void * data)32 lower_load_vertex_id(nir_builder *b, nir_intrinsic_instr *intr,
33 UNUSED void *data)
34 {
35 if (intr->intrinsic != nir_intrinsic_load_vertex_id)
36 return false;
37
38 b->cursor = nir_before_instr(&intr->instr);
39 nir_def_replace(&intr->def, nir_iadd(b, nir_load_raw_vertex_id_pan(b),
40 nir_load_raw_vertex_offset_pan(b)));
41 return true;
42 }
43
44 bool
pan_nir_lower_vertex_id(nir_shader * shader)45 pan_nir_lower_vertex_id(nir_shader *shader)
46 {
47 return nir_shader_intrinsics_pass(shader, lower_load_vertex_id,
48 nir_metadata_control_flow, NULL);
49 }
50