1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright © Microsoft Corporation
3bf215546Sopenharmony_ci *
4bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
5bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
6bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
7bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
9bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
10bf215546Sopenharmony_ci *
11bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
12bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
13bf215546Sopenharmony_ci * Software.
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20bf215546Sopenharmony_ci * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21bf215546Sopenharmony_ci * IN THE SOFTWARE.
22bf215546Sopenharmony_ci */
23bf215546Sopenharmony_ci
24bf215546Sopenharmony_ci#include "dxil_signature.h"
25bf215546Sopenharmony_ci#include "dxil_enums.h"
26bf215546Sopenharmony_ci#include "dxil_module.h"
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci#include "glsl_types.h"
29bf215546Sopenharmony_ci#include "nir_to_dxil.h"
30bf215546Sopenharmony_ci#include "util/u_debug.h"
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include <string.h>
33bf215546Sopenharmony_ci
34bf215546Sopenharmony_ci
35bf215546Sopenharmony_cistruct semantic_info {
36bf215546Sopenharmony_ci   enum dxil_semantic_kind kind;
37bf215546Sopenharmony_ci   char name[64];
38bf215546Sopenharmony_ci   int index;
39bf215546Sopenharmony_ci   enum dxil_prog_sig_comp_type comp_type;
40bf215546Sopenharmony_ci   uint8_t sig_comp_type;
41bf215546Sopenharmony_ci   int32_t start_row;
42bf215546Sopenharmony_ci   int32_t rows;
43bf215546Sopenharmony_ci   uint8_t start_col;
44bf215546Sopenharmony_ci   uint8_t cols;
45bf215546Sopenharmony_ci   uint8_t interpolation;
46bf215546Sopenharmony_ci   uint8_t stream;
47bf215546Sopenharmony_ci   const char *sysvalue_name;
48bf215546Sopenharmony_ci};
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_ci
51bf215546Sopenharmony_cistatic bool
52bf215546Sopenharmony_ciis_depth_output(enum dxil_semantic_kind kind)
53bf215546Sopenharmony_ci{
54bf215546Sopenharmony_ci   return kind == DXIL_SEM_DEPTH || kind == DXIL_SEM_DEPTH_GE ||
55bf215546Sopenharmony_ci          kind == DXIL_SEM_DEPTH_LE || kind == DXIL_SEM_STENCIL_REF;
56bf215546Sopenharmony_ci}
57bf215546Sopenharmony_ci
58bf215546Sopenharmony_cistatic uint8_t
59bf215546Sopenharmony_ciget_interpolation(nir_variable *var)
60bf215546Sopenharmony_ci{
61bf215546Sopenharmony_ci   if (var->data.patch)
62bf215546Sopenharmony_ci      return DXIL_INTERP_UNDEFINED;
63bf215546Sopenharmony_ci
64bf215546Sopenharmony_ci   if (glsl_type_is_integer(glsl_without_array_or_matrix(var->type)))
65bf215546Sopenharmony_ci      return DXIL_INTERP_CONSTANT;
66bf215546Sopenharmony_ci
67bf215546Sopenharmony_ci   if (var->data.sample) {
68bf215546Sopenharmony_ci      if (var->data.location == VARYING_SLOT_POS)
69bf215546Sopenharmony_ci         return DXIL_INTERP_LINEAR_NOPERSPECTIVE_SAMPLE;
70bf215546Sopenharmony_ci      switch (var->data.interpolation) {
71bf215546Sopenharmony_ci      case INTERP_MODE_NONE: return DXIL_INTERP_LINEAR_SAMPLE;
72bf215546Sopenharmony_ci      case INTERP_MODE_FLAT: return DXIL_INTERP_CONSTANT;
73bf215546Sopenharmony_ci      case INTERP_MODE_NOPERSPECTIVE: return DXIL_INTERP_LINEAR_NOPERSPECTIVE_SAMPLE;
74bf215546Sopenharmony_ci      case INTERP_MODE_SMOOTH: return DXIL_INTERP_LINEAR_SAMPLE;
75bf215546Sopenharmony_ci      }
76bf215546Sopenharmony_ci   } else if (unlikely(var->data.centroid)) {
77bf215546Sopenharmony_ci      if (var->data.location == VARYING_SLOT_POS)
78bf215546Sopenharmony_ci         return DXIL_INTERP_LINEAR_NOPERSPECTIVE_CENTROID;
79bf215546Sopenharmony_ci      switch (var->data.interpolation) {
80bf215546Sopenharmony_ci      case INTERP_MODE_NONE: return DXIL_INTERP_LINEAR_CENTROID;
81bf215546Sopenharmony_ci      case INTERP_MODE_FLAT: return DXIL_INTERP_CONSTANT;
82bf215546Sopenharmony_ci      case INTERP_MODE_NOPERSPECTIVE: return DXIL_INTERP_LINEAR_NOPERSPECTIVE_CENTROID;
83bf215546Sopenharmony_ci      case INTERP_MODE_SMOOTH: return DXIL_INTERP_LINEAR_CENTROID;
84bf215546Sopenharmony_ci      }
85bf215546Sopenharmony_ci   } else {
86bf215546Sopenharmony_ci      if (var->data.location == VARYING_SLOT_POS)
87bf215546Sopenharmony_ci         return DXIL_INTERP_LINEAR_NOPERSPECTIVE;
88bf215546Sopenharmony_ci      switch (var->data.interpolation) {
89bf215546Sopenharmony_ci      case INTERP_MODE_NONE: return DXIL_INTERP_LINEAR;
90bf215546Sopenharmony_ci      case INTERP_MODE_FLAT: return DXIL_INTERP_CONSTANT;
91bf215546Sopenharmony_ci      case INTERP_MODE_NOPERSPECTIVE: return DXIL_INTERP_LINEAR_NOPERSPECTIVE;
92bf215546Sopenharmony_ci      case INTERP_MODE_SMOOTH: return DXIL_INTERP_LINEAR;
93bf215546Sopenharmony_ci      }
94bf215546Sopenharmony_ci   }
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_ci   return DXIL_INTERP_LINEAR;
97bf215546Sopenharmony_ci}
98bf215546Sopenharmony_ci
99bf215546Sopenharmony_cistatic const char *
100bf215546Sopenharmony_ciin_sysvalue_name(nir_variable *var)
101bf215546Sopenharmony_ci{
102bf215546Sopenharmony_ci   switch (var->data.location) {
103bf215546Sopenharmony_ci   case VARYING_SLOT_POS:
104bf215546Sopenharmony_ci      return "POS";
105bf215546Sopenharmony_ci   case VARYING_SLOT_FACE:
106bf215546Sopenharmony_ci      return "FACE";
107bf215546Sopenharmony_ci   case VARYING_SLOT_LAYER:
108bf215546Sopenharmony_ci      return "RTINDEX";
109bf215546Sopenharmony_ci   default:
110bf215546Sopenharmony_ci      return "NONE";
111bf215546Sopenharmony_ci   }
112bf215546Sopenharmony_ci}
113bf215546Sopenharmony_ci
114bf215546Sopenharmony_ci/*
115bf215546Sopenharmony_ci * The signatures are written into the stream in two pieces:
116bf215546Sopenharmony_ci * DxilProgramSignatureElement is a fixes size structure that gets dumped
117bf215546Sopenharmony_ci * to the stream in order of the registers and each contains an offset
118bf215546Sopenharmony_ci * to the semantic name string. Then these strings are dumped into the stream.
119bf215546Sopenharmony_ci */
120bf215546Sopenharmony_cistatic unsigned
121bf215546Sopenharmony_ciget_additional_semantic_info(nir_shader *s, nir_variable *var, struct semantic_info *info,
122bf215546Sopenharmony_ci                             unsigned next_row, unsigned clip_size)
123bf215546Sopenharmony_ci{
124bf215546Sopenharmony_ci   const struct glsl_type *type = var->type;
125bf215546Sopenharmony_ci   if (nir_is_arrayed_io(var, s->info.stage))
126bf215546Sopenharmony_ci      type = glsl_get_array_element(type);
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci   info->comp_type =
129bf215546Sopenharmony_ci      dxil_get_prog_sig_comp_type(type);
130bf215546Sopenharmony_ci
131bf215546Sopenharmony_ci   bool is_depth = is_depth_output(info->kind);
132bf215546Sopenharmony_ci
133bf215546Sopenharmony_ci   if (!glsl_type_is_struct(type)) {
134bf215546Sopenharmony_ci      info->sig_comp_type = dxil_get_comp_type(type);
135bf215546Sopenharmony_ci   } else if (var->data.interpolation == INTERP_MODE_FLAT) {
136bf215546Sopenharmony_ci      info->sig_comp_type = DXIL_COMP_TYPE_U32;
137bf215546Sopenharmony_ci      info->comp_type = DXIL_PROG_SIG_COMP_TYPE_UINT32;
138bf215546Sopenharmony_ci   } else {
139bf215546Sopenharmony_ci      info->sig_comp_type = DXIL_COMP_TYPE_F32;
140bf215546Sopenharmony_ci      info->comp_type = DXIL_PROG_SIG_COMP_TYPE_FLOAT32;
141bf215546Sopenharmony_ci   }
142bf215546Sopenharmony_ci
143bf215546Sopenharmony_ci   bool is_gs_input = s->info.stage == MESA_SHADER_GEOMETRY &&
144bf215546Sopenharmony_ci      (var->data.mode & (nir_var_shader_in | nir_var_system_value));
145bf215546Sopenharmony_ci
146bf215546Sopenharmony_ci   info->stream = var->data.stream;
147bf215546Sopenharmony_ci   info->rows = 1;
148bf215546Sopenharmony_ci   if (info->kind == DXIL_SEM_TARGET) {
149bf215546Sopenharmony_ci      info->start_row = info->index;
150bf215546Sopenharmony_ci      info->cols = (uint8_t)glsl_get_components(type);
151bf215546Sopenharmony_ci   } else if (is_depth ||
152bf215546Sopenharmony_ci              (info->kind == DXIL_SEM_PRIMITIVE_ID && is_gs_input) ||
153bf215546Sopenharmony_ci              info->kind == DXIL_SEM_COVERAGE ||
154bf215546Sopenharmony_ci              info->kind == DXIL_SEM_SAMPLE_INDEX) {
155bf215546Sopenharmony_ci      // This turns into a 'N/A' mask in the disassembly
156bf215546Sopenharmony_ci      info->start_row = -1;
157bf215546Sopenharmony_ci      info->cols = 1;
158bf215546Sopenharmony_ci   } else if (info->kind == DXIL_SEM_TESS_FACTOR ||
159bf215546Sopenharmony_ci              info->kind == DXIL_SEM_INSIDE_TESS_FACTOR) {
160bf215546Sopenharmony_ci      assert(var->data.compact);
161bf215546Sopenharmony_ci      info->start_row = next_row;
162bf215546Sopenharmony_ci      info->rows = glsl_get_aoa_size(type);
163bf215546Sopenharmony_ci      info->cols = 1;
164bf215546Sopenharmony_ci      next_row += info->rows;
165bf215546Sopenharmony_ci   } else if (var->data.compact) {
166bf215546Sopenharmony_ci      if (var->data.location_frac) {
167bf215546Sopenharmony_ci         info->start_row = next_row - 1;
168bf215546Sopenharmony_ci      } else {
169bf215546Sopenharmony_ci         info->start_row = next_row;
170bf215546Sopenharmony_ci         next_row++;
171bf215546Sopenharmony_ci      }
172bf215546Sopenharmony_ci
173bf215546Sopenharmony_ci      assert(glsl_type_is_array(type) && info->kind == DXIL_SEM_CLIP_DISTANCE);
174bf215546Sopenharmony_ci      unsigned num_floats = glsl_get_aoa_size(type);
175bf215546Sopenharmony_ci      unsigned start_offset = (var->data.location - VARYING_SLOT_CLIP_DIST0) * 4 +
176bf215546Sopenharmony_ci         var->data.location_frac;
177bf215546Sopenharmony_ci
178bf215546Sopenharmony_ci      if (start_offset >= clip_size) {
179bf215546Sopenharmony_ci         info->kind = DXIL_SEM_CULL_DISTANCE;
180bf215546Sopenharmony_ci         snprintf(info->name, 64, "SV_CullDistance");
181bf215546Sopenharmony_ci      }
182bf215546Sopenharmony_ci      info->cols = num_floats;
183bf215546Sopenharmony_ci      info->start_col = (uint8_t)var->data.location_frac;
184bf215546Sopenharmony_ci   } else {
185bf215546Sopenharmony_ci      info->start_row = next_row;
186bf215546Sopenharmony_ci      info->rows = glsl_count_vec4_slots(type, false, false);
187bf215546Sopenharmony_ci      if (glsl_type_is_array(type))
188bf215546Sopenharmony_ci         type = glsl_get_array_element(type);
189bf215546Sopenharmony_ci      next_row += info->rows;
190bf215546Sopenharmony_ci      info->start_col = (uint8_t)var->data.location_frac;
191bf215546Sopenharmony_ci      info->cols = MIN2(glsl_get_component_slots(type), 4);
192bf215546Sopenharmony_ci   }
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci   return next_row;
195bf215546Sopenharmony_ci}
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_citypedef void (*semantic_info_proc)(nir_variable *var, struct semantic_info *info, gl_shader_stage stage);
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_cistatic void
200bf215546Sopenharmony_ciget_semantic_vs_in_name(nir_variable *var, struct semantic_info *info, gl_shader_stage stage)
201bf215546Sopenharmony_ci{
202bf215546Sopenharmony_ci   strcpy(info->name, "TEXCOORD");
203bf215546Sopenharmony_ci   info->index = var->data.driver_location;
204bf215546Sopenharmony_ci   info->kind = DXIL_SEM_ARBITRARY;
205bf215546Sopenharmony_ci}
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_cistatic void
208bf215546Sopenharmony_ciget_semantic_sv_name(nir_variable *var, struct semantic_info *info, gl_shader_stage stage)
209bf215546Sopenharmony_ci{
210bf215546Sopenharmony_ci   if (stage != MESA_SHADER_VERTEX)
211bf215546Sopenharmony_ci      info->interpolation = get_interpolation(var);
212bf215546Sopenharmony_ci
213bf215546Sopenharmony_ci   switch (var->data.location) {
214bf215546Sopenharmony_ci   case SYSTEM_VALUE_VERTEX_ID_ZERO_BASE:
215bf215546Sopenharmony_ci      info->kind = DXIL_SEM_VERTEX_ID;
216bf215546Sopenharmony_ci      break;
217bf215546Sopenharmony_ci   case SYSTEM_VALUE_FRONT_FACE:
218bf215546Sopenharmony_ci      info->kind = DXIL_SEM_IS_FRONT_FACE;
219bf215546Sopenharmony_ci      break;
220bf215546Sopenharmony_ci   case SYSTEM_VALUE_INSTANCE_ID:
221bf215546Sopenharmony_ci      info->kind = DXIL_SEM_INSTANCE_ID;
222bf215546Sopenharmony_ci      break;
223bf215546Sopenharmony_ci   case SYSTEM_VALUE_PRIMITIVE_ID:
224bf215546Sopenharmony_ci      info->kind = DXIL_SEM_PRIMITIVE_ID;
225bf215546Sopenharmony_ci      break;
226bf215546Sopenharmony_ci   case SYSTEM_VALUE_SAMPLE_ID:
227bf215546Sopenharmony_ci      info->kind = DXIL_SEM_SAMPLE_INDEX;
228bf215546Sopenharmony_ci      break;
229bf215546Sopenharmony_ci   default:
230bf215546Sopenharmony_ci      unreachable("unsupported system value");
231bf215546Sopenharmony_ci   }
232bf215546Sopenharmony_ci   strncpy(info->name, var->name, ARRAY_SIZE(info->name) - 1);
233bf215546Sopenharmony_ci}
234bf215546Sopenharmony_ci
235bf215546Sopenharmony_cistatic void
236bf215546Sopenharmony_ciget_semantic_ps_outname(nir_variable *var, struct semantic_info *info)
237bf215546Sopenharmony_ci{
238bf215546Sopenharmony_ci   info->kind = DXIL_SEM_INVALID;
239bf215546Sopenharmony_ci   switch (var->data.location) {
240bf215546Sopenharmony_ci   case FRAG_RESULT_COLOR:
241bf215546Sopenharmony_ci      snprintf(info->name, 64, "%s", "SV_Target");
242bf215546Sopenharmony_ci      info->index = var->data.index;
243bf215546Sopenharmony_ci      info->kind = DXIL_SEM_TARGET;
244bf215546Sopenharmony_ci      break;
245bf215546Sopenharmony_ci   case FRAG_RESULT_DATA0:
246bf215546Sopenharmony_ci   case FRAG_RESULT_DATA1:
247bf215546Sopenharmony_ci   case FRAG_RESULT_DATA2:
248bf215546Sopenharmony_ci   case FRAG_RESULT_DATA3:
249bf215546Sopenharmony_ci   case FRAG_RESULT_DATA4:
250bf215546Sopenharmony_ci   case FRAG_RESULT_DATA5:
251bf215546Sopenharmony_ci   case FRAG_RESULT_DATA6:
252bf215546Sopenharmony_ci   case FRAG_RESULT_DATA7:
253bf215546Sopenharmony_ci      snprintf(info->name, 64, "%s", "SV_Target");
254bf215546Sopenharmony_ci      info->index = var->data.location - FRAG_RESULT_DATA0;
255bf215546Sopenharmony_ci      if (var->data.location == FRAG_RESULT_DATA0 &&
256bf215546Sopenharmony_ci          var->data.index > 0)
257bf215546Sopenharmony_ci         info->index = var->data.index;
258bf215546Sopenharmony_ci      info->kind = DXIL_SEM_TARGET;
259bf215546Sopenharmony_ci      break;
260bf215546Sopenharmony_ci   case FRAG_RESULT_DEPTH:
261bf215546Sopenharmony_ci      snprintf(info->name, 64, "%s", "SV_Depth");
262bf215546Sopenharmony_ci      info->kind = DXIL_SEM_DEPTH;
263bf215546Sopenharmony_ci      break;
264bf215546Sopenharmony_ci   case FRAG_RESULT_STENCIL:
265bf215546Sopenharmony_ci      snprintf(info->name, 64, "%s", "SV_StencilRef");
266bf215546Sopenharmony_ci      info->kind = DXIL_SEM_STENCIL_REF; //??
267bf215546Sopenharmony_ci      break;
268bf215546Sopenharmony_ci   case FRAG_RESULT_SAMPLE_MASK:
269bf215546Sopenharmony_ci      snprintf(info->name, 64, "%s", "SV_Coverage");
270bf215546Sopenharmony_ci      info->kind = DXIL_SEM_COVERAGE; //??
271bf215546Sopenharmony_ci      break;
272bf215546Sopenharmony_ci   default:
273bf215546Sopenharmony_ci      snprintf(info->name, 64, "%s", "UNDEFINED");
274bf215546Sopenharmony_ci      break;
275bf215546Sopenharmony_ci   }
276bf215546Sopenharmony_ci}
277bf215546Sopenharmony_ci
278bf215546Sopenharmony_cistatic void
279bf215546Sopenharmony_ciget_semantic_name(nir_variable *var, struct semantic_info *info,
280bf215546Sopenharmony_ci                  const struct glsl_type *type)
281bf215546Sopenharmony_ci{
282bf215546Sopenharmony_ci   info->kind = DXIL_SEM_INVALID;
283bf215546Sopenharmony_ci   info->interpolation = get_interpolation(var);
284bf215546Sopenharmony_ci   switch (var->data.location) {
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ci   case VARYING_SLOT_POS:
287bf215546Sopenharmony_ci      assert(glsl_get_components(type) == 4);
288bf215546Sopenharmony_ci      snprintf(info->name, 64, "%s", "SV_Position");
289bf215546Sopenharmony_ci      info->kind = DXIL_SEM_POSITION;
290bf215546Sopenharmony_ci      break;
291bf215546Sopenharmony_ci
292bf215546Sopenharmony_ci    case VARYING_SLOT_FACE:
293bf215546Sopenharmony_ci      assert(glsl_get_components(var->type) == 1);
294bf215546Sopenharmony_ci      snprintf(info->name, 64, "%s", "SV_IsFrontFace");
295bf215546Sopenharmony_ci      info->kind = DXIL_SEM_IS_FRONT_FACE;
296bf215546Sopenharmony_ci      break;
297bf215546Sopenharmony_ci
298bf215546Sopenharmony_ci   case VARYING_SLOT_PRIMITIVE_ID:
299bf215546Sopenharmony_ci     assert(glsl_get_components(var->type) == 1);
300bf215546Sopenharmony_ci     snprintf(info->name, 64, "%s", "SV_PrimitiveID");
301bf215546Sopenharmony_ci     info->kind = DXIL_SEM_PRIMITIVE_ID;
302bf215546Sopenharmony_ci     break;
303bf215546Sopenharmony_ci
304bf215546Sopenharmony_ci   case VARYING_SLOT_CLIP_DIST1:
305bf215546Sopenharmony_ci      info->index = 1;
306bf215546Sopenharmony_ci      FALLTHROUGH;
307bf215546Sopenharmony_ci   case VARYING_SLOT_CLIP_DIST0:
308bf215546Sopenharmony_ci      assert(var->data.location == VARYING_SLOT_CLIP_DIST1 || info->index == 0);
309bf215546Sopenharmony_ci      snprintf(info->name, 64, "%s", "SV_ClipDistance");
310bf215546Sopenharmony_ci      info->kind = DXIL_SEM_CLIP_DISTANCE;
311bf215546Sopenharmony_ci      break;
312bf215546Sopenharmony_ci
313bf215546Sopenharmony_ci   case VARYING_SLOT_TESS_LEVEL_INNER:
314bf215546Sopenharmony_ci      assert(glsl_get_components(var->type) <= 2);
315bf215546Sopenharmony_ci      snprintf(info->name, 64, "%s", "SV_InsideTessFactor");
316bf215546Sopenharmony_ci      info->kind = DXIL_SEM_INSIDE_TESS_FACTOR;
317bf215546Sopenharmony_ci      break;
318bf215546Sopenharmony_ci
319bf215546Sopenharmony_ci   case VARYING_SLOT_TESS_LEVEL_OUTER:
320bf215546Sopenharmony_ci      assert(glsl_get_components(var->type) <= 4);
321bf215546Sopenharmony_ci      snprintf(info->name, 64, "%s", "SV_TessFactor");
322bf215546Sopenharmony_ci      info->kind = DXIL_SEM_TESS_FACTOR;
323bf215546Sopenharmony_ci      break;
324bf215546Sopenharmony_ci
325bf215546Sopenharmony_ci   case VARYING_SLOT_VIEWPORT:
326bf215546Sopenharmony_ci      assert(glsl_get_components(var->type) == 1);
327bf215546Sopenharmony_ci      snprintf(info->name, 64, "%s", "SV_ViewportArrayIndex");
328bf215546Sopenharmony_ci      info->kind = DXIL_SEM_VIEWPORT_ARRAY_INDEX;
329bf215546Sopenharmony_ci      break;
330bf215546Sopenharmony_ci
331bf215546Sopenharmony_ci   case VARYING_SLOT_LAYER:
332bf215546Sopenharmony_ci      assert(glsl_get_components(var->type) == 1);
333bf215546Sopenharmony_ci      snprintf(info->name, 64, "%s", "SV_RenderTargetArrayIndex");
334bf215546Sopenharmony_ci      info->kind = DXIL_SEM_RENDERTARGET_ARRAY_INDEX;
335bf215546Sopenharmony_ci      break;
336bf215546Sopenharmony_ci
337bf215546Sopenharmony_ci   default: {
338bf215546Sopenharmony_ci         info->index = var->data.driver_location;
339bf215546Sopenharmony_ci         strcpy(info->name, "TEXCOORD");
340bf215546Sopenharmony_ci         info->kind = DXIL_SEM_ARBITRARY;
341bf215546Sopenharmony_ci      }
342bf215546Sopenharmony_ci   }
343bf215546Sopenharmony_ci}
344bf215546Sopenharmony_ci
345bf215546Sopenharmony_cistatic void
346bf215546Sopenharmony_ciget_semantic_in_name(nir_variable *var, struct semantic_info *info, gl_shader_stage stage)
347bf215546Sopenharmony_ci{
348bf215546Sopenharmony_ci   const struct glsl_type *type = var->type;
349bf215546Sopenharmony_ci   if (nir_is_arrayed_io(var, stage) &&
350bf215546Sopenharmony_ci       glsl_type_is_array(type))
351bf215546Sopenharmony_ci      type = glsl_get_array_element(type);
352bf215546Sopenharmony_ci
353bf215546Sopenharmony_ci   get_semantic_name(var, info, type);
354bf215546Sopenharmony_ci   info->sysvalue_name = in_sysvalue_name(var);
355bf215546Sopenharmony_ci}
356bf215546Sopenharmony_ci
357bf215546Sopenharmony_ci
358bf215546Sopenharmony_cistatic enum dxil_prog_sig_semantic
359bf215546Sopenharmony_ciprog_semantic_from_kind(enum dxil_semantic_kind kind, unsigned num_vals, unsigned start_val)
360bf215546Sopenharmony_ci{
361bf215546Sopenharmony_ci   switch (kind) {
362bf215546Sopenharmony_ci   case DXIL_SEM_ARBITRARY: return DXIL_PROG_SEM_UNDEFINED;
363bf215546Sopenharmony_ci   case DXIL_SEM_VERTEX_ID: return DXIL_PROG_SEM_VERTEX_ID;
364bf215546Sopenharmony_ci   case DXIL_SEM_INSTANCE_ID: return DXIL_PROG_SEM_INSTANCE_ID;
365bf215546Sopenharmony_ci   case DXIL_SEM_POSITION: return DXIL_PROG_SEM_POSITION;
366bf215546Sopenharmony_ci   case DXIL_SEM_COVERAGE: return DXIL_PROG_SEM_COVERAGE;
367bf215546Sopenharmony_ci   case DXIL_SEM_INNER_COVERAGE: return DXIL_PROG_SEM_INNER_COVERAGE;
368bf215546Sopenharmony_ci   case DXIL_SEM_PRIMITIVE_ID: return DXIL_PROG_SEM_PRIMITIVE_ID;
369bf215546Sopenharmony_ci   case DXIL_SEM_SAMPLE_INDEX: return DXIL_PROG_SEM_SAMPLE_INDEX;
370bf215546Sopenharmony_ci   case DXIL_SEM_IS_FRONT_FACE: return DXIL_PROG_SEM_IS_FRONTFACE;
371bf215546Sopenharmony_ci   case DXIL_SEM_RENDERTARGET_ARRAY_INDEX: return DXIL_PROG_SEM_RENDERTARGET_ARRAY_INDEX;
372bf215546Sopenharmony_ci   case DXIL_SEM_VIEWPORT_ARRAY_INDEX: return DXIL_PROG_SEM_VIEWPORT_ARRAY_INDEX;
373bf215546Sopenharmony_ci   case DXIL_SEM_CLIP_DISTANCE: return DXIL_PROG_SEM_CLIP_DISTANCE;
374bf215546Sopenharmony_ci   case DXIL_SEM_CULL_DISTANCE: return DXIL_PROG_SEM_CULL_DISTANCE;
375bf215546Sopenharmony_ci   case DXIL_SEM_BARYCENTRICS: return DXIL_PROG_SEM_BARYCENTRICS;
376bf215546Sopenharmony_ci   case DXIL_SEM_SHADING_RATE: return DXIL_PROG_SEM_SHADING_RATE;
377bf215546Sopenharmony_ci   case DXIL_SEM_CULL_PRIMITIVE: return DXIL_PROG_SEM_CULL_PRIMITIVE;
378bf215546Sopenharmony_ci   case DXIL_SEM_TARGET: return DXIL_PROG_SEM_TARGET;
379bf215546Sopenharmony_ci   case DXIL_SEM_DEPTH: return DXIL_PROG_SEM_DEPTH;
380bf215546Sopenharmony_ci   case DXIL_SEM_DEPTH_LE: return DXIL_PROG_SEM_DEPTH_LE;
381bf215546Sopenharmony_ci   case DXIL_SEM_DEPTH_GE: return DXIL_PROG_SEM_DEPTH_GE;
382bf215546Sopenharmony_ci   case DXIL_SEM_STENCIL_REF: return DXIL_PROG_SEM_STENCIL_REF;
383bf215546Sopenharmony_ci   case DXIL_SEM_TESS_FACTOR:
384bf215546Sopenharmony_ci      switch (num_vals) {
385bf215546Sopenharmony_ci      case 4: return DXIL_PROG_SEM_FINAL_QUAD_EDGE_TESSFACTOR;
386bf215546Sopenharmony_ci      case 3: return DXIL_PROG_SEM_FINAL_TRI_EDGE_TESSFACTOR;
387bf215546Sopenharmony_ci      case 2: return start_val == 0 ?
388bf215546Sopenharmony_ci         DXIL_PROG_SEM_FINAL_LINE_DENSITY_TESSFACTOR :
389bf215546Sopenharmony_ci         DXIL_PROG_SEM_FINAL_LINE_DETAIL_TESSFACTOR;
390bf215546Sopenharmony_ci      default:
391bf215546Sopenharmony_ci         unreachable("Invalid row count for tess factor");
392bf215546Sopenharmony_ci      }
393bf215546Sopenharmony_ci   case DXIL_SEM_INSIDE_TESS_FACTOR:
394bf215546Sopenharmony_ci      switch (num_vals) {
395bf215546Sopenharmony_ci      case 2: return DXIL_PROG_SEM_FINAL_QUAD_INSIDE_EDGE_TESSFACTOR;
396bf215546Sopenharmony_ci      case 1: return DXIL_PROG_SEM_FINAL_TRI_INSIDE_EDGE_TESSFACTOR;
397bf215546Sopenharmony_ci      default:
398bf215546Sopenharmony_ci         unreachable("Invalid row count for inner tess factor");
399bf215546Sopenharmony_ci      }
400bf215546Sopenharmony_ci   default:
401bf215546Sopenharmony_ci       return DXIL_PROG_SEM_UNDEFINED;
402bf215546Sopenharmony_ci   }
403bf215546Sopenharmony_ci}
404bf215546Sopenharmony_ci
405bf215546Sopenharmony_cistatic
406bf215546Sopenharmony_ciuint32_t
407bf215546Sopenharmony_cicopy_semantic_name_to_string(struct _mesa_string_buffer *string_out, const char *name)
408bf215546Sopenharmony_ci{
409bf215546Sopenharmony_ci   /*  copy the semantic name */
410bf215546Sopenharmony_ci   uint32_t retval = string_out->length;
411bf215546Sopenharmony_ci   size_t name_len = strlen(name) + 1;
412bf215546Sopenharmony_ci   _mesa_string_buffer_append_len(string_out, name, name_len);
413bf215546Sopenharmony_ci   return retval;
414bf215546Sopenharmony_ci}
415bf215546Sopenharmony_ci
416bf215546Sopenharmony_cistatic
417bf215546Sopenharmony_ciuint32_t
418bf215546Sopenharmony_ciappend_semantic_index_to_table(struct dxil_psv_sem_index_table *table, uint32_t index,
419bf215546Sopenharmony_ci                               uint32_t num_rows)
420bf215546Sopenharmony_ci{
421bf215546Sopenharmony_ci   for (unsigned i = 0; i < table->size; ++i) {
422bf215546Sopenharmony_ci      unsigned j = 0;
423bf215546Sopenharmony_ci      for (; j < num_rows && i + j < table->size; ++j)
424bf215546Sopenharmony_ci         if (table->data[i + j] != index + j)
425bf215546Sopenharmony_ci            break;
426bf215546Sopenharmony_ci      if (j == num_rows)
427bf215546Sopenharmony_ci         return i;
428bf215546Sopenharmony_ci      else if (j > 0)
429bf215546Sopenharmony_ci         i += j - 1;
430bf215546Sopenharmony_ci   }
431bf215546Sopenharmony_ci   uint32_t retval = table->size;
432bf215546Sopenharmony_ci   assert(table->size + num_rows <= 80);
433bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_rows; ++i)
434bf215546Sopenharmony_ci      table->data[table->size++] = index + i;
435bf215546Sopenharmony_ci   return retval;
436bf215546Sopenharmony_ci}
437bf215546Sopenharmony_ci
438bf215546Sopenharmony_cistatic const struct dxil_mdnode *
439bf215546Sopenharmony_cifill_SV_param_nodes(struct dxil_module *mod, unsigned record_id,
440bf215546Sopenharmony_ci                    const struct dxil_signature_record *rec,
441bf215546Sopenharmony_ci                    const struct dxil_psv_signature_element *psv,
442bf215546Sopenharmony_ci                    bool is_input) {
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci   const struct dxil_mdnode *SV_params_nodes[11];
445bf215546Sopenharmony_ci   /* For this to always work we should use vectorize_io, but for FS out and VS in
446bf215546Sopenharmony_ci    * this is not implemented globally */
447bf215546Sopenharmony_ci   const struct dxil_mdnode *flattened_semantics[256];
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci   for (unsigned i = 0; i < rec->num_elements; ++i)
450bf215546Sopenharmony_ci      flattened_semantics[i] = dxil_get_metadata_int32(mod, rec->elements[i].semantic_index);
451bf215546Sopenharmony_ci
452bf215546Sopenharmony_ci   SV_params_nodes[0] = dxil_get_metadata_int32(mod, (int)record_id); // Unique element ID
453bf215546Sopenharmony_ci   SV_params_nodes[1] = dxil_get_metadata_string(mod, rec->name); // Element name
454bf215546Sopenharmony_ci   SV_params_nodes[2] = dxil_get_metadata_int8(mod, rec->sig_comp_type); // Element type
455bf215546Sopenharmony_ci   SV_params_nodes[3] = dxil_get_metadata_int8(mod, (int8_t)psv->semantic_kind); // Effective system value
456bf215546Sopenharmony_ci   SV_params_nodes[4] = dxil_get_metadata_node(mod, flattened_semantics,
457bf215546Sopenharmony_ci                                               rec->num_elements); // Semantic index vector
458bf215546Sopenharmony_ci   SV_params_nodes[5] = dxil_get_metadata_int8(mod, psv->interpolation_mode); // Interpolation mode
459bf215546Sopenharmony_ci   SV_params_nodes[6] = dxil_get_metadata_int32(mod, psv->rows); // Number of rows
460bf215546Sopenharmony_ci   SV_params_nodes[7] = dxil_get_metadata_int8(mod, psv->cols_and_start & 0xf); // Number of columns
461bf215546Sopenharmony_ci   SV_params_nodes[8] = dxil_get_metadata_int32(mod, rec->elements[0].reg); // Element packing start row
462bf215546Sopenharmony_ci   SV_params_nodes[9] = dxil_get_metadata_int8(mod, (psv->cols_and_start >> 4) & 0x3); // Element packing start column
463bf215546Sopenharmony_ci
464bf215546Sopenharmony_ci   const struct dxil_mdnode *SV_metadata[6];
465bf215546Sopenharmony_ci   unsigned num_metadata_nodes = 0;
466bf215546Sopenharmony_ci   if (rec->elements[0].stream != 0) {
467bf215546Sopenharmony_ci      SV_metadata[num_metadata_nodes++] = dxil_get_metadata_int32(mod, DXIL_SIGNATURE_ELEMENT_OUTPUT_STREAM);
468bf215546Sopenharmony_ci      SV_metadata[num_metadata_nodes++] = dxil_get_metadata_int32(mod, rec->elements[0].stream);
469bf215546Sopenharmony_ci   }
470bf215546Sopenharmony_ci   uint8_t usage_mask = rec->elements[0].always_reads_mask;
471bf215546Sopenharmony_ci   if (!is_input)
472bf215546Sopenharmony_ci      usage_mask = 0xf & ~rec->elements[0].never_writes_mask;
473bf215546Sopenharmony_ci   if (usage_mask && mod->minor_validator >= 5) {
474bf215546Sopenharmony_ci      usage_mask >>= (psv->cols_and_start >> 4) & 0x3;
475bf215546Sopenharmony_ci      SV_metadata[num_metadata_nodes++] = dxil_get_metadata_int32(mod, DXIL_SIGNATURE_ELEMENT_USAGE_COMPONENT_MASK);
476bf215546Sopenharmony_ci      SV_metadata[num_metadata_nodes++] = dxil_get_metadata_int8(mod, usage_mask);
477bf215546Sopenharmony_ci   }
478bf215546Sopenharmony_ci
479bf215546Sopenharmony_ci   uint8_t dynamic_index_mask = psv->dynamic_mask_and_stream & 0xf;
480bf215546Sopenharmony_ci   if (dynamic_index_mask) {
481bf215546Sopenharmony_ci      SV_metadata[num_metadata_nodes++] = dxil_get_metadata_int32(mod, DXIL_SIGNATURE_ELEMENT_DYNAMIC_INDEX_COMPONENT_MASK);
482bf215546Sopenharmony_ci      SV_metadata[num_metadata_nodes++] = dxil_get_metadata_int8(mod, dynamic_index_mask);
483bf215546Sopenharmony_ci   }
484bf215546Sopenharmony_ci
485bf215546Sopenharmony_ci   SV_params_nodes[10] = num_metadata_nodes ? dxil_get_metadata_node(mod, SV_metadata, num_metadata_nodes) : NULL;
486bf215546Sopenharmony_ci
487bf215546Sopenharmony_ci   return dxil_get_metadata_node(mod, SV_params_nodes, ARRAY_SIZE(SV_params_nodes));
488bf215546Sopenharmony_ci}
489bf215546Sopenharmony_ci
490bf215546Sopenharmony_cistatic void
491bf215546Sopenharmony_cifill_signature_element(struct dxil_signature_element *elm,
492bf215546Sopenharmony_ci                       struct semantic_info *semantic,
493bf215546Sopenharmony_ci                       unsigned row)
494bf215546Sopenharmony_ci{
495bf215546Sopenharmony_ci   memset(elm, 0, sizeof(struct dxil_signature_element));
496bf215546Sopenharmony_ci   elm->stream = semantic->stream;
497bf215546Sopenharmony_ci   // elm->semantic_name_offset = 0;  // Offset needs to be filled out when writing
498bf215546Sopenharmony_ci   elm->semantic_index = semantic->index + row;
499bf215546Sopenharmony_ci   elm->system_value = (uint32_t) prog_semantic_from_kind(semantic->kind, semantic->rows, row);
500bf215546Sopenharmony_ci   elm->comp_type = (uint32_t) semantic->comp_type;
501bf215546Sopenharmony_ci   elm->reg = semantic->start_row + row;
502bf215546Sopenharmony_ci
503bf215546Sopenharmony_ci   assert(semantic->cols + semantic->start_col <= 4);
504bf215546Sopenharmony_ci   elm->mask = (uint8_t) (((1 << semantic->cols) - 1) << semantic->start_col);
505bf215546Sopenharmony_ci   elm->min_precision = DXIL_MIN_PREC_DEFAULT;
506bf215546Sopenharmony_ci}
507bf215546Sopenharmony_ci
508bf215546Sopenharmony_cistatic bool
509bf215546Sopenharmony_cifill_psv_signature_element(struct dxil_psv_signature_element *psv_elm,
510bf215546Sopenharmony_ci                           struct semantic_info *semantic, struct dxil_module *mod)
511bf215546Sopenharmony_ci{
512bf215546Sopenharmony_ci   memset(psv_elm, 0, sizeof(struct dxil_psv_signature_element));
513bf215546Sopenharmony_ci   psv_elm->rows = semantic->rows;
514bf215546Sopenharmony_ci   if (semantic->start_row >= 0) {
515bf215546Sopenharmony_ci      assert(semantic->start_row < 256);
516bf215546Sopenharmony_ci      psv_elm->start_row = semantic->start_row;
517bf215546Sopenharmony_ci      psv_elm->cols_and_start = (1u << 6) | (semantic->start_col << 4) | semantic->cols;
518bf215546Sopenharmony_ci   } else {
519bf215546Sopenharmony_ci      /* The validation expects that the the start row is not egative
520bf215546Sopenharmony_ci       * and apparently the extra bit in the cols_and_start indicates that the
521bf215546Sopenharmony_ci       * row is meant literally, so don't set it in this case.
522bf215546Sopenharmony_ci       * (Source of information: Comparing with the validation structures
523bf215546Sopenharmony_ci       * created by dxcompiler)
524bf215546Sopenharmony_ci       */
525bf215546Sopenharmony_ci      psv_elm->start_row = 0;
526bf215546Sopenharmony_ci      psv_elm->cols_and_start = (semantic->start_col << 4) | semantic->cols;
527bf215546Sopenharmony_ci   }
528bf215546Sopenharmony_ci   psv_elm->semantic_kind = (uint8_t)semantic->kind;
529bf215546Sopenharmony_ci   psv_elm->component_type = semantic->comp_type;
530bf215546Sopenharmony_ci   psv_elm->interpolation_mode = semantic->interpolation;
531bf215546Sopenharmony_ci   psv_elm->dynamic_mask_and_stream = (semantic->stream) << 4;
532bf215546Sopenharmony_ci   if (semantic->kind == DXIL_SEM_ARBITRARY && strlen(semantic->name)) {
533bf215546Sopenharmony_ci      psv_elm->semantic_name_offset =
534bf215546Sopenharmony_ci            copy_semantic_name_to_string(mod->sem_string_table, semantic->name);
535bf215546Sopenharmony_ci
536bf215546Sopenharmony_ci      /* TODO: clean up memory */
537bf215546Sopenharmony_ci      if (psv_elm->semantic_name_offset == (uint32_t)-1)
538bf215546Sopenharmony_ci         return false;
539bf215546Sopenharmony_ci   }
540bf215546Sopenharmony_ci
541bf215546Sopenharmony_ci   psv_elm->semantic_indexes_offset =
542bf215546Sopenharmony_ci         append_semantic_index_to_table(&mod->sem_index_table, semantic->index, semantic->rows);
543bf215546Sopenharmony_ci
544bf215546Sopenharmony_ci   return true;
545bf215546Sopenharmony_ci}
546bf215546Sopenharmony_ci
547bf215546Sopenharmony_cistatic bool
548bf215546Sopenharmony_cifill_io_signature(struct dxil_module *mod, int id,
549bf215546Sopenharmony_ci                  struct semantic_info *semantic,
550bf215546Sopenharmony_ci                  struct dxil_signature_record *rec,
551bf215546Sopenharmony_ci                  struct dxil_psv_signature_element *psv_elm)
552bf215546Sopenharmony_ci{
553bf215546Sopenharmony_ci   rec->name = ralloc_strdup(mod->ralloc_ctx, semantic->name);
554bf215546Sopenharmony_ci   rec->num_elements = semantic->rows;
555bf215546Sopenharmony_ci   rec->sig_comp_type = semantic->sig_comp_type;
556bf215546Sopenharmony_ci
557bf215546Sopenharmony_ci   for (unsigned i = 0; i < semantic->rows; ++i)
558bf215546Sopenharmony_ci      fill_signature_element(&rec->elements[i], semantic, i);
559bf215546Sopenharmony_ci   return fill_psv_signature_element(psv_elm, semantic, mod);
560bf215546Sopenharmony_ci}
561bf215546Sopenharmony_ci
562bf215546Sopenharmony_cistatic unsigned
563bf215546Sopenharmony_ciget_input_signature_group(struct dxil_module *mod,
564bf215546Sopenharmony_ci                          unsigned num_inputs,
565bf215546Sopenharmony_ci                          nir_shader *s, nir_variable_mode modes,
566bf215546Sopenharmony_ci                          semantic_info_proc get_semantics, unsigned *row_iter,
567bf215546Sopenharmony_ci                          unsigned input_clip_size)
568bf215546Sopenharmony_ci{
569bf215546Sopenharmony_ci   nir_foreach_variable_with_modes(var, s, modes) {
570bf215546Sopenharmony_ci      if (var->data.patch)
571bf215546Sopenharmony_ci         continue;
572bf215546Sopenharmony_ci
573bf215546Sopenharmony_ci      struct semantic_info semantic = {0};
574bf215546Sopenharmony_ci      get_semantics(var, &semantic, s->info.stage);
575bf215546Sopenharmony_ci      mod->inputs[num_inputs].sysvalue = semantic.sysvalue_name;
576bf215546Sopenharmony_ci      *row_iter = get_additional_semantic_info(s, var, &semantic, *row_iter, input_clip_size);
577bf215546Sopenharmony_ci
578bf215546Sopenharmony_ci      mod->input_mappings[var->data.driver_location] = num_inputs;
579bf215546Sopenharmony_ci      struct dxil_psv_signature_element *psv_elm = &mod->psv_inputs[num_inputs];
580bf215546Sopenharmony_ci
581bf215546Sopenharmony_ci      if (!fill_io_signature(mod, num_inputs, &semantic,
582bf215546Sopenharmony_ci                             &mod->inputs[num_inputs], psv_elm))
583bf215546Sopenharmony_ci         return 0;
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci      mod->num_psv_inputs = MAX2(mod->num_psv_inputs,
586bf215546Sopenharmony_ci                                 semantic.start_row + semantic.rows);
587bf215546Sopenharmony_ci
588bf215546Sopenharmony_ci      ++num_inputs;
589bf215546Sopenharmony_ci      assert(num_inputs < VARYING_SLOT_MAX);
590bf215546Sopenharmony_ci   }
591bf215546Sopenharmony_ci   return num_inputs;
592bf215546Sopenharmony_ci}
593bf215546Sopenharmony_ci
594bf215546Sopenharmony_cistatic void
595bf215546Sopenharmony_ciprocess_input_signature(struct dxil_module *mod, nir_shader *s, unsigned input_clip_size)
596bf215546Sopenharmony_ci{
597bf215546Sopenharmony_ci   if (s->info.stage == MESA_SHADER_KERNEL)
598bf215546Sopenharmony_ci      return;
599bf215546Sopenharmony_ci   unsigned next_row = 0;
600bf215546Sopenharmony_ci
601bf215546Sopenharmony_ci   mod->num_sig_inputs = get_input_signature_group(mod, 0,
602bf215546Sopenharmony_ci                                                   s, nir_var_shader_in,
603bf215546Sopenharmony_ci                                                   s->info.stage == MESA_SHADER_VERTEX ?
604bf215546Sopenharmony_ci                                                      get_semantic_vs_in_name : get_semantic_in_name,
605bf215546Sopenharmony_ci                                                   &next_row, input_clip_size);
606bf215546Sopenharmony_ci
607bf215546Sopenharmony_ci   mod->num_sig_inputs = get_input_signature_group(mod, mod->num_sig_inputs,
608bf215546Sopenharmony_ci                                                   s, nir_var_system_value,
609bf215546Sopenharmony_ci                                                   get_semantic_sv_name,
610bf215546Sopenharmony_ci                                                   &next_row, input_clip_size);
611bf215546Sopenharmony_ci
612bf215546Sopenharmony_ci}
613bf215546Sopenharmony_ci
614bf215546Sopenharmony_cistatic const char *out_sysvalue_name(nir_variable *var)
615bf215546Sopenharmony_ci{
616bf215546Sopenharmony_ci   switch (var->data.location) {
617bf215546Sopenharmony_ci   case VARYING_SLOT_FACE:
618bf215546Sopenharmony_ci      return "FACE";
619bf215546Sopenharmony_ci   case VARYING_SLOT_POS:
620bf215546Sopenharmony_ci      return "POS";
621bf215546Sopenharmony_ci   case VARYING_SLOT_CLIP_DIST0:
622bf215546Sopenharmony_ci   case VARYING_SLOT_CLIP_DIST1:
623bf215546Sopenharmony_ci      return "CLIPDST";
624bf215546Sopenharmony_ci   case VARYING_SLOT_PRIMITIVE_ID:
625bf215546Sopenharmony_ci      return "PRIMID";
626bf215546Sopenharmony_ci   default:
627bf215546Sopenharmony_ci      return "NO";
628bf215546Sopenharmony_ci   }
629bf215546Sopenharmony_ci}
630bf215546Sopenharmony_ci
631bf215546Sopenharmony_cistatic void
632bf215546Sopenharmony_ciprocess_output_signature(struct dxil_module *mod, nir_shader *s)
633bf215546Sopenharmony_ci{
634bf215546Sopenharmony_ci   unsigned num_outputs = 0;
635bf215546Sopenharmony_ci   unsigned next_row = 0;
636bf215546Sopenharmony_ci   nir_foreach_variable_with_modes(var, s, nir_var_shader_out) {
637bf215546Sopenharmony_ci      struct semantic_info semantic = {0};
638bf215546Sopenharmony_ci      if (var->data.patch)
639bf215546Sopenharmony_ci         continue;
640bf215546Sopenharmony_ci
641bf215546Sopenharmony_ci      if (s->info.stage == MESA_SHADER_FRAGMENT) {
642bf215546Sopenharmony_ci         get_semantic_ps_outname(var, &semantic);
643bf215546Sopenharmony_ci         mod->outputs[num_outputs].sysvalue = "TARGET";
644bf215546Sopenharmony_ci      } else {
645bf215546Sopenharmony_ci         const struct glsl_type *type = var->type;
646bf215546Sopenharmony_ci         if (nir_is_arrayed_io(var, s->info.stage))
647bf215546Sopenharmony_ci            type = glsl_get_array_element(type);
648bf215546Sopenharmony_ci         get_semantic_name(var, &semantic, type);
649bf215546Sopenharmony_ci         mod->outputs[num_outputs].sysvalue = out_sysvalue_name(var);
650bf215546Sopenharmony_ci      }
651bf215546Sopenharmony_ci      next_row = get_additional_semantic_info(s, var, &semantic, next_row, s->info.clip_distance_array_size);
652bf215546Sopenharmony_ci
653bf215546Sopenharmony_ci      mod->info.has_out_position |= semantic.kind== DXIL_SEM_POSITION;
654bf215546Sopenharmony_ci      mod->info.has_out_depth |= semantic.kind == DXIL_SEM_DEPTH;
655bf215546Sopenharmony_ci
656bf215546Sopenharmony_ci      struct dxil_psv_signature_element *psv_elm = &mod->psv_outputs[num_outputs];
657bf215546Sopenharmony_ci
658bf215546Sopenharmony_ci      if (!fill_io_signature(mod, num_outputs, &semantic,
659bf215546Sopenharmony_ci                             &mod->outputs[num_outputs], psv_elm))
660bf215546Sopenharmony_ci         return;
661bf215546Sopenharmony_ci
662bf215546Sopenharmony_ci      for (unsigned i = 0; i < mod->outputs[num_outputs].num_elements; ++i) {
663bf215546Sopenharmony_ci         struct dxil_signature_element *elm = &mod->outputs[num_outputs].elements[i];
664bf215546Sopenharmony_ci         if (mod->minor_validator <= 4)
665bf215546Sopenharmony_ci            elm->never_writes_mask = 0xff & ~elm->mask;
666bf215546Sopenharmony_ci         else
667bf215546Sopenharmony_ci            /* This will be updated by the module processing */
668bf215546Sopenharmony_ci            elm->never_writes_mask = 0xf & ~elm->mask;
669bf215546Sopenharmony_ci      }
670bf215546Sopenharmony_ci
671bf215546Sopenharmony_ci      ++num_outputs;
672bf215546Sopenharmony_ci
673bf215546Sopenharmony_ci      mod->num_psv_outputs[semantic.stream] = MAX2(mod->num_psv_outputs[semantic.stream],
674bf215546Sopenharmony_ci                                                   semantic.start_row + semantic.rows);
675bf215546Sopenharmony_ci   }
676bf215546Sopenharmony_ci   mod->num_sig_outputs = num_outputs;
677bf215546Sopenharmony_ci}
678bf215546Sopenharmony_ci
679bf215546Sopenharmony_cistatic const char *
680bf215546Sopenharmony_cipatch_sysvalue_name(nir_variable *var)
681bf215546Sopenharmony_ci{
682bf215546Sopenharmony_ci   switch (var->data.location) {
683bf215546Sopenharmony_ci   case VARYING_SLOT_TESS_LEVEL_OUTER:
684bf215546Sopenharmony_ci      switch (glsl_get_aoa_size(var->type)) {
685bf215546Sopenharmony_ci      case 4:
686bf215546Sopenharmony_ci         return "QUADEDGE";
687bf215546Sopenharmony_ci      case 3:
688bf215546Sopenharmony_ci         return "TRIEDGE";
689bf215546Sopenharmony_ci      case 2:
690bf215546Sopenharmony_ci         return var->data.location_frac == 0 ?
691bf215546Sopenharmony_ci            "LINEDET" : "LINEDEN";
692bf215546Sopenharmony_ci      default:
693bf215546Sopenharmony_ci         unreachable("Unexpected outer tess factor array size");
694bf215546Sopenharmony_ci      }
695bf215546Sopenharmony_ci      break;
696bf215546Sopenharmony_ci   case VARYING_SLOT_TESS_LEVEL_INNER:
697bf215546Sopenharmony_ci      switch (glsl_get_aoa_size(var->type)) {
698bf215546Sopenharmony_ci      case 2:
699bf215546Sopenharmony_ci         return "QUADINT";
700bf215546Sopenharmony_ci      case 1:
701bf215546Sopenharmony_ci         return "TRIINT";
702bf215546Sopenharmony_ci      default:
703bf215546Sopenharmony_ci         unreachable("Unexpected inner tess factory array size");
704bf215546Sopenharmony_ci      }
705bf215546Sopenharmony_ci      break;
706bf215546Sopenharmony_ci   default:
707bf215546Sopenharmony_ci      return "NO";
708bf215546Sopenharmony_ci   }
709bf215546Sopenharmony_ci}
710bf215546Sopenharmony_ci
711bf215546Sopenharmony_cistatic void
712bf215546Sopenharmony_ciprocess_patch_const_signature(struct dxil_module *mod, nir_shader *s)
713bf215546Sopenharmony_ci{
714bf215546Sopenharmony_ci   if (s->info.stage != MESA_SHADER_TESS_CTRL &&
715bf215546Sopenharmony_ci       s->info.stage != MESA_SHADER_TESS_EVAL)
716bf215546Sopenharmony_ci      return;
717bf215546Sopenharmony_ci
718bf215546Sopenharmony_ci   nir_variable_mode mode = s->info.stage == MESA_SHADER_TESS_CTRL ?
719bf215546Sopenharmony_ci      nir_var_shader_out : nir_var_shader_in;
720bf215546Sopenharmony_ci   unsigned num_consts = 0;
721bf215546Sopenharmony_ci   unsigned next_row = 0;
722bf215546Sopenharmony_ci   nir_foreach_variable_with_modes(var, s, mode) {
723bf215546Sopenharmony_ci      struct semantic_info semantic = {0};
724bf215546Sopenharmony_ci      if (!var->data.patch)
725bf215546Sopenharmony_ci         continue;
726bf215546Sopenharmony_ci
727bf215546Sopenharmony_ci      const struct glsl_type *type = var->type;
728bf215546Sopenharmony_ci      get_semantic_name(var, &semantic, type);
729bf215546Sopenharmony_ci
730bf215546Sopenharmony_ci      mod->patch_consts[num_consts].sysvalue = patch_sysvalue_name(var);
731bf215546Sopenharmony_ci      next_row = get_additional_semantic_info(s, var, &semantic, next_row, 0);
732bf215546Sopenharmony_ci
733bf215546Sopenharmony_ci      struct dxil_psv_signature_element *psv_elm = &mod->psv_patch_consts[num_consts];
734bf215546Sopenharmony_ci
735bf215546Sopenharmony_ci      if (!fill_io_signature(mod, num_consts, &semantic,
736bf215546Sopenharmony_ci                             &mod->patch_consts[num_consts], psv_elm))
737bf215546Sopenharmony_ci         return;
738bf215546Sopenharmony_ci
739bf215546Sopenharmony_ci      if (mode == nir_var_shader_out) {
740bf215546Sopenharmony_ci         for (unsigned i = 0; i < mod->patch_consts[num_consts].num_elements; ++i) {
741bf215546Sopenharmony_ci            struct dxil_signature_element *elm = &mod->patch_consts[num_consts].elements[i];
742bf215546Sopenharmony_ci            if (mod->minor_validator <= 4)
743bf215546Sopenharmony_ci               elm->never_writes_mask = 0xff & ~elm->mask;
744bf215546Sopenharmony_ci            else
745bf215546Sopenharmony_ci               /* This will be updated by the module processing */
746bf215546Sopenharmony_ci               elm->never_writes_mask = 0xf & ~elm->mask;
747bf215546Sopenharmony_ci         }
748bf215546Sopenharmony_ci      }
749bf215546Sopenharmony_ci
750bf215546Sopenharmony_ci      ++num_consts;
751bf215546Sopenharmony_ci
752bf215546Sopenharmony_ci      mod->num_psv_patch_consts = MAX2(mod->num_psv_patch_consts,
753bf215546Sopenharmony_ci                                       semantic.start_row + semantic.rows);
754bf215546Sopenharmony_ci   }
755bf215546Sopenharmony_ci   mod->num_sig_patch_consts = num_consts;
756bf215546Sopenharmony_ci}
757bf215546Sopenharmony_ci
758bf215546Sopenharmony_civoid
759bf215546Sopenharmony_cipreprocess_signatures(struct dxil_module *mod, nir_shader *s, unsigned input_clip_size)
760bf215546Sopenharmony_ci{
761bf215546Sopenharmony_ci   /* DXC does the same: Add an empty string before everything else */
762bf215546Sopenharmony_ci   mod->sem_string_table = _mesa_string_buffer_create(mod->ralloc_ctx, 1024);
763bf215546Sopenharmony_ci   copy_semantic_name_to_string(mod->sem_string_table, "");
764bf215546Sopenharmony_ci
765bf215546Sopenharmony_ci   process_input_signature(mod, s, input_clip_size);
766bf215546Sopenharmony_ci   process_output_signature(mod, s);
767bf215546Sopenharmony_ci   process_patch_const_signature(mod, s);
768bf215546Sopenharmony_ci}
769bf215546Sopenharmony_ci
770bf215546Sopenharmony_cistatic const struct dxil_mdnode *
771bf215546Sopenharmony_ciget_signature_metadata(struct dxil_module *mod,
772bf215546Sopenharmony_ci                       const struct dxil_signature_record *recs,
773bf215546Sopenharmony_ci                       const struct dxil_psv_signature_element *psvs,
774bf215546Sopenharmony_ci                       unsigned num_elements,
775bf215546Sopenharmony_ci                       bool is_input)
776bf215546Sopenharmony_ci{
777bf215546Sopenharmony_ci   if (num_elements == 0)
778bf215546Sopenharmony_ci      return NULL;
779bf215546Sopenharmony_ci
780bf215546Sopenharmony_ci   const struct dxil_mdnode *nodes[VARYING_SLOT_MAX];
781bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_elements; ++i) {
782bf215546Sopenharmony_ci      nodes[i] = fill_SV_param_nodes(mod, i, &recs[i], &psvs[i], is_input);
783bf215546Sopenharmony_ci   }
784bf215546Sopenharmony_ci
785bf215546Sopenharmony_ci   return dxil_get_metadata_node(mod, nodes, num_elements);
786bf215546Sopenharmony_ci}
787bf215546Sopenharmony_ci
788bf215546Sopenharmony_ciconst struct dxil_mdnode *
789bf215546Sopenharmony_ciget_signatures(struct dxil_module *mod)
790bf215546Sopenharmony_ci{
791bf215546Sopenharmony_ci   const struct dxil_mdnode *input_signature = get_signature_metadata(mod, mod->inputs, mod->psv_inputs, mod->num_sig_inputs, true);
792bf215546Sopenharmony_ci   const struct dxil_mdnode *output_signature = get_signature_metadata(mod, mod->outputs, mod->psv_outputs, mod->num_sig_outputs, false);
793bf215546Sopenharmony_ci   const struct dxil_mdnode *patch_const_signature = get_signature_metadata(mod, mod->patch_consts, mod->psv_patch_consts, mod->num_sig_patch_consts,
794bf215546Sopenharmony_ci      mod->shader_kind == DXIL_DOMAIN_SHADER);
795bf215546Sopenharmony_ci
796bf215546Sopenharmony_ci   const struct dxil_mdnode *SV_nodes[3] = {
797bf215546Sopenharmony_ci      input_signature,
798bf215546Sopenharmony_ci      output_signature,
799bf215546Sopenharmony_ci      patch_const_signature
800bf215546Sopenharmony_ci   };
801bf215546Sopenharmony_ci   if (output_signature || input_signature || patch_const_signature)
802bf215546Sopenharmony_ci      return dxil_get_metadata_node(mod, SV_nodes, ARRAY_SIZE(SV_nodes));
803bf215546Sopenharmony_ci   else
804bf215546Sopenharmony_ci      return NULL;
805bf215546Sopenharmony_ci}
806