Path: blob/21.2-virgl/src/gallium/auxiliary/draw/draw_tess.c
4565 views
/**************************************************************************1*2* Copyright 2020 Red Hat.3* All Rights Reserved.4*5* Permission is hereby granted, free of charge, to any person obtaining a6* copy of this software and associated documentation files (the "Software"),7* to deal in the Software without restriction, including without limitation8* the rights to use, copy, modify, merge, publish, distribute, sublicense,9* and/or sell copies of the Software, and to permit persons to whom the10* Software is furnished to do so, subject to the following conditions:11*12* The above copyright notice and this permission notice shall be included13* in all copies or substantial portions of the Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS16* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,17* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL18* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER19* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,20* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE21* SOFTWARE.22*23**************************************************************************/24#include "draw_tess.h"25#ifdef DRAW_LLVM_AVAILABLE26#include "draw_llvm.h"27#endif2829#include "tessellator/p_tessellator.h"30#include "nir/nir_to_tgsi_info.h"31#include "util/u_prim.h"32#include "util/u_math.h"33#include "util/u_memory.h"34#include "util/ralloc.h"35static inline int36draw_tes_get_input_index(int semantic, int index,37const struct tgsi_shader_info *input_info)38{39int i;40const ubyte *input_semantic_names = input_info->output_semantic_name;41const ubyte *input_semantic_indices = input_info->output_semantic_index;42for (i = 0; i < PIPE_MAX_SHADER_OUTPUTS; i++) {43if (input_semantic_names[i] == semantic &&44input_semantic_indices[i] == index)45return i;46}47return -1;48}4950#ifdef DRAW_LLVM_AVAILABLE51#define DEBUG_INPUTS 052static void53llvm_fetch_tcs_input(struct draw_tess_ctrl_shader *shader,54const struct draw_prim_info *input_prim_info,55unsigned prim_id,56unsigned num_vertices)57{58const float (*input_ptr)[4];59float (*input_data)[32][NUM_TCS_INPUTS][TGSI_NUM_CHANNELS] = &shader->tcs_input->data;60unsigned slot, i;61int vs_slot;62unsigned input_vertex_stride = shader->input_vertex_stride;6364input_ptr = shader->input;65for (i = 0; i < num_vertices; i++) {66const float (*input)[4];67int vertex_idx = prim_id * num_vertices + i;68if (input_prim_info->linear == FALSE)69vertex_idx = input_prim_info->elts[vertex_idx];70#if DEBUG_INPUTS71debug_printf("%d) tcs vertex index = %d (prim idx = %d)\n",72i, prim_id, 0);73#endif74input = (const float (*)[4])((const char *)input_ptr + (vertex_idx * input_vertex_stride));75for (slot = 0, vs_slot = 0; slot < shader->info.num_inputs; ++slot) {76vs_slot = draw_tes_get_input_index(77shader->info.input_semantic_name[slot],78shader->info.input_semantic_index[slot],79shader->input_info);80if (vs_slot < 0) {81debug_printf("VS/TCS signature mismatch!\n");82(*input_data)[i][slot][0] = 0;83(*input_data)[i][slot][1] = 0;84(*input_data)[i][slot][2] = 0;85(*input_data)[i][slot][3] = 0;86} else {87(*input_data)[i][slot][0] = input[vs_slot][0];88(*input_data)[i][slot][1] = input[vs_slot][1];89(*input_data)[i][slot][2] = input[vs_slot][2];90(*input_data)[i][slot][3] = input[vs_slot][3];91#if DEBUG_INPUTS92debug_printf("\t\t%p = %f %f %f %f\n", &(*input_data)[i][slot][0],93(*input_data)[i][slot][0],94(*input_data)[i][slot][1],95(*input_data)[i][slot][2],96(*input_data)[i][slot][3]);97#endif98++vs_slot;99}100}101}102}103104#define DEBUG_OUTPUTS 0105static void106llvm_store_tcs_output(struct draw_tess_ctrl_shader *shader,107unsigned prim_id,108struct draw_vertex_info *output_verts,109unsigned vert_start)110{111float (*output_ptr)[4];112float (*output_data)[32][PIPE_MAX_SHADER_INPUTS][TGSI_NUM_CHANNELS] = &shader->tcs_output->data;113unsigned slot, i;114unsigned num_vertices = shader->vertices_out;115116char *output = (char *)output_verts->verts->data;117output += vert_start * output_verts->stride;118119for (i = 0; i < num_vertices; i++) {120121#if DEBUG_OUTPUTS122debug_printf("%d) tcs store vertex index = %d (prim idx = %d)\n",123i, prim_id, 0);124#endif125output_ptr = (float(*)[4])(output + (i * output_verts->stride));126127for (slot = 0; slot < shader->info.num_outputs; ++slot) {128output_ptr[slot][0] = (*output_data)[i][slot][0];129output_ptr[slot][1] = (*output_data)[i][slot][1];130output_ptr[slot][2] = (*output_data)[i][slot][2];131output_ptr[slot][3] = (*output_data)[i][slot][3];132#if DEBUG_OUTPUTS133debug_printf("\t\t%p = %f %f %f %f\n",134&output_ptr[slot][0],135output_ptr[slot][0],136output_ptr[slot][1],137output_ptr[slot][2],138output_ptr[slot][3]);139#endif140}141}142}143144static void145llvm_tcs_run(struct draw_tess_ctrl_shader *shader, uint32_t prim_id)146{147shader->current_variant->jit_func(shader->jit_context, shader->tcs_input->data, shader->tcs_output->data, prim_id,148shader->draw->pt.vertices_per_patch, shader->draw->pt.user.viewid);149}150#endif151152/**153* Execute tess ctrl shader.154*/155int draw_tess_ctrl_shader_run(struct draw_tess_ctrl_shader *shader,156const void *constants[PIPE_MAX_CONSTANT_BUFFERS],157const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS],158const struct draw_vertex_info *input_verts,159const struct draw_prim_info *input_prim,160const struct tgsi_shader_info *input_info,161struct draw_vertex_info *output_verts,162struct draw_prim_info *output_prims )163{164const float (*input)[4] = (const float (*)[4])input_verts->verts->data;165unsigned num_outputs = draw_total_tcs_outputs(shader->draw);166unsigned input_stride = input_verts->vertex_size;167unsigned vertex_size = sizeof(struct vertex_header) + num_outputs * 4 * sizeof(float);168unsigned num_patches = input_prim->count / shader->draw->pt.vertices_per_patch;169170output_verts->vertex_size = vertex_size;171output_verts->stride = output_verts->vertex_size;172output_verts->verts = NULL;173output_verts->count = 0;174shader->input = input;175shader->input_vertex_stride = input_stride;176shader->input_info = input_info;177178output_prims->linear = TRUE;179output_prims->start = 0;180output_prims->elts = NULL;181output_prims->count = 0;182output_prims->prim = PIPE_PRIM_PATCHES;183output_prims->flags = 0;184output_prims->primitive_lengths = NULL;185output_prims->primitive_count = 0;186187if (shader->draw->collect_statistics) {188shader->draw->statistics.hs_invocations += num_patches;189}190#ifdef DRAW_LLVM_AVAILABLE191for (unsigned i = 0; i < num_patches; i++) {192uint32_t vert_start = output_verts->count;193194output_verts->count += shader->vertices_out;195196llvm_fetch_tcs_input(shader, input_prim, i, shader->draw->pt.vertices_per_patch);197198llvm_tcs_run(shader, i);199200uint32_t old_verts = util_align_npot(vert_start, 16);201uint32_t new_verts = util_align_npot(output_verts->count, 16);202uint32_t old_size = output_verts->vertex_size * old_verts;203uint32_t new_size = output_verts->vertex_size * new_verts;204output_verts->verts = REALLOC(output_verts->verts, old_size, new_size);205206llvm_store_tcs_output(shader, i, output_verts, vert_start);207}208#endif209210output_prims->primitive_count = num_patches;211return 0;212}213214#ifdef DRAW_LLVM_AVAILABLE215#define DEBUG_INPUTS 0216static void217llvm_fetch_tes_input(struct draw_tess_eval_shader *shader,218const struct draw_prim_info *input_prim_info,219unsigned prim_id,220unsigned num_vertices)221{222const float (*input_ptr)[4];223float (*input_data)[32][PIPE_MAX_SHADER_INPUTS][TGSI_NUM_CHANNELS] = &shader->tes_input->data;224unsigned slot, i;225int vs_slot;226unsigned input_vertex_stride = shader->input_vertex_stride;227228input_ptr = shader->input;229for (i = 0; i < num_vertices; i++) {230const float (*input)[4];231int vertex_idx = prim_id * num_vertices + i;232233if (input_prim_info->linear == FALSE)234vertex_idx = input_prim_info->elts[vertex_idx];235#if DEBUG_INPUTS236debug_printf("%d) tes vertex index = %d (prim idx = %d)\n",237i, prim_id, 0);238#endif239input = (const float (*)[4])((const char *)input_ptr + (vertex_idx * input_vertex_stride));240for (slot = 0, vs_slot = 0; slot < shader->info.num_inputs; ++slot) {241vs_slot = draw_tes_get_input_index(242shader->info.input_semantic_name[slot],243shader->info.input_semantic_index[slot],244shader->input_info);245if (vs_slot < 0) {246debug_printf("TCS/TES signature mismatch!\n");247(*input_data)[i][slot][0] = 0;248(*input_data)[i][slot][1] = 0;249(*input_data)[i][slot][2] = 0;250(*input_data)[i][slot][3] = 0;251} else {252(*input_data)[i][slot][0] = input[vs_slot][0];253(*input_data)[i][slot][1] = input[vs_slot][1];254(*input_data)[i][slot][2] = input[vs_slot][2];255(*input_data)[i][slot][3] = input[vs_slot][3];256#if DEBUG_INPUTS257debug_printf("\t\t%p = %f %f %f %f\n",258&input[vs_slot][0],259(*input_data)[i][slot][0],260(*input_data)[i][slot][1],261(*input_data)[i][slot][2],262(*input_data)[i][slot][3]);263#endif264++vs_slot;265}266}267}268}269270static void271llvm_fetch_tess_factors(struct draw_tess_eval_shader *shader,272unsigned patch_id,273unsigned num_vertices,274struct pipe_tessellation_factors *factors)275{276int outer_slot = draw_tes_get_input_index(277TGSI_SEMANTIC_TESSOUTER, 0, shader->input_info);278int inner_slot = draw_tes_get_input_index(279TGSI_SEMANTIC_TESSINNER, 0, shader->input_info);280const float (*input_ptr)[4];281const float (*input)[4];282input_ptr = shader->input;283input = (const float (*)[4])((const char *)input_ptr + ((patch_id * num_vertices) * shader->input_vertex_stride));284285if (outer_slot != -1) {286for (unsigned i = 0; i < 4; i++)287factors->outer_tf[i] = input[outer_slot][i];288} else {289for (unsigned i = 0; i < 4; i++)290factors->outer_tf[i] = shader->draw->default_outer_tess_level[i];291}292if (inner_slot != -1) {293for (unsigned i = 0; i < 2; i++)294factors->inner_tf[i] = input[inner_slot][i];295} else {296for (unsigned i = 0; i < 2; i++)297factors->inner_tf[i] = shader->draw->default_inner_tess_level[i];298}299}300301static void302llvm_tes_run(struct draw_tess_eval_shader *shader,303uint32_t prim_id,304uint32_t patch_vertices_in,305struct pipe_tessellator_data *tess_data,306struct pipe_tessellation_factors *tess_factors,307struct vertex_header *output)308{309shader->current_variant->jit_func(shader->jit_context, shader->tes_input->data, output, prim_id,310tess_data->num_domain_points, tess_data->domain_points_u, tess_data->domain_points_v,311tess_factors->outer_tf, tess_factors->inner_tf, patch_vertices_in,312shader->draw->pt.user.viewid);313}314#endif315316/**317* Execute tess eval shader.318*/319int draw_tess_eval_shader_run(struct draw_tess_eval_shader *shader,320const void *constants[PIPE_MAX_CONSTANT_BUFFERS],321const unsigned constants_size[PIPE_MAX_CONSTANT_BUFFERS],322unsigned num_input_vertices_per_patch,323const struct draw_vertex_info *input_verts,324const struct draw_prim_info *input_prim,325const struct tgsi_shader_info *input_info,326struct draw_vertex_info *output_verts,327struct draw_prim_info *output_prims,328ushort **elts_out)329{330const float (*input)[4] = (const float (*)[4])input_verts->verts->data;331unsigned num_outputs = draw_total_tes_outputs(shader->draw);332unsigned input_stride = input_verts->vertex_size;333unsigned vertex_size = sizeof(struct vertex_header) + num_outputs * 4 * sizeof(float);334ushort *elts = NULL;335output_verts->vertex_size = vertex_size;336output_verts->stride = output_verts->vertex_size;337output_verts->count = 0;338output_verts->verts = NULL;339340output_prims->linear = FALSE;341output_prims->start = 0;342output_prims->elts = NULL;343output_prims->count = 0;344output_prims->prim = get_tes_output_prim(shader);345output_prims->flags = 0;346output_prims->primitive_lengths = NULL;347output_prims->primitive_count = 0;348349shader->input = input;350shader->input_vertex_stride = input_stride;351shader->input_info = input_info;352353#ifdef DRAW_LLVM_AVAILABLE354struct pipe_tessellation_factors factors;355struct pipe_tessellator_data data = { 0 };356struct pipe_tessellator *ptess = p_tess_init(shader->prim_mode,357shader->spacing,358!shader->vertex_order_cw,359shader->point_mode);360for (unsigned i = 0; i < input_prim->primitive_count; i++) {361uint32_t vert_start = output_verts->count;362uint32_t prim_start = output_prims->primitive_count;363uint32_t elt_start = output_prims->count;364365llvm_fetch_tess_factors(shader, i, num_input_vertices_per_patch, &factors);366367/* tessellate with the factors for this primitive */368p_tessellate(ptess, &factors, &data);369370if (data.num_domain_points == 0)371continue;372373uint32_t old_verts = vert_start;374uint32_t new_verts = vert_start + util_align_npot(data.num_domain_points, 4);375uint32_t old_size = output_verts->vertex_size * old_verts;376uint32_t new_size = output_verts->vertex_size * new_verts;377output_verts->verts = REALLOC(output_verts->verts, old_size, new_size);378379output_verts->count += data.num_domain_points;380381output_prims->count += data.num_indices;382elts = REALLOC(elts, elt_start * sizeof(uint16_t),383output_prims->count * sizeof(uint16_t));384385for (unsigned i = 0; i < data.num_indices; i++)386elts[elt_start + i] = vert_start + data.indices[i];387388llvm_fetch_tes_input(shader, input_prim, i, num_input_vertices_per_patch);389/* run once per primitive? */390char *output = (char *)output_verts->verts;391output += vert_start * vertex_size;392llvm_tes_run(shader, i, num_input_vertices_per_patch, &data, &factors, (struct vertex_header *)output);393394if (shader->draw->collect_statistics) {395shader->draw->statistics.ds_invocations += data.num_domain_points;396}397398uint32_t prim_len = u_prim_vertex_count(output_prims->prim)->min;399output_prims->primitive_count += data.num_indices / prim_len;400output_prims->primitive_lengths = REALLOC(output_prims->primitive_lengths, prim_start * sizeof(uint32_t),401output_prims->primitive_count * sizeof(uint32_t));402for (unsigned i = prim_start; i < output_prims->primitive_count; i++) {403output_prims->primitive_lengths[i] = prim_len;404}405}406p_tess_destroy(ptess);407#endif408409*elts_out = elts;410output_prims->elts = elts;411return 0;412}413414struct draw_tess_ctrl_shader *415draw_create_tess_ctrl_shader(struct draw_context *draw,416const struct pipe_shader_state *state)417{418#ifdef DRAW_LLVM_AVAILABLE419boolean use_llvm = draw->llvm != NULL;420struct llvm_tess_ctrl_shader *llvm_tcs = NULL;421#endif422struct draw_tess_ctrl_shader *tcs;423424#ifdef DRAW_LLVM_AVAILABLE425if (use_llvm) {426llvm_tcs = CALLOC_STRUCT(llvm_tess_ctrl_shader);427428if (!llvm_tcs)429return NULL;430431tcs = &llvm_tcs->base;432433make_empty_list(&llvm_tcs->variants);434} else435#endif436{437tcs = CALLOC_STRUCT(draw_tess_ctrl_shader);438}439440if (!tcs)441return NULL;442443tcs->draw = draw;444tcs->state = *state;445446nir_tgsi_scan_shader(state->ir.nir, &tcs->info, true);447448tcs->vector_length = 4;449tcs->vertices_out = tcs->info.properties[TGSI_PROPERTY_TCS_VERTICES_OUT];450#ifdef DRAW_LLVM_AVAILABLE451if (use_llvm) {452453tcs->tcs_input = align_malloc(sizeof(struct draw_tcs_inputs), 16);454memset(tcs->tcs_input, 0, sizeof(struct draw_tcs_inputs));455456tcs->tcs_output = align_malloc(sizeof(struct draw_tcs_outputs), 16);457memset(tcs->tcs_output, 0, sizeof(struct draw_tcs_outputs));458459tcs->jit_context = &draw->llvm->tcs_jit_context;460llvm_tcs->variant_key_size =461draw_tcs_llvm_variant_key_size(462MAX2(tcs->info.file_max[TGSI_FILE_SAMPLER]+1,463tcs->info.file_max[TGSI_FILE_SAMPLER_VIEW]+1),464tcs->info.file_max[TGSI_FILE_IMAGE]+1);465}466#endif467return tcs;468}469470void draw_bind_tess_ctrl_shader(struct draw_context *draw,471struct draw_tess_ctrl_shader *dtcs)472{473draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE);474if (dtcs) {475draw->tcs.tess_ctrl_shader = dtcs;476} else {477draw->tcs.tess_ctrl_shader = NULL;478}479}480481void draw_delete_tess_ctrl_shader(struct draw_context *draw,482struct draw_tess_ctrl_shader *dtcs)483{484if (!dtcs)485return;486487#ifdef DRAW_LLVM_AVAILABLE488if (draw->llvm) {489struct llvm_tess_ctrl_shader *shader = llvm_tess_ctrl_shader(dtcs);490491struct draw_tcs_llvm_variant_list_item *li;492493li = first_elem(&shader->variants);494while(!at_end(&shader->variants, li)) {495struct draw_tcs_llvm_variant_list_item *next = next_elem(li);496draw_tcs_llvm_destroy_variant(li->base);497li = next;498}499500assert(shader->variants_cached == 0);501align_free(dtcs->tcs_input);502align_free(dtcs->tcs_output);503}504#endif505506if (dtcs->state.ir.nir)507ralloc_free(dtcs->state.ir.nir);508FREE(dtcs);509}510511#ifdef DRAW_LLVM_AVAILABLE512void draw_tcs_set_current_variant(struct draw_tess_ctrl_shader *shader,513struct draw_tcs_llvm_variant *variant)514{515shader->current_variant = variant;516}517#endif518519struct draw_tess_eval_shader *520draw_create_tess_eval_shader(struct draw_context *draw,521const struct pipe_shader_state *state)522{523#ifdef DRAW_LLVM_AVAILABLE524boolean use_llvm = draw->llvm != NULL;525struct llvm_tess_eval_shader *llvm_tes = NULL;526#endif527struct draw_tess_eval_shader *tes;528529#ifdef DRAW_LLVM_AVAILABLE530if (use_llvm) {531llvm_tes = CALLOC_STRUCT(llvm_tess_eval_shader);532533if (!llvm_tes)534return NULL;535536tes = &llvm_tes->base;537make_empty_list(&llvm_tes->variants);538} else539#endif540{541tes = CALLOC_STRUCT(draw_tess_eval_shader);542}543544if (!tes)545return NULL;546547tes->draw = draw;548tes->state = *state;549550nir_tgsi_scan_shader(state->ir.nir, &tes->info, true);551552tes->prim_mode = tes->info.properties[TGSI_PROPERTY_TES_PRIM_MODE];553tes->spacing = tes->info.properties[TGSI_PROPERTY_TES_SPACING];554tes->vertex_order_cw = tes->info.properties[TGSI_PROPERTY_TES_VERTEX_ORDER_CW];555tes->point_mode = tes->info.properties[TGSI_PROPERTY_TES_POINT_MODE];556557tes->vector_length = 4;558559tes->position_output = -1;560for (unsigned i = 0; i < tes->info.num_outputs; i++) {561if (tes->info.output_semantic_name[i] == TGSI_SEMANTIC_POSITION &&562tes->info.output_semantic_index[i] == 0)563tes->position_output = i;564if (tes->info.output_semantic_name[i] == TGSI_SEMANTIC_VIEWPORT_INDEX)565tes->viewport_index_output = i;566if (tes->info.output_semantic_name[i] == TGSI_SEMANTIC_CLIPDIST) {567debug_assert(tes->info.output_semantic_index[i] <568PIPE_MAX_CLIP_OR_CULL_DISTANCE_ELEMENT_COUNT);569tes->ccdistance_output[tes->info.output_semantic_index[i]] = i;570}571}572573#ifdef DRAW_LLVM_AVAILABLE574if (use_llvm) {575576tes->tes_input = align_malloc(sizeof(struct draw_tes_inputs), 16);577memset(tes->tes_input, 0, sizeof(struct draw_tes_inputs));578579tes->jit_context = &draw->llvm->tes_jit_context;580llvm_tes->variant_key_size =581draw_tes_llvm_variant_key_size(582MAX2(tes->info.file_max[TGSI_FILE_SAMPLER]+1,583tes->info.file_max[TGSI_FILE_SAMPLER_VIEW]+1),584tes->info.file_max[TGSI_FILE_IMAGE]+1);585}586#endif587return tes;588}589590void draw_bind_tess_eval_shader(struct draw_context *draw,591struct draw_tess_eval_shader *dtes)592{593draw_do_flush(draw, DRAW_FLUSH_STATE_CHANGE);594if (dtes) {595draw->tes.tess_eval_shader = dtes;596draw->tes.position_output = dtes->position_output;597} else {598draw->tes.tess_eval_shader = NULL;599}600}601602void draw_delete_tess_eval_shader(struct draw_context *draw,603struct draw_tess_eval_shader *dtes)604{605if (!dtes)606return;607608#ifdef DRAW_LLVM_AVAILABLE609if (draw->llvm) {610struct llvm_tess_eval_shader *shader = llvm_tess_eval_shader(dtes);611struct draw_tes_llvm_variant_list_item *li;612613li = first_elem(&shader->variants);614while(!at_end(&shader->variants, li)) {615struct draw_tes_llvm_variant_list_item *next = next_elem(li);616draw_tes_llvm_destroy_variant(li->base);617li = next;618}619620assert(shader->variants_cached == 0);621align_free(dtes->tes_input);622}623#endif624if (dtes->state.ir.nir)625ralloc_free(dtes->state.ir.nir);626FREE(dtes);627}628629#ifdef DRAW_LLVM_AVAILABLE630void draw_tes_set_current_variant(struct draw_tess_eval_shader *shader,631struct draw_tes_llvm_variant *variant)632{633shader->current_variant = variant;634}635#endif636637enum pipe_prim_type get_tes_output_prim(struct draw_tess_eval_shader *shader)638{639if (shader->point_mode)640return PIPE_PRIM_POINTS;641else if (shader->prim_mode == PIPE_PRIM_LINES)642return PIPE_PRIM_LINES;643else644return PIPE_PRIM_TRIANGLES;645}646647648