Path: blob/21.2-virgl/src/gallium/auxiliary/nir/tgsi_to_nir.c
4561 views
/*1* Copyright © 2014-2015 Broadcom2* Copyright (C) 2014 Rob Clark <[email protected]>3*4* Permission is hereby granted, free of charge, to any person obtaining a5* copy of this software and associated documentation files (the "Software"),6* to deal in the Software without restriction, including without limitation7* the rights to use, copy, modify, merge, publish, distribute, sublicense,8* and/or sell copies of the Software, and to permit persons to whom the9* Software is furnished to do so, subject to the following conditions:10*11* The above copyright notice and this permission notice (including the next12* paragraph) shall be included in all copies or substantial portions of the13* Software.14*15* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR16* 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, ARISING20* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS21* IN THE SOFTWARE.22*/2324#include "util/blob.h"25#include "util/disk_cache.h"26#include "util/u_memory.h"27#include "util/ralloc.h"28#include "pipe/p_screen.h"2930#include "compiler/nir/nir.h"31#include "compiler/nir/nir_control_flow.h"32#include "compiler/nir/nir_builder.h"33#include "compiler/nir/nir_serialize.h"34#include "compiler/shader_enums.h"3536#include "tgsi_to_nir.h"37#include "tgsi/tgsi_parse.h"38#include "tgsi/tgsi_dump.h"39#include "tgsi/tgsi_info.h"40#include "tgsi/tgsi_scan.h"41#include "tgsi/tgsi_from_mesa.h"4243#define SWIZ(X, Y, Z, W) (unsigned[4]){ \44TGSI_SWIZZLE_##X, \45TGSI_SWIZZLE_##Y, \46TGSI_SWIZZLE_##Z, \47TGSI_SWIZZLE_##W, \48}4950struct ttn_reg_info {51/** nir register containing this TGSI index. */52nir_register *reg;53nir_variable *var;54/** Offset (in vec4s) from the start of var for this TGSI index. */55int offset;56};5758struct ttn_compile {59union tgsi_full_token *token;60nir_builder build;61struct tgsi_shader_info *scan;6263struct ttn_reg_info *output_regs;64struct ttn_reg_info *temp_regs;65nir_ssa_def **imm_defs;6667unsigned num_samp_types;68nir_alu_type *samp_types;6970nir_register *addr_reg;7172nir_variable **inputs;73nir_variable **outputs;74nir_variable *samplers[PIPE_MAX_SAMPLERS];75nir_variable *images[PIPE_MAX_SHADER_IMAGES];76nir_variable *ssbo[PIPE_MAX_SHADER_BUFFERS];77uint32_t ubo_sizes[PIPE_MAX_CONSTANT_BUFFERS];7879unsigned num_samplers;80unsigned num_images;81unsigned num_msaa_images;8283nir_variable *input_var_face;84nir_variable *input_var_position;85nir_variable *input_var_point;8687/* How many TGSI_FILE_IMMEDIATE vec4s have been parsed so far. */88unsigned next_imm;8990bool cap_face_is_sysval;91bool cap_position_is_sysval;92bool cap_point_is_sysval;93bool cap_samplers_as_deref;94};9596#define ttn_swizzle(b, src, x, y, z, w) \97nir_swizzle(b, src, SWIZ(x, y, z, w), 4)98#define ttn_channel(b, src, swiz) \99nir_channel(b, src, TGSI_SWIZZLE_##swiz)100101gl_varying_slot102tgsi_varying_semantic_to_slot(unsigned semantic, unsigned index)103{104switch (semantic) {105case TGSI_SEMANTIC_POSITION:106return VARYING_SLOT_POS;107case TGSI_SEMANTIC_COLOR:108if (index == 0)109return VARYING_SLOT_COL0;110else111return VARYING_SLOT_COL1;112case TGSI_SEMANTIC_BCOLOR:113if (index == 0)114return VARYING_SLOT_BFC0;115else116return VARYING_SLOT_BFC1;117case TGSI_SEMANTIC_FOG:118return VARYING_SLOT_FOGC;119case TGSI_SEMANTIC_PSIZE:120return VARYING_SLOT_PSIZ;121case TGSI_SEMANTIC_GENERIC:122assert(index < 32);123return VARYING_SLOT_VAR0 + index;124case TGSI_SEMANTIC_FACE:125return VARYING_SLOT_FACE;126case TGSI_SEMANTIC_EDGEFLAG:127return VARYING_SLOT_EDGE;128case TGSI_SEMANTIC_PRIMID:129return VARYING_SLOT_PRIMITIVE_ID;130case TGSI_SEMANTIC_CLIPDIST:131if (index == 0)132return VARYING_SLOT_CLIP_DIST0;133else134return VARYING_SLOT_CLIP_DIST1;135case TGSI_SEMANTIC_CLIPVERTEX:136return VARYING_SLOT_CLIP_VERTEX;137case TGSI_SEMANTIC_TEXCOORD:138assert(index < 8);139return VARYING_SLOT_TEX0 + index;140case TGSI_SEMANTIC_PCOORD:141return VARYING_SLOT_PNTC;142case TGSI_SEMANTIC_VIEWPORT_INDEX:143return VARYING_SLOT_VIEWPORT;144case TGSI_SEMANTIC_LAYER:145return VARYING_SLOT_LAYER;146case TGSI_SEMANTIC_TESSINNER:147return VARYING_SLOT_TESS_LEVEL_INNER;148case TGSI_SEMANTIC_TESSOUTER:149return VARYING_SLOT_TESS_LEVEL_OUTER;150default:151fprintf(stderr, "Bad TGSI semantic: %d/%d\n", semantic, index);152abort();153}154}155156static enum gl_frag_depth_layout157ttn_get_depth_layout(unsigned tgsi_fs_depth_layout)158{159switch (tgsi_fs_depth_layout) {160case TGSI_FS_DEPTH_LAYOUT_NONE:161return FRAG_DEPTH_LAYOUT_NONE;162case TGSI_FS_DEPTH_LAYOUT_ANY:163return FRAG_DEPTH_LAYOUT_ANY;164case TGSI_FS_DEPTH_LAYOUT_GREATER:165return FRAG_DEPTH_LAYOUT_GREATER;166case TGSI_FS_DEPTH_LAYOUT_LESS:167return FRAG_DEPTH_LAYOUT_LESS;168case TGSI_FS_DEPTH_LAYOUT_UNCHANGED:169return FRAG_DEPTH_LAYOUT_UNCHANGED;170default:171unreachable("bad TGSI FS depth layout");172}173}174175static nir_ssa_def *176ttn_src_for_dest(nir_builder *b, nir_alu_dest *dest)177{178nir_alu_src src;179memset(&src, 0, sizeof(src));180181if (dest->dest.is_ssa)182src.src = nir_src_for_ssa(&dest->dest.ssa);183else {184assert(!dest->dest.reg.indirect);185src.src = nir_src_for_reg(dest->dest.reg.reg);186src.src.reg.base_offset = dest->dest.reg.base_offset;187}188189for (int i = 0; i < 4; i++)190src.swizzle[i] = i;191192return nir_mov_alu(b, src, 4);193}194195static enum glsl_interp_mode196ttn_translate_interp_mode(unsigned tgsi_interp)197{198switch (tgsi_interp) {199case TGSI_INTERPOLATE_CONSTANT:200return INTERP_MODE_FLAT;201case TGSI_INTERPOLATE_LINEAR:202return INTERP_MODE_NOPERSPECTIVE;203case TGSI_INTERPOLATE_PERSPECTIVE:204return INTERP_MODE_SMOOTH;205case TGSI_INTERPOLATE_COLOR:206return INTERP_MODE_NONE;207default:208unreachable("bad TGSI interpolation mode");209}210}211212static void213ttn_emit_declaration(struct ttn_compile *c)214{215nir_builder *b = &c->build;216struct tgsi_full_declaration *decl = &c->token->FullDeclaration;217unsigned array_size = decl->Range.Last - decl->Range.First + 1;218unsigned file = decl->Declaration.File;219unsigned i;220221if (file == TGSI_FILE_TEMPORARY) {222if (decl->Declaration.Array) {223/* for arrays, we create variables instead of registers: */224nir_variable *var =225nir_variable_create(b->shader, nir_var_shader_temp,226glsl_array_type(glsl_vec4_type(), array_size, 0),227ralloc_asprintf(b->shader, "arr_%d",228decl->Array.ArrayID));229230for (i = 0; i < array_size; i++) {231/* point all the matching slots to the same var,232* with appropriate offset set, mostly just so233* we know what to do when tgsi does a non-indirect234* access235*/236c->temp_regs[decl->Range.First + i].reg = NULL;237c->temp_regs[decl->Range.First + i].var = var;238c->temp_regs[decl->Range.First + i].offset = i;239}240} else {241for (i = 0; i < array_size; i++) {242nir_register *reg = nir_local_reg_create(b->impl);243reg->num_components = 4;244c->temp_regs[decl->Range.First + i].reg = reg;245c->temp_regs[decl->Range.First + i].var = NULL;246c->temp_regs[decl->Range.First + i].offset = 0;247}248}249} else if (file == TGSI_FILE_ADDRESS) {250c->addr_reg = nir_local_reg_create(b->impl);251c->addr_reg->num_components = 4;252} else if (file == TGSI_FILE_SYSTEM_VALUE) {253/* Nothing to record for system values. */254} else if (file == TGSI_FILE_BUFFER) {255/* Nothing to record for buffers. */256} else if (file == TGSI_FILE_IMAGE) {257/* Nothing to record for images. */258} else if (file == TGSI_FILE_SAMPLER) {259/* Nothing to record for samplers. */260} else if (file == TGSI_FILE_SAMPLER_VIEW) {261struct tgsi_declaration_sampler_view *sview = &decl->SamplerView;262nir_alu_type type;263264assert((sview->ReturnTypeX == sview->ReturnTypeY) &&265(sview->ReturnTypeX == sview->ReturnTypeZ) &&266(sview->ReturnTypeX == sview->ReturnTypeW));267268switch (sview->ReturnTypeX) {269case TGSI_RETURN_TYPE_SINT:270type = nir_type_int32;271break;272case TGSI_RETURN_TYPE_UINT:273type = nir_type_uint32;274break;275case TGSI_RETURN_TYPE_FLOAT:276default:277type = nir_type_float32;278break;279}280281for (i = 0; i < array_size; i++) {282c->samp_types[decl->Range.First + i] = type;283}284} else {285bool is_array = (array_size > 1);286287assert(file == TGSI_FILE_INPUT ||288file == TGSI_FILE_OUTPUT ||289file == TGSI_FILE_CONSTANT);290291/* nothing to do for UBOs: */292if ((file == TGSI_FILE_CONSTANT) && decl->Declaration.Dimension &&293decl->Dim.Index2D != 0) {294b->shader->info.num_ubos =295MAX2(b->shader->info.num_ubos, decl->Dim.Index2D);296c->ubo_sizes[decl->Dim.Index2D] =297MAX2(c->ubo_sizes[decl->Dim.Index2D], decl->Range.Last * 16);298return;299}300301if ((file == TGSI_FILE_INPUT) || (file == TGSI_FILE_OUTPUT)) {302is_array = (is_array && decl->Declaration.Array &&303(decl->Array.ArrayID != 0));304}305306for (i = 0; i < array_size; i++) {307unsigned idx = decl->Range.First + i;308nir_variable *var = rzalloc(b->shader, nir_variable);309310var->data.driver_location = idx;311312var->type = glsl_vec4_type();313if (is_array)314var->type = glsl_array_type(var->type, array_size, 0);315316switch (file) {317case TGSI_FILE_INPUT:318var->data.read_only = true;319var->data.mode = nir_var_shader_in;320var->name = ralloc_asprintf(var, "in_%d", idx);321322if (c->scan->processor == PIPE_SHADER_FRAGMENT) {323if (decl->Semantic.Name == TGSI_SEMANTIC_FACE) {324var->type = glsl_bool_type();325if (c->cap_face_is_sysval) {326var->data.mode = nir_var_system_value;327var->data.location = SYSTEM_VALUE_FRONT_FACE;328} else {329var->data.location = VARYING_SLOT_FACE;330}331c->input_var_face = var;332} else if (decl->Semantic.Name == TGSI_SEMANTIC_POSITION) {333if (c->cap_position_is_sysval) {334var->data.mode = nir_var_system_value;335var->data.location = SYSTEM_VALUE_FRAG_COORD;336} else {337var->data.location = VARYING_SLOT_POS;338}339c->input_var_position = var;340} else if (decl->Semantic.Name == TGSI_SEMANTIC_PCOORD) {341if (c->cap_point_is_sysval) {342var->data.mode = nir_var_system_value;343var->data.location = SYSTEM_VALUE_POINT_COORD;344} else {345var->data.location = VARYING_SLOT_PNTC;346}347c->input_var_point = var;348} else {349var->data.location =350tgsi_varying_semantic_to_slot(decl->Semantic.Name,351decl->Semantic.Index);352}353} else {354assert(!decl->Declaration.Semantic);355var->data.location = VERT_ATTRIB_GENERIC0 + idx;356}357var->data.index = 0;358var->data.interpolation =359ttn_translate_interp_mode(decl->Interp.Interpolate);360361c->inputs[idx] = var;362363for (int i = 0; i < array_size; i++)364b->shader->info.inputs_read |= 1ull << (var->data.location + i);365366break;367case TGSI_FILE_OUTPUT: {368int semantic_name = decl->Semantic.Name;369int semantic_index = decl->Semantic.Index;370/* Since we can't load from outputs in the IR, we make temporaries371* for the outputs and emit stores to the real outputs at the end of372* the shader.373*/374nir_register *reg = nir_local_reg_create(b->impl);375reg->num_components = 4;376if (is_array)377reg->num_array_elems = array_size;378379var->data.mode = nir_var_shader_out;380var->name = ralloc_asprintf(var, "out_%d", idx);381var->data.index = 0;382var->data.interpolation =383ttn_translate_interp_mode(decl->Interp.Interpolate);384var->data.patch = semantic_name == TGSI_SEMANTIC_TESSINNER ||385semantic_name == TGSI_SEMANTIC_TESSOUTER ||386semantic_name == TGSI_SEMANTIC_PATCH;387388if (c->scan->processor == PIPE_SHADER_FRAGMENT) {389switch (semantic_name) {390case TGSI_SEMANTIC_COLOR: {391/* TODO tgsi loses some information, so we cannot392* actually differentiate here between DSB and MRT393* at this point. But so far no drivers using tgsi-394* to-nir support dual source blend:395*/396bool dual_src_blend = false;397if (dual_src_blend && (semantic_index == 1)) {398var->data.location = FRAG_RESULT_DATA0;399var->data.index = 1;400} else {401if (c->scan->properties[TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS])402var->data.location = FRAG_RESULT_COLOR;403else404var->data.location = FRAG_RESULT_DATA0 + semantic_index;405}406break;407}408case TGSI_SEMANTIC_POSITION:409var->data.location = FRAG_RESULT_DEPTH;410var->type = glsl_float_type();411break;412case TGSI_SEMANTIC_STENCIL:413var->data.location = FRAG_RESULT_STENCIL;414var->type = glsl_int_type();415break;416case TGSI_SEMANTIC_SAMPLEMASK:417var->data.location = FRAG_RESULT_SAMPLE_MASK;418var->type = glsl_int_type();419break;420421default:422fprintf(stderr, "Bad TGSI semantic: %d/%d\n",423decl->Semantic.Name, decl->Semantic.Index);424abort();425}426} else {427var->data.location =428tgsi_varying_semantic_to_slot(semantic_name, semantic_index);429if (var->data.location == VARYING_SLOT_FOGC ||430var->data.location == VARYING_SLOT_PSIZ) {431var->type = glsl_float_type();432}433}434435if (is_array) {436unsigned j;437for (j = 0; j < array_size; j++) {438c->output_regs[idx + j].offset = i + j;439c->output_regs[idx + j].reg = reg;440}441} else {442c->output_regs[idx].offset = i;443c->output_regs[idx].reg = reg;444}445446c->outputs[idx] = var;447448for (int i = 0; i < array_size; i++)449b->shader->info.outputs_written |= 1ull << (var->data.location + i);450}451break;452case TGSI_FILE_CONSTANT:453var->data.mode = nir_var_uniform;454var->name = ralloc_asprintf(var, "uniform_%d", idx);455var->data.location = idx;456break;457default:458unreachable("bad declaration file");459return;460}461462nir_shader_add_variable(b->shader, var);463464if (is_array)465break;466}467468}469}470471static void472ttn_emit_immediate(struct ttn_compile *c)473{474nir_builder *b = &c->build;475struct tgsi_full_immediate *tgsi_imm = &c->token->FullImmediate;476nir_load_const_instr *load_const;477int i;478479load_const = nir_load_const_instr_create(b->shader, 4, 32);480c->imm_defs[c->next_imm] = &load_const->def;481c->next_imm++;482483for (i = 0; i < load_const->def.num_components; i++)484load_const->value[i].u32 = tgsi_imm->u[i].Uint;485486nir_builder_instr_insert(b, &load_const->instr);487}488489static nir_ssa_def *490ttn_src_for_indirect(struct ttn_compile *c, struct tgsi_ind_register *indirect);491492/* generate either a constant or indirect deref chain for accessing an493* array variable.494*/495static nir_deref_instr *496ttn_array_deref(struct ttn_compile *c, nir_variable *var, unsigned offset,497struct tgsi_ind_register *indirect)498{499nir_deref_instr *deref = nir_build_deref_var(&c->build, var);500nir_ssa_def *index = nir_imm_int(&c->build, offset);501if (indirect)502index = nir_iadd(&c->build, index, ttn_src_for_indirect(c, indirect));503return nir_build_deref_array(&c->build, deref, index);504}505506/* Special case: Turn the frontface varying into a load of the507* frontface variable, and create the vector as required by TGSI.508*/509static nir_ssa_def *510ttn_emulate_tgsi_front_face(struct ttn_compile *c)511{512nir_ssa_def *tgsi_frontface[4];513514if (c->cap_face_is_sysval) {515/* When it's a system value, it should be an integer vector: (F, 0, 0, 1)516* F is 0xffffffff if front-facing, 0 if not.517*/518519nir_ssa_def *frontface = nir_load_front_face(&c->build, 1);520521tgsi_frontface[0] = nir_bcsel(&c->build,522frontface,523nir_imm_int(&c->build, 0xffffffff),524nir_imm_int(&c->build, 0));525tgsi_frontface[1] = nir_imm_int(&c->build, 0);526tgsi_frontface[2] = nir_imm_int(&c->build, 0);527tgsi_frontface[3] = nir_imm_int(&c->build, 1);528} else {529/* When it's an input, it should be a float vector: (F, 0.0, 0.0, 1.0)530* F is positive if front-facing, negative if not.531*/532533assert(c->input_var_face);534nir_ssa_def *frontface = nir_load_var(&c->build, c->input_var_face);535536tgsi_frontface[0] = nir_bcsel(&c->build,537frontface,538nir_imm_float(&c->build, 1.0),539nir_imm_float(&c->build, -1.0));540tgsi_frontface[1] = nir_imm_float(&c->build, 0.0);541tgsi_frontface[2] = nir_imm_float(&c->build, 0.0);542tgsi_frontface[3] = nir_imm_float(&c->build, 1.0);543}544545return nir_vec(&c->build, tgsi_frontface, 4);546}547548static nir_src549ttn_src_for_file_and_index(struct ttn_compile *c, unsigned file, unsigned index,550struct tgsi_ind_register *indirect,551struct tgsi_dimension *dim,552struct tgsi_ind_register *dimind,553bool src_is_float)554{555nir_builder *b = &c->build;556nir_src src;557558memset(&src, 0, sizeof(src));559560switch (file) {561case TGSI_FILE_TEMPORARY:562if (c->temp_regs[index].var) {563unsigned offset = c->temp_regs[index].offset;564nir_variable *var = c->temp_regs[index].var;565nir_ssa_def *load = nir_load_deref(&c->build,566ttn_array_deref(c, var, offset, indirect));567568src = nir_src_for_ssa(load);569} else {570assert(!indirect);571src.reg.reg = c->temp_regs[index].reg;572}573assert(!dim);574break;575576case TGSI_FILE_ADDRESS:577src.reg.reg = c->addr_reg;578assert(!dim);579break;580581case TGSI_FILE_IMMEDIATE:582src = nir_src_for_ssa(c->imm_defs[index]);583assert(!indirect);584assert(!dim);585break;586587case TGSI_FILE_SYSTEM_VALUE: {588nir_ssa_def *load;589590assert(!indirect);591assert(!dim);592593switch (c->scan->system_value_semantic_name[index]) {594case TGSI_SEMANTIC_VERTEXID_NOBASE:595load = nir_load_vertex_id_zero_base(b);596break;597case TGSI_SEMANTIC_VERTEXID:598load = nir_load_vertex_id(b);599break;600case TGSI_SEMANTIC_BASEVERTEX:601load = nir_load_base_vertex(b);602break;603case TGSI_SEMANTIC_INSTANCEID:604load = nir_load_instance_id(b);605break;606case TGSI_SEMANTIC_FACE:607assert(c->cap_face_is_sysval);608load = ttn_emulate_tgsi_front_face(c);609break;610case TGSI_SEMANTIC_POSITION:611assert(c->cap_position_is_sysval);612load = nir_load_frag_coord(b);613break;614case TGSI_SEMANTIC_PCOORD:615assert(c->cap_point_is_sysval);616load = nir_load_point_coord(b);617break;618case TGSI_SEMANTIC_THREAD_ID:619load = nir_load_local_invocation_id(b);620break;621case TGSI_SEMANTIC_BLOCK_ID:622load = nir_load_workgroup_id(b, 32);623break;624case TGSI_SEMANTIC_BLOCK_SIZE:625load = nir_load_workgroup_size(b);626break;627case TGSI_SEMANTIC_CS_USER_DATA_AMD:628load = nir_load_user_data_amd(b);629break;630case TGSI_SEMANTIC_TESS_DEFAULT_INNER_LEVEL:631load = nir_load_tess_level_inner_default(b);632break;633case TGSI_SEMANTIC_TESS_DEFAULT_OUTER_LEVEL:634load = nir_load_tess_level_outer_default(b);635break;636case TGSI_SEMANTIC_SAMPLEID:637load = nir_load_sample_id(b);638break;639default:640unreachable("bad system value");641}642643if (load->num_components == 2)644load = nir_swizzle(b, load, SWIZ(X, Y, Y, Y), 4);645else if (load->num_components == 3)646load = nir_swizzle(b, load, SWIZ(X, Y, Z, Z), 4);647648src = nir_src_for_ssa(load);649break;650}651652case TGSI_FILE_INPUT:653if (c->scan->processor == PIPE_SHADER_FRAGMENT &&654c->scan->input_semantic_name[index] == TGSI_SEMANTIC_FACE) {655assert(!c->cap_face_is_sysval && c->input_var_face);656return nir_src_for_ssa(ttn_emulate_tgsi_front_face(c));657} else if (c->scan->processor == PIPE_SHADER_FRAGMENT &&658c->scan->input_semantic_name[index] == TGSI_SEMANTIC_POSITION) {659assert(!c->cap_position_is_sysval && c->input_var_position);660return nir_src_for_ssa(nir_load_var(&c->build, c->input_var_position));661} else if (c->scan->processor == PIPE_SHADER_FRAGMENT &&662c->scan->input_semantic_name[index] == TGSI_SEMANTIC_PCOORD) {663assert(!c->cap_point_is_sysval && c->input_var_point);664return nir_src_for_ssa(nir_load_var(&c->build, c->input_var_point));665} else {666/* Indirection on input arrays isn't supported by TTN. */667assert(!dim);668nir_deref_instr *deref = nir_build_deref_var(&c->build,669c->inputs[index]);670return nir_src_for_ssa(nir_load_deref(&c->build, deref));671}672break;673674case TGSI_FILE_OUTPUT:675if (c->scan->processor == PIPE_SHADER_FRAGMENT) {676c->outputs[index]->data.fb_fetch_output = 1;677nir_deref_instr *deref = nir_build_deref_var(&c->build,678c->outputs[index]);679return nir_src_for_ssa(nir_load_deref(&c->build, deref));680}681unreachable("unsupported output read");682break;683684case TGSI_FILE_CONSTANT: {685nir_intrinsic_instr *load;686nir_intrinsic_op op;687unsigned srcn = 0;688689if (dim && (dim->Index > 0 || dim->Indirect)) {690op = nir_intrinsic_load_ubo;691} else {692op = nir_intrinsic_load_uniform;693}694695load = nir_intrinsic_instr_create(b->shader, op);696if (op == nir_intrinsic_load_uniform) {697nir_intrinsic_set_dest_type(load, src_is_float ? nir_type_float :698nir_type_int);699}700701load->num_components = 4;702if (dim && (dim->Index > 0 || dim->Indirect)) {703if (dimind) {704load->src[srcn] =705ttn_src_for_file_and_index(c, dimind->File, dimind->Index,706NULL, NULL, NULL, false);707} else {708/* UBOs start at index 1 in TGSI: */709load->src[srcn] =710nir_src_for_ssa(nir_imm_int(b, dim->Index - 1));711}712srcn++;713}714715nir_ssa_def *offset;716if (op == nir_intrinsic_load_ubo) {717/* UBO loads don't have a base offset. */718offset = nir_imm_int(b, index);719if (indirect) {720offset = nir_iadd(b, offset, ttn_src_for_indirect(c, indirect));721}722/* UBO offsets are in bytes, but TGSI gives them to us in vec4's */723offset = nir_ishl(b, offset, nir_imm_int(b, 4));724nir_intrinsic_set_align(load, 16, 0);725726/* Set a very conservative base/range of the access: 16 bytes if not727* indirect at all, offset to the end of the UBO if the offset is728* indirect, and totally unknown if the block number is indirect.729*/730uint32_t base = index * 16;731nir_intrinsic_set_range_base(load, base);732if (dimind)733nir_intrinsic_set_range(load, ~0);734else if (indirect)735nir_intrinsic_set_range(load, c->ubo_sizes[dim->Index] - base);736else737nir_intrinsic_set_range(load, base + 16);738} else {739nir_intrinsic_set_base(load, index);740if (indirect) {741offset = ttn_src_for_indirect(c, indirect);742nir_intrinsic_set_range(load, c->build.shader->num_uniforms * 16 - index);743} else {744offset = nir_imm_int(b, 0);745nir_intrinsic_set_range(load, 1);746}747}748load->src[srcn++] = nir_src_for_ssa(offset);749750nir_ssa_dest_init(&load->instr, &load->dest, 4, 32, NULL);751nir_builder_instr_insert(b, &load->instr);752753src = nir_src_for_ssa(&load->dest.ssa);754break;755}756757default:758unreachable("bad src file");759}760761762return src;763}764765static nir_ssa_def *766ttn_src_for_indirect(struct ttn_compile *c, struct tgsi_ind_register *indirect)767{768nir_builder *b = &c->build;769nir_alu_src src;770memset(&src, 0, sizeof(src));771for (int i = 0; i < 4; i++)772src.swizzle[i] = indirect->Swizzle;773src.src = ttn_src_for_file_and_index(c,774indirect->File,775indirect->Index,776NULL, NULL, NULL,777false);778return nir_mov_alu(b, src, 1);779}780781static nir_alu_dest782ttn_get_dest(struct ttn_compile *c, struct tgsi_full_dst_register *tgsi_fdst)783{784struct tgsi_dst_register *tgsi_dst = &tgsi_fdst->Register;785nir_alu_dest dest;786unsigned index = tgsi_dst->Index;787788memset(&dest, 0, sizeof(dest));789790if (tgsi_dst->File == TGSI_FILE_TEMPORARY) {791if (c->temp_regs[index].var) {792nir_register *reg;793794/* this works, because TGSI will give us a base offset795* (in case of indirect index) that points back into796* the array. Access can be direct or indirect, we797* don't really care. Just create a one-shot dst reg798* that will get store_var'd back into the array var799* at the end of ttn_emit_instruction()800*/801reg = nir_local_reg_create(c->build.impl);802reg->num_components = 4;803dest.dest.reg.reg = reg;804dest.dest.reg.base_offset = 0;805} else {806assert(!tgsi_dst->Indirect);807dest.dest.reg.reg = c->temp_regs[index].reg;808dest.dest.reg.base_offset = c->temp_regs[index].offset;809}810} else if (tgsi_dst->File == TGSI_FILE_OUTPUT) {811dest.dest.reg.reg = c->output_regs[index].reg;812dest.dest.reg.base_offset = c->output_regs[index].offset;813} else if (tgsi_dst->File == TGSI_FILE_ADDRESS) {814assert(index == 0);815dest.dest.reg.reg = c->addr_reg;816}817818dest.write_mask = tgsi_dst->WriteMask;819dest.saturate = false;820821if (tgsi_dst->Indirect && (tgsi_dst->File != TGSI_FILE_TEMPORARY)) {822nir_src *indirect = ralloc(c->build.shader, nir_src);823*indirect = nir_src_for_ssa(ttn_src_for_indirect(c, &tgsi_fdst->Indirect));824dest.dest.reg.indirect = indirect;825}826827return dest;828}829830static nir_variable *831ttn_get_var(struct ttn_compile *c, struct tgsi_full_dst_register *tgsi_fdst)832{833struct tgsi_dst_register *tgsi_dst = &tgsi_fdst->Register;834unsigned index = tgsi_dst->Index;835836if (tgsi_dst->File == TGSI_FILE_TEMPORARY) {837/* we should not have an indirect when there is no var! */838if (!c->temp_regs[index].var)839assert(!tgsi_dst->Indirect);840return c->temp_regs[index].var;841}842843return NULL;844}845846static nir_ssa_def *847ttn_get_src(struct ttn_compile *c, struct tgsi_full_src_register *tgsi_fsrc,848int src_idx)849{850nir_builder *b = &c->build;851struct tgsi_src_register *tgsi_src = &tgsi_fsrc->Register;852enum tgsi_opcode opcode = c->token->FullInstruction.Instruction.Opcode;853unsigned tgsi_src_type = tgsi_opcode_infer_src_type(opcode, src_idx);854bool src_is_float = (tgsi_src_type == TGSI_TYPE_FLOAT ||855tgsi_src_type == TGSI_TYPE_DOUBLE ||856tgsi_src_type == TGSI_TYPE_UNTYPED);857nir_alu_src src;858859memset(&src, 0, sizeof(src));860861if (tgsi_src->File == TGSI_FILE_NULL) {862return nir_imm_float(b, 0.0);863} else if (tgsi_src->File == TGSI_FILE_SAMPLER ||864tgsi_src->File == TGSI_FILE_IMAGE ||865tgsi_src->File == TGSI_FILE_BUFFER) {866/* Only the index of the resource gets used in texturing, and it will867* handle looking that up on its own instead of using the nir_alu_src.868*/869assert(!tgsi_src->Indirect);870return NULL;871} else {872struct tgsi_ind_register *ind = NULL;873struct tgsi_dimension *dim = NULL;874struct tgsi_ind_register *dimind = NULL;875if (tgsi_src->Indirect)876ind = &tgsi_fsrc->Indirect;877if (tgsi_src->Dimension) {878dim = &tgsi_fsrc->Dimension;879if (dim->Indirect)880dimind = &tgsi_fsrc->DimIndirect;881}882src.src = ttn_src_for_file_and_index(c,883tgsi_src->File,884tgsi_src->Index,885ind, dim, dimind,886src_is_float);887}888889src.swizzle[0] = tgsi_src->SwizzleX;890src.swizzle[1] = tgsi_src->SwizzleY;891src.swizzle[2] = tgsi_src->SwizzleZ;892src.swizzle[3] = tgsi_src->SwizzleW;893894nir_ssa_def *def = nir_mov_alu(b, src, 4);895896if (tgsi_type_is_64bit(tgsi_src_type))897def = nir_bitcast_vector(b, def, 64);898899if (tgsi_src->Absolute) {900assert(src_is_float);901def = nir_fabs(b, def);902}903904if (tgsi_src->Negate) {905if (src_is_float)906def = nir_fneg(b, def);907else908def = nir_ineg(b, def);909}910911return def;912}913914static void915ttn_move_dest_masked(nir_builder *b, nir_alu_dest dest,916nir_ssa_def *def, unsigned write_mask)917{918if (!(dest.write_mask & write_mask))919return;920921nir_alu_instr *mov = nir_alu_instr_create(b->shader, nir_op_mov);922mov->dest = dest;923mov->dest.write_mask &= write_mask;924mov->src[0].src = nir_src_for_ssa(def);925for (unsigned i = def->num_components; i < 4; i++)926mov->src[0].swizzle[i] = def->num_components - 1;927nir_builder_instr_insert(b, &mov->instr);928}929930static void931ttn_move_dest(nir_builder *b, nir_alu_dest dest, nir_ssa_def *def)932{933ttn_move_dest_masked(b, dest, def, TGSI_WRITEMASK_XYZW);934}935936static void937ttn_alu(nir_builder *b, nir_op op, nir_alu_dest dest, unsigned dest_bitsize,938nir_ssa_def **src)939{940nir_ssa_def *def = nir_build_alu_src_arr(b, op, src);941if (def->bit_size == 1)942def = nir_ineg(b, nir_b2i(b, def, dest_bitsize));943assert(def->bit_size == dest_bitsize);944if (dest_bitsize == 64) {945if (def->num_components > 2) {946/* 32 -> 64 bit conversion ops are supposed to only convert the first947* two components, and we need to truncate here to avoid creating a948* vec8 after bitcasting the destination.949*/950def = nir_channels(b, def, 0x3);951}952def = nir_bitcast_vector(b, def, 32);953}954ttn_move_dest(b, dest, def);955}956957static void958ttn_arl(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)959{960ttn_move_dest(b, dest, nir_f2i32(b, nir_ffloor(b, src[0])));961}962963/* EXP - Approximate Exponential Base 2964* dst.x = 2^{\lfloor src.x\rfloor}965* dst.y = src.x - \lfloor src.x\rfloor966* dst.z = 2^{src.x}967* dst.w = 1.0968*/969static void970ttn_exp(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)971{972nir_ssa_def *srcx = ttn_channel(b, src[0], X);973974ttn_move_dest_masked(b, dest, nir_fexp2(b, nir_ffloor(b, srcx)),975TGSI_WRITEMASK_X);976ttn_move_dest_masked(b, dest, nir_fsub(b, srcx, nir_ffloor(b, srcx)),977TGSI_WRITEMASK_Y);978ttn_move_dest_masked(b, dest, nir_fexp2(b, srcx), TGSI_WRITEMASK_Z);979ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_W);980}981982/* LOG - Approximate Logarithm Base 2983* dst.x = \lfloor\log_2{|src.x|}\rfloor984* dst.y = \frac{|src.x|}{2^{\lfloor\log_2{|src.x|}\rfloor}}985* dst.z = \log_2{|src.x|}986* dst.w = 1.0987*/988static void989ttn_log(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)990{991nir_ssa_def *abs_srcx = nir_fabs(b, ttn_channel(b, src[0], X));992nir_ssa_def *log2 = nir_flog2(b, abs_srcx);993994ttn_move_dest_masked(b, dest, nir_ffloor(b, log2), TGSI_WRITEMASK_X);995ttn_move_dest_masked(b, dest,996nir_fdiv(b, abs_srcx, nir_fexp2(b, nir_ffloor(b, log2))),997TGSI_WRITEMASK_Y);998ttn_move_dest_masked(b, dest, nir_flog2(b, abs_srcx), TGSI_WRITEMASK_Z);999ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_W);1000}10011002/* DST - Distance Vector1003* dst.x = 1.01004* dst.y = src0.y \times src1.y1005* dst.z = src0.z1006* dst.w = src1.w1007*/1008static void1009ttn_dst(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)1010{1011ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_X);1012ttn_move_dest_masked(b, dest, nir_fmul(b, src[0], src[1]), TGSI_WRITEMASK_Y);1013ttn_move_dest_masked(b, dest, nir_mov(b, src[0]), TGSI_WRITEMASK_Z);1014ttn_move_dest_masked(b, dest, nir_mov(b, src[1]), TGSI_WRITEMASK_W);1015}10161017/* LIT - Light Coefficients1018* dst.x = 1.01019* dst.y = max(src.x, 0.0)1020* dst.z = (src.x > 0.0) ? max(src.y, 0.0)^{clamp(src.w, -128.0, 128.0))} : 01021* dst.w = 1.01022*/1023static void1024ttn_lit(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)1025{1026ttn_move_dest_masked(b, dest, nir_imm_float(b, 1.0), TGSI_WRITEMASK_XW);10271028ttn_move_dest_masked(b, dest, nir_fmax(b, ttn_channel(b, src[0], X),1029nir_imm_float(b, 0.0)), TGSI_WRITEMASK_Y);10301031if (dest.write_mask & TGSI_WRITEMASK_Z) {1032nir_ssa_def *src0_y = ttn_channel(b, src[0], Y);1033nir_ssa_def *wclamp = nir_fmax(b, nir_fmin(b, ttn_channel(b, src[0], W),1034nir_imm_float(b, 128.0)),1035nir_imm_float(b, -128.0));1036nir_ssa_def *pow = nir_fpow(b, nir_fmax(b, src0_y, nir_imm_float(b, 0.0)),1037wclamp);10381039ttn_move_dest_masked(b, dest,1040nir_bcsel(b,1041nir_flt(b,1042ttn_channel(b, src[0], X),1043nir_imm_float(b, 0.0)),1044nir_imm_float(b, 0.0),1045pow),1046TGSI_WRITEMASK_Z);1047}1048}10491050static void1051ttn_sle(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)1052{1053ttn_move_dest(b, dest, nir_sge(b, src[1], src[0]));1054}10551056static void1057ttn_sgt(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)1058{1059ttn_move_dest(b, dest, nir_slt(b, src[1], src[0]));1060}10611062static void1063ttn_dp2(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)1064{1065ttn_move_dest(b, dest, nir_fdot2(b, src[0], src[1]));1066}10671068static void1069ttn_dp3(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)1070{1071ttn_move_dest(b, dest, nir_fdot3(b, src[0], src[1]));1072}10731074static void1075ttn_dp4(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)1076{1077ttn_move_dest(b, dest, nir_fdot4(b, src[0], src[1]));1078}10791080static void1081ttn_umad(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)1082{1083ttn_move_dest(b, dest, nir_iadd(b, nir_imul(b, src[0], src[1]), src[2]));1084}10851086static void1087ttn_arr(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)1088{1089ttn_move_dest(b, dest, nir_f2i32(b, nir_fround_even(b, src[0])));1090}10911092static void1093ttn_cmp(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)1094{1095ttn_move_dest(b, dest, nir_bcsel(b,1096nir_flt(b, src[0], nir_imm_float(b, 0.0)),1097src[1], src[2]));1098}10991100static void1101ttn_ucmp(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)1102{1103ttn_move_dest(b, dest, nir_bcsel(b,1104nir_ine(b, src[0], nir_imm_int(b, 0)),1105src[1], src[2]));1106}11071108static void1109ttn_barrier(nir_builder *b)1110{1111nir_control_barrier(b);1112}11131114static void1115ttn_kill(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)1116{1117nir_discard(b);1118b->shader->info.fs.uses_discard = true;1119}11201121static void1122ttn_kill_if(nir_builder *b, nir_op op, nir_alu_dest dest, nir_ssa_def **src)1123{1124/* flt must be exact, because NaN shouldn't discard. (apps rely on this) */1125b->exact = true;1126nir_ssa_def *cmp = nir_bany(b, nir_flt(b, src[0], nir_imm_float(b, 0.0)));1127b->exact = false;11281129nir_discard_if(b, cmp);1130b->shader->info.fs.uses_discard = true;1131}11321133static void1134get_texture_info(unsigned texture,1135enum glsl_sampler_dim *dim,1136bool *is_shadow,1137bool *is_array)1138{1139assert(is_array);1140*is_array = false;11411142if (is_shadow)1143*is_shadow = false;11441145switch (texture) {1146case TGSI_TEXTURE_BUFFER:1147*dim = GLSL_SAMPLER_DIM_BUF;1148break;1149case TGSI_TEXTURE_1D:1150*dim = GLSL_SAMPLER_DIM_1D;1151break;1152case TGSI_TEXTURE_1D_ARRAY:1153*dim = GLSL_SAMPLER_DIM_1D;1154*is_array = true;1155break;1156case TGSI_TEXTURE_SHADOW1D:1157*dim = GLSL_SAMPLER_DIM_1D;1158*is_shadow = true;1159break;1160case TGSI_TEXTURE_SHADOW1D_ARRAY:1161*dim = GLSL_SAMPLER_DIM_1D;1162*is_shadow = true;1163*is_array = true;1164break;1165case TGSI_TEXTURE_2D:1166*dim = GLSL_SAMPLER_DIM_2D;1167break;1168case TGSI_TEXTURE_2D_ARRAY:1169*dim = GLSL_SAMPLER_DIM_2D;1170*is_array = true;1171break;1172case TGSI_TEXTURE_2D_MSAA:1173*dim = GLSL_SAMPLER_DIM_MS;1174break;1175case TGSI_TEXTURE_2D_ARRAY_MSAA:1176*dim = GLSL_SAMPLER_DIM_MS;1177*is_array = true;1178break;1179case TGSI_TEXTURE_SHADOW2D:1180*dim = GLSL_SAMPLER_DIM_2D;1181*is_shadow = true;1182break;1183case TGSI_TEXTURE_SHADOW2D_ARRAY:1184*dim = GLSL_SAMPLER_DIM_2D;1185*is_shadow = true;1186*is_array = true;1187break;1188case TGSI_TEXTURE_3D:1189*dim = GLSL_SAMPLER_DIM_3D;1190break;1191case TGSI_TEXTURE_CUBE:1192*dim = GLSL_SAMPLER_DIM_CUBE;1193break;1194case TGSI_TEXTURE_CUBE_ARRAY:1195*dim = GLSL_SAMPLER_DIM_CUBE;1196*is_array = true;1197break;1198case TGSI_TEXTURE_SHADOWCUBE:1199*dim = GLSL_SAMPLER_DIM_CUBE;1200*is_shadow = true;1201break;1202case TGSI_TEXTURE_SHADOWCUBE_ARRAY:1203*dim = GLSL_SAMPLER_DIM_CUBE;1204*is_shadow = true;1205*is_array = true;1206break;1207case TGSI_TEXTURE_RECT:1208*dim = GLSL_SAMPLER_DIM_RECT;1209break;1210case TGSI_TEXTURE_SHADOWRECT:1211*dim = GLSL_SAMPLER_DIM_RECT;1212*is_shadow = true;1213break;1214default:1215fprintf(stderr, "Unknown TGSI texture target %d\n", texture);1216abort();1217}1218}12191220static enum glsl_base_type1221base_type_for_alu_type(nir_alu_type type)1222{1223type = nir_alu_type_get_base_type(type);12241225switch (type) {1226case nir_type_float:1227return GLSL_TYPE_FLOAT;1228case nir_type_int:1229return GLSL_TYPE_INT;1230case nir_type_uint:1231return GLSL_TYPE_UINT;1232default:1233unreachable("invalid type");1234}1235}12361237static nir_variable *1238get_sampler_var(struct ttn_compile *c, int binding,1239enum glsl_sampler_dim dim,1240bool is_shadow,1241bool is_array,1242enum glsl_base_type base_type,1243nir_texop op)1244{1245nir_variable *var = c->samplers[binding];1246if (!var) {1247const struct glsl_type *type =1248glsl_sampler_type(dim, is_shadow, is_array, base_type);1249var = nir_variable_create(c->build.shader, nir_var_uniform, type,1250"sampler");1251var->data.binding = binding;1252var->data.explicit_binding = true;12531254c->samplers[binding] = var;1255c->num_samplers = MAX2(c->num_samplers, binding + 1);12561257/* Record textures used */1258BITSET_SET(c->build.shader->info.textures_used, binding);1259if (op == nir_texop_txf ||1260op == nir_texop_txf_ms ||1261op == nir_texop_txf_ms_mcs)1262BITSET_SET(c->build.shader->info.textures_used_by_txf, binding);1263}12641265return var;1266}12671268static nir_variable *1269get_image_var(struct ttn_compile *c, int binding,1270enum glsl_sampler_dim dim,1271bool is_array,1272enum glsl_base_type base_type,1273enum gl_access_qualifier access,1274enum pipe_format format)1275{1276nir_variable *var = c->images[binding];12771278if (!var) {1279const struct glsl_type *type = glsl_image_type(dim, is_array, base_type);12801281var = nir_variable_create(c->build.shader, nir_var_uniform, type, "image");1282var->data.binding = binding;1283var->data.explicit_binding = true;1284var->data.access = access;1285var->data.image.format = format;12861287c->images[binding] = var;1288c->num_images = MAX2(c->num_images, binding + 1);1289if (dim == GLSL_SAMPLER_DIM_MS)1290c->num_msaa_images = c->num_images;1291}12921293return var;1294}12951296static void1297add_ssbo_var(struct ttn_compile *c, int binding)1298{1299nir_variable *var = c->ssbo[binding];13001301if (!var) {1302/* A length of 0 is used to denote unsized arrays */1303const struct glsl_type *type = glsl_array_type(glsl_uint_type(), 0, 0);13041305struct glsl_struct_field field = {1306.type = type,1307.name = "data",1308.location = -1,1309};13101311var = nir_variable_create(c->build.shader, nir_var_mem_ssbo, type, "ssbo");1312var->data.binding = binding;1313var->interface_type =1314glsl_interface_type(&field, 1, GLSL_INTERFACE_PACKING_STD430,1315false, "data");1316c->ssbo[binding] = var;1317}1318}13191320static void1321ttn_tex(struct ttn_compile *c, nir_alu_dest dest, nir_ssa_def **src)1322{1323nir_builder *b = &c->build;1324struct tgsi_full_instruction *tgsi_inst = &c->token->FullInstruction;1325nir_tex_instr *instr;1326nir_texop op;1327unsigned num_srcs, samp = 1, sview, i;13281329switch (tgsi_inst->Instruction.Opcode) {1330case TGSI_OPCODE_TEX:1331op = nir_texop_tex;1332num_srcs = 1;1333break;1334case TGSI_OPCODE_TEX2:1335op = nir_texop_tex;1336num_srcs = 1;1337samp = 2;1338break;1339case TGSI_OPCODE_TXP:1340op = nir_texop_tex;1341num_srcs = 2;1342break;1343case TGSI_OPCODE_TXB:1344op = nir_texop_txb;1345num_srcs = 2;1346break;1347case TGSI_OPCODE_TXB2:1348op = nir_texop_txb;1349num_srcs = 2;1350samp = 2;1351break;1352case TGSI_OPCODE_TXL:1353case TGSI_OPCODE_TEX_LZ:1354op = nir_texop_txl;1355num_srcs = 2;1356break;1357case TGSI_OPCODE_TXL2:1358op = nir_texop_txl;1359num_srcs = 2;1360samp = 2;1361break;1362case TGSI_OPCODE_TXF:1363case TGSI_OPCODE_TXF_LZ:1364if (tgsi_inst->Texture.Texture == TGSI_TEXTURE_2D_MSAA ||1365tgsi_inst->Texture.Texture == TGSI_TEXTURE_2D_ARRAY_MSAA) {1366op = nir_texop_txf_ms;1367} else {1368op = nir_texop_txf;1369}1370num_srcs = 2;1371break;1372case TGSI_OPCODE_TXD:1373op = nir_texop_txd;1374num_srcs = 3;1375samp = 3;1376break;1377case TGSI_OPCODE_LODQ:1378op = nir_texop_lod;1379num_srcs = 1;1380break;13811382default:1383fprintf(stderr, "unknown TGSI tex op %d\n", tgsi_inst->Instruction.Opcode);1384abort();1385}13861387if (tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D ||1388tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOW1D_ARRAY ||1389tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOW2D ||1390tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOW2D_ARRAY ||1391tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOWRECT ||1392tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE ||1393tgsi_inst->Texture.Texture == TGSI_TEXTURE_SHADOWCUBE_ARRAY) {1394num_srcs++;1395}13961397/* Deref sources */1398num_srcs += 2;13991400num_srcs += tgsi_inst->Texture.NumOffsets;14011402instr = nir_tex_instr_create(b->shader, num_srcs);1403instr->op = op;14041405get_texture_info(tgsi_inst->Texture.Texture,1406&instr->sampler_dim, &instr->is_shadow, &instr->is_array);14071408instr->coord_components =1409glsl_get_sampler_dim_coordinate_components(instr->sampler_dim);14101411if (instr->is_array)1412instr->coord_components++;14131414assert(tgsi_inst->Src[samp].Register.File == TGSI_FILE_SAMPLER);14151416/* TODO if we supported any opc's which take an explicit SVIEW1417* src, we would use that here instead. But for the "legacy"1418* texture opc's the SVIEW index is same as SAMP index:1419*/1420sview = tgsi_inst->Src[samp].Register.Index;14211422if (op == nir_texop_lod) {1423instr->dest_type = nir_type_float32;1424} else if (sview < c->num_samp_types) {1425instr->dest_type = c->samp_types[sview];1426} else {1427instr->dest_type = nir_type_float32;1428}14291430nir_variable *var =1431get_sampler_var(c, sview, instr->sampler_dim,1432instr->is_shadow,1433instr->is_array,1434base_type_for_alu_type(instr->dest_type),1435op);14361437nir_deref_instr *deref = nir_build_deref_var(b, var);14381439unsigned src_number = 0;14401441instr->src[src_number].src = nir_src_for_ssa(&deref->dest.ssa);1442instr->src[src_number].src_type = nir_tex_src_texture_deref;1443src_number++;1444instr->src[src_number].src = nir_src_for_ssa(&deref->dest.ssa);1445instr->src[src_number].src_type = nir_tex_src_sampler_deref;1446src_number++;14471448instr->src[src_number].src =1449nir_src_for_ssa(nir_swizzle(b, src[0], SWIZ(X, Y, Z, W),1450instr->coord_components));1451instr->src[src_number].src_type = nir_tex_src_coord;1452src_number++;14531454if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXP) {1455instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W));1456instr->src[src_number].src_type = nir_tex_src_projector;1457src_number++;1458}14591460if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXB) {1461instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W));1462instr->src[src_number].src_type = nir_tex_src_bias;1463src_number++;1464}14651466if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXB2) {1467instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[1], X));1468instr->src[src_number].src_type = nir_tex_src_bias;1469src_number++;1470}14711472if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXL ||1473tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TEX_LZ) {1474if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TEX_LZ)1475instr->src[src_number].src = nir_src_for_ssa(nir_imm_int(b, 0));1476else1477instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W));1478instr->src[src_number].src_type = nir_tex_src_lod;1479src_number++;1480}14811482if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXL2) {1483instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[1], X));1484instr->src[src_number].src_type = nir_tex_src_lod;1485src_number++;1486}14871488if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXF ||1489tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXF_LZ) {1490if (op == nir_texop_txf_ms) {1491instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W));1492instr->src[src_number].src_type = nir_tex_src_ms_index;1493} else {1494if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXF_LZ)1495instr->src[src_number].src = nir_src_for_ssa(nir_imm_int(b, 0));1496else1497instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W));1498instr->src[src_number].src_type = nir_tex_src_lod;1499}1500src_number++;1501}15021503if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_TXD) {1504instr->src[src_number].src_type = nir_tex_src_ddx;1505instr->src[src_number].src =1506nir_src_for_ssa(nir_swizzle(b, src[1], SWIZ(X, Y, Z, W),1507nir_tex_instr_src_size(instr, src_number)));1508src_number++;1509instr->src[src_number].src_type = nir_tex_src_ddy;1510instr->src[src_number].src =1511nir_src_for_ssa(nir_swizzle(b, src[2], SWIZ(X, Y, Z, W),1512nir_tex_instr_src_size(instr, src_number)));1513src_number++;1514}15151516if (instr->is_shadow) {1517if (instr->coord_components == 4)1518instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[1], X));1519else if (instr->coord_components == 3)1520instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], W));1521else1522instr->src[src_number].src = nir_src_for_ssa(ttn_channel(b, src[0], Z));15231524instr->src[src_number].src_type = nir_tex_src_comparator;1525src_number++;1526}15271528for (i = 0; i < tgsi_inst->Texture.NumOffsets; i++) {1529struct tgsi_texture_offset *tex_offset = &tgsi_inst->TexOffsets[i];1530/* since TexOffset ins't using tgsi_full_src_register we get to1531* do some extra gymnastics:1532*/1533nir_alu_src src;15341535memset(&src, 0, sizeof(src));15361537src.src = ttn_src_for_file_and_index(c,1538tex_offset->File,1539tex_offset->Index,1540NULL, NULL, NULL,1541true);15421543src.swizzle[0] = tex_offset->SwizzleX;1544src.swizzle[1] = tex_offset->SwizzleY;1545src.swizzle[2] = tex_offset->SwizzleZ;1546src.swizzle[3] = TGSI_SWIZZLE_W;15471548instr->src[src_number].src_type = nir_tex_src_offset;1549instr->src[src_number].src = nir_src_for_ssa(1550nir_mov_alu(b, src, nir_tex_instr_src_size(instr, src_number)));1551src_number++;1552}15531554assert(src_number == num_srcs);1555assert(src_number == instr->num_srcs);15561557nir_ssa_dest_init(&instr->instr, &instr->dest,1558nir_tex_instr_dest_size(instr),155932, NULL);1560nir_builder_instr_insert(b, &instr->instr);15611562/* Resolve the writemask on the texture op. */1563ttn_move_dest(b, dest, &instr->dest.ssa);1564}15651566/* TGSI_OPCODE_TXQ is actually two distinct operations:1567*1568* dst.x = texture\_width(unit, lod)1569* dst.y = texture\_height(unit, lod)1570* dst.z = texture\_depth(unit, lod)1571* dst.w = texture\_levels(unit)1572*1573* dst.xyz map to NIR txs opcode, and dst.w maps to query_levels1574*/1575static void1576ttn_txq(struct ttn_compile *c, nir_alu_dest dest, nir_ssa_def **src)1577{1578nir_builder *b = &c->build;1579struct tgsi_full_instruction *tgsi_inst = &c->token->FullInstruction;1580nir_tex_instr *txs, *qlv;15811582txs = nir_tex_instr_create(b->shader, 2);1583txs->op = nir_texop_txs;1584get_texture_info(tgsi_inst->Texture.Texture,1585&txs->sampler_dim, &txs->is_shadow, &txs->is_array);15861587qlv = nir_tex_instr_create(b->shader, 1);1588qlv->op = nir_texop_query_levels;1589get_texture_info(tgsi_inst->Texture.Texture,1590&qlv->sampler_dim, &qlv->is_shadow, &qlv->is_array);15911592assert(tgsi_inst->Src[1].Register.File == TGSI_FILE_SAMPLER);1593int tex_index = tgsi_inst->Src[1].Register.Index;15941595nir_variable *var =1596get_sampler_var(c, tex_index, txs->sampler_dim,1597txs->is_shadow,1598txs->is_array,1599base_type_for_alu_type(txs->dest_type),1600nir_texop_txs);16011602nir_deref_instr *deref = nir_build_deref_var(b, var);16031604txs->src[0].src = nir_src_for_ssa(&deref->dest.ssa);1605txs->src[0].src_type = nir_tex_src_texture_deref;16061607qlv->src[0].src = nir_src_for_ssa(&deref->dest.ssa);1608qlv->src[0].src_type = nir_tex_src_texture_deref;16091610/* lod: */1611txs->src[1].src = nir_src_for_ssa(ttn_channel(b, src[0], X));1612txs->src[1].src_type = nir_tex_src_lod;16131614nir_ssa_dest_init(&txs->instr, &txs->dest,1615nir_tex_instr_dest_size(txs), 32, NULL);1616nir_builder_instr_insert(b, &txs->instr);16171618nir_ssa_dest_init(&qlv->instr, &qlv->dest, 1, 32, NULL);1619nir_builder_instr_insert(b, &qlv->instr);16201621ttn_move_dest_masked(b, dest, &txs->dest.ssa, TGSI_WRITEMASK_XYZ);1622ttn_move_dest_masked(b, dest, &qlv->dest.ssa, TGSI_WRITEMASK_W);1623}16241625static enum glsl_base_type1626get_image_base_type(struct tgsi_full_instruction *tgsi_inst)1627{1628const struct util_format_description *desc =1629util_format_description(tgsi_inst->Memory.Format);16301631if (desc->channel[0].pure_integer) {1632if (desc->channel[0].type == UTIL_FORMAT_TYPE_SIGNED)1633return GLSL_TYPE_INT;1634else1635return GLSL_TYPE_UINT;1636}1637return GLSL_TYPE_FLOAT;1638}16391640static enum gl_access_qualifier1641get_mem_qualifier(struct tgsi_full_instruction *tgsi_inst)1642{1643enum gl_access_qualifier access = 0;16441645if (tgsi_inst->Memory.Qualifier & TGSI_MEMORY_COHERENT)1646access |= ACCESS_COHERENT;1647if (tgsi_inst->Memory.Qualifier & TGSI_MEMORY_RESTRICT)1648access |= ACCESS_RESTRICT;1649if (tgsi_inst->Memory.Qualifier & TGSI_MEMORY_VOLATILE)1650access |= ACCESS_VOLATILE;1651if (tgsi_inst->Memory.Qualifier & TGSI_MEMORY_STREAM_CACHE_POLICY)1652access |= ACCESS_STREAM_CACHE_POLICY;16531654return access;1655}16561657static void1658ttn_mem(struct ttn_compile *c, nir_alu_dest dest, nir_ssa_def **src)1659{1660nir_builder *b = &c->build;1661struct tgsi_full_instruction *tgsi_inst = &c->token->FullInstruction;1662nir_intrinsic_instr *instr = NULL;1663unsigned resource_index, addr_src_index, file;16641665switch (tgsi_inst->Instruction.Opcode) {1666case TGSI_OPCODE_LOAD:1667assert(!tgsi_inst->Src[0].Register.Indirect);1668resource_index = tgsi_inst->Src[0].Register.Index;1669file = tgsi_inst->Src[0].Register.File;1670addr_src_index = 1;1671break;1672case TGSI_OPCODE_STORE:1673assert(!tgsi_inst->Dst[0].Register.Indirect);1674resource_index = tgsi_inst->Dst[0].Register.Index;1675file = tgsi_inst->Dst[0].Register.File;1676addr_src_index = 0;1677break;1678default:1679unreachable("unexpected memory opcode");1680}16811682if (file == TGSI_FILE_BUFFER) {1683nir_intrinsic_op op;16841685switch (tgsi_inst->Instruction.Opcode) {1686case TGSI_OPCODE_LOAD:1687op = nir_intrinsic_load_ssbo;1688break;1689case TGSI_OPCODE_STORE:1690op = nir_intrinsic_store_ssbo;1691break;1692default:1693unreachable("unexpected buffer opcode");1694}16951696add_ssbo_var(c, resource_index);16971698instr = nir_intrinsic_instr_create(b->shader, op);1699instr->num_components = util_last_bit(tgsi_inst->Dst[0].Register.WriteMask);1700nir_intrinsic_set_access(instr, get_mem_qualifier(tgsi_inst));1701nir_intrinsic_set_align(instr, 4, 0);17021703unsigned i = 0;1704if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_STORE)1705instr->src[i++] = nir_src_for_ssa(nir_swizzle(b, src[1], SWIZ(X, Y, Z, W),1706instr->num_components));1707instr->src[i++] = nir_src_for_ssa(nir_imm_int(b, resource_index));1708instr->src[i++] = nir_src_for_ssa(ttn_channel(b, src[addr_src_index], X));17091710if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_STORE)1711nir_intrinsic_set_write_mask(instr, tgsi_inst->Dst[0].Register.WriteMask);17121713} else if (file == TGSI_FILE_IMAGE) {1714nir_intrinsic_op op;17151716switch (tgsi_inst->Instruction.Opcode) {1717case TGSI_OPCODE_LOAD:1718op = nir_intrinsic_image_deref_load;1719break;1720case TGSI_OPCODE_STORE:1721op = nir_intrinsic_image_deref_store;1722break;1723default:1724unreachable("unexpected file opcode");1725}17261727instr = nir_intrinsic_instr_create(b->shader, op);17281729/* Set the image variable dereference. */1730enum glsl_sampler_dim dim;1731bool is_array;1732get_texture_info(tgsi_inst->Memory.Texture, &dim, NULL, &is_array);17331734enum glsl_base_type base_type = get_image_base_type(tgsi_inst);1735enum gl_access_qualifier access = get_mem_qualifier(tgsi_inst);17361737nir_variable *image =1738get_image_var(c, resource_index,1739dim, is_array, base_type, access,1740tgsi_inst->Memory.Format);1741nir_deref_instr *image_deref = nir_build_deref_var(b, image);1742const struct glsl_type *type = image_deref->type;17431744nir_intrinsic_set_access(instr, image_deref->var->data.access);17451746instr->src[0] = nir_src_for_ssa(&image_deref->dest.ssa);1747instr->src[1] = nir_src_for_ssa(src[addr_src_index]);17481749/* Set the sample argument, which is undefined for single-sample images. */1750if (glsl_get_sampler_dim(type) == GLSL_SAMPLER_DIM_MS) {1751instr->src[2] = nir_src_for_ssa(ttn_channel(b, src[addr_src_index], W));1752} else {1753instr->src[2] = nir_src_for_ssa(nir_ssa_undef(b, 1, 32));1754}17551756if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_LOAD) {1757instr->src[3] = nir_src_for_ssa(nir_imm_int(b, 0)); /* LOD */1758}17591760unsigned num_components = util_last_bit(tgsi_inst->Dst[0].Register.WriteMask);17611762if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_STORE) {1763instr->src[3] = nir_src_for_ssa(nir_swizzle(b, src[1], SWIZ(X, Y, Z, W),1764num_components));1765instr->src[4] = nir_src_for_ssa(nir_imm_int(b, 0)); /* LOD */1766}17671768instr->num_components = num_components;1769} else {1770unreachable("unexpected file");1771}177217731774if (tgsi_inst->Instruction.Opcode == TGSI_OPCODE_LOAD) {1775nir_ssa_dest_init(&instr->instr, &instr->dest, instr->num_components,177632, NULL);1777nir_builder_instr_insert(b, &instr->instr);1778ttn_move_dest(b, dest, &instr->dest.ssa);1779} else {1780nir_builder_instr_insert(b, &instr->instr);1781}1782}17831784static const nir_op op_trans[TGSI_OPCODE_LAST] = {1785[TGSI_OPCODE_ARL] = 0,1786[TGSI_OPCODE_MOV] = nir_op_mov,1787[TGSI_OPCODE_FBFETCH] = nir_op_mov,1788[TGSI_OPCODE_LIT] = 0,1789[TGSI_OPCODE_RCP] = nir_op_frcp,1790[TGSI_OPCODE_RSQ] = nir_op_frsq,1791[TGSI_OPCODE_EXP] = 0,1792[TGSI_OPCODE_LOG] = 0,1793[TGSI_OPCODE_MUL] = nir_op_fmul,1794[TGSI_OPCODE_ADD] = nir_op_fadd,1795[TGSI_OPCODE_DP3] = 0,1796[TGSI_OPCODE_DP4] = 0,1797[TGSI_OPCODE_DST] = 0,1798[TGSI_OPCODE_MIN] = nir_op_fmin,1799[TGSI_OPCODE_MAX] = nir_op_fmax,1800[TGSI_OPCODE_SLT] = nir_op_slt,1801[TGSI_OPCODE_SGE] = nir_op_sge,1802[TGSI_OPCODE_MAD] = nir_op_ffma,1803[TGSI_OPCODE_TEX_LZ] = 0,1804[TGSI_OPCODE_LRP] = 0,1805[TGSI_OPCODE_SQRT] = nir_op_fsqrt,1806[TGSI_OPCODE_FRC] = nir_op_ffract,1807[TGSI_OPCODE_TXF_LZ] = 0,1808[TGSI_OPCODE_FLR] = nir_op_ffloor,1809[TGSI_OPCODE_ROUND] = nir_op_fround_even,1810[TGSI_OPCODE_EX2] = nir_op_fexp2,1811[TGSI_OPCODE_LG2] = nir_op_flog2,1812[TGSI_OPCODE_POW] = nir_op_fpow,1813[TGSI_OPCODE_COS] = nir_op_fcos,1814[TGSI_OPCODE_DDX] = nir_op_fddx,1815[TGSI_OPCODE_DDY] = nir_op_fddy,1816[TGSI_OPCODE_KILL] = 0,1817[TGSI_OPCODE_PK2H] = 0, /* XXX */1818[TGSI_OPCODE_PK2US] = 0, /* XXX */1819[TGSI_OPCODE_PK4B] = 0, /* XXX */1820[TGSI_OPCODE_PK4UB] = 0, /* XXX */1821[TGSI_OPCODE_SEQ] = nir_op_seq,1822[TGSI_OPCODE_SGT] = 0,1823[TGSI_OPCODE_SIN] = nir_op_fsin,1824[TGSI_OPCODE_SNE] = nir_op_sne,1825[TGSI_OPCODE_SLE] = 0,1826[TGSI_OPCODE_TEX] = 0,1827[TGSI_OPCODE_TXD] = 0,1828[TGSI_OPCODE_TXP] = 0,1829[TGSI_OPCODE_UP2H] = 0, /* XXX */1830[TGSI_OPCODE_UP2US] = 0, /* XXX */1831[TGSI_OPCODE_UP4B] = 0, /* XXX */1832[TGSI_OPCODE_UP4UB] = 0, /* XXX */1833[TGSI_OPCODE_ARR] = 0,18341835/* No function calls, yet. */1836[TGSI_OPCODE_CAL] = 0, /* XXX */1837[TGSI_OPCODE_RET] = 0, /* XXX */18381839[TGSI_OPCODE_SSG] = nir_op_fsign,1840[TGSI_OPCODE_CMP] = 0,1841[TGSI_OPCODE_TXB] = 0,1842[TGSI_OPCODE_DIV] = nir_op_fdiv,1843[TGSI_OPCODE_DP2] = 0,1844[TGSI_OPCODE_TXL] = 0,18451846[TGSI_OPCODE_BRK] = 0,1847[TGSI_OPCODE_IF] = 0,1848[TGSI_OPCODE_UIF] = 0,1849[TGSI_OPCODE_ELSE] = 0,1850[TGSI_OPCODE_ENDIF] = 0,18511852[TGSI_OPCODE_DDX_FINE] = nir_op_fddx_fine,1853[TGSI_OPCODE_DDY_FINE] = nir_op_fddy_fine,18541855[TGSI_OPCODE_CEIL] = nir_op_fceil,1856[TGSI_OPCODE_I2F] = nir_op_i2f32,1857[TGSI_OPCODE_NOT] = nir_op_inot,1858[TGSI_OPCODE_TRUNC] = nir_op_ftrunc,1859[TGSI_OPCODE_SHL] = nir_op_ishl,1860[TGSI_OPCODE_AND] = nir_op_iand,1861[TGSI_OPCODE_OR] = nir_op_ior,1862[TGSI_OPCODE_MOD] = nir_op_umod,1863[TGSI_OPCODE_XOR] = nir_op_ixor,1864[TGSI_OPCODE_TXF] = 0,1865[TGSI_OPCODE_TXQ] = 0,18661867[TGSI_OPCODE_CONT] = 0,18681869[TGSI_OPCODE_EMIT] = 0, /* XXX */1870[TGSI_OPCODE_ENDPRIM] = 0, /* XXX */18711872[TGSI_OPCODE_BGNLOOP] = 0,1873[TGSI_OPCODE_BGNSUB] = 0, /* XXX: no function calls */1874[TGSI_OPCODE_ENDLOOP] = 0,1875[TGSI_OPCODE_ENDSUB] = 0, /* XXX: no function calls */18761877[TGSI_OPCODE_NOP] = 0,1878[TGSI_OPCODE_FSEQ] = nir_op_feq,1879[TGSI_OPCODE_FSGE] = nir_op_fge,1880[TGSI_OPCODE_FSLT] = nir_op_flt,1881[TGSI_OPCODE_FSNE] = nir_op_fneu,18821883[TGSI_OPCODE_KILL_IF] = 0,18841885[TGSI_OPCODE_END] = 0,18861887[TGSI_OPCODE_F2I] = nir_op_f2i32,1888[TGSI_OPCODE_IDIV] = nir_op_idiv,1889[TGSI_OPCODE_IMAX] = nir_op_imax,1890[TGSI_OPCODE_IMIN] = nir_op_imin,1891[TGSI_OPCODE_INEG] = nir_op_ineg,1892[TGSI_OPCODE_ISGE] = nir_op_ige,1893[TGSI_OPCODE_ISHR] = nir_op_ishr,1894[TGSI_OPCODE_ISLT] = nir_op_ilt,1895[TGSI_OPCODE_F2U] = nir_op_f2u32,1896[TGSI_OPCODE_U2F] = nir_op_u2f32,1897[TGSI_OPCODE_UADD] = nir_op_iadd,1898[TGSI_OPCODE_UDIV] = nir_op_udiv,1899[TGSI_OPCODE_UMAD] = 0,1900[TGSI_OPCODE_UMAX] = nir_op_umax,1901[TGSI_OPCODE_UMIN] = nir_op_umin,1902[TGSI_OPCODE_UMOD] = nir_op_umod,1903[TGSI_OPCODE_UMUL] = nir_op_imul,1904[TGSI_OPCODE_USEQ] = nir_op_ieq,1905[TGSI_OPCODE_USGE] = nir_op_uge,1906[TGSI_OPCODE_USHR] = nir_op_ushr,1907[TGSI_OPCODE_USLT] = nir_op_ult,1908[TGSI_OPCODE_USNE] = nir_op_ine,19091910[TGSI_OPCODE_SWITCH] = 0, /* not emitted by glsl_to_tgsi.cpp */1911[TGSI_OPCODE_CASE] = 0, /* not emitted by glsl_to_tgsi.cpp */1912[TGSI_OPCODE_DEFAULT] = 0, /* not emitted by glsl_to_tgsi.cpp */1913[TGSI_OPCODE_ENDSWITCH] = 0, /* not emitted by glsl_to_tgsi.cpp */19141915/* XXX: SAMPLE opcodes */19161917[TGSI_OPCODE_UARL] = nir_op_mov,1918[TGSI_OPCODE_UCMP] = 0,1919[TGSI_OPCODE_IABS] = nir_op_iabs,1920[TGSI_OPCODE_ISSG] = nir_op_isign,19211922[TGSI_OPCODE_LOAD] = 0,1923[TGSI_OPCODE_STORE] = 0,19241925/* XXX: atomics */19261927[TGSI_OPCODE_TEX2] = 0,1928[TGSI_OPCODE_TXB2] = 0,1929[TGSI_OPCODE_TXL2] = 0,19301931[TGSI_OPCODE_IMUL_HI] = nir_op_imul_high,1932[TGSI_OPCODE_UMUL_HI] = nir_op_umul_high,19331934[TGSI_OPCODE_TG4] = 0,1935[TGSI_OPCODE_LODQ] = 0,19361937[TGSI_OPCODE_IBFE] = nir_op_ibitfield_extract,1938[TGSI_OPCODE_UBFE] = nir_op_ubitfield_extract,1939[TGSI_OPCODE_BFI] = nir_op_bitfield_insert,1940[TGSI_OPCODE_BREV] = nir_op_bitfield_reverse,1941[TGSI_OPCODE_POPC] = nir_op_bit_count,1942[TGSI_OPCODE_LSB] = nir_op_find_lsb,1943[TGSI_OPCODE_IMSB] = nir_op_ifind_msb,1944[TGSI_OPCODE_UMSB] = nir_op_ufind_msb,19451946[TGSI_OPCODE_INTERP_CENTROID] = 0, /* XXX */1947[TGSI_OPCODE_INTERP_SAMPLE] = 0, /* XXX */1948[TGSI_OPCODE_INTERP_OFFSET] = 0, /* XXX */19491950[TGSI_OPCODE_F2D] = nir_op_f2f64,1951[TGSI_OPCODE_D2F] = nir_op_f2f32,1952[TGSI_OPCODE_DMUL] = nir_op_fmul,1953[TGSI_OPCODE_D2U] = nir_op_f2u32,1954[TGSI_OPCODE_U2D] = nir_op_u2f64,19551956[TGSI_OPCODE_U64ADD] = nir_op_iadd,1957[TGSI_OPCODE_U64MUL] = nir_op_imul,1958[TGSI_OPCODE_U64DIV] = nir_op_udiv,1959[TGSI_OPCODE_U64SNE] = nir_op_ine,1960[TGSI_OPCODE_I64NEG] = nir_op_ineg,1961[TGSI_OPCODE_I64ABS] = nir_op_iabs,1962};19631964static void1965ttn_emit_instruction(struct ttn_compile *c)1966{1967nir_builder *b = &c->build;1968struct tgsi_full_instruction *tgsi_inst = &c->token->FullInstruction;1969unsigned i;1970unsigned tgsi_op = tgsi_inst->Instruction.Opcode;1971struct tgsi_full_dst_register *tgsi_dst = &tgsi_inst->Dst[0];19721973if (tgsi_op == TGSI_OPCODE_END)1974return;19751976nir_ssa_def *src[TGSI_FULL_MAX_SRC_REGISTERS];1977for (i = 0; i < tgsi_inst->Instruction.NumSrcRegs; i++) {1978src[i] = ttn_get_src(c, &tgsi_inst->Src[i], i);1979}1980nir_alu_dest dest = ttn_get_dest(c, tgsi_dst);19811982unsigned tgsi_dst_type = tgsi_opcode_infer_dst_type(tgsi_op, 0);19831984/* The destination bitsize of the NIR opcode (not TGSI, where it's always1985* 32 bits). This needs to be passed into ttn_alu() because it can't be1986* inferred for comparison opcodes.1987*/1988unsigned dst_bitsize = tgsi_type_is_64bit(tgsi_dst_type) ? 64 : 32;19891990switch (tgsi_op) {1991case TGSI_OPCODE_RSQ:1992ttn_move_dest(b, dest, nir_frsq(b, ttn_channel(b, src[0], X)));1993break;19941995case TGSI_OPCODE_SQRT:1996ttn_move_dest(b, dest, nir_fsqrt(b, ttn_channel(b, src[0], X)));1997break;19981999case TGSI_OPCODE_RCP:2000ttn_move_dest(b, dest, nir_frcp(b, ttn_channel(b, src[0], X)));2001break;20022003case TGSI_OPCODE_EX2:2004ttn_move_dest(b, dest, nir_fexp2(b, ttn_channel(b, src[0], X)));2005break;20062007case TGSI_OPCODE_LG2:2008ttn_move_dest(b, dest, nir_flog2(b, ttn_channel(b, src[0], X)));2009break;20102011case TGSI_OPCODE_POW:2012ttn_move_dest(b, dest, nir_fpow(b,2013ttn_channel(b, src[0], X),2014ttn_channel(b, src[1], X)));2015break;20162017case TGSI_OPCODE_COS:2018ttn_move_dest(b, dest, nir_fcos(b, ttn_channel(b, src[0], X)));2019break;20202021case TGSI_OPCODE_SIN:2022ttn_move_dest(b, dest, nir_fsin(b, ttn_channel(b, src[0], X)));2023break;20242025case TGSI_OPCODE_ARL:2026ttn_arl(b, op_trans[tgsi_op], dest, src);2027break;20282029case TGSI_OPCODE_EXP:2030ttn_exp(b, op_trans[tgsi_op], dest, src);2031break;20322033case TGSI_OPCODE_LOG:2034ttn_log(b, op_trans[tgsi_op], dest, src);2035break;20362037case TGSI_OPCODE_DST:2038ttn_dst(b, op_trans[tgsi_op], dest, src);2039break;20402041case TGSI_OPCODE_LIT:2042ttn_lit(b, op_trans[tgsi_op], dest, src);2043break;20442045case TGSI_OPCODE_DP2:2046ttn_dp2(b, op_trans[tgsi_op], dest, src);2047break;20482049case TGSI_OPCODE_DP3:2050ttn_dp3(b, op_trans[tgsi_op], dest, src);2051break;20522053case TGSI_OPCODE_DP4:2054ttn_dp4(b, op_trans[tgsi_op], dest, src);2055break;20562057case TGSI_OPCODE_UMAD:2058ttn_umad(b, op_trans[tgsi_op], dest, src);2059break;20602061case TGSI_OPCODE_LRP:2062ttn_move_dest(b, dest, nir_flrp(b, src[2], src[1], src[0]));2063break;20642065case TGSI_OPCODE_KILL:2066ttn_kill(b, op_trans[tgsi_op], dest, src);2067break;20682069case TGSI_OPCODE_ARR:2070ttn_arr(b, op_trans[tgsi_op], dest, src);2071break;20722073case TGSI_OPCODE_CMP:2074ttn_cmp(b, op_trans[tgsi_op], dest, src);2075break;20762077case TGSI_OPCODE_UCMP:2078ttn_ucmp(b, op_trans[tgsi_op], dest, src);2079break;20802081case TGSI_OPCODE_SGT:2082ttn_sgt(b, op_trans[tgsi_op], dest, src);2083break;20842085case TGSI_OPCODE_SLE:2086ttn_sle(b, op_trans[tgsi_op], dest, src);2087break;20882089case TGSI_OPCODE_KILL_IF:2090ttn_kill_if(b, op_trans[tgsi_op], dest, src);2091break;20922093case TGSI_OPCODE_TEX:2094case TGSI_OPCODE_TEX_LZ:2095case TGSI_OPCODE_TXP:2096case TGSI_OPCODE_TXL:2097case TGSI_OPCODE_TXB:2098case TGSI_OPCODE_TXD:2099case TGSI_OPCODE_TEX2:2100case TGSI_OPCODE_TXL2:2101case TGSI_OPCODE_TXB2:2102case TGSI_OPCODE_TXF:2103case TGSI_OPCODE_TXF_LZ:2104case TGSI_OPCODE_TG4:2105case TGSI_OPCODE_LODQ:2106ttn_tex(c, dest, src);2107break;21082109case TGSI_OPCODE_TXQ:2110ttn_txq(c, dest, src);2111break;21122113case TGSI_OPCODE_LOAD:2114case TGSI_OPCODE_STORE:2115ttn_mem(c, dest, src);2116break;21172118case TGSI_OPCODE_NOP:2119break;21202121case TGSI_OPCODE_IF:2122nir_push_if(b, nir_fneu(b, nir_channel(b, src[0], 0), nir_imm_float(b, 0.0)));2123break;21242125case TGSI_OPCODE_UIF:2126nir_push_if(b, nir_ine(b, nir_channel(b, src[0], 0), nir_imm_int(b, 0)));2127break;21282129case TGSI_OPCODE_ELSE:2130nir_push_else(&c->build, NULL);2131break;21322133case TGSI_OPCODE_ENDIF:2134nir_pop_if(&c->build, NULL);2135break;21362137case TGSI_OPCODE_BGNLOOP:2138nir_push_loop(&c->build);2139break;21402141case TGSI_OPCODE_BRK:2142nir_jump(b, nir_jump_break);2143break;21442145case TGSI_OPCODE_CONT:2146nir_jump(b, nir_jump_continue);2147break;21482149case TGSI_OPCODE_ENDLOOP:2150nir_pop_loop(&c->build, NULL);2151break;21522153case TGSI_OPCODE_BARRIER:2154ttn_barrier(b);2155break;21562157default:2158if (op_trans[tgsi_op] != 0 || tgsi_op == TGSI_OPCODE_MOV) {2159ttn_alu(b, op_trans[tgsi_op], dest, dst_bitsize, src);2160} else {2161fprintf(stderr, "unknown TGSI opcode: %s\n",2162tgsi_get_opcode_name(tgsi_op));2163abort();2164}2165break;2166}21672168if (tgsi_inst->Instruction.Saturate) {2169assert(!dest.dest.is_ssa);2170ttn_move_dest(b, dest, nir_fsat(b, ttn_src_for_dest(b, &dest)));2171}21722173/* if the dst has a matching var, append store_var to move2174* output from reg to var2175*/2176nir_variable *var = ttn_get_var(c, tgsi_dst);2177if (var) {2178unsigned index = tgsi_dst->Register.Index;2179unsigned offset = c->temp_regs[index].offset;2180struct tgsi_ind_register *indirect = tgsi_dst->Register.Indirect ?2181&tgsi_dst->Indirect : NULL;2182nir_src val = nir_src_for_reg(dest.dest.reg.reg);2183nir_store_deref(b, ttn_array_deref(c, var, offset, indirect),2184nir_ssa_for_src(b, val, 4), dest.write_mask);2185}2186}21872188/**2189* Puts a NIR intrinsic to store of each TGSI_FILE_OUTPUT value to the output2190* variables at the end of the shader.2191*2192* We don't generate these incrementally as the TGSI_FILE_OUTPUT values are2193* written, because there's no output load intrinsic, which means we couldn't2194* handle writemasks.2195*/2196static void2197ttn_add_output_stores(struct ttn_compile *c)2198{2199nir_builder *b = &c->build;22002201for (int i = 0; i < c->build.shader->num_outputs; i++) {2202nir_variable *var = c->outputs[i];2203if (!var)2204continue;22052206nir_src src = nir_src_for_reg(c->output_regs[i].reg);2207src.reg.base_offset = c->output_regs[i].offset;22082209nir_ssa_def *store_value = nir_ssa_for_src(b, src, 4);2210if (c->build.shader->info.stage == MESA_SHADER_FRAGMENT) {2211/* TGSI uses TGSI_SEMANTIC_POSITION.z for the depth output2212* and TGSI_SEMANTIC_STENCIL.y for the stencil output,2213* while NIR uses a single-component output.2214*/2215if (var->data.location == FRAG_RESULT_DEPTH)2216store_value = nir_channel(b, store_value, 2);2217else if (var->data.location == FRAG_RESULT_STENCIL)2218store_value = nir_channel(b, store_value, 1);2219else if (var->data.location == FRAG_RESULT_SAMPLE_MASK)2220store_value = nir_channel(b, store_value, 0);2221} else {2222/* FOGC and PSIZ are scalar values */2223if (var->data.location == VARYING_SLOT_FOGC ||2224var->data.location == VARYING_SLOT_PSIZ) {2225store_value = nir_channel(b, store_value, 0);2226}2227}22282229nir_store_deref(b, nir_build_deref_var(b, var), store_value,2230(1 << store_value->num_components) - 1);2231}2232}22332234/**2235* Parses the given TGSI tokens.2236*/2237static void2238ttn_parse_tgsi(struct ttn_compile *c, const void *tgsi_tokens)2239{2240struct tgsi_parse_context parser;2241ASSERTED int ret;22422243ret = tgsi_parse_init(&parser, tgsi_tokens);2244assert(ret == TGSI_PARSE_OK);22452246while (!tgsi_parse_end_of_tokens(&parser)) {2247tgsi_parse_token(&parser);2248c->token = &parser.FullToken;22492250switch (parser.FullToken.Token.Type) {2251case TGSI_TOKEN_TYPE_DECLARATION:2252ttn_emit_declaration(c);2253break;22542255case TGSI_TOKEN_TYPE_INSTRUCTION:2256ttn_emit_instruction(c);2257break;22582259case TGSI_TOKEN_TYPE_IMMEDIATE:2260ttn_emit_immediate(c);2261break;2262}2263}22642265tgsi_parse_free(&parser);2266}22672268static void2269ttn_read_pipe_caps(struct ttn_compile *c,2270struct pipe_screen *screen)2271{2272c->cap_samplers_as_deref = screen->get_param(screen, PIPE_CAP_NIR_SAMPLERS_AS_DEREF);2273c->cap_face_is_sysval = screen->get_param(screen, PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL);2274c->cap_position_is_sysval = screen->get_param(screen, PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL);2275c->cap_point_is_sysval = screen->get_param(screen, PIPE_CAP_TGSI_FS_POINT_IS_SYSVAL);2276}22772278/**2279* Initializes a TGSI-to-NIR compiler.2280*/2281static struct ttn_compile *2282ttn_compile_init(const void *tgsi_tokens,2283const nir_shader_compiler_options *options,2284struct pipe_screen *screen)2285{2286struct ttn_compile *c;2287struct nir_shader *s;2288struct tgsi_shader_info scan;22892290assert(options || screen);2291c = rzalloc(NULL, struct ttn_compile);22922293tgsi_scan_shader(tgsi_tokens, &scan);2294c->scan = &scan;22952296if (!options) {2297options =2298screen->get_compiler_options(screen, PIPE_SHADER_IR_NIR, scan.processor);2299}23002301c->build = nir_builder_init_simple_shader(tgsi_processor_to_shader_stage(scan.processor),2302options, "TTN");23032304s = c->build.shader;23052306if (screen) {2307ttn_read_pipe_caps(c, screen);2308} else {2309/* TTN used to be hard coded to always make FACE a sysval,2310* so it makes sense to preserve that behavior so users don't break. */2311c->cap_face_is_sysval = true;2312}23132314if (s->info.stage == MESA_SHADER_FRAGMENT)2315s->info.fs.untyped_color_outputs = true;23162317s->num_inputs = scan.file_max[TGSI_FILE_INPUT] + 1;2318s->num_uniforms = scan.const_file_max[0] + 1;2319s->num_outputs = scan.file_max[TGSI_FILE_OUTPUT] + 1;2320s->info.num_ssbos = util_last_bit(scan.shader_buffers_declared);2321s->info.num_ubos = util_last_bit(scan.const_buffers_declared >> 1);2322s->info.num_images = util_last_bit(scan.images_declared);2323s->info.num_textures = util_last_bit(scan.samplers_declared);23242325for (unsigned i = 0; i < TGSI_PROPERTY_COUNT; i++) {2326unsigned value = scan.properties[i];23272328switch (i) {2329case TGSI_PROPERTY_FS_COLOR0_WRITES_ALL_CBUFS:2330break; /* handled in ttn_emit_declaration */2331case TGSI_PROPERTY_FS_COORD_ORIGIN:2332if (s->info.stage == MESA_SHADER_FRAGMENT)2333s->info.fs.origin_upper_left = value == TGSI_FS_COORD_ORIGIN_UPPER_LEFT;2334break;2335case TGSI_PROPERTY_FS_COORD_PIXEL_CENTER:2336if (s->info.stage == MESA_SHADER_FRAGMENT)2337s->info.fs.pixel_center_integer = value == TGSI_FS_COORD_PIXEL_CENTER_INTEGER;2338break;2339case TGSI_PROPERTY_FS_DEPTH_LAYOUT:2340if (s->info.stage == MESA_SHADER_FRAGMENT)2341s->info.fs.depth_layout = ttn_get_depth_layout(value);2342break;2343case TGSI_PROPERTY_VS_WINDOW_SPACE_POSITION:2344if (s->info.stage == MESA_SHADER_VERTEX)2345s->info.vs.window_space_position = value;2346break;2347case TGSI_PROPERTY_NEXT_SHADER:2348s->info.next_stage = tgsi_processor_to_shader_stage(value);2349break;2350case TGSI_PROPERTY_VS_BLIT_SGPRS_AMD:2351if (s->info.stage == MESA_SHADER_VERTEX)2352s->info.vs.blit_sgprs_amd = value;2353break;2354case TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH:2355if (s->info.stage == MESA_SHADER_COMPUTE)2356s->info.workgroup_size[0] = value;2357break;2358case TGSI_PROPERTY_CS_FIXED_BLOCK_HEIGHT:2359if (s->info.stage == MESA_SHADER_COMPUTE)2360s->info.workgroup_size[1] = value;2361break;2362case TGSI_PROPERTY_CS_FIXED_BLOCK_DEPTH:2363if (s->info.stage == MESA_SHADER_COMPUTE)2364s->info.workgroup_size[2] = value;2365break;2366case TGSI_PROPERTY_CS_USER_DATA_COMPONENTS_AMD:2367if (s->info.stage == MESA_SHADER_COMPUTE)2368s->info.cs.user_data_components_amd = value;2369break;2370case TGSI_PROPERTY_NUM_CLIPDIST_ENABLED:2371s->info.clip_distance_array_size = value;2372break;2373default:2374if (value) {2375fprintf(stderr, "tgsi_to_nir: unhandled TGSI property %u = %u\n",2376i, value);2377unreachable("unhandled TGSI property");2378}2379}2380}23812382if (s->info.stage == MESA_SHADER_COMPUTE &&2383(!s->info.workgroup_size[0] ||2384!s->info.workgroup_size[1] ||2385!s->info.workgroup_size[2]))2386s->info.workgroup_size_variable = true;23872388c->inputs = rzalloc_array(c, struct nir_variable *, s->num_inputs);2389c->outputs = rzalloc_array(c, struct nir_variable *, s->num_outputs);23902391c->output_regs = rzalloc_array(c, struct ttn_reg_info,2392scan.file_max[TGSI_FILE_OUTPUT] + 1);2393c->temp_regs = rzalloc_array(c, struct ttn_reg_info,2394scan.file_max[TGSI_FILE_TEMPORARY] + 1);2395c->imm_defs = rzalloc_array(c, nir_ssa_def *,2396scan.file_max[TGSI_FILE_IMMEDIATE] + 1);23972398c->num_samp_types = scan.file_max[TGSI_FILE_SAMPLER_VIEW] + 1;2399c->samp_types = rzalloc_array(c, nir_alu_type, c->num_samp_types);24002401ttn_parse_tgsi(c, tgsi_tokens);2402ttn_add_output_stores(c);24032404nir_validate_shader(c->build.shader, "TTN: after parsing TGSI and creating the NIR shader");24052406return c;2407}24082409static void2410ttn_optimize_nir(nir_shader *nir)2411{2412bool progress;2413do {2414progress = false;24152416NIR_PASS_V(nir, nir_lower_vars_to_ssa);24172418if (nir->options->lower_to_scalar) {2419NIR_PASS_V(nir, nir_lower_alu_to_scalar, NULL, NULL);2420NIR_PASS_V(nir, nir_lower_phis_to_scalar, false);2421}24222423NIR_PASS_V(nir, nir_lower_alu);2424NIR_PASS_V(nir, nir_lower_pack);2425NIR_PASS(progress, nir, nir_copy_prop);2426NIR_PASS(progress, nir, nir_opt_remove_phis);2427NIR_PASS(progress, nir, nir_opt_dce);24282429if (nir_opt_trivial_continues(nir)) {2430progress = true;2431NIR_PASS(progress, nir, nir_copy_prop);2432NIR_PASS(progress, nir, nir_opt_dce);2433}24342435NIR_PASS(progress, nir, nir_opt_if, false);2436NIR_PASS(progress, nir, nir_opt_dead_cf);2437NIR_PASS(progress, nir, nir_opt_cse);2438NIR_PASS(progress, nir, nir_opt_peephole_select, 8, true, true);24392440NIR_PASS(progress, nir, nir_opt_algebraic);2441NIR_PASS(progress, nir, nir_opt_constant_folding);24422443NIR_PASS(progress, nir, nir_opt_undef);2444NIR_PASS(progress, nir, nir_opt_conditional_discard);24452446if (nir->options->max_unroll_iterations) {2447NIR_PASS(progress, nir, nir_opt_loop_unroll, (nir_variable_mode)0);2448}24492450} while (progress);24512452}24532454/**2455* Finalizes the NIR in a similar way as st_glsl_to_nir does.2456*2457* Drivers expect that these passes are already performed,2458* so we have to do it here too.2459*/2460static void2461ttn_finalize_nir(struct ttn_compile *c, struct pipe_screen *screen)2462{2463struct nir_shader *nir = c->build.shader;24642465NIR_PASS_V(nir, nir_lower_vars_to_ssa);2466NIR_PASS_V(nir, nir_lower_regs_to_ssa);24672468NIR_PASS_V(nir, nir_lower_global_vars_to_local);2469NIR_PASS_V(nir, nir_split_var_copies);2470NIR_PASS_V(nir, nir_lower_var_copies);2471NIR_PASS_V(nir, nir_lower_system_values);2472NIR_PASS_V(nir, nir_lower_compute_system_values, NULL);24732474if (!screen->get_param(screen, PIPE_CAP_TEXRECT)) {2475const struct nir_lower_tex_options opts = { .lower_rect = true, };2476NIR_PASS_V(nir, nir_lower_tex, &opts);2477}24782479if (nir->options->lower_uniforms_to_ubo)2480NIR_PASS_V(nir, nir_lower_uniforms_to_ubo, false, false);24812482if (!c->cap_samplers_as_deref)2483NIR_PASS_V(nir, nir_lower_samplers);24842485if (screen->finalize_nir) {2486screen->finalize_nir(screen, nir, true);2487} else {2488ttn_optimize_nir(nir);2489nir_shader_gather_info(nir, c->build.impl);2490}24912492nir->info.num_images = c->num_images;2493nir->info.num_textures = c->num_samplers;24942495nir_validate_shader(nir, "TTN: after all optimizations");2496}24972498static void save_nir_to_disk_cache(struct disk_cache *cache,2499uint8_t key[CACHE_KEY_SIZE],2500const nir_shader *s)2501{2502struct blob blob = {0};25032504blob_init(&blob);2505/* Because we cannot fully trust disk_cache_put2506* (EGL_ANDROID_blob_cache) we add the shader size,2507* which we'll check after disk_cache_get().2508*/2509if (blob_reserve_uint32(&blob) != 0) {2510blob_finish(&blob);2511return;2512}25132514nir_serialize(&blob, s, true);2515*(uint32_t *)blob.data = blob.size;25162517disk_cache_put(cache, key, blob.data, blob.size, NULL);2518blob_finish(&blob);2519}25202521static nir_shader *2522load_nir_from_disk_cache(struct disk_cache *cache,2523struct pipe_screen *screen,2524uint8_t key[CACHE_KEY_SIZE],2525unsigned processor)2526{2527const nir_shader_compiler_options *options =2528screen->get_compiler_options(screen, PIPE_SHADER_IR_NIR, processor);2529struct blob_reader blob_reader;2530size_t size;2531nir_shader *s;25322533uint32_t *buffer = (uint32_t *)disk_cache_get(cache, key, &size);2534if (!buffer)2535return NULL;25362537/* Match found. No need to check crc32 or other things.2538* disk_cache_get is supposed to do that for us.2539* However we do still check if the first element is indeed the size,2540* as we cannot fully trust disk_cache_get (EGL_ANDROID_blob_cache) */2541if (buffer[0] != size) {2542return NULL;2543}25442545size -= 4;2546blob_reader_init(&blob_reader, buffer + 1, size);2547s = nir_deserialize(NULL, options, &blob_reader);2548free(buffer); /* buffer was malloc-ed */2549return s;2550}25512552struct nir_shader *2553tgsi_to_nir(const void *tgsi_tokens,2554struct pipe_screen *screen,2555bool allow_disk_cache)2556{2557struct disk_cache *cache = NULL;2558struct ttn_compile *c;2559struct nir_shader *s = NULL;2560uint8_t key[CACHE_KEY_SIZE];2561unsigned processor;25622563if (allow_disk_cache)2564cache = screen->get_disk_shader_cache(screen);25652566/* Look first in the cache */2567if (cache) {2568disk_cache_compute_key(cache,2569tgsi_tokens,2570tgsi_num_tokens(tgsi_tokens) * sizeof(struct tgsi_token),2571key);2572processor = tgsi_get_processor_type(tgsi_tokens);2573s = load_nir_from_disk_cache(cache, screen, key, processor);2574}25752576if (s)2577return s;25782579/* Not in the cache */25802581c = ttn_compile_init(tgsi_tokens, NULL, screen);2582s = c->build.shader;2583ttn_finalize_nir(c, screen);2584ralloc_free(c);25852586if (cache)2587save_nir_to_disk_cache(cache, key, s);25882589return s;2590}25912592struct nir_shader *2593tgsi_to_nir_noscreen(const void *tgsi_tokens,2594const nir_shader_compiler_options *options)2595{2596struct ttn_compile *c;2597struct nir_shader *s;25982599c = ttn_compile_init(tgsi_tokens, options, NULL);2600s = c->build.shader;2601ralloc_free(c);26022603return s;2604}2605260626072608