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