1 /**************************************************************************
2 *
3 * Copyright 2023 Red Hat.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a
7 * copy of this software and associated documentation files (the "Software"),
8 * to deal in the Software without restriction, including without limitation
9 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10 * and/or sell copies of the Software, and to permit persons to whom the
11 * Software is furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included
14 * in all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
22 * DEALINGS IN THE SOFTWARE.
23 *
24 **************************************************************************/
25
26 #include "draw_mesh.h"
27 #include "draw_context.h"
28
29 #include "tgsi/tgsi_scan.h"
30 #include "nir/nir_to_tgsi_info.h"
31 #include "pipe/p_shader_tokens.h"
32
33 struct draw_mesh_shader *
draw_create_mesh_shader(struct draw_context * draw,const struct pipe_shader_state * state)34 draw_create_mesh_shader(struct draw_context *draw,
35 const struct pipe_shader_state *state)
36 {
37 struct draw_mesh_shader *ms;
38
39 ms = CALLOC_STRUCT(draw_mesh_shader);
40
41 if (!ms)
42 return NULL;
43
44 ms->draw = draw;
45
46 nir_tgsi_scan_shader(state->ir.nir, &ms->info, true);
47
48 nir_shader *nir = state->ir.nir;
49
50 ms->output_primitive = nir->info.mesh.primitive_type;
51
52 ms->position_output = -1;
53 bool found_clipvertex = false;
54 for (unsigned i = 0; i < ms->info.num_outputs; i++) {
55 if (ms->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
56 ms->info.output_semantic_index[i] == 0)
57 ms->position_output = i;
58 if (ms->info.output_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX)
59 ms->viewport_index_output = i;
60 if (ms->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPVERTEX &&
61 ms->info.output_semantic_index[i] == 0) {
62 found_clipvertex = true;
63 ms->clipvertex_output = i;
64 }
65 if (ms->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPDIST) {
66 assert(ms->info.output_semantic_index[i] <
67 PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT);
68 ms->ccdistance_output[ms->info.output_semantic_index[i]] = i;
69 }
70 }
71 if (!found_clipvertex)
72 ms->clipvertex_output = ms->position_output;
73 return ms;
74 }
75
76 void
draw_bind_mesh_shader(struct draw_context * draw,struct draw_mesh_shader * dms)77 draw_bind_mesh_shader(struct draw_context *draw,
78 struct draw_mesh_shader *dms)
79 {
80 draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE);
81
82 if (dms) {
83 draw->ms.mesh_shader = dms;
84 draw->ms.num_ms_outputs = dms->info.num_outputs;
85 draw->ms.position_output = dms->position_output;
86 draw->ms.clipvertex_output = dms->clipvertex_output;
87 } else {
88 draw->ms.mesh_shader = NULL;
89 draw->ms.num_ms_outputs = 0;
90 }
91 }
92
93 void
draw_delete_mesh_shader(struct draw_context * draw,struct draw_mesh_shader * dms)94 draw_delete_mesh_shader(struct draw_context *draw,
95 struct draw_mesh_shader *dms)
96 {
97 if (!dms)
98 return;
99
100 FREE(dms);
101 }
102