1bf215546Sopenharmony_ci/**************************************************************************
2bf215546Sopenharmony_ci *
3bf215546Sopenharmony_ci * Copyright 2020 Red Hat.
4bf215546Sopenharmony_ci * All Rights Reserved.
5bf215546Sopenharmony_ci *
6bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
7bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
8bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
9bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
10bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
11bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
12bf215546Sopenharmony_ci *
13bf215546Sopenharmony_ci * The above copyright notice and this permission notice shall be included
14bf215546Sopenharmony_ci * in all copies or substantial portions of the Software.
15bf215546Sopenharmony_ci *
16bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
19bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20bf215546Sopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21bf215546Sopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22bf215546Sopenharmony_ci * SOFTWARE.
23bf215546Sopenharmony_ci *
24bf215546Sopenharmony_ci **************************************************************************/
25bf215546Sopenharmony_ci#include "draw_tess.h"
26bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
27bf215546Sopenharmony_ci#include "draw_llvm.h"
28bf215546Sopenharmony_ci#endif
29bf215546Sopenharmony_ci
30bf215546Sopenharmony_ci#include "tessellator/p_tessellator.h"
31bf215546Sopenharmony_ci#include "nir/nir_to_tgsi_info.h"
32bf215546Sopenharmony_ci#include "util/u_prim.h"
33bf215546Sopenharmony_ci#include "util/u_math.h"
34bf215546Sopenharmony_ci#include "util/u_memory.h"
35bf215546Sopenharmony_ci#include "util/ralloc.h"
36bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
37bf215546Sopenharmony_cistatic inline int
38bf215546Sopenharmony_cidraw_tes_get_input_index(int semantic, int index,
39bf215546Sopenharmony_ci                         const struct tgsi_shader_info *input_info)
40bf215546Sopenharmony_ci{
41bf215546Sopenharmony_ci   int i;
42bf215546Sopenharmony_ci   const ubyte *input_semantic_names = input_info->output_semantic_name;
43bf215546Sopenharmony_ci   const ubyte *input_semantic_indices = input_info->output_semantic_index;
44bf215546Sopenharmony_ci   for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {
45bf215546Sopenharmony_ci      if (input_semantic_names[i] == semantic &&
46bf215546Sopenharmony_ci          input_semantic_indices[i] == index)
47bf215546Sopenharmony_ci         return i;
48bf215546Sopenharmony_ci   }
49bf215546Sopenharmony_ci   return -1;
50bf215546Sopenharmony_ci}
51bf215546Sopenharmony_ci
52bf215546Sopenharmony_ci#define DEBUG_INPUTS 0
53bf215546Sopenharmony_cistatic void
54bf215546Sopenharmony_cillvm_fetch_tcs_input(struct draw_tess_ctrl_shader *shader,
55bf215546Sopenharmony_ci                     const struct draw_prim_info *input_prim_info,
56bf215546Sopenharmony_ci                     unsigned prim_id,
57bf215546Sopenharmony_ci                     unsigned num_vertices)
58bf215546Sopenharmony_ci{
59bf215546Sopenharmony_ci   const float (*input_ptr)[4];
60bf215546Sopenharmony_ci   float (*input_data)[32][NUM_TCS_INPUTS][TGSI_NUM_CHANNELS] = &shader->tcs_input->data;
61bf215546Sopenharmony_ci   unsigned slot, i;
62bf215546Sopenharmony_ci   int vs_slot;
63bf215546Sopenharmony_ci   unsigned input_vertex_stride = shader->input_vertex_stride;
64bf215546Sopenharmony_ci
65bf215546Sopenharmony_ci   input_ptr = shader->input;
66bf215546Sopenharmony_ci   for (i = 0; i < num_vertices; i++) {
67bf215546Sopenharmony_ci      const float (*input)[4];
68bf215546Sopenharmony_ci      int vertex_idx = prim_id * num_vertices + i;
69bf215546Sopenharmony_ci      if (input_prim_info->linear == FALSE)
70bf215546Sopenharmony_ci         vertex_idx = input_prim_info->elts[vertex_idx];
71bf215546Sopenharmony_ci#if DEBUG_INPUTS
72bf215546Sopenharmony_ci      debug_printf("%d) tcs vertex index = %d (prim idx = %d)\n",
73bf215546Sopenharmony_ci                   i, prim_id, 0);
74bf215546Sopenharmony_ci#endif
75bf215546Sopenharmony_ci      input = (const float (*)[4])((const char *)input_ptr + (vertex_idx * input_vertex_stride));
76bf215546Sopenharmony_ci      for (slot = 0, vs_slot = 0; slot < shader->info.num_inputs; ++slot) {
77bf215546Sopenharmony_ci         vs_slot = draw_tes_get_input_index(
78bf215546Sopenharmony_ci                                            shader->info.input_semantic_name[slot],
79bf215546Sopenharmony_ci                                            shader->info.input_semantic_index[slot],
80bf215546Sopenharmony_ci                                            shader->input_info);
81bf215546Sopenharmony_ci         if (vs_slot < 0) {
82bf215546Sopenharmony_ci            debug_printf("VS/TCS signature mismatch!\n");
83bf215546Sopenharmony_ci            (*input_data)[i][slot][0] = 0;
84bf215546Sopenharmony_ci            (*input_data)[i][slot][1] = 0;
85bf215546Sopenharmony_ci            (*input_data)[i][slot][2] = 0;
86bf215546Sopenharmony_ci            (*input_data)[i][slot][3] = 0;
87bf215546Sopenharmony_ci         } else {
88bf215546Sopenharmony_ci            (*input_data)[i][slot][0] = input[vs_slot][0];
89bf215546Sopenharmony_ci            (*input_data)[i][slot][1] = input[vs_slot][1];
90bf215546Sopenharmony_ci            (*input_data)[i][slot][2] = input[vs_slot][2];
91bf215546Sopenharmony_ci            (*input_data)[i][slot][3] = input[vs_slot][3];
92bf215546Sopenharmony_ci#if DEBUG_INPUTS
93bf215546Sopenharmony_ci            debug_printf("\t\t%p = %f %f %f %f\n", &(*input_data)[i][slot][0],
94bf215546Sopenharmony_ci                         (*input_data)[i][slot][0],
95bf215546Sopenharmony_ci                         (*input_data)[i][slot][1],
96bf215546Sopenharmony_ci                         (*input_data)[i][slot][2],
97bf215546Sopenharmony_ci                         (*input_data)[i][slot][3]);
98bf215546Sopenharmony_ci#endif
99bf215546Sopenharmony_ci            ++vs_slot;
100bf215546Sopenharmony_ci         }
101bf215546Sopenharmony_ci      }
102bf215546Sopenharmony_ci   }
103bf215546Sopenharmony_ci}
104bf215546Sopenharmony_ci
105bf215546Sopenharmony_ci#define DEBUG_OUTPUTS 0
106bf215546Sopenharmony_cistatic void
107bf215546Sopenharmony_cillvm_store_tcs_output(struct draw_tess_ctrl_shader *shader,
108bf215546Sopenharmony_ci                      unsigned prim_id,
109bf215546Sopenharmony_ci                      struct draw_vertex_info *output_verts,
110bf215546Sopenharmony_ci                      unsigned vert_start)
111bf215546Sopenharmony_ci{
112bf215546Sopenharmony_ci   float (*output_ptr)[4];
113bf215546Sopenharmony_ci   float (*output_data)[32][PIPE_MAX_SHADER_INPUTS][TGSI_NUM_CHANNELS] = &shader->tcs_output->data;
114bf215546Sopenharmony_ci   unsigned slot, i;
115bf215546Sopenharmony_ci   unsigned num_vertices = shader->vertices_out;
116bf215546Sopenharmony_ci
117bf215546Sopenharmony_ci   char *output = (char *)output_verts->verts->data;
118bf215546Sopenharmony_ci   output += vert_start * output_verts->stride;
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_ci   for (i = 0; i < num_vertices; i++) {
121bf215546Sopenharmony_ci
122bf215546Sopenharmony_ci#if DEBUG_OUTPUTS
123bf215546Sopenharmony_ci      debug_printf("%d) tcs store vertex index = %d (prim idx = %d)\n",
124bf215546Sopenharmony_ci                   i, prim_id, 0);
125bf215546Sopenharmony_ci#endif
126bf215546Sopenharmony_ci      output_ptr = (float(*)[4])(output + (i * output_verts->stride));
127bf215546Sopenharmony_ci
128bf215546Sopenharmony_ci      for (slot = 0; slot < shader->info.num_outputs; ++slot) {
129bf215546Sopenharmony_ci         output_ptr[slot][0] = (*output_data)[i][slot][0];
130bf215546Sopenharmony_ci         output_ptr[slot][1] = (*output_data)[i][slot][1];
131bf215546Sopenharmony_ci         output_ptr[slot][2] = (*output_data)[i][slot][2];
132bf215546Sopenharmony_ci         output_ptr[slot][3] = (*output_data)[i][slot][3];
133bf215546Sopenharmony_ci#if DEBUG_OUTPUTS
134bf215546Sopenharmony_ci         debug_printf("\t\t%p = %f %f %f %f\n",
135bf215546Sopenharmony_ci                      &output_ptr[slot][0],
136bf215546Sopenharmony_ci                      output_ptr[slot][0],
137bf215546Sopenharmony_ci                      output_ptr[slot][1],
138bf215546Sopenharmony_ci                      output_ptr[slot][2],
139bf215546Sopenharmony_ci                      output_ptr[slot][3]);
140bf215546Sopenharmony_ci#endif
141bf215546Sopenharmony_ci      }
142bf215546Sopenharmony_ci   }
143bf215546Sopenharmony_ci}
144bf215546Sopenharmony_ci
145bf215546Sopenharmony_cistatic void
146bf215546Sopenharmony_cillvm_tcs_run(struct draw_tess_ctrl_shader *shader, uint32_t prim_id)
147bf215546Sopenharmony_ci{
148bf215546Sopenharmony_ci   shader->current_variant->jit_func(shader->jit_context, shader->tcs_input->data, shader->tcs_output->data, prim_id,
149bf215546Sopenharmony_ci                                     shader->draw->pt.vertices_per_patch, shader->draw->pt.user.viewid);
150bf215546Sopenharmony_ci}
151bf215546Sopenharmony_ci#endif
152bf215546Sopenharmony_ci
153bf215546Sopenharmony_ci/**
154bf215546Sopenharmony_ci * Execute tess ctrl shader.
155bf215546Sopenharmony_ci */
156bf215546Sopenharmony_ciint draw_tess_ctrl_shader_run(struct draw_tess_ctrl_shader *shader,
157bf215546Sopenharmony_ci                              const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
158bf215546Sopenharmony_ci                              const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS],
159bf215546Sopenharmony_ci                              const struct draw_vertex_info *input_verts,
160bf215546Sopenharmony_ci                              const struct draw_prim_info *input_prim,
161bf215546Sopenharmony_ci                              const struct tgsi_shader_info *input_info,
162bf215546Sopenharmony_ci                              struct draw_vertex_info *output_verts,
163bf215546Sopenharmony_ci                              struct draw_prim_info *output_prims )
164bf215546Sopenharmony_ci{
165bf215546Sopenharmony_ci   const float (*input)[4] = (const float (*)[4])input_verts->verts->data;
166bf215546Sopenharmony_ci   unsigned num_outputs = draw_total_tcs_outputs(shader->draw);
167bf215546Sopenharmony_ci   unsigned input_stride = input_verts->vertex_size;
168bf215546Sopenharmony_ci   unsigned vertex_size = sizeof(struct vertex_header) + num_outputs * 4 * sizeof(float);
169bf215546Sopenharmony_ci   unsigned num_patches = input_prim->count / shader->draw->pt.vertices_per_patch;
170bf215546Sopenharmony_ci
171bf215546Sopenharmony_ci   output_verts->vertex_size = vertex_size;
172bf215546Sopenharmony_ci   output_verts->stride = output_verts->vertex_size;
173bf215546Sopenharmony_ci   output_verts->verts = NULL;
174bf215546Sopenharmony_ci   output_verts->count = 0;
175bf215546Sopenharmony_ci   shader->input = input;
176bf215546Sopenharmony_ci   shader->input_vertex_stride = input_stride;
177bf215546Sopenharmony_ci   shader->input_info = input_info;
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci   output_prims->linear = TRUE;
180bf215546Sopenharmony_ci   output_prims->start = 0;
181bf215546Sopenharmony_ci   output_prims->elts = NULL;
182bf215546Sopenharmony_ci   output_prims->count = 0;
183bf215546Sopenharmony_ci   output_prims->prim = PIPE_PRIM_PATCHES;
184bf215546Sopenharmony_ci   output_prims->flags = 0;
185bf215546Sopenharmony_ci   output_prims->primitive_lengths = NULL;
186bf215546Sopenharmony_ci   output_prims->primitive_count = 0;
187bf215546Sopenharmony_ci
188bf215546Sopenharmony_ci   if (shader->draw->collect_statistics) {
189bf215546Sopenharmony_ci      shader->draw->statistics.hs_invocations += num_patches;
190bf215546Sopenharmony_ci   }
191bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
192bf215546Sopenharmony_ci   for (unsigned i = 0; i < num_patches; i++) {
193bf215546Sopenharmony_ci      uint32_t vert_start = output_verts->count;
194bf215546Sopenharmony_ci
195bf215546Sopenharmony_ci      output_verts->count += shader->vertices_out;
196bf215546Sopenharmony_ci
197bf215546Sopenharmony_ci      llvm_fetch_tcs_input(shader, input_prim, i, shader->draw->pt.vertices_per_patch);
198bf215546Sopenharmony_ci
199bf215546Sopenharmony_ci      llvm_tcs_run(shader, i);
200bf215546Sopenharmony_ci
201bf215546Sopenharmony_ci      uint32_t old_verts = util_align_npot(vert_start, 16);
202bf215546Sopenharmony_ci      uint32_t new_verts = util_align_npot(output_verts->count, 16);
203bf215546Sopenharmony_ci      uint32_t old_size = output_verts->vertex_size * old_verts;
204bf215546Sopenharmony_ci      uint32_t new_size = output_verts->vertex_size * new_verts;
205bf215546Sopenharmony_ci      output_verts->verts = REALLOC(output_verts->verts, old_size, new_size);
206bf215546Sopenharmony_ci
207bf215546Sopenharmony_ci      llvm_store_tcs_output(shader, i, output_verts, vert_start);
208bf215546Sopenharmony_ci   }
209bf215546Sopenharmony_ci#endif
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci   output_prims->primitive_count = num_patches;
212bf215546Sopenharmony_ci   return 0;
213bf215546Sopenharmony_ci}
214bf215546Sopenharmony_ci
215bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
216bf215546Sopenharmony_ci#define DEBUG_INPUTS 0
217bf215546Sopenharmony_cistatic void
218bf215546Sopenharmony_cillvm_fetch_tes_input(struct draw_tess_eval_shader *shader,
219bf215546Sopenharmony_ci                     const struct draw_prim_info *input_prim_info,
220bf215546Sopenharmony_ci                     unsigned prim_id,
221bf215546Sopenharmony_ci                     unsigned num_vertices)
222bf215546Sopenharmony_ci{
223bf215546Sopenharmony_ci   const float (*input_ptr)[4];
224bf215546Sopenharmony_ci   float (*input_data)[32][PIPE_MAX_SHADER_INPUTS][TGSI_NUM_CHANNELS] = &shader->tes_input->data;
225bf215546Sopenharmony_ci   unsigned slot, i;
226bf215546Sopenharmony_ci   int vs_slot;
227bf215546Sopenharmony_ci   unsigned input_vertex_stride = shader->input_vertex_stride;
228bf215546Sopenharmony_ci
229bf215546Sopenharmony_ci   input_ptr = shader->input;
230bf215546Sopenharmony_ci   for (i = 0; i < num_vertices; i++) {
231bf215546Sopenharmony_ci      const float (*input)[4];
232bf215546Sopenharmony_ci      int vertex_idx = prim_id * num_vertices + i;
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_ci      if (input_prim_info->linear == FALSE)
235bf215546Sopenharmony_ci         vertex_idx = input_prim_info->elts[vertex_idx];
236bf215546Sopenharmony_ci#if DEBUG_INPUTS
237bf215546Sopenharmony_ci      debug_printf("%d) tes vertex index = %d (prim idx = %d)\n",
238bf215546Sopenharmony_ci                   i, prim_id, 0);
239bf215546Sopenharmony_ci#endif
240bf215546Sopenharmony_ci      input = (const float (*)[4])((const char *)input_ptr + (vertex_idx * input_vertex_stride));
241bf215546Sopenharmony_ci      for (slot = 0, vs_slot = 0; slot < shader->info.num_inputs; ++slot) {
242bf215546Sopenharmony_ci         vs_slot = draw_tes_get_input_index(
243bf215546Sopenharmony_ci                                            shader->info.input_semantic_name[slot],
244bf215546Sopenharmony_ci                                            shader->info.input_semantic_index[slot],
245bf215546Sopenharmony_ci                                            shader->input_info);
246bf215546Sopenharmony_ci         if (vs_slot < 0) {
247bf215546Sopenharmony_ci            debug_printf("TCS/TES signature mismatch!\n");
248bf215546Sopenharmony_ci            (*input_data)[i][slot][0] = 0;
249bf215546Sopenharmony_ci            (*input_data)[i][slot][1] = 0;
250bf215546Sopenharmony_ci            (*input_data)[i][slot][2] = 0;
251bf215546Sopenharmony_ci            (*input_data)[i][slot][3] = 0;
252bf215546Sopenharmony_ci         } else {
253bf215546Sopenharmony_ci            (*input_data)[i][slot][0] = input[vs_slot][0];
254bf215546Sopenharmony_ci            (*input_data)[i][slot][1] = input[vs_slot][1];
255bf215546Sopenharmony_ci            (*input_data)[i][slot][2] = input[vs_slot][2];
256bf215546Sopenharmony_ci            (*input_data)[i][slot][3] = input[vs_slot][3];
257bf215546Sopenharmony_ci#if DEBUG_INPUTS
258bf215546Sopenharmony_ci            debug_printf("\t\t%p = %f %f %f %f\n",
259bf215546Sopenharmony_ci                         &input[vs_slot][0],
260bf215546Sopenharmony_ci                         (*input_data)[i][slot][0],
261bf215546Sopenharmony_ci                         (*input_data)[i][slot][1],
262bf215546Sopenharmony_ci                         (*input_data)[i][slot][2],
263bf215546Sopenharmony_ci                         (*input_data)[i][slot][3]);
264bf215546Sopenharmony_ci#endif
265bf215546Sopenharmony_ci            ++vs_slot;
266bf215546Sopenharmony_ci         }
267bf215546Sopenharmony_ci      }
268bf215546Sopenharmony_ci   }
269bf215546Sopenharmony_ci}
270bf215546Sopenharmony_ci
271bf215546Sopenharmony_cistatic void
272bf215546Sopenharmony_cillvm_fetch_tess_factors(struct draw_tess_eval_shader *shader,
273bf215546Sopenharmony_ci                        unsigned patch_id,
274bf215546Sopenharmony_ci                        unsigned num_vertices,
275bf215546Sopenharmony_ci                        struct pipe_tessellation_factors *factors)
276bf215546Sopenharmony_ci{
277bf215546Sopenharmony_ci   int outer_slot = draw_tes_get_input_index(
278bf215546Sopenharmony_ci      TGSI_SEMANTIC_TESSOUTER, 0, shader->input_info);
279bf215546Sopenharmony_ci   int inner_slot = draw_tes_get_input_index(
280bf215546Sopenharmony_ci      TGSI_SEMANTIC_TESSINNER, 0, shader->input_info);
281bf215546Sopenharmony_ci   const float (*input_ptr)[4];
282bf215546Sopenharmony_ci   const float (*input)[4];
283bf215546Sopenharmony_ci   input_ptr = shader->input;
284bf215546Sopenharmony_ci   input = (const float (*)[4])((const char *)input_ptr + ((patch_id * num_vertices) * shader->input_vertex_stride));
285bf215546Sopenharmony_ci
286bf215546Sopenharmony_ci   if (outer_slot != -1) {
287bf215546Sopenharmony_ci      for (unsigned i = 0; i < 4; i++)
288bf215546Sopenharmony_ci         factors->outer_tf[i] = input[outer_slot][i];
289bf215546Sopenharmony_ci   } else {
290bf215546Sopenharmony_ci      for (unsigned i = 0; i < 4; i++)
291bf215546Sopenharmony_ci         factors->outer_tf[i] = shader->draw->default_outer_tess_level[i];
292bf215546Sopenharmony_ci   }
293bf215546Sopenharmony_ci   if (inner_slot != -1) {
294bf215546Sopenharmony_ci      for (unsigned i = 0; i < 2; i++)
295bf215546Sopenharmony_ci         factors->inner_tf[i] = input[inner_slot][i];
296bf215546Sopenharmony_ci   } else {
297bf215546Sopenharmony_ci      for (unsigned i = 0; i < 2; i++)
298bf215546Sopenharmony_ci         factors->inner_tf[i] = shader->draw->default_inner_tess_level[i];
299bf215546Sopenharmony_ci   }
300bf215546Sopenharmony_ci}
301bf215546Sopenharmony_ci
302bf215546Sopenharmony_cistatic void
303bf215546Sopenharmony_cillvm_tes_run(struct draw_tess_eval_shader *shader,
304bf215546Sopenharmony_ci             uint32_t prim_id,
305bf215546Sopenharmony_ci             uint32_t patch_vertices_in,
306bf215546Sopenharmony_ci             struct pipe_tessellator_data *tess_data,
307bf215546Sopenharmony_ci             struct pipe_tessellation_factors *tess_factors,
308bf215546Sopenharmony_ci             struct vertex_header *output)
309bf215546Sopenharmony_ci{
310bf215546Sopenharmony_ci   shader->current_variant->jit_func(shader->jit_context, shader->tes_input->data, output, prim_id,
311bf215546Sopenharmony_ci                                     tess_data->num_domain_points, tess_data->domain_points_u, tess_data->domain_points_v,
312bf215546Sopenharmony_ci                                     tess_factors->outer_tf, tess_factors->inner_tf, patch_vertices_in,
313bf215546Sopenharmony_ci                                     shader->draw->pt.user.viewid);
314bf215546Sopenharmony_ci}
315bf215546Sopenharmony_ci#endif
316bf215546Sopenharmony_ci
317bf215546Sopenharmony_ci/**
318bf215546Sopenharmony_ci * Execute tess eval shader.
319bf215546Sopenharmony_ci */
320bf215546Sopenharmony_ciint draw_tess_eval_shader_run(struct draw_tess_eval_shader *shader,
321bf215546Sopenharmony_ci                              const void *constants[PIPE_MAX_CONSTANT_BUFFERS],
322bf215546Sopenharmony_ci                              const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS],
323bf215546Sopenharmony_ci                              unsigned num_input_vertices_per_patch,
324bf215546Sopenharmony_ci                              const struct draw_vertex_info *input_verts,
325bf215546Sopenharmony_ci                              const struct draw_prim_info *input_prim,
326bf215546Sopenharmony_ci                              const struct tgsi_shader_info *input_info,
327bf215546Sopenharmony_ci                              struct draw_vertex_info *output_verts,
328bf215546Sopenharmony_ci                              struct draw_prim_info *output_prims,
329bf215546Sopenharmony_ci                              ushort **elts_out)
330bf215546Sopenharmony_ci{
331bf215546Sopenharmony_ci   const float (*input)[4] = (const float (*)[4])input_verts->verts->data;
332bf215546Sopenharmony_ci   unsigned num_outputs = draw_total_tes_outputs(shader->draw);
333bf215546Sopenharmony_ci   unsigned input_stride = input_verts->vertex_size;
334bf215546Sopenharmony_ci   unsigned vertex_size = sizeof(struct vertex_header) + num_outputs * 4 * sizeof(float);
335bf215546Sopenharmony_ci   ushort *elts = NULL;
336bf215546Sopenharmony_ci   output_verts->vertex_size = vertex_size;
337bf215546Sopenharmony_ci   output_verts->stride = output_verts->vertex_size;
338bf215546Sopenharmony_ci   output_verts->count = 0;
339bf215546Sopenharmony_ci   output_verts->verts = NULL;
340bf215546Sopenharmony_ci
341bf215546Sopenharmony_ci   output_prims->linear = FALSE;
342bf215546Sopenharmony_ci   output_prims->start = 0;
343bf215546Sopenharmony_ci   output_prims->elts = NULL;
344bf215546Sopenharmony_ci   output_prims->count = 0;
345bf215546Sopenharmony_ci   output_prims->prim = get_tes_output_prim(shader);
346bf215546Sopenharmony_ci   output_prims->flags = 0;
347bf215546Sopenharmony_ci   output_prims->primitive_lengths = NULL;
348bf215546Sopenharmony_ci   output_prims->primitive_count = 0;
349bf215546Sopenharmony_ci
350bf215546Sopenharmony_ci   shader->input = input;
351bf215546Sopenharmony_ci   shader->input_vertex_stride = input_stride;
352bf215546Sopenharmony_ci   shader->input_info = input_info;
353bf215546Sopenharmony_ci
354bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
355bf215546Sopenharmony_ci   struct pipe_tessellation_factors factors;
356bf215546Sopenharmony_ci   struct pipe_tessellator_data data = { 0 };
357bf215546Sopenharmony_ci   struct pipe_tessellator *ptess = p_tess_init(shader->prim_mode,
358bf215546Sopenharmony_ci                                                shader->spacing,
359bf215546Sopenharmony_ci                                                !shader->vertex_order_cw,
360bf215546Sopenharmony_ci                                                shader->point_mode);
361bf215546Sopenharmony_ci   for (unsigned i = 0; i < input_prim->primitive_count; i++) {
362bf215546Sopenharmony_ci      uint32_t vert_start = output_verts->count;
363bf215546Sopenharmony_ci      uint32_t prim_start = output_prims->primitive_count;
364bf215546Sopenharmony_ci      uint32_t elt_start = output_prims->count;
365bf215546Sopenharmony_ci
366bf215546Sopenharmony_ci      llvm_fetch_tess_factors(shader, i, num_input_vertices_per_patch, &factors);
367bf215546Sopenharmony_ci
368bf215546Sopenharmony_ci      /* tessellate with the factors for this primitive */
369bf215546Sopenharmony_ci      p_tessellate(ptess, &factors, &data);
370bf215546Sopenharmony_ci
371bf215546Sopenharmony_ci      if (data.num_domain_points == 0)
372bf215546Sopenharmony_ci         continue;
373bf215546Sopenharmony_ci
374bf215546Sopenharmony_ci      uint32_t old_verts = vert_start;
375bf215546Sopenharmony_ci      uint32_t new_verts = vert_start + util_align_npot(data.num_domain_points, 4);
376bf215546Sopenharmony_ci      uint32_t old_size = output_verts->vertex_size * old_verts;
377bf215546Sopenharmony_ci      uint32_t new_size = output_verts->vertex_size * new_verts;
378bf215546Sopenharmony_ci      output_verts->verts = REALLOC(output_verts->verts, old_size, new_size);
379bf215546Sopenharmony_ci
380bf215546Sopenharmony_ci      output_verts->count += data.num_domain_points;
381bf215546Sopenharmony_ci
382bf215546Sopenharmony_ci      output_prims->count += data.num_indices;
383bf215546Sopenharmony_ci      elts = REALLOC(elts, elt_start * sizeof(uint16_t),
384bf215546Sopenharmony_ci                     output_prims->count * sizeof(uint16_t));
385bf215546Sopenharmony_ci
386bf215546Sopenharmony_ci      for (unsigned i = 0; i < data.num_indices; i++)
387bf215546Sopenharmony_ci         elts[elt_start + i] = vert_start + data.indices[i];
388bf215546Sopenharmony_ci
389bf215546Sopenharmony_ci      llvm_fetch_tes_input(shader, input_prim, i, num_input_vertices_per_patch);
390bf215546Sopenharmony_ci      /* run once per primitive? */
391bf215546Sopenharmony_ci      char *output = (char *)output_verts->verts;
392bf215546Sopenharmony_ci      output += vert_start * vertex_size;
393bf215546Sopenharmony_ci      llvm_tes_run(shader, i, num_input_vertices_per_patch, &data, &factors, (struct vertex_header *)output);
394bf215546Sopenharmony_ci
395bf215546Sopenharmony_ci      if (shader->draw->collect_statistics) {
396bf215546Sopenharmony_ci         shader->draw->statistics.ds_invocations += data.num_domain_points;
397bf215546Sopenharmony_ci      }
398bf215546Sopenharmony_ci
399bf215546Sopenharmony_ci      uint32_t prim_len = u_prim_vertex_count(output_prims->prim)->min;
400bf215546Sopenharmony_ci      output_prims->primitive_count += data.num_indices / prim_len;
401bf215546Sopenharmony_ci      output_prims->primitive_lengths = REALLOC(output_prims->primitive_lengths, prim_start * sizeof(uint32_t),
402bf215546Sopenharmony_ci                                                output_prims->primitive_count * sizeof(uint32_t));
403bf215546Sopenharmony_ci      for (unsigned i = prim_start; i < output_prims->primitive_count; i++) {
404bf215546Sopenharmony_ci         output_prims->primitive_lengths[i] = prim_len;
405bf215546Sopenharmony_ci      }
406bf215546Sopenharmony_ci   }
407bf215546Sopenharmony_ci   p_tess_destroy(ptess);
408bf215546Sopenharmony_ci#endif
409bf215546Sopenharmony_ci
410bf215546Sopenharmony_ci   *elts_out = elts;
411bf215546Sopenharmony_ci   output_prims->elts = elts;
412bf215546Sopenharmony_ci   return 0;
413bf215546Sopenharmony_ci}
414bf215546Sopenharmony_ci
415bf215546Sopenharmony_cistruct draw_tess_ctrl_shader *
416bf215546Sopenharmony_cidraw_create_tess_ctrl_shader(struct draw_context *draw,
417bf215546Sopenharmony_ci                             const struct pipe_shader_state *state)
418bf215546Sopenharmony_ci{
419bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
420bf215546Sopenharmony_ci   boolean use_llvm = draw->llvm != NULL;
421bf215546Sopenharmony_ci   struct llvm_tess_ctrl_shader *llvm_tcs = NULL;
422bf215546Sopenharmony_ci#endif
423bf215546Sopenharmony_ci   struct draw_tess_ctrl_shader *tcs;
424bf215546Sopenharmony_ci
425bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
426bf215546Sopenharmony_ci   if (use_llvm) {
427bf215546Sopenharmony_ci      llvm_tcs = CALLOC_STRUCT(llvm_tess_ctrl_shader);
428bf215546Sopenharmony_ci
429bf215546Sopenharmony_ci      if (!llvm_tcs)
430bf215546Sopenharmony_ci         return NULL;
431bf215546Sopenharmony_ci
432bf215546Sopenharmony_ci      tcs = &llvm_tcs->base;
433bf215546Sopenharmony_ci
434bf215546Sopenharmony_ci      list_inithead(&llvm_tcs->variants.list);
435bf215546Sopenharmony_ci   } else
436bf215546Sopenharmony_ci#endif
437bf215546Sopenharmony_ci   {
438bf215546Sopenharmony_ci      tcs = CALLOC_STRUCT(draw_tess_ctrl_shader);
439bf215546Sopenharmony_ci   }
440bf215546Sopenharmony_ci
441bf215546Sopenharmony_ci   if (!tcs)
442bf215546Sopenharmony_ci      return NULL;
443bf215546Sopenharmony_ci
444bf215546Sopenharmony_ci   tcs->draw = draw;
445bf215546Sopenharmony_ci   tcs->state = *state;
446bf215546Sopenharmony_ci
447bf215546Sopenharmony_ci   nir_tgsi_scan_shader(state->ir.nir, &tcs->info, true);
448bf215546Sopenharmony_ci
449bf215546Sopenharmony_ci   tcs->vector_length = 4;
450bf215546Sopenharmony_ci   tcs->vertices_out = tcs->info.properties[TGSI_PROPERTY_TCS_VERTICES_OUT];
451bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
452bf215546Sopenharmony_ci   if (use_llvm) {
453bf215546Sopenharmony_ci
454bf215546Sopenharmony_ci      tcs->tcs_input = align_malloc(sizeof(struct draw_tcs_inputs), 16);
455bf215546Sopenharmony_ci      memset(tcs->tcs_input, 0, sizeof(struct draw_tcs_inputs));
456bf215546Sopenharmony_ci
457bf215546Sopenharmony_ci      tcs->tcs_output = align_malloc(sizeof(struct draw_tcs_outputs), 16);
458bf215546Sopenharmony_ci      memset(tcs->tcs_output, 0, sizeof(struct draw_tcs_outputs));
459bf215546Sopenharmony_ci
460bf215546Sopenharmony_ci      tcs->jit_context = &draw->llvm->tcs_jit_context;
461bf215546Sopenharmony_ci      llvm_tcs->variant_key_size =
462bf215546Sopenharmony_ci         draw_tcs_llvm_variant_key_size(
463bf215546Sopenharmony_ci                                        tcs->info.file_max[TGSI_FILE_SAMPLER]+1,
464bf215546Sopenharmony_ci                                        tcs->info.file_max[TGSI_FILE_SAMPLER_VIEW]+1,
465bf215546Sopenharmony_ci                                        tcs->info.file_max[TGSI_FILE_IMAGE]+1);
466bf215546Sopenharmony_ci   }
467bf215546Sopenharmony_ci#endif
468bf215546Sopenharmony_ci   return tcs;
469bf215546Sopenharmony_ci}
470bf215546Sopenharmony_ci
471bf215546Sopenharmony_civoid draw_bind_tess_ctrl_shader(struct draw_context *draw,
472bf215546Sopenharmony_ci                                struct draw_tess_ctrl_shader *dtcs)
473bf215546Sopenharmony_ci{
474bf215546Sopenharmony_ci   draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE);
475bf215546Sopenharmony_ci   if (dtcs) {
476bf215546Sopenharmony_ci      draw->tcs.tess_ctrl_shader = dtcs;
477bf215546Sopenharmony_ci   } else {
478bf215546Sopenharmony_ci      draw->tcs.tess_ctrl_shader = NULL;
479bf215546Sopenharmony_ci   }
480bf215546Sopenharmony_ci}
481bf215546Sopenharmony_ci
482bf215546Sopenharmony_civoid draw_delete_tess_ctrl_shader(struct draw_context *draw,
483bf215546Sopenharmony_ci                                  struct draw_tess_ctrl_shader *dtcs)
484bf215546Sopenharmony_ci{
485bf215546Sopenharmony_ci   if (!dtcs)
486bf215546Sopenharmony_ci      return;
487bf215546Sopenharmony_ci
488bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
489bf215546Sopenharmony_ci   if (draw->llvm) {
490bf215546Sopenharmony_ci      struct llvm_tess_ctrl_shader *shader = llvm_tess_ctrl_shader(dtcs);
491bf215546Sopenharmony_ci
492bf215546Sopenharmony_ci      struct draw_tcs_llvm_variant_list_item *li, *next;
493bf215546Sopenharmony_ci
494bf215546Sopenharmony_ci      LIST_FOR_EACH_ENTRY_SAFE(li, next, &shader->variants.list, list) {
495bf215546Sopenharmony_ci         draw_tcs_llvm_destroy_variant(li->base);
496bf215546Sopenharmony_ci      }
497bf215546Sopenharmony_ci
498bf215546Sopenharmony_ci      assert(shader->variants_cached == 0);
499bf215546Sopenharmony_ci      align_free(dtcs->tcs_input);
500bf215546Sopenharmony_ci      align_free(dtcs->tcs_output);
501bf215546Sopenharmony_ci   }
502bf215546Sopenharmony_ci#endif
503bf215546Sopenharmony_ci
504bf215546Sopenharmony_ci   if (dtcs->state.type == PIPE_SHADER_IR_NIR && dtcs->state.ir.nir)
505bf215546Sopenharmony_ci      ralloc_free(dtcs->state.ir.nir);
506bf215546Sopenharmony_ci   FREE(dtcs);
507bf215546Sopenharmony_ci}
508bf215546Sopenharmony_ci
509bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
510bf215546Sopenharmony_civoid draw_tcs_set_current_variant(struct draw_tess_ctrl_shader *shader,
511bf215546Sopenharmony_ci                                  struct draw_tcs_llvm_variant *variant)
512bf215546Sopenharmony_ci{
513bf215546Sopenharmony_ci   shader->current_variant = variant;
514bf215546Sopenharmony_ci}
515bf215546Sopenharmony_ci#endif
516bf215546Sopenharmony_ci
517bf215546Sopenharmony_cistruct draw_tess_eval_shader *
518bf215546Sopenharmony_cidraw_create_tess_eval_shader(struct draw_context *draw,
519bf215546Sopenharmony_ci                             const struct pipe_shader_state *state)
520bf215546Sopenharmony_ci{
521bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
522bf215546Sopenharmony_ci   boolean use_llvm = draw->llvm != NULL;
523bf215546Sopenharmony_ci   struct llvm_tess_eval_shader *llvm_tes = NULL;
524bf215546Sopenharmony_ci#endif
525bf215546Sopenharmony_ci   struct draw_tess_eval_shader *tes;
526bf215546Sopenharmony_ci
527bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
528bf215546Sopenharmony_ci   if (use_llvm) {
529bf215546Sopenharmony_ci      llvm_tes = CALLOC_STRUCT(llvm_tess_eval_shader);
530bf215546Sopenharmony_ci
531bf215546Sopenharmony_ci      if (!llvm_tes)
532bf215546Sopenharmony_ci         return NULL;
533bf215546Sopenharmony_ci
534bf215546Sopenharmony_ci      tes = &llvm_tes->base;
535bf215546Sopenharmony_ci      list_inithead(&llvm_tes->variants.list);
536bf215546Sopenharmony_ci   } else
537bf215546Sopenharmony_ci#endif
538bf215546Sopenharmony_ci   {
539bf215546Sopenharmony_ci      tes = CALLOC_STRUCT(draw_tess_eval_shader);
540bf215546Sopenharmony_ci   }
541bf215546Sopenharmony_ci
542bf215546Sopenharmony_ci   if (!tes)
543bf215546Sopenharmony_ci      return NULL;
544bf215546Sopenharmony_ci
545bf215546Sopenharmony_ci   tes->draw = draw;
546bf215546Sopenharmony_ci   tes->state = *state;
547bf215546Sopenharmony_ci
548bf215546Sopenharmony_ci   nir_tgsi_scan_shader(state->ir.nir, &tes->info, true);
549bf215546Sopenharmony_ci
550bf215546Sopenharmony_ci   tes->prim_mode = tes->info.properties[TGSI_PROPERTY_TES_PRIM_MODE];
551bf215546Sopenharmony_ci   tes->spacing = tes->info.properties[TGSI_PROPERTY_TES_SPACING];
552bf215546Sopenharmony_ci   tes->vertex_order_cw = tes->info.properties[TGSI_PROPERTY_TES_VERTEX_ORDER_CW];
553bf215546Sopenharmony_ci   tes->point_mode = tes->info.properties[TGSI_PROPERTY_TES_POINT_MODE];
554bf215546Sopenharmony_ci
555bf215546Sopenharmony_ci   tes->vector_length = 4;
556bf215546Sopenharmony_ci
557bf215546Sopenharmony_ci   tes->position_output = -1;
558bf215546Sopenharmony_ci   bool found_clipvertex = false;
559bf215546Sopenharmony_ci   for (unsigned i = 0; i < tes->info.num_outputs; i++) {
560bf215546Sopenharmony_ci      if (tes->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&
561bf215546Sopenharmony_ci          tes->info.output_semantic_index[i] == 0)
562bf215546Sopenharmony_ci         tes->position_output = i;
563bf215546Sopenharmony_ci      if (tes->info.output_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX)
564bf215546Sopenharmony_ci         tes->viewport_index_output = i;
565bf215546Sopenharmony_ci      if (tes->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPVERTEX &&
566bf215546Sopenharmony_ci          tes->info.output_semantic_index[i] == 0) {
567bf215546Sopenharmony_ci         found_clipvertex = true;
568bf215546Sopenharmony_ci         tes->clipvertex_output = i;
569bf215546Sopenharmony_ci      }
570bf215546Sopenharmony_ci      if (tes->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPDIST) {
571bf215546Sopenharmony_ci         assert(tes->info.output_semantic_index[i] <
572bf215546Sopenharmony_ci                      PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT);
573bf215546Sopenharmony_ci         tes->ccdistance_output[tes->info.output_semantic_index[i]] = i;
574bf215546Sopenharmony_ci      }
575bf215546Sopenharmony_ci   }
576bf215546Sopenharmony_ci   if (!found_clipvertex)
577bf215546Sopenharmony_ci      tes->clipvertex_output = tes->position_output;
578bf215546Sopenharmony_ci
579bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
580bf215546Sopenharmony_ci   if (use_llvm) {
581bf215546Sopenharmony_ci
582bf215546Sopenharmony_ci      tes->tes_input = align_malloc(sizeof(struct draw_tes_inputs), 16);
583bf215546Sopenharmony_ci      memset(tes->tes_input, 0, sizeof(struct draw_tes_inputs));
584bf215546Sopenharmony_ci
585bf215546Sopenharmony_ci      tes->jit_context = &draw->llvm->tes_jit_context;
586bf215546Sopenharmony_ci      llvm_tes->variant_key_size =
587bf215546Sopenharmony_ci         draw_tes_llvm_variant_key_size(
588bf215546Sopenharmony_ci                                        tes->info.file_max[TGSI_FILE_SAMPLER]+1,
589bf215546Sopenharmony_ci                                        tes->info.file_max[TGSI_FILE_SAMPLER_VIEW]+1,
590bf215546Sopenharmony_ci                                        tes->info.file_max[TGSI_FILE_IMAGE]+1);
591bf215546Sopenharmony_ci   }
592bf215546Sopenharmony_ci#endif
593bf215546Sopenharmony_ci   return tes;
594bf215546Sopenharmony_ci}
595bf215546Sopenharmony_ci
596bf215546Sopenharmony_civoid draw_bind_tess_eval_shader(struct draw_context *draw,
597bf215546Sopenharmony_ci                                struct draw_tess_eval_shader *dtes)
598bf215546Sopenharmony_ci{
599bf215546Sopenharmony_ci   draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE);
600bf215546Sopenharmony_ci   if (dtes) {
601bf215546Sopenharmony_ci      draw->tes.tess_eval_shader = dtes;
602bf215546Sopenharmony_ci      draw->tes.num_tes_outputs = dtes->info.num_outputs;
603bf215546Sopenharmony_ci      draw->tes.position_output = dtes->position_output;
604bf215546Sopenharmony_ci      draw->tes.clipvertex_output = dtes->clipvertex_output;
605bf215546Sopenharmony_ci   } else {
606bf215546Sopenharmony_ci      draw->tes.tess_eval_shader = NULL;
607bf215546Sopenharmony_ci   }
608bf215546Sopenharmony_ci}
609bf215546Sopenharmony_ci
610bf215546Sopenharmony_civoid draw_delete_tess_eval_shader(struct draw_context *draw,
611bf215546Sopenharmony_ci                                  struct draw_tess_eval_shader *dtes)
612bf215546Sopenharmony_ci{
613bf215546Sopenharmony_ci   if (!dtes)
614bf215546Sopenharmony_ci      return;
615bf215546Sopenharmony_ci
616bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
617bf215546Sopenharmony_ci   if (draw->llvm) {
618bf215546Sopenharmony_ci      struct llvm_tess_eval_shader *shader = llvm_tess_eval_shader(dtes);
619bf215546Sopenharmony_ci      struct draw_tes_llvm_variant_list_item *li, *next;
620bf215546Sopenharmony_ci
621bf215546Sopenharmony_ci      LIST_FOR_EACH_ENTRY_SAFE(li, next, &shader->variants.list, list) {
622bf215546Sopenharmony_ci         draw_tes_llvm_destroy_variant(li->base);
623bf215546Sopenharmony_ci      }
624bf215546Sopenharmony_ci
625bf215546Sopenharmony_ci      assert(shader->variants_cached == 0);
626bf215546Sopenharmony_ci      align_free(dtes->tes_input);
627bf215546Sopenharmony_ci   }
628bf215546Sopenharmony_ci#endif
629bf215546Sopenharmony_ci   if (dtes->state.type == PIPE_SHADER_IR_NIR && dtes->state.ir.nir)
630bf215546Sopenharmony_ci      ralloc_free(dtes->state.ir.nir);
631bf215546Sopenharmony_ci   FREE(dtes);
632bf215546Sopenharmony_ci}
633bf215546Sopenharmony_ci
634bf215546Sopenharmony_ci#ifdef DRAW_LLVM_AVAILABLE
635bf215546Sopenharmony_civoid draw_tes_set_current_variant(struct draw_tess_eval_shader *shader,
636bf215546Sopenharmony_ci                                  struct draw_tes_llvm_variant *variant)
637bf215546Sopenharmony_ci{
638bf215546Sopenharmony_ci   shader->current_variant = variant;
639bf215546Sopenharmony_ci}
640bf215546Sopenharmony_ci#endif
641bf215546Sopenharmony_ci
642bf215546Sopenharmony_cienum pipe_prim_type get_tes_output_prim(struct draw_tess_eval_shader *shader)
643bf215546Sopenharmony_ci{
644bf215546Sopenharmony_ci   if (shader->point_mode)
645bf215546Sopenharmony_ci      return PIPE_PRIM_POINTS;
646bf215546Sopenharmony_ci   else if (shader->prim_mode == PIPE_PRIM_LINES)
647bf215546Sopenharmony_ci      return PIPE_PRIM_LINES;
648bf215546Sopenharmony_ci   else
649bf215546Sopenharmony_ci      return PIPE_PRIM_TRIANGLES;
650bf215546Sopenharmony_ci}
651