Path: blob/21.2-virgl/src/gallium/drivers/zink/zink_compiler.c
4570 views
/*1* Copyright 2018 Collabora Ltd.2*3* Permission is hereby granted, free of charge, to any person obtaining a4* copy of this software and associated documentation files (the "Software"),5* to deal in the Software without restriction, including without limitation6* on the rights to use, copy, modify, merge, publish, distribute, sub7* license, and/or sell copies of the Software, and to permit persons to whom8* the Software is furnished to do so, subject to the following conditions:9*10* The above copyright notice and this permission notice (including the next11* paragraph) shall be included in all copies or substantial portions of the12* Software.13*14* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR15* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,16* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL17* THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM,18* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR19* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE20* USE OR OTHER DEALINGS IN THE SOFTWARE.21*/2223#include "zink_context.h"24#include "zink_compiler.h"25#include "zink_program.h"26#include "zink_screen.h"27#include "nir_to_spirv/nir_to_spirv.h"2829#include "pipe/p_state.h"3031#include "nir.h"32#include "compiler/nir/nir_builder.h"3334#include "nir/tgsi_to_nir.h"35#include "tgsi/tgsi_dump.h"36#include "tgsi/tgsi_from_mesa.h"3738#include "util/u_memory.h"3940static void41create_vs_pushconst(nir_shader *nir)42{43nir_variable *vs_pushconst;44/* create compatible layout for the ntv push constant loader */45struct glsl_struct_field *fields = rzalloc_array(nir, struct glsl_struct_field, 2);46fields[0].type = glsl_array_type(glsl_uint_type(), 1, 0);47fields[0].name = ralloc_asprintf(nir, "draw_mode_is_indexed");48fields[0].offset = offsetof(struct zink_gfx_push_constant, draw_mode_is_indexed);49fields[1].type = glsl_array_type(glsl_uint_type(), 1, 0);50fields[1].name = ralloc_asprintf(nir, "draw_id");51fields[1].offset = offsetof(struct zink_gfx_push_constant, draw_id);52vs_pushconst = nir_variable_create(nir, nir_var_mem_push_const,53glsl_struct_type(fields, 2, "struct", false), "vs_pushconst");54vs_pushconst->data.location = INT_MAX; //doesn't really matter55}5657static void58create_cs_pushconst(nir_shader *nir)59{60nir_variable *cs_pushconst;61/* create compatible layout for the ntv push constant loader */62struct glsl_struct_field *fields = rzalloc_size(nir, 1 * sizeof(struct glsl_struct_field));63fields[0].type = glsl_array_type(glsl_uint_type(), 1, 0);64fields[0].name = ralloc_asprintf(nir, "work_dim");65fields[0].offset = 0;66cs_pushconst = nir_variable_create(nir, nir_var_mem_push_const,67glsl_struct_type(fields, 1, "struct", false), "cs_pushconst");68cs_pushconst->data.location = INT_MAX; //doesn't really matter69}7071static bool72reads_work_dim(nir_shader *shader)73{74return BITSET_TEST(shader->info.system_values_read, SYSTEM_VALUE_WORK_DIM);75}7677static bool78lower_discard_if_instr(nir_intrinsic_instr *instr, nir_builder *b)79{80if (instr->intrinsic == nir_intrinsic_discard_if) {81b->cursor = nir_before_instr(&instr->instr);8283nir_if *if_stmt = nir_push_if(b, nir_ssa_for_src(b, instr->src[0], 1));84nir_discard(b);85nir_pop_if(b, if_stmt);86nir_instr_remove(&instr->instr);87return true;88}89/* a shader like this (shaders@glsl-fs-discard-04):9091uniform int j, k;9293void main()94{95for (int i = 0; i < j; i++) {96if (i > k)97continue;98discard;99}100gl_FragColor = vec4(0.0, 1.0, 0.0, 0.0);101}102103104105will generate nir like:106107loop {108//snip109if ssa_11 {110block block_5:111/ preds: block_4 /112vec1 32 ssa_17 = iadd ssa_50, ssa_31113/ succs: block_7 /114} else {115block block_6:116/ preds: block_4 /117intrinsic discard () () <-- not last instruction118vec1 32 ssa_23 = iadd ssa_50, ssa_31 <-- dead code loop itr increment119/ succs: block_7 /120}121//snip122}123124which means that we can't assert like this:125126assert(instr->intrinsic != nir_intrinsic_discard ||127nir_block_last_instr(instr->instr.block) == &instr->instr);128129130and it's unnecessary anyway since post-vtn optimizing will dce the instructions following the discard131*/132133return false;134}135136static bool137lower_discard_if(nir_shader *shader)138{139bool progress = false;140141nir_foreach_function(function, shader) {142if (function->impl) {143nir_builder builder;144nir_builder_init(&builder, function->impl);145nir_foreach_block(block, function->impl) {146nir_foreach_instr_safe(instr, block) {147if (instr->type == nir_instr_type_intrinsic)148progress |= lower_discard_if_instr(149nir_instr_as_intrinsic(instr),150&builder);151}152}153154nir_metadata_preserve(function->impl, nir_metadata_dominance);155}156}157158return progress;159}160161static bool162lower_work_dim_instr(nir_builder *b, nir_instr *in, void *data)163{164if (in->type != nir_instr_type_intrinsic)165return false;166nir_intrinsic_instr *instr = nir_instr_as_intrinsic(in);167if (instr->intrinsic != nir_intrinsic_load_work_dim)168return false;169170if (instr->intrinsic == nir_intrinsic_load_work_dim) {171b->cursor = nir_after_instr(&instr->instr);172nir_intrinsic_instr *load = nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);173load->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));174nir_intrinsic_set_range(load, 3 * sizeof(uint32_t));175load->num_components = 1;176nir_ssa_dest_init(&load->instr, &load->dest, 1, 32, "work_dim");177nir_builder_instr_insert(b, &load->instr);178179nir_ssa_def_rewrite_uses(&instr->dest.ssa, &load->dest.ssa);180}181182return true;183}184185static bool186lower_work_dim(nir_shader *shader)187{188if (shader->info.stage != MESA_SHADER_KERNEL)189return false;190191if (!reads_work_dim(shader))192return false;193194return nir_shader_instructions_pass(shader, lower_work_dim_instr, nir_metadata_dominance, NULL);195}196197static bool198lower_64bit_vertex_attribs_instr(nir_builder *b, nir_instr *instr, void *data)199{200if (instr->type != nir_instr_type_deref)201return false;202nir_deref_instr *deref = nir_instr_as_deref(instr);203if (deref->deref_type != nir_deref_type_var)204return false;205nir_variable *var = nir_deref_instr_get_variable(deref);206if (var->data.mode != nir_var_shader_in)207return false;208if (!glsl_type_is_64bit(var->type) || !glsl_type_is_vector(var->type) || glsl_get_vector_elements(var->type) < 3)209return false;210211/* create second variable for the split */212nir_variable *var2 = nir_variable_clone(var, b->shader);213/* split new variable into second slot */214var2->data.driver_location++;215nir_shader_add_variable(b->shader, var2);216217unsigned total_num_components = glsl_get_vector_elements(var->type);218/* new variable is the second half of the dvec */219var2->type = glsl_vector_type(glsl_get_base_type(var->type), glsl_get_vector_elements(var->type) - 2);220/* clamp original variable to a dvec2 */221deref->type = var->type = glsl_vector_type(glsl_get_base_type(var->type), 2);222223/* create deref instr for new variable */224b->cursor = nir_after_instr(instr);225nir_deref_instr *deref2 = nir_build_deref_var(b, var2);226227nir_foreach_use_safe(use_src, &deref->dest.ssa) {228nir_instr *use_instr = use_src->parent_instr;229assert(use_instr->type == nir_instr_type_intrinsic &&230nir_instr_as_intrinsic(use_instr)->intrinsic == nir_intrinsic_load_deref);231232/* this is a load instruction for the deref, and we need to split it into two instructions that we can233* then zip back into a single ssa def */234nir_intrinsic_instr *intr = nir_instr_as_intrinsic(use_instr);235/* clamp the first load to 2 64bit components */236intr->num_components = intr->dest.ssa.num_components = 2;237b->cursor = nir_after_instr(use_instr);238/* this is the second load instruction for the second half of the dvec3/4 components */239nir_intrinsic_instr *intr2 = nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_deref);240intr2->src[0] = nir_src_for_ssa(&deref2->dest.ssa);241intr2->num_components = total_num_components - 2;242nir_ssa_dest_init(&intr2->instr, &intr2->dest, intr2->num_components, 64, NULL);243nir_builder_instr_insert(b, &intr2->instr);244245nir_ssa_def *def[4];246/* create a new dvec3/4 comprised of all the loaded components from both variables */247def[0] = nir_vector_extract(b, &intr->dest.ssa, nir_imm_int(b, 0));248def[1] = nir_vector_extract(b, &intr->dest.ssa, nir_imm_int(b, 1));249def[2] = nir_vector_extract(b, &intr2->dest.ssa, nir_imm_int(b, 0));250if (total_num_components == 4)251def[3] = nir_vector_extract(b, &intr2->dest.ssa, nir_imm_int(b, 1));252nir_ssa_def *new_vec = nir_vec(b, def, total_num_components);253/* use the assembled dvec3/4 for all other uses of the load */254nir_ssa_def_rewrite_uses_after(&intr->dest.ssa, new_vec,255new_vec->parent_instr);256}257258return true;259}260261/* "64-bit three- and four-component vectors consume two consecutive locations."262* - 14.1.4. Location Assignment263*264* this pass splits dvec3 and dvec4 vertex inputs into a dvec2 and a double/dvec2 which265* are assigned to consecutive locations, loaded separately, and then assembled back into a266* composite value that's used in place of the original loaded ssa src267*/268static bool269lower_64bit_vertex_attribs(nir_shader *shader)270{271if (shader->info.stage != MESA_SHADER_VERTEX)272return false;273274return nir_shader_instructions_pass(shader, lower_64bit_vertex_attribs_instr, nir_metadata_dominance, NULL);275}276277static bool278lower_basevertex_instr(nir_builder *b, nir_instr *in, void *data)279{280if (in->type != nir_instr_type_intrinsic)281return false;282nir_intrinsic_instr *instr = nir_instr_as_intrinsic(in);283if (instr->intrinsic != nir_intrinsic_load_base_vertex)284return false;285286b->cursor = nir_after_instr(&instr->instr);287nir_intrinsic_instr *load = nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);288load->src[0] = nir_src_for_ssa(nir_imm_int(b, 0));289nir_intrinsic_set_range(load, 4);290load->num_components = 1;291nir_ssa_dest_init(&load->instr, &load->dest, 1, 32, "draw_mode_is_indexed");292nir_builder_instr_insert(b, &load->instr);293294nir_ssa_def *composite = nir_build_alu(b, nir_op_bcsel,295nir_build_alu(b, nir_op_ieq, &load->dest.ssa, nir_imm_int(b, 1), NULL, NULL),296&instr->dest.ssa,297nir_imm_int(b, 0),298NULL);299300nir_ssa_def_rewrite_uses_after(&instr->dest.ssa, composite,301composite->parent_instr);302return true;303}304305static bool306lower_basevertex(nir_shader *shader)307{308if (shader->info.stage != MESA_SHADER_VERTEX)309return false;310311if (!BITSET_TEST(shader->info.system_values_read, SYSTEM_VALUE_BASE_VERTEX))312return false;313314return nir_shader_instructions_pass(shader, lower_basevertex_instr, nir_metadata_dominance, NULL);315}316317318static bool319lower_drawid_instr(nir_builder *b, nir_instr *in, void *data)320{321if (in->type != nir_instr_type_intrinsic)322return false;323nir_intrinsic_instr *instr = nir_instr_as_intrinsic(in);324if (instr->intrinsic != nir_intrinsic_load_draw_id)325return false;326327b->cursor = nir_before_instr(&instr->instr);328nir_intrinsic_instr *load = nir_intrinsic_instr_create(b->shader, nir_intrinsic_load_push_constant);329load->src[0] = nir_src_for_ssa(nir_imm_int(b, 1));330nir_intrinsic_set_range(load, 4);331load->num_components = 1;332nir_ssa_dest_init(&load->instr, &load->dest, 1, 32, "draw_id");333nir_builder_instr_insert(b, &load->instr);334335nir_ssa_def_rewrite_uses(&instr->dest.ssa, &load->dest.ssa);336337return true;338}339340static bool341lower_drawid(nir_shader *shader)342{343if (shader->info.stage != MESA_SHADER_VERTEX)344return false;345346if (!BITSET_TEST(shader->info.system_values_read, SYSTEM_VALUE_DRAW_ID))347return false;348349return nir_shader_instructions_pass(shader, lower_drawid_instr, nir_metadata_dominance, NULL);350}351352static bool353lower_dual_blend(nir_shader *shader)354{355bool progress = false;356nir_variable *var = nir_find_variable_with_location(shader, nir_var_shader_out, FRAG_RESULT_DATA1);357if (var) {358var->data.location = FRAG_RESULT_DATA0;359var->data.index = 1;360progress = true;361}362nir_shader_preserve_all_metadata(shader);363return progress;364}365366void367zink_screen_init_compiler(struct zink_screen *screen)368{369static const struct nir_shader_compiler_options370default_options = {371.lower_ffma16 = true,372.lower_ffma32 = true,373.lower_ffma64 = true,374.lower_scmp = true,375.lower_fdph = true,376.lower_flrp32 = true,377.lower_fpow = true,378.lower_fsat = true,379.lower_extract_byte = true,380.lower_extract_word = true,381.lower_insert_byte = true,382.lower_insert_word = true,383.lower_mul_high = true,384.lower_rotate = true,385.lower_uadd_carry = true,386.lower_pack_64_2x32_split = true,387.lower_unpack_64_2x32_split = true,388.lower_vector_cmp = true,389.lower_int64_options = 0,390.lower_doubles_options = ~nir_lower_fp64_full_software,391.lower_uniforms_to_ubo = true,392.has_fsub = true,393.has_isub = true,394.lower_mul_2x32_64 = true,395.support_16bit_alu = true, /* not quite what it sounds like */396};397398screen->nir_options = default_options;399400if (!screen->info.feats.features.shaderInt64)401screen->nir_options.lower_int64_options = ~0;402403if (!screen->info.feats.features.shaderFloat64) {404screen->nir_options.lower_doubles_options = ~0;405screen->nir_options.lower_flrp64 = true;406screen->nir_options.lower_ffma64 = true;407}408}409410const void *411zink_get_compiler_options(struct pipe_screen *pscreen,412enum pipe_shader_ir ir,413enum pipe_shader_type shader)414{415assert(ir == PIPE_SHADER_IR_NIR);416return &zink_screen(pscreen)->nir_options;417}418419struct nir_shader *420zink_tgsi_to_nir(struct pipe_screen *screen, const struct tgsi_token *tokens)421{422if (zink_debug & ZINK_DEBUG_TGSI) {423fprintf(stderr, "TGSI shader:\n---8<---\n");424tgsi_dump_to_file(tokens, 0, stderr);425fprintf(stderr, "---8<---\n\n");426}427428return tgsi_to_nir(tokens, screen, false);429}430431static void432optimize_nir(struct nir_shader *s)433{434bool progress;435do {436progress = false;437NIR_PASS_V(s, nir_lower_vars_to_ssa);438NIR_PASS(progress, s, nir_copy_prop);439NIR_PASS(progress, s, nir_opt_remove_phis);440NIR_PASS(progress, s, nir_opt_dce);441NIR_PASS(progress, s, nir_opt_dead_cf);442NIR_PASS(progress, s, nir_opt_cse);443NIR_PASS(progress, s, nir_opt_peephole_select, 8, true, true);444NIR_PASS(progress, s, nir_opt_algebraic);445NIR_PASS(progress, s, nir_opt_constant_folding);446NIR_PASS(progress, s, nir_opt_undef);447NIR_PASS(progress, s, zink_nir_lower_b2b);448} while (progress);449450do {451progress = false;452NIR_PASS(progress, s, nir_opt_algebraic_late);453if (progress) {454NIR_PASS_V(s, nir_copy_prop);455NIR_PASS_V(s, nir_opt_dce);456NIR_PASS_V(s, nir_opt_cse);457}458} while (progress);459}460461/* check for a genuine gl_PointSize output vs one from nir_lower_point_size_mov */462static bool463check_psiz(struct nir_shader *s)464{465nir_foreach_shader_out_variable(var, s) {466if (var->data.location == VARYING_SLOT_PSIZ) {467/* genuine PSIZ outputs will have this set */468return !!var->data.explicit_location;469}470}471return false;472}473474static void475update_so_info(struct zink_shader *zs, const struct pipe_stream_output_info *so_info,476uint64_t outputs_written, bool have_psiz)477{478uint8_t reverse_map[64] = {0};479unsigned slot = 0;480/* semi-copied from iris */481while (outputs_written) {482int bit = u_bit_scan64(&outputs_written);483/* PSIZ from nir_lower_point_size_mov breaks stream output, so always skip it */484if (bit == VARYING_SLOT_PSIZ && !have_psiz)485continue;486reverse_map[slot++] = bit;487}488489nir_foreach_shader_out_variable(var, zs->nir)490var->data.explicit_xfb_buffer = 0;491492bool inlined[64] = {0};493for (unsigned i = 0; i < so_info->num_outputs; i++) {494const struct pipe_stream_output *output = &so_info->output[i];495unsigned slot = reverse_map[output->register_index];496/* always set stride to be used during draw */497zs->streamout.so_info.stride[output->output_buffer] = so_info->stride[output->output_buffer];498if ((zs->nir->info.stage != MESA_SHADER_GEOMETRY || util_bitcount(zs->nir->info.gs.active_stream_mask) == 1) &&499!output->start_component) {500nir_variable *var = NULL;501while (!var)502var = nir_find_variable_with_location(zs->nir, nir_var_shader_out, slot--);503slot++;504if (inlined[slot])505continue;506assert(var && var->data.location == slot);507/* if this is the entire variable, try to blast it out during the initial declaration */508if (glsl_get_components(var->type) == output->num_components) {509var->data.explicit_xfb_buffer = 1;510var->data.xfb.buffer = output->output_buffer;511var->data.xfb.stride = so_info->stride[output->output_buffer] * 4;512var->data.offset = output->dst_offset * 4;513var->data.stream = output->stream;514inlined[slot] = true;515continue;516}517}518zs->streamout.so_info.output[zs->streamout.so_info.num_outputs] = *output;519/* Map Gallium's condensed "slots" back to real VARYING_SLOT_* enums */520zs->streamout.so_info_slots[zs->streamout.so_info.num_outputs++] = reverse_map[output->register_index];521}522zs->streamout.have_xfb = !!zs->streamout.so_info.num_outputs;523}524525static void526assign_producer_var_io(gl_shader_stage stage, nir_variable *var, unsigned *reserved, unsigned char *slot_map)527{528unsigned slot = var->data.location;529switch (var->data.location) {530case VARYING_SLOT_POS:531case VARYING_SLOT_PNTC:532case VARYING_SLOT_PSIZ:533case VARYING_SLOT_LAYER:534case VARYING_SLOT_PRIMITIVE_ID:535case VARYING_SLOT_CLIP_DIST0:536case VARYING_SLOT_CULL_DIST0:537case VARYING_SLOT_VIEWPORT:538case VARYING_SLOT_FACE:539case VARYING_SLOT_TESS_LEVEL_OUTER:540case VARYING_SLOT_TESS_LEVEL_INNER:541/* use a sentinel value to avoid counting later */542var->data.driver_location = UINT_MAX;543break;544545default:546if (var->data.patch) {547assert(var->data.location >= VARYING_SLOT_PATCH0);548slot = var->data.location - VARYING_SLOT_PATCH0;549} else if (var->data.location >= VARYING_SLOT_VAR0 &&550var->data.mode == nir_var_shader_in &&551stage == MESA_SHADER_TESS_EVAL) {552slot = var->data.location - VARYING_SLOT_VAR0;553} else {554if (slot_map[var->data.location] == 0xff) {555assert(*reserved < MAX_VARYING);556slot_map[var->data.location] = *reserved;557*reserved += glsl_count_vec4_slots(var->type, false, false);558}559slot = slot_map[var->data.location];560assert(slot < MAX_VARYING);561}562var->data.driver_location = slot;563}564}565566ALWAYS_INLINE static bool567is_texcoord(gl_shader_stage stage, const nir_variable *var)568{569if (stage != MESA_SHADER_FRAGMENT)570return false;571return var->data.location >= VARYING_SLOT_TEX0 &&572var->data.location <= VARYING_SLOT_TEX7;573}574575static bool576assign_consumer_var_io(gl_shader_stage stage, nir_variable *var, unsigned *reserved, unsigned char *slot_map)577{578switch (var->data.location) {579case VARYING_SLOT_POS:580case VARYING_SLOT_PNTC:581case VARYING_SLOT_PSIZ:582case VARYING_SLOT_LAYER:583case VARYING_SLOT_PRIMITIVE_ID:584case VARYING_SLOT_CLIP_DIST0:585case VARYING_SLOT_CULL_DIST0:586case VARYING_SLOT_VIEWPORT:587case VARYING_SLOT_FACE:588case VARYING_SLOT_TESS_LEVEL_OUTER:589case VARYING_SLOT_TESS_LEVEL_INNER:590/* use a sentinel value to avoid counting later */591var->data.driver_location = UINT_MAX;592break;593default:594if (var->data.patch) {595assert(var->data.location >= VARYING_SLOT_PATCH0);596var->data.driver_location = var->data.location - VARYING_SLOT_PATCH0;597} else if (var->data.location >= VARYING_SLOT_VAR0 &&598stage == MESA_SHADER_TESS_CTRL &&599var->data.mode == nir_var_shader_out)600var->data.driver_location = var->data.location - VARYING_SLOT_VAR0;601else {602if (slot_map[var->data.location] == (unsigned char)-1) {603if (!is_texcoord(stage, var))604/* dead io */605return false;606/* texcoords can't be eliminated in fs due to GL_COORD_REPLACE */607slot_map[var->data.location] = (*reserved)++;608}609var->data.driver_location = slot_map[var->data.location];610}611}612return true;613}614615616static bool617rewrite_and_discard_read(nir_builder *b, nir_instr *instr, void *data)618{619nir_variable *var = data;620if (instr->type != nir_instr_type_intrinsic)621return false;622623nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);624if (intr->intrinsic != nir_intrinsic_load_deref)625return false;626nir_variable *deref_var = nir_intrinsic_get_var(intr, 0);627if (deref_var != var)628return false;629nir_ssa_def *undef = nir_ssa_undef(b, nir_dest_num_components(intr->dest), nir_dest_bit_size(intr->dest));630nir_ssa_def_rewrite_uses(&intr->dest.ssa, undef);631return true;632}633634void635zink_compiler_assign_io(nir_shader *producer, nir_shader *consumer)636{637unsigned reserved = 0;638unsigned char slot_map[VARYING_SLOT_MAX];639memset(slot_map, -1, sizeof(slot_map));640bool do_fixup = false;641nir_shader *nir = producer->info.stage == MESA_SHADER_TESS_CTRL ? producer : consumer;642if (producer->info.stage == MESA_SHADER_TESS_CTRL) {643/* never assign from tcs -> tes, always invert */644nir_foreach_variable_with_modes(var, consumer, nir_var_shader_in)645assign_producer_var_io(consumer->info.stage, var, &reserved, slot_map);646nir_foreach_variable_with_modes_safe(var, producer, nir_var_shader_out) {647if (!assign_consumer_var_io(producer->info.stage, var, &reserved, slot_map))648/* this is an output, nothing more needs to be done for it to be dropped */649do_fixup = true;650}651} else {652nir_foreach_variable_with_modes(var, producer, nir_var_shader_out)653assign_producer_var_io(producer->info.stage, var, &reserved, slot_map);654nir_foreach_variable_with_modes_safe(var, consumer, nir_var_shader_in) {655if (!assign_consumer_var_io(consumer->info.stage, var, &reserved, slot_map)) {656do_fixup = true;657/* input needs to be rewritten as an undef to ensure the entire deref chain is deleted */658nir_shader_instructions_pass(consumer, rewrite_and_discard_read, nir_metadata_dominance, var);659}660}661}662if (!do_fixup)663return;664nir_fixup_deref_modes(nir);665NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_shader_temp, NULL);666optimize_nir(nir);667}668669VkShaderModule670zink_shader_compile(struct zink_screen *screen, struct zink_shader *zs, nir_shader *base_nir, struct zink_shader_key *key)671{672VkShaderModule mod = VK_NULL_HANDLE;673void *streamout = NULL;674nir_shader *nir = nir_shader_clone(NULL, base_nir);675676if (key) {677if (key->inline_uniforms) {678NIR_PASS_V(nir, nir_inline_uniforms,679nir->info.num_inlinable_uniforms,680key->base.inlined_uniform_values,681nir->info.inlinable_uniform_dw_offsets);682683optimize_nir(nir);684685/* This must be done again. */686NIR_PASS_V(nir, nir_io_add_const_offset_to_base, nir_var_shader_in |687nir_var_shader_out);688}689}690691/* TODO: use a separate mem ctx here for ralloc */692if (zs->nir->info.stage < MESA_SHADER_FRAGMENT) {693if (zink_vs_key(key)->last_vertex_stage) {694if (zs->streamout.have_xfb)695streamout = &zs->streamout;696697if (!zink_vs_key(key)->clip_halfz) {698NIR_PASS_V(nir, nir_lower_clip_halfz);699}700if (zink_vs_key(key)->push_drawid) {701NIR_PASS_V(nir, lower_drawid);702}703}704} else if (zs->nir->info.stage == MESA_SHADER_FRAGMENT) {705if (!zink_fs_key(key)->samples &&706nir->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_SAMPLE_MASK)) {707/* VK will always use gl_SampleMask[] values even if sample count is 0,708* so we need to skip this write here to mimic GL's behavior of ignoring it709*/710nir_foreach_shader_out_variable(var, nir) {711if (var->data.location == FRAG_RESULT_SAMPLE_MASK)712var->data.mode = nir_var_shader_temp;713}714nir_fixup_deref_modes(nir);715NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_shader_temp, NULL);716optimize_nir(nir);717}718if (zink_fs_key(key)->force_dual_color_blend && nir->info.outputs_written & BITFIELD64_BIT(FRAG_RESULT_DATA1)) {719NIR_PASS_V(nir, lower_dual_blend);720}721if (zink_fs_key(key)->coord_replace_bits) {722NIR_PASS_V(nir, nir_lower_texcoord_replace, zink_fs_key(key)->coord_replace_bits,723false, zink_fs_key(key)->coord_replace_yinvert);724}725}726NIR_PASS_V(nir, nir_convert_from_ssa, true);727728struct spirv_shader *spirv = nir_to_spirv(nir, streamout, screen->spirv_version);729if (!spirv)730goto done;731732if (zink_debug & ZINK_DEBUG_SPIRV) {733char buf[256];734static int i;735snprintf(buf, sizeof(buf), "dump%02d.spv", i++);736FILE *fp = fopen(buf, "wb");737if (fp) {738fwrite(spirv->words, sizeof(uint32_t), spirv->num_words, fp);739fclose(fp);740fprintf(stderr, "wrote '%s'...\n", buf);741}742}743744VkShaderModuleCreateInfo smci = {0};745smci.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO;746smci.codeSize = spirv->num_words * sizeof(uint32_t);747smci.pCode = spirv->words;748749if (vkCreateShaderModule(screen->dev, &smci, NULL, &mod) != VK_SUCCESS)750mod = VK_NULL_HANDLE;751752done:753ralloc_free(nir);754755/* TODO: determine if there's any reason to cache spirv output? */756ralloc_free(spirv);757return mod;758}759760static bool761lower_baseinstance_instr(nir_builder *b, nir_instr *instr, void *data)762{763if (instr->type != nir_instr_type_intrinsic)764return false;765nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);766if (intr->intrinsic != nir_intrinsic_load_instance_id)767return false;768b->cursor = nir_after_instr(instr);769nir_ssa_def *def = nir_isub(b, &intr->dest.ssa, nir_load_base_instance(b));770nir_ssa_def_rewrite_uses_after(&intr->dest.ssa, def, def->parent_instr);771return true;772}773774static bool775lower_baseinstance(nir_shader *shader)776{777if (shader->info.stage != MESA_SHADER_VERTEX)778return false;779return nir_shader_instructions_pass(shader, lower_baseinstance_instr, nir_metadata_dominance, NULL);780}781782bool nir_lower_dynamic_bo_access(nir_shader *shader);783784/* gl_nir_lower_buffers makes variables unusable for all UBO/SSBO access785* so instead we delete all those broken variables and just make new ones786*/787static bool788unbreak_bos(nir_shader *shader)789{790uint32_t ssbo_used = 0;791uint32_t ubo_used = 0;792uint64_t max_ssbo_size = 0;793uint64_t max_ubo_size = 0;794bool ssbo_sizes[PIPE_MAX_SHADER_BUFFERS] = {false};795796if (!shader->info.num_ssbos && !shader->info.num_ubos && !shader->num_uniforms)797return false;798nir_function_impl *impl = nir_shader_get_entrypoint(shader);799nir_foreach_block(block, impl) {800nir_foreach_instr(instr, block) {801if (instr->type != nir_instr_type_intrinsic)802continue;803804nir_intrinsic_instr *intrin = nir_instr_as_intrinsic(instr);805switch (intrin->intrinsic) {806case nir_intrinsic_store_ssbo:807ssbo_used |= BITFIELD_BIT(nir_src_as_uint(intrin->src[1]));808break;809810case nir_intrinsic_get_ssbo_size: {811uint32_t slot = nir_src_as_uint(intrin->src[0]);812ssbo_used |= BITFIELD_BIT(slot);813ssbo_sizes[slot] = true;814break;815}816case nir_intrinsic_ssbo_atomic_add:817case nir_intrinsic_ssbo_atomic_imin:818case nir_intrinsic_ssbo_atomic_umin:819case nir_intrinsic_ssbo_atomic_imax:820case nir_intrinsic_ssbo_atomic_umax:821case nir_intrinsic_ssbo_atomic_and:822case nir_intrinsic_ssbo_atomic_or:823case nir_intrinsic_ssbo_atomic_xor:824case nir_intrinsic_ssbo_atomic_exchange:825case nir_intrinsic_ssbo_atomic_comp_swap:826case nir_intrinsic_ssbo_atomic_fmin:827case nir_intrinsic_ssbo_atomic_fmax:828case nir_intrinsic_ssbo_atomic_fcomp_swap:829case nir_intrinsic_load_ssbo:830ssbo_used |= BITFIELD_BIT(nir_src_as_uint(intrin->src[0]));831break;832case nir_intrinsic_load_ubo:833case nir_intrinsic_load_ubo_vec4:834ubo_used |= BITFIELD_BIT(nir_src_as_uint(intrin->src[0]));835break;836default:837break;838}839}840}841842nir_foreach_variable_with_modes(var, shader, nir_var_mem_ssbo | nir_var_mem_ubo) {843const struct glsl_type *type = glsl_without_array(var->type);844if (type_is_counter(type))845continue;846unsigned size = glsl_count_attribute_slots(glsl_type_is_array(var->type) ? var->type : type, false);847if (var->data.mode == nir_var_mem_ubo)848max_ubo_size = MAX2(max_ubo_size, size);849else850max_ssbo_size = MAX2(max_ssbo_size, size);851var->data.mode = nir_var_shader_temp;852}853nir_fixup_deref_modes(shader);854NIR_PASS_V(shader, nir_remove_dead_variables, nir_var_shader_temp, NULL);855optimize_nir(shader);856857if (!ssbo_used && !ubo_used)858return false;859860struct glsl_struct_field *fields = rzalloc_array(shader, struct glsl_struct_field, 2);861fields[0].name = ralloc_strdup(shader, "base");862fields[1].name = ralloc_strdup(shader, "unsized");863if (ubo_used) {864const struct glsl_type *ubo_type = glsl_array_type(glsl_uint_type(), max_ubo_size * 4, 4);865fields[0].type = ubo_type;866u_foreach_bit(slot, ubo_used) {867char buf[64];868snprintf(buf, sizeof(buf), "ubo_slot_%u", slot);869nir_variable *var = nir_variable_create(shader, nir_var_mem_ubo, glsl_struct_type(fields, 1, "struct", false), buf);870var->interface_type = var->type;871var->data.driver_location = slot;872}873}874if (ssbo_used) {875const struct glsl_type *ssbo_type = glsl_array_type(glsl_uint_type(), max_ssbo_size * 4, 4);876const struct glsl_type *unsized = glsl_array_type(glsl_uint_type(), 0, 4);877fields[0].type = ssbo_type;878u_foreach_bit(slot, ssbo_used) {879char buf[64];880snprintf(buf, sizeof(buf), "ssbo_slot_%u", slot);881if (ssbo_sizes[slot])882fields[1].type = unsized;883else884fields[1].type = NULL;885nir_variable *var = nir_variable_create(shader, nir_var_mem_ssbo,886glsl_struct_type(fields, 1 + !!ssbo_sizes[slot], "struct", false), buf);887var->interface_type = var->type;888var->data.driver_location = slot;889}890}891return true;892}893894static uint32_t895zink_binding(gl_shader_stage stage, VkDescriptorType type, int index)896{897if (stage == MESA_SHADER_NONE) {898unreachable("not supported");899} else {900switch (type) {901case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:902case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:903assert(index < PIPE_MAX_CONSTANT_BUFFERS);904return (stage * PIPE_MAX_CONSTANT_BUFFERS) + index;905906case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:907case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:908assert(index < PIPE_MAX_SAMPLERS);909return (stage * PIPE_MAX_SAMPLERS) + index;910911case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:912assert(index < PIPE_MAX_SHADER_BUFFERS);913return (stage * PIPE_MAX_SHADER_BUFFERS) + index;914915case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:916case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:917assert(index < PIPE_MAX_SHADER_IMAGES);918return (stage * PIPE_MAX_SHADER_IMAGES) + index;919920default:921unreachable("unexpected type");922}923}924}925926struct zink_shader *927zink_shader_create(struct zink_screen *screen, struct nir_shader *nir,928const struct pipe_stream_output_info *so_info)929{930struct zink_shader *ret = CALLOC_STRUCT(zink_shader);931bool have_psiz = false;932933ret->programs = _mesa_pointer_set_create(NULL);934935nir_variable_mode indirect_derefs_modes = nir_var_function_temp;936if (nir->info.stage == MESA_SHADER_TESS_CTRL ||937nir->info.stage == MESA_SHADER_TESS_EVAL)938indirect_derefs_modes |= nir_var_shader_in | nir_var_shader_out;939940NIR_PASS_V(nir, nir_lower_indirect_derefs, indirect_derefs_modes,941UINT32_MAX);942943if (nir->info.stage == MESA_SHADER_VERTEX)944create_vs_pushconst(nir);945else if (nir->info.stage == MESA_SHADER_TESS_CTRL ||946nir->info.stage == MESA_SHADER_TESS_EVAL)947NIR_PASS_V(nir, nir_lower_io_arrays_to_elements_no_indirects, false);948else if (nir->info.stage == MESA_SHADER_KERNEL)949create_cs_pushconst(nir);950951if (nir->info.stage < MESA_SHADER_FRAGMENT)952have_psiz = check_psiz(nir);953NIR_PASS_V(nir, lower_basevertex);954NIR_PASS_V(nir, lower_work_dim);955NIR_PASS_V(nir, nir_lower_regs_to_ssa);956NIR_PASS_V(nir, lower_baseinstance);957optimize_nir(nir);958NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_function_temp, NULL);959NIR_PASS_V(nir, lower_discard_if);960NIR_PASS_V(nir, nir_lower_fragcolor,961nir->info.fs.color_is_dual_source ? 1 : 8);962NIR_PASS_V(nir, lower_64bit_vertex_attribs);963NIR_PASS_V(nir, unbreak_bos);964965if (zink_debug & ZINK_DEBUG_NIR) {966fprintf(stderr, "NIR shader:\n---8<---\n");967nir_print_shader(nir, stderr);968fprintf(stderr, "---8<---\n");969}970971foreach_list_typed_reverse(nir_variable, var, node, &nir->variables) {972if (_nir_shader_variable_has_mode(var, nir_var_uniform |973nir_var_mem_ubo |974nir_var_mem_ssbo)) {975enum zink_descriptor_type ztype;976const struct glsl_type *type = glsl_without_array(var->type);977if (var->data.mode == nir_var_mem_ubo) {978ztype = ZINK_DESCRIPTOR_TYPE_UBO;979/* buffer 0 is a push descriptor */980var->data.descriptor_set = !!var->data.driver_location;981var->data.binding = !var->data.driver_location ? nir->info.stage :982zink_binding(nir->info.stage,983VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,984var->data.driver_location);985assert(var->data.driver_location || var->data.binding < 10);986VkDescriptorType vktype = !var->data.driver_location ? VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC : VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;987int binding = var->data.binding;988989ret->bindings[ztype][ret->num_bindings[ztype]].index = var->data.driver_location;990ret->bindings[ztype][ret->num_bindings[ztype]].binding = binding;991ret->bindings[ztype][ret->num_bindings[ztype]].type = vktype;992ret->bindings[ztype][ret->num_bindings[ztype]].size = 1;993ret->ubos_used |= (1 << ret->bindings[ztype][ret->num_bindings[ztype]].index);994ret->num_bindings[ztype]++;995} else if (var->data.mode == nir_var_mem_ssbo) {996ztype = ZINK_DESCRIPTOR_TYPE_SSBO;997var->data.descriptor_set = ztype + 1;998var->data.binding = zink_binding(nir->info.stage,999VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,1000var->data.driver_location);1001ret->bindings[ztype][ret->num_bindings[ztype]].index = var->data.driver_location;1002ret->ssbos_used |= (1 << ret->bindings[ztype][ret->num_bindings[ztype]].index);1003ret->bindings[ztype][ret->num_bindings[ztype]].binding = var->data.binding;1004ret->bindings[ztype][ret->num_bindings[ztype]].type = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;1005ret->bindings[ztype][ret->num_bindings[ztype]].size = 1;1006ret->num_bindings[ztype]++;1007} else {1008assert(var->data.mode == nir_var_uniform);1009if (glsl_type_is_sampler(type) || glsl_type_is_image(type)) {1010VkDescriptorType vktype = glsl_type_is_image(type) ? zink_image_type(type) : zink_sampler_type(type);1011if (vktype == VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER)1012ret->num_texel_buffers++;1013ztype = zink_desc_type_from_vktype(vktype);1014var->data.driver_location = var->data.binding;1015var->data.descriptor_set = ztype + 1;1016var->data.binding = zink_binding(nir->info.stage, vktype, var->data.driver_location);1017ret->bindings[ztype][ret->num_bindings[ztype]].index = var->data.driver_location;1018ret->bindings[ztype][ret->num_bindings[ztype]].binding = var->data.binding;1019ret->bindings[ztype][ret->num_bindings[ztype]].type = vktype;1020if (glsl_type_is_array(var->type))1021ret->bindings[ztype][ret->num_bindings[ztype]].size = glsl_get_aoa_size(var->type);1022else1023ret->bindings[ztype][ret->num_bindings[ztype]].size = 1;1024ret->num_bindings[ztype]++;1025}1026}1027}1028}10291030ret->nir = nir;1031if (so_info && nir->info.outputs_written && nir->info.has_transform_feedback_varyings)1032update_so_info(ret, so_info, nir->info.outputs_written, have_psiz);10331034return ret;1035}10361037void1038zink_shader_finalize(struct pipe_screen *pscreen, void *nirptr, bool optimize)1039{1040struct zink_screen *screen = zink_screen(pscreen);1041nir_shader *nir = nirptr;10421043if (!screen->info.feats.features.shaderImageGatherExtended) {1044nir_lower_tex_options tex_opts = {0};1045tex_opts.lower_tg4_offsets = true;1046NIR_PASS_V(nir, nir_lower_tex, &tex_opts);1047}1048NIR_PASS_V(nir, nir_lower_uniforms_to_ubo, true, false);1049if (nir->info.stage == MESA_SHADER_GEOMETRY)1050NIR_PASS_V(nir, nir_lower_gs_intrinsics, nir_lower_gs_intrinsics_per_stream);1051optimize_nir(nir);1052if (nir->info.num_ubos || nir->info.num_ssbos)1053NIR_PASS_V(nir, nir_lower_dynamic_bo_access);1054nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));1055if (screen->driconf.inline_uniforms)1056nir_find_inlinable_uniforms(nir);1057}10581059void1060zink_shader_free(struct zink_context *ctx, struct zink_shader *shader)1061{1062struct zink_screen *screen = zink_screen(ctx->base.screen);1063set_foreach(shader->programs, entry) {1064if (shader->nir->info.stage == MESA_SHADER_COMPUTE) {1065struct zink_compute_program *comp = (void*)entry->key;1066_mesa_hash_table_remove_key(ctx->compute_program_cache, comp->shader);1067comp->shader = NULL;1068bool in_use = comp == ctx->curr_compute;1069if (in_use)1070ctx->compute_stage = NULL;1071if (zink_compute_program_reference(screen, &comp, NULL) && in_use)1072ctx->curr_compute = NULL;1073} else {1074struct zink_gfx_program *prog = (void*)entry->key;1075enum pipe_shader_type pstage = pipe_shader_type_from_mesa(shader->nir->info.stage);1076assert(pstage < ZINK_SHADER_COUNT);1077bool in_use = prog == ctx->curr_program;1078if (shader->nir->info.stage != MESA_SHADER_TESS_CTRL || !shader->is_generated)1079_mesa_hash_table_remove_key(ctx->program_cache, prog->shaders);1080prog->shaders[pstage] = NULL;1081if (shader->nir->info.stage == MESA_SHADER_TESS_EVAL && shader->generated)1082/* automatically destroy generated tcs shaders when tes is destroyed */1083zink_shader_free(ctx, shader->generated);1084if (in_use) {1085ctx->gfx_pipeline_state.modules[pstage] = VK_NULL_HANDLE;1086ctx->gfx_stages[pstage] = NULL;1087}1088if (zink_gfx_program_reference(screen, &prog, NULL) && in_use)1089ctx->curr_program = NULL;1090}1091}1092_mesa_set_destroy(shader->programs, NULL);1093ralloc_free(shader->nir);1094FREE(shader);1095}109610971098/* creating a passthrough tcs shader that's roughly:10991100#version 1501101#extension GL_ARB_tessellation_shader : require11021103in vec4 some_var[gl_MaxPatchVertices];1104out vec4 some_var_out;11051106layout(push_constant) uniform tcsPushConstants {1107layout(offset = 0) float TessLevelInner[2];1108layout(offset = 8) float TessLevelOuter[4];1109} u_tcsPushConstants;1110layout(vertices = $vertices_per_patch) out;1111void main()1112{1113gl_TessLevelInner = u_tcsPushConstants.TessLevelInner;1114gl_TessLevelOuter = u_tcsPushConstants.TessLevelOuter;1115some_var_out = some_var[gl_InvocationID];1116}11171118*/1119struct zink_shader *1120zink_shader_tcs_create(struct zink_context *ctx, struct zink_shader *vs)1121{1122unsigned vertices_per_patch = ctx->gfx_pipeline_state.vertices_per_patch;1123struct zink_shader *ret = CALLOC_STRUCT(zink_shader);1124ret->programs = _mesa_pointer_set_create(NULL);11251126nir_shader *nir = nir_shader_create(NULL, MESA_SHADER_TESS_CTRL, &zink_screen(ctx->base.screen)->nir_options, NULL);1127nir_function *fn = nir_function_create(nir, "main");1128fn->is_entrypoint = true;1129nir_function_impl *impl = nir_function_impl_create(fn);11301131nir_builder b;1132nir_builder_init(&b, impl);1133b.cursor = nir_before_block(nir_start_block(impl));11341135nir_ssa_def *invocation_id = nir_load_invocation_id(&b);11361137nir_foreach_shader_out_variable(var, vs->nir) {1138const struct glsl_type *type = var->type;1139const struct glsl_type *in_type = var->type;1140const struct glsl_type *out_type = var->type;1141char buf[1024];1142snprintf(buf, sizeof(buf), "%s_out", var->name);1143in_type = glsl_array_type(type, 32 /* MAX_PATCH_VERTICES */, 0);1144out_type = glsl_array_type(type, vertices_per_patch, 0);11451146nir_variable *in = nir_variable_create(nir, nir_var_shader_in, in_type, var->name);1147nir_variable *out = nir_variable_create(nir, nir_var_shader_out, out_type, buf);1148out->data.location = in->data.location = var->data.location;1149out->data.location_frac = in->data.location_frac = var->data.location_frac;11501151/* gl_in[] receives values from equivalent built-in output1152variables written by the vertex shader (section 2.14.7). Each array1153element of gl_in[] is a structure holding values for a specific vertex of1154the input patch. The length of gl_in[] is equal to the1155implementation-dependent maximum patch size (gl_MaxPatchVertices).1156- ARB_tessellation_shader1157*/1158for (unsigned i = 0; i < vertices_per_patch; i++) {1159/* we need to load the invocation-specific value of the vertex output and then store it to the per-patch output */1160nir_if *start_block = nir_push_if(&b, nir_ieq(&b, invocation_id, nir_imm_int(&b, i)));1161nir_deref_instr *in_array_var = nir_build_deref_array(&b, nir_build_deref_var(&b, in), invocation_id);1162nir_ssa_def *load = nir_load_deref(&b, in_array_var);1163nir_deref_instr *out_array_var = nir_build_deref_array_imm(&b, nir_build_deref_var(&b, out), i);1164nir_store_deref(&b, out_array_var, load, 0xff);1165nir_pop_if(&b, start_block);1166}1167}1168nir_variable *gl_TessLevelInner = nir_variable_create(nir, nir_var_shader_out, glsl_array_type(glsl_float_type(), 2, 0), "gl_TessLevelInner");1169gl_TessLevelInner->data.location = VARYING_SLOT_TESS_LEVEL_INNER;1170gl_TessLevelInner->data.patch = 1;1171nir_variable *gl_TessLevelOuter = nir_variable_create(nir, nir_var_shader_out, glsl_array_type(glsl_float_type(), 4, 0), "gl_TessLevelOuter");1172gl_TessLevelOuter->data.location = VARYING_SLOT_TESS_LEVEL_OUTER;1173gl_TessLevelOuter->data.patch = 1;11741175/* hacks so we can size these right for now */1176struct glsl_struct_field *fields = rzalloc_array(nir, struct glsl_struct_field, 3);1177/* just use a single blob for padding here because it's easier */1178fields[0].type = glsl_array_type(glsl_uint_type(), offsetof(struct zink_gfx_push_constant, default_inner_level) / 4, 0);1179fields[0].name = ralloc_asprintf(nir, "padding");1180fields[0].offset = 0;1181fields[1].type = glsl_array_type(glsl_uint_type(), 2, 0);1182fields[1].name = ralloc_asprintf(nir, "gl_TessLevelInner");1183fields[1].offset = offsetof(struct zink_gfx_push_constant, default_inner_level);1184fields[2].type = glsl_array_type(glsl_uint_type(), 4, 0);1185fields[2].name = ralloc_asprintf(nir, "gl_TessLevelOuter");1186fields[2].offset = offsetof(struct zink_gfx_push_constant, default_outer_level);1187nir_variable *pushconst = nir_variable_create(nir, nir_var_mem_push_const,1188glsl_struct_type(fields, 3, "struct", false), "pushconst");1189pushconst->data.location = VARYING_SLOT_VAR0;11901191nir_ssa_def *load_inner = nir_load_push_constant(&b, 2, 32, nir_imm_int(&b, 1), .base = 1, .range = 8);1192nir_ssa_def *load_outer = nir_load_push_constant(&b, 4, 32, nir_imm_int(&b, 2), .base = 2, .range = 16);11931194for (unsigned i = 0; i < 2; i++) {1195nir_deref_instr *store_idx = nir_build_deref_array_imm(&b, nir_build_deref_var(&b, gl_TessLevelInner), i);1196nir_store_deref(&b, store_idx, nir_channel(&b, load_inner, i), 0xff);1197}1198for (unsigned i = 0; i < 4; i++) {1199nir_deref_instr *store_idx = nir_build_deref_array_imm(&b, nir_build_deref_var(&b, gl_TessLevelOuter), i);1200nir_store_deref(&b, store_idx, nir_channel(&b, load_outer, i), 0xff);1201}12021203nir->info.tess.tcs_vertices_out = vertices_per_patch;1204nir_validate_shader(nir, "created");12051206NIR_PASS_V(nir, nir_lower_regs_to_ssa);1207optimize_nir(nir);1208NIR_PASS_V(nir, nir_remove_dead_variables, nir_var_function_temp, NULL);1209NIR_PASS_V(nir, lower_discard_if);1210NIR_PASS_V(nir, nir_convert_from_ssa, true);12111212ret->nir = nir;1213ret->is_generated = true;1214return ret;1215}121612171218