1bf215546Sopenharmony_ci/************************************************************************** 2bf215546Sopenharmony_ci * 3bf215546Sopenharmony_ci * Copyright 2008 VMware, Inc. 4bf215546Sopenharmony_ci * All Rights Reserved. 5bf215546Sopenharmony_ci * Copyright 2008 VMware, Inc. All rights Reserved. 6bf215546Sopenharmony_ci * 7bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 8bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 9bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 10bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 11bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 12bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 13bf215546Sopenharmony_ci * the following conditions: 14bf215546Sopenharmony_ci * 15bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 16bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 17bf215546Sopenharmony_ci * of the Software. 18bf215546Sopenharmony_ci * 19bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 20bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 21bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 22bf215546Sopenharmony_ci * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 23bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 24bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 25bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 26bf215546Sopenharmony_ci * 27bf215546Sopenharmony_ci **************************************************************************/ 28bf215546Sopenharmony_ci 29bf215546Sopenharmony_ci/** 30bf215546Sopenharmony_ci * TGSI program scan utility. 31bf215546Sopenharmony_ci * Used to determine which registers and instructions are used by a shader. 32bf215546Sopenharmony_ci * 33bf215546Sopenharmony_ci * Authors: Brian Paul 34bf215546Sopenharmony_ci */ 35bf215546Sopenharmony_ci 36bf215546Sopenharmony_ci 37bf215546Sopenharmony_ci#include "util/u_debug.h" 38bf215546Sopenharmony_ci#include "util/u_math.h" 39bf215546Sopenharmony_ci#include "util/u_memory.h" 40bf215546Sopenharmony_ci#include "util/u_prim.h" 41bf215546Sopenharmony_ci#include "tgsi/tgsi_info.h" 42bf215546Sopenharmony_ci#include "tgsi/tgsi_parse.h" 43bf215546Sopenharmony_ci#include "tgsi/tgsi_util.h" 44bf215546Sopenharmony_ci#include "tgsi/tgsi_scan.h" 45bf215546Sopenharmony_ci 46bf215546Sopenharmony_ci 47bf215546Sopenharmony_cistatic bool 48bf215546Sopenharmony_ciis_memory_file(unsigned file) 49bf215546Sopenharmony_ci{ 50bf215546Sopenharmony_ci return file == TGSI_FILE_SAMPLER || 51bf215546Sopenharmony_ci file == TGSI_FILE_SAMPLER_VIEW || 52bf215546Sopenharmony_ci file == TGSI_FILE_IMAGE || 53bf215546Sopenharmony_ci file == TGSI_FILE_BUFFER || 54bf215546Sopenharmony_ci file == TGSI_FILE_HW_ATOMIC; 55bf215546Sopenharmony_ci} 56bf215546Sopenharmony_ci 57bf215546Sopenharmony_ci 58bf215546Sopenharmony_cistatic bool 59bf215546Sopenharmony_ciis_mem_query_inst(enum tgsi_opcode opcode) 60bf215546Sopenharmony_ci{ 61bf215546Sopenharmony_ci return opcode == TGSI_OPCODE_RESQ || 62bf215546Sopenharmony_ci opcode == TGSI_OPCODE_TXQ || 63bf215546Sopenharmony_ci opcode == TGSI_OPCODE_TXQS || 64bf215546Sopenharmony_ci opcode == TGSI_OPCODE_LODQ; 65bf215546Sopenharmony_ci} 66bf215546Sopenharmony_ci 67bf215546Sopenharmony_ci/** 68bf215546Sopenharmony_ci * Is the opcode a "true" texture instruction which samples from a 69bf215546Sopenharmony_ci * texture map? 70bf215546Sopenharmony_ci */ 71bf215546Sopenharmony_cistatic bool 72bf215546Sopenharmony_ciis_texture_inst(enum tgsi_opcode opcode) 73bf215546Sopenharmony_ci{ 74bf215546Sopenharmony_ci return (!is_mem_query_inst(opcode) && 75bf215546Sopenharmony_ci tgsi_get_opcode_info(opcode)->is_tex); 76bf215546Sopenharmony_ci} 77bf215546Sopenharmony_ci 78bf215546Sopenharmony_ci 79bf215546Sopenharmony_ci/** 80bf215546Sopenharmony_ci * Is the opcode an instruction which computes a derivative explicitly or 81bf215546Sopenharmony_ci * implicitly? 82bf215546Sopenharmony_ci */ 83bf215546Sopenharmony_cistatic bool 84bf215546Sopenharmony_cicomputes_derivative(enum tgsi_opcode opcode) 85bf215546Sopenharmony_ci{ 86bf215546Sopenharmony_ci if (tgsi_get_opcode_info(opcode)->is_tex) { 87bf215546Sopenharmony_ci return opcode != TGSI_OPCODE_TG4 && 88bf215546Sopenharmony_ci opcode != TGSI_OPCODE_TXD && 89bf215546Sopenharmony_ci opcode != TGSI_OPCODE_TXF && 90bf215546Sopenharmony_ci opcode != TGSI_OPCODE_TXF_LZ && 91bf215546Sopenharmony_ci opcode != TGSI_OPCODE_TEX_LZ && 92bf215546Sopenharmony_ci opcode != TGSI_OPCODE_TXL && 93bf215546Sopenharmony_ci opcode != TGSI_OPCODE_TXL2 && 94bf215546Sopenharmony_ci opcode != TGSI_OPCODE_TXQ && 95bf215546Sopenharmony_ci opcode != TGSI_OPCODE_TXQS; 96bf215546Sopenharmony_ci } 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci return opcode == TGSI_OPCODE_DDX || opcode == TGSI_OPCODE_DDX_FINE || 99bf215546Sopenharmony_ci opcode == TGSI_OPCODE_DDY || opcode == TGSI_OPCODE_DDY_FINE || 100bf215546Sopenharmony_ci opcode == TGSI_OPCODE_SAMPLE || 101bf215546Sopenharmony_ci opcode == TGSI_OPCODE_SAMPLE_B || 102bf215546Sopenharmony_ci opcode == TGSI_OPCODE_SAMPLE_C; 103bf215546Sopenharmony_ci} 104bf215546Sopenharmony_ci 105bf215546Sopenharmony_ci 106bf215546Sopenharmony_cistatic void 107bf215546Sopenharmony_ciscan_src_operand(struct tgsi_shader_info *info, 108bf215546Sopenharmony_ci const struct tgsi_full_instruction *fullinst, 109bf215546Sopenharmony_ci const struct tgsi_full_src_register *src, 110bf215546Sopenharmony_ci unsigned src_index, 111bf215546Sopenharmony_ci unsigned usage_mask_after_swizzle, 112bf215546Sopenharmony_ci bool is_interp_instruction, 113bf215546Sopenharmony_ci bool *is_mem_inst) 114bf215546Sopenharmony_ci{ 115bf215546Sopenharmony_ci int ind = src->Register.Index; 116bf215546Sopenharmony_ci 117bf215546Sopenharmony_ci if (info->processor == PIPE_SHADER_COMPUTE && 118bf215546Sopenharmony_ci src->Register.File == TGSI_FILE_SYSTEM_VALUE) { 119bf215546Sopenharmony_ci unsigned name, mask; 120bf215546Sopenharmony_ci 121bf215546Sopenharmony_ci name = info->system_value_semantic_name[src->Register.Index]; 122bf215546Sopenharmony_ci 123bf215546Sopenharmony_ci switch (name) { 124bf215546Sopenharmony_ci case TGSI_SEMANTIC_THREAD_ID: 125bf215546Sopenharmony_ci case TGSI_SEMANTIC_BLOCK_ID: 126bf215546Sopenharmony_ci mask = usage_mask_after_swizzle & TGSI_WRITEMASK_XYZ; 127bf215546Sopenharmony_ci while (mask) { 128bf215546Sopenharmony_ci unsigned i = u_bit_scan(&mask); 129bf215546Sopenharmony_ci 130bf215546Sopenharmony_ci if (name == TGSI_SEMANTIC_THREAD_ID) 131bf215546Sopenharmony_ci info->uses_thread_id[i] = true; 132bf215546Sopenharmony_ci else 133bf215546Sopenharmony_ci info->uses_block_id[i] = true; 134bf215546Sopenharmony_ci } 135bf215546Sopenharmony_ci break; 136bf215546Sopenharmony_ci case TGSI_SEMANTIC_BLOCK_SIZE: 137bf215546Sopenharmony_ci /* The block size is translated to IMM with a fixed block size. */ 138bf215546Sopenharmony_ci if (info->properties[TGSI_PROPERTY_CS_FIXED_BLOCK_WIDTH] == 0) 139bf215546Sopenharmony_ci info->uses_block_size = true; 140bf215546Sopenharmony_ci break; 141bf215546Sopenharmony_ci case TGSI_SEMANTIC_GRID_SIZE: 142bf215546Sopenharmony_ci info->uses_grid_size = true; 143bf215546Sopenharmony_ci break; 144bf215546Sopenharmony_ci } 145bf215546Sopenharmony_ci } 146bf215546Sopenharmony_ci 147bf215546Sopenharmony_ci /* Mark which inputs are effectively used */ 148bf215546Sopenharmony_ci if (src->Register.File == TGSI_FILE_INPUT) { 149bf215546Sopenharmony_ci if (src->Register.Indirect) { 150bf215546Sopenharmony_ci for (ind = 0; ind < info->num_inputs; ++ind) { 151bf215546Sopenharmony_ci info->input_usage_mask[ind] |= usage_mask_after_swizzle; 152bf215546Sopenharmony_ci } 153bf215546Sopenharmony_ci } else { 154bf215546Sopenharmony_ci assert(ind >= 0); 155bf215546Sopenharmony_ci assert(ind < PIPE_MAX_SHADER_INPUTS); 156bf215546Sopenharmony_ci info->input_usage_mask[ind] |= usage_mask_after_swizzle; 157bf215546Sopenharmony_ci } 158bf215546Sopenharmony_ci 159bf215546Sopenharmony_ci if (info->processor == PIPE_SHADER_FRAGMENT) { 160bf215546Sopenharmony_ci unsigned name, index, input; 161bf215546Sopenharmony_ci 162bf215546Sopenharmony_ci if (src->Register.Indirect && src->Indirect.ArrayID) 163bf215546Sopenharmony_ci input = info->input_array_first[src->Indirect.ArrayID]; 164bf215546Sopenharmony_ci else 165bf215546Sopenharmony_ci input = src->Register.Index; 166bf215546Sopenharmony_ci 167bf215546Sopenharmony_ci name = info->input_semantic_name[input]; 168bf215546Sopenharmony_ci index = info->input_semantic_index[input]; 169bf215546Sopenharmony_ci 170bf215546Sopenharmony_ci if (name == TGSI_SEMANTIC_POSITION && 171bf215546Sopenharmony_ci usage_mask_after_swizzle & TGSI_WRITEMASK_Z) 172bf215546Sopenharmony_ci info->reads_z = true; 173bf215546Sopenharmony_ci 174bf215546Sopenharmony_ci if (name == TGSI_SEMANTIC_COLOR) 175bf215546Sopenharmony_ci info->colors_read |= usage_mask_after_swizzle << (index * 4); 176bf215546Sopenharmony_ci 177bf215546Sopenharmony_ci /* Process only interpolated varyings. Don't include POSITION. 178bf215546Sopenharmony_ci * Don't include integer varyings, because they are not 179bf215546Sopenharmony_ci * interpolated. Don't process inputs interpolated by INTERP 180bf215546Sopenharmony_ci * opcodes. Those are tracked separately. 181bf215546Sopenharmony_ci */ 182bf215546Sopenharmony_ci if ((!is_interp_instruction || src_index != 0) && 183bf215546Sopenharmony_ci (name == TGSI_SEMANTIC_GENERIC || 184bf215546Sopenharmony_ci name == TGSI_SEMANTIC_TEXCOORD || 185bf215546Sopenharmony_ci name == TGSI_SEMANTIC_COLOR || 186bf215546Sopenharmony_ci name == TGSI_SEMANTIC_BCOLOR || 187bf215546Sopenharmony_ci name == TGSI_SEMANTIC_FOG || 188bf215546Sopenharmony_ci name == TGSI_SEMANTIC_CLIPDIST)) { 189bf215546Sopenharmony_ci switch (info->input_interpolate[input]) { 190bf215546Sopenharmony_ci case TGSI_INTERPOLATE_COLOR: 191bf215546Sopenharmony_ci case TGSI_INTERPOLATE_PERSPECTIVE: 192bf215546Sopenharmony_ci switch (info->input_interpolate_loc[input]) { 193bf215546Sopenharmony_ci case TGSI_INTERPOLATE_LOC_CENTER: 194bf215546Sopenharmony_ci info->uses_persp_center = TRUE; 195bf215546Sopenharmony_ci break; 196bf215546Sopenharmony_ci case TGSI_INTERPOLATE_LOC_CENTROID: 197bf215546Sopenharmony_ci info->uses_persp_centroid = TRUE; 198bf215546Sopenharmony_ci break; 199bf215546Sopenharmony_ci case TGSI_INTERPOLATE_LOC_SAMPLE: 200bf215546Sopenharmony_ci info->uses_persp_sample = TRUE; 201bf215546Sopenharmony_ci break; 202bf215546Sopenharmony_ci } 203bf215546Sopenharmony_ci break; 204bf215546Sopenharmony_ci case TGSI_INTERPOLATE_LINEAR: 205bf215546Sopenharmony_ci switch (info->input_interpolate_loc[input]) { 206bf215546Sopenharmony_ci case TGSI_INTERPOLATE_LOC_CENTER: 207bf215546Sopenharmony_ci info->uses_linear_center = TRUE; 208bf215546Sopenharmony_ci break; 209bf215546Sopenharmony_ci case TGSI_INTERPOLATE_LOC_CENTROID: 210bf215546Sopenharmony_ci info->uses_linear_centroid = TRUE; 211bf215546Sopenharmony_ci break; 212bf215546Sopenharmony_ci case TGSI_INTERPOLATE_LOC_SAMPLE: 213bf215546Sopenharmony_ci info->uses_linear_sample = TRUE; 214bf215546Sopenharmony_ci break; 215bf215546Sopenharmony_ci } 216bf215546Sopenharmony_ci break; 217bf215546Sopenharmony_ci /* TGSI_INTERPOLATE_CONSTANT doesn't do any interpolation. */ 218bf215546Sopenharmony_ci } 219bf215546Sopenharmony_ci } 220bf215546Sopenharmony_ci } 221bf215546Sopenharmony_ci } 222bf215546Sopenharmony_ci 223bf215546Sopenharmony_ci if (info->processor == PIPE_SHADER_TESS_CTRL && 224bf215546Sopenharmony_ci src->Register.File == TGSI_FILE_OUTPUT) { 225bf215546Sopenharmony_ci unsigned input; 226bf215546Sopenharmony_ci 227bf215546Sopenharmony_ci if (src->Register.Indirect && src->Indirect.ArrayID) 228bf215546Sopenharmony_ci input = info->output_array_first[src->Indirect.ArrayID]; 229bf215546Sopenharmony_ci else 230bf215546Sopenharmony_ci input = src->Register.Index; 231bf215546Sopenharmony_ci 232bf215546Sopenharmony_ci switch (info->output_semantic_name[input]) { 233bf215546Sopenharmony_ci case TGSI_SEMANTIC_PATCH: 234bf215546Sopenharmony_ci info->reads_perpatch_outputs = true; 235bf215546Sopenharmony_ci break; 236bf215546Sopenharmony_ci case TGSI_SEMANTIC_TESSINNER: 237bf215546Sopenharmony_ci case TGSI_SEMANTIC_TESSOUTER: 238bf215546Sopenharmony_ci info->reads_tessfactor_outputs = true; 239bf215546Sopenharmony_ci break; 240bf215546Sopenharmony_ci default: 241bf215546Sopenharmony_ci info->reads_pervertex_outputs = true; 242bf215546Sopenharmony_ci } 243bf215546Sopenharmony_ci } 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci /* check for indirect register reads */ 246bf215546Sopenharmony_ci if (src->Register.Indirect) { 247bf215546Sopenharmony_ci info->indirect_files |= (1 << src->Register.File); 248bf215546Sopenharmony_ci info->indirect_files_read |= (1 << src->Register.File); 249bf215546Sopenharmony_ci 250bf215546Sopenharmony_ci /* record indirect constant buffer indexing */ 251bf215546Sopenharmony_ci if (src->Register.File == TGSI_FILE_CONSTANT) { 252bf215546Sopenharmony_ci if (src->Register.Dimension) { 253bf215546Sopenharmony_ci if (src->Dimension.Indirect) 254bf215546Sopenharmony_ci info->const_buffers_indirect = info->const_buffers_declared; 255bf215546Sopenharmony_ci else 256bf215546Sopenharmony_ci info->const_buffers_indirect |= 1u << src->Dimension.Index; 257bf215546Sopenharmony_ci } else { 258bf215546Sopenharmony_ci info->const_buffers_indirect |= 1; 259bf215546Sopenharmony_ci } 260bf215546Sopenharmony_ci } 261bf215546Sopenharmony_ci } 262bf215546Sopenharmony_ci 263bf215546Sopenharmony_ci if (src->Register.Dimension && src->Dimension.Indirect) 264bf215546Sopenharmony_ci info->dim_indirect_files |= 1u << src->Register.File; 265bf215546Sopenharmony_ci 266bf215546Sopenharmony_ci /* Texture samplers */ 267bf215546Sopenharmony_ci if (src->Register.File == TGSI_FILE_SAMPLER) { 268bf215546Sopenharmony_ci const unsigned index = src->Register.Index; 269bf215546Sopenharmony_ci 270bf215546Sopenharmony_ci assert(fullinst->Instruction.Texture); 271bf215546Sopenharmony_ci assert(index < PIPE_MAX_SAMPLERS); 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci if (is_texture_inst(fullinst->Instruction.Opcode)) { 274bf215546Sopenharmony_ci const unsigned target = fullinst->Texture.Texture; 275bf215546Sopenharmony_ci assert(target < TGSI_TEXTURE_UNKNOWN); 276bf215546Sopenharmony_ci /* for texture instructions, check that the texture instruction 277bf215546Sopenharmony_ci * target matches the previous sampler view declaration (if there 278bf215546Sopenharmony_ci * was one.) 279bf215546Sopenharmony_ci */ 280bf215546Sopenharmony_ci if (info->sampler_targets[index] == TGSI_TEXTURE_UNKNOWN) { 281bf215546Sopenharmony_ci /* probably no sampler view declaration */ 282bf215546Sopenharmony_ci info->sampler_targets[index] = target; 283bf215546Sopenharmony_ci } else { 284bf215546Sopenharmony_ci /* Make sure the texture instruction's sampler/target info 285bf215546Sopenharmony_ci * agrees with the sampler view declaration. 286bf215546Sopenharmony_ci */ 287bf215546Sopenharmony_ci assert(info->sampler_targets[index] == target); 288bf215546Sopenharmony_ci } 289bf215546Sopenharmony_ci } 290bf215546Sopenharmony_ci } 291bf215546Sopenharmony_ci 292bf215546Sopenharmony_ci if (is_memory_file(src->Register.File) && 293bf215546Sopenharmony_ci !is_mem_query_inst(fullinst->Instruction.Opcode)) { 294bf215546Sopenharmony_ci *is_mem_inst = true; 295bf215546Sopenharmony_ci 296bf215546Sopenharmony_ci if (src->Register.File == TGSI_FILE_IMAGE && 297bf215546Sopenharmony_ci (fullinst->Memory.Texture == TGSI_TEXTURE_2D_MSAA || 298bf215546Sopenharmony_ci fullinst->Memory.Texture == TGSI_TEXTURE_2D_ARRAY_MSAA)) { 299bf215546Sopenharmony_ci if (src->Register.Indirect) 300bf215546Sopenharmony_ci info->msaa_images_declared = info->images_declared; 301bf215546Sopenharmony_ci else 302bf215546Sopenharmony_ci info->msaa_images_declared |= 1 << src->Register.Index; 303bf215546Sopenharmony_ci } 304bf215546Sopenharmony_ci 305bf215546Sopenharmony_ci if (tgsi_get_opcode_info(fullinst->Instruction.Opcode)->is_store) { 306bf215546Sopenharmony_ci info->writes_memory = TRUE; 307bf215546Sopenharmony_ci 308bf215546Sopenharmony_ci if (src->Register.File == TGSI_FILE_IMAGE) { 309bf215546Sopenharmony_ci if (src->Register.Indirect) 310bf215546Sopenharmony_ci info->images_atomic = info->images_declared; 311bf215546Sopenharmony_ci else 312bf215546Sopenharmony_ci info->images_atomic |= 1 << src->Register.Index; 313bf215546Sopenharmony_ci } else if (src->Register.File == TGSI_FILE_BUFFER) { 314bf215546Sopenharmony_ci if (src->Register.Indirect) 315bf215546Sopenharmony_ci info->shader_buffers_atomic = info->shader_buffers_declared; 316bf215546Sopenharmony_ci else 317bf215546Sopenharmony_ci info->shader_buffers_atomic |= 1 << src->Register.Index; 318bf215546Sopenharmony_ci } 319bf215546Sopenharmony_ci } else { 320bf215546Sopenharmony_ci if (src->Register.File == TGSI_FILE_IMAGE) { 321bf215546Sopenharmony_ci if (src->Register.Indirect) 322bf215546Sopenharmony_ci info->images_load = info->images_declared; 323bf215546Sopenharmony_ci else 324bf215546Sopenharmony_ci info->images_load |= 1 << src->Register.Index; 325bf215546Sopenharmony_ci } else if (src->Register.File == TGSI_FILE_BUFFER) { 326bf215546Sopenharmony_ci if (src->Register.Indirect) 327bf215546Sopenharmony_ci info->shader_buffers_load = info->shader_buffers_declared; 328bf215546Sopenharmony_ci else 329bf215546Sopenharmony_ci info->shader_buffers_load |= 1 << src->Register.Index; 330bf215546Sopenharmony_ci } 331bf215546Sopenharmony_ci } 332bf215546Sopenharmony_ci } 333bf215546Sopenharmony_ci} 334bf215546Sopenharmony_ci 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_cistatic void 337bf215546Sopenharmony_ciscan_instruction(struct tgsi_shader_info *info, 338bf215546Sopenharmony_ci const struct tgsi_full_instruction *fullinst, 339bf215546Sopenharmony_ci unsigned *current_depth) 340bf215546Sopenharmony_ci{ 341bf215546Sopenharmony_ci unsigned i; 342bf215546Sopenharmony_ci bool is_mem_inst = false; 343bf215546Sopenharmony_ci bool is_interp_instruction = false; 344bf215546Sopenharmony_ci unsigned sampler_src; 345bf215546Sopenharmony_ci 346bf215546Sopenharmony_ci assert(fullinst->Instruction.Opcode < TGSI_OPCODE_LAST); 347bf215546Sopenharmony_ci info->opcode_count[fullinst->Instruction.Opcode]++; 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ci switch (fullinst->Instruction.Opcode) { 350bf215546Sopenharmony_ci case TGSI_OPCODE_IF: 351bf215546Sopenharmony_ci case TGSI_OPCODE_UIF: 352bf215546Sopenharmony_ci case TGSI_OPCODE_BGNLOOP: 353bf215546Sopenharmony_ci (*current_depth)++; 354bf215546Sopenharmony_ci info->max_depth = MAX2(info->max_depth, *current_depth); 355bf215546Sopenharmony_ci break; 356bf215546Sopenharmony_ci case TGSI_OPCODE_ENDIF: 357bf215546Sopenharmony_ci case TGSI_OPCODE_ENDLOOP: 358bf215546Sopenharmony_ci (*current_depth)--; 359bf215546Sopenharmony_ci break; 360bf215546Sopenharmony_ci case TGSI_OPCODE_TEX: 361bf215546Sopenharmony_ci case TGSI_OPCODE_TEX_LZ: 362bf215546Sopenharmony_ci case TGSI_OPCODE_TXB: 363bf215546Sopenharmony_ci case TGSI_OPCODE_TXD: 364bf215546Sopenharmony_ci case TGSI_OPCODE_TXL: 365bf215546Sopenharmony_ci case TGSI_OPCODE_TXP: 366bf215546Sopenharmony_ci case TGSI_OPCODE_TXQ: 367bf215546Sopenharmony_ci case TGSI_OPCODE_TXQS: 368bf215546Sopenharmony_ci case TGSI_OPCODE_TXF: 369bf215546Sopenharmony_ci case TGSI_OPCODE_TXF_LZ: 370bf215546Sopenharmony_ci case TGSI_OPCODE_TEX2: 371bf215546Sopenharmony_ci case TGSI_OPCODE_TXB2: 372bf215546Sopenharmony_ci case TGSI_OPCODE_TXL2: 373bf215546Sopenharmony_ci case TGSI_OPCODE_TG4: 374bf215546Sopenharmony_ci case TGSI_OPCODE_LODQ: 375bf215546Sopenharmony_ci sampler_src = fullinst->Instruction.NumSrcRegs - 1; 376bf215546Sopenharmony_ci if (fullinst->Src[sampler_src].Register.File != TGSI_FILE_SAMPLER) 377bf215546Sopenharmony_ci info->uses_bindless_samplers = true; 378bf215546Sopenharmony_ci break; 379bf215546Sopenharmony_ci case TGSI_OPCODE_RESQ: 380bf215546Sopenharmony_ci if (tgsi_is_bindless_image_file(fullinst->Src[0].Register.File)) 381bf215546Sopenharmony_ci info->uses_bindless_images = true; 382bf215546Sopenharmony_ci break; 383bf215546Sopenharmony_ci case TGSI_OPCODE_LOAD: 384bf215546Sopenharmony_ci if (tgsi_is_bindless_image_file(fullinst->Src[0].Register.File)) { 385bf215546Sopenharmony_ci info->uses_bindless_images = true; 386bf215546Sopenharmony_ci 387bf215546Sopenharmony_ci if (fullinst->Memory.Texture == TGSI_TEXTURE_BUFFER) 388bf215546Sopenharmony_ci info->uses_bindless_buffer_load = true; 389bf215546Sopenharmony_ci else 390bf215546Sopenharmony_ci info->uses_bindless_image_load = true; 391bf215546Sopenharmony_ci } 392bf215546Sopenharmony_ci break; 393bf215546Sopenharmony_ci case TGSI_OPCODE_ATOMUADD: 394bf215546Sopenharmony_ci case TGSI_OPCODE_ATOMXCHG: 395bf215546Sopenharmony_ci case TGSI_OPCODE_ATOMCAS: 396bf215546Sopenharmony_ci case TGSI_OPCODE_ATOMAND: 397bf215546Sopenharmony_ci case TGSI_OPCODE_ATOMOR: 398bf215546Sopenharmony_ci case TGSI_OPCODE_ATOMXOR: 399bf215546Sopenharmony_ci case TGSI_OPCODE_ATOMUMIN: 400bf215546Sopenharmony_ci case TGSI_OPCODE_ATOMUMAX: 401bf215546Sopenharmony_ci case TGSI_OPCODE_ATOMIMIN: 402bf215546Sopenharmony_ci case TGSI_OPCODE_ATOMIMAX: 403bf215546Sopenharmony_ci case TGSI_OPCODE_ATOMFADD: 404bf215546Sopenharmony_ci case TGSI_OPCODE_ATOMINC_WRAP: 405bf215546Sopenharmony_ci case TGSI_OPCODE_ATOMDEC_WRAP: 406bf215546Sopenharmony_ci if (tgsi_is_bindless_image_file(fullinst->Src[0].Register.File)) { 407bf215546Sopenharmony_ci info->uses_bindless_images = true; 408bf215546Sopenharmony_ci 409bf215546Sopenharmony_ci if (fullinst->Memory.Texture == TGSI_TEXTURE_BUFFER) 410bf215546Sopenharmony_ci info->uses_bindless_buffer_atomic = true; 411bf215546Sopenharmony_ci else 412bf215546Sopenharmony_ci info->uses_bindless_image_atomic = true; 413bf215546Sopenharmony_ci } 414bf215546Sopenharmony_ci break; 415bf215546Sopenharmony_ci case TGSI_OPCODE_STORE: 416bf215546Sopenharmony_ci if (tgsi_is_bindless_image_file(fullinst->Dst[0].Register.File)) { 417bf215546Sopenharmony_ci info->uses_bindless_images = true; 418bf215546Sopenharmony_ci 419bf215546Sopenharmony_ci if (fullinst->Memory.Texture == TGSI_TEXTURE_BUFFER) 420bf215546Sopenharmony_ci info->uses_bindless_buffer_store = true; 421bf215546Sopenharmony_ci else 422bf215546Sopenharmony_ci info->uses_bindless_image_store = true; 423bf215546Sopenharmony_ci } 424bf215546Sopenharmony_ci break; 425bf215546Sopenharmony_ci case TGSI_OPCODE_FBFETCH: 426bf215546Sopenharmony_ci info->uses_fbfetch = true; 427bf215546Sopenharmony_ci break; 428bf215546Sopenharmony_ci default: 429bf215546Sopenharmony_ci break; 430bf215546Sopenharmony_ci } 431bf215546Sopenharmony_ci 432bf215546Sopenharmony_ci if (fullinst->Instruction.Opcode == TGSI_OPCODE_INTERP_CENTROID || 433bf215546Sopenharmony_ci fullinst->Instruction.Opcode == TGSI_OPCODE_INTERP_OFFSET || 434bf215546Sopenharmony_ci fullinst->Instruction.Opcode == TGSI_OPCODE_INTERP_SAMPLE) { 435bf215546Sopenharmony_ci const struct tgsi_full_src_register *src0 = &fullinst->Src[0]; 436bf215546Sopenharmony_ci unsigned input; 437bf215546Sopenharmony_ci 438bf215546Sopenharmony_ci is_interp_instruction = true; 439bf215546Sopenharmony_ci 440bf215546Sopenharmony_ci if (src0->Register.Indirect && src0->Indirect.ArrayID) 441bf215546Sopenharmony_ci input = info->input_array_first[src0->Indirect.ArrayID]; 442bf215546Sopenharmony_ci else 443bf215546Sopenharmony_ci input = src0->Register.Index; 444bf215546Sopenharmony_ci 445bf215546Sopenharmony_ci /* For the INTERP opcodes, the interpolation is always 446bf215546Sopenharmony_ci * PERSPECTIVE unless LINEAR is specified. 447bf215546Sopenharmony_ci */ 448bf215546Sopenharmony_ci switch (info->input_interpolate[input]) { 449bf215546Sopenharmony_ci case TGSI_INTERPOLATE_COLOR: 450bf215546Sopenharmony_ci case TGSI_INTERPOLATE_CONSTANT: 451bf215546Sopenharmony_ci case TGSI_INTERPOLATE_PERSPECTIVE: 452bf215546Sopenharmony_ci switch (fullinst->Instruction.Opcode) { 453bf215546Sopenharmony_ci case TGSI_OPCODE_INTERP_CENTROID: 454bf215546Sopenharmony_ci info->uses_persp_opcode_interp_centroid = TRUE; 455bf215546Sopenharmony_ci break; 456bf215546Sopenharmony_ci case TGSI_OPCODE_INTERP_OFFSET: 457bf215546Sopenharmony_ci info->uses_persp_opcode_interp_offset = TRUE; 458bf215546Sopenharmony_ci break; 459bf215546Sopenharmony_ci case TGSI_OPCODE_INTERP_SAMPLE: 460bf215546Sopenharmony_ci info->uses_persp_opcode_interp_sample = TRUE; 461bf215546Sopenharmony_ci break; 462bf215546Sopenharmony_ci } 463bf215546Sopenharmony_ci break; 464bf215546Sopenharmony_ci 465bf215546Sopenharmony_ci case TGSI_INTERPOLATE_LINEAR: 466bf215546Sopenharmony_ci switch (fullinst->Instruction.Opcode) { 467bf215546Sopenharmony_ci case TGSI_OPCODE_INTERP_CENTROID: 468bf215546Sopenharmony_ci info->uses_linear_opcode_interp_centroid = TRUE; 469bf215546Sopenharmony_ci break; 470bf215546Sopenharmony_ci case TGSI_OPCODE_INTERP_OFFSET: 471bf215546Sopenharmony_ci info->uses_linear_opcode_interp_offset = TRUE; 472bf215546Sopenharmony_ci break; 473bf215546Sopenharmony_ci case TGSI_OPCODE_INTERP_SAMPLE: 474bf215546Sopenharmony_ci info->uses_linear_opcode_interp_sample = TRUE; 475bf215546Sopenharmony_ci break; 476bf215546Sopenharmony_ci } 477bf215546Sopenharmony_ci break; 478bf215546Sopenharmony_ci } 479bf215546Sopenharmony_ci } 480bf215546Sopenharmony_ci 481bf215546Sopenharmony_ci if ((fullinst->Instruction.Opcode >= TGSI_OPCODE_F2D && 482bf215546Sopenharmony_ci fullinst->Instruction.Opcode <= TGSI_OPCODE_DSSG) || 483bf215546Sopenharmony_ci fullinst->Instruction.Opcode == TGSI_OPCODE_DFMA || 484bf215546Sopenharmony_ci fullinst->Instruction.Opcode == TGSI_OPCODE_DDIV || 485bf215546Sopenharmony_ci fullinst->Instruction.Opcode == TGSI_OPCODE_D2U64 || 486bf215546Sopenharmony_ci fullinst->Instruction.Opcode == TGSI_OPCODE_D2I64 || 487bf215546Sopenharmony_ci fullinst->Instruction.Opcode == TGSI_OPCODE_U642D || 488bf215546Sopenharmony_ci fullinst->Instruction.Opcode == TGSI_OPCODE_I642D) 489bf215546Sopenharmony_ci info->uses_doubles = TRUE; 490bf215546Sopenharmony_ci 491bf215546Sopenharmony_ci for (i = 0; i < fullinst->Instruction.NumSrcRegs; i++) { 492bf215546Sopenharmony_ci scan_src_operand(info, fullinst, &fullinst->Src[i], i, 493bf215546Sopenharmony_ci tgsi_util_get_inst_usage_mask(fullinst, i), 494bf215546Sopenharmony_ci is_interp_instruction, &is_mem_inst); 495bf215546Sopenharmony_ci 496bf215546Sopenharmony_ci if (fullinst->Src[i].Register.Indirect) { 497bf215546Sopenharmony_ci struct tgsi_full_src_register src = {{0}}; 498bf215546Sopenharmony_ci 499bf215546Sopenharmony_ci src.Register.File = fullinst->Src[i].Indirect.File; 500bf215546Sopenharmony_ci src.Register.Index = fullinst->Src[i].Indirect.Index; 501bf215546Sopenharmony_ci 502bf215546Sopenharmony_ci scan_src_operand(info, fullinst, &src, -1, 503bf215546Sopenharmony_ci 1 << fullinst->Src[i].Indirect.Swizzle, 504bf215546Sopenharmony_ci false, NULL); 505bf215546Sopenharmony_ci } 506bf215546Sopenharmony_ci 507bf215546Sopenharmony_ci if (fullinst->Src[i].Register.Dimension && 508bf215546Sopenharmony_ci fullinst->Src[i].Dimension.Indirect) { 509bf215546Sopenharmony_ci struct tgsi_full_src_register src = {{0}}; 510bf215546Sopenharmony_ci 511bf215546Sopenharmony_ci src.Register.File = fullinst->Src[i].DimIndirect.File; 512bf215546Sopenharmony_ci src.Register.Index = fullinst->Src[i].DimIndirect.Index; 513bf215546Sopenharmony_ci 514bf215546Sopenharmony_ci scan_src_operand(info, fullinst, &src, -1, 515bf215546Sopenharmony_ci 1 << fullinst->Src[i].DimIndirect.Swizzle, 516bf215546Sopenharmony_ci false, NULL); 517bf215546Sopenharmony_ci } 518bf215546Sopenharmony_ci } 519bf215546Sopenharmony_ci 520bf215546Sopenharmony_ci if (fullinst->Instruction.Texture) { 521bf215546Sopenharmony_ci for (i = 0; i < fullinst->Texture.NumOffsets; i++) { 522bf215546Sopenharmony_ci struct tgsi_full_src_register src = {{0}}; 523bf215546Sopenharmony_ci 524bf215546Sopenharmony_ci src.Register.File = fullinst->TexOffsets[i].File; 525bf215546Sopenharmony_ci src.Register.Index = fullinst->TexOffsets[i].Index; 526bf215546Sopenharmony_ci 527bf215546Sopenharmony_ci /* The usage mask is suboptimal but should be safe. */ 528bf215546Sopenharmony_ci scan_src_operand(info, fullinst, &src, -1, 529bf215546Sopenharmony_ci (1 << fullinst->TexOffsets[i].SwizzleX) | 530bf215546Sopenharmony_ci (1 << fullinst->TexOffsets[i].SwizzleY) | 531bf215546Sopenharmony_ci (1 << fullinst->TexOffsets[i].SwizzleZ), 532bf215546Sopenharmony_ci false, &is_mem_inst); 533bf215546Sopenharmony_ci } 534bf215546Sopenharmony_ci } 535bf215546Sopenharmony_ci 536bf215546Sopenharmony_ci /* check for indirect register writes */ 537bf215546Sopenharmony_ci for (i = 0; i < fullinst->Instruction.NumDstRegs; i++) { 538bf215546Sopenharmony_ci const struct tgsi_full_dst_register *dst = &fullinst->Dst[i]; 539bf215546Sopenharmony_ci 540bf215546Sopenharmony_ci if (dst->Register.Indirect) { 541bf215546Sopenharmony_ci struct tgsi_full_src_register src = {{0}}; 542bf215546Sopenharmony_ci 543bf215546Sopenharmony_ci src.Register.File = dst->Indirect.File; 544bf215546Sopenharmony_ci src.Register.Index = dst->Indirect.Index; 545bf215546Sopenharmony_ci 546bf215546Sopenharmony_ci scan_src_operand(info, fullinst, &src, -1, 547bf215546Sopenharmony_ci 1 << dst->Indirect.Swizzle, false, NULL); 548bf215546Sopenharmony_ci 549bf215546Sopenharmony_ci info->indirect_files |= (1 << dst->Register.File); 550bf215546Sopenharmony_ci info->indirect_files_written |= (1 << dst->Register.File); 551bf215546Sopenharmony_ci } 552bf215546Sopenharmony_ci 553bf215546Sopenharmony_ci if (dst->Register.Dimension && dst->Dimension.Indirect) { 554bf215546Sopenharmony_ci struct tgsi_full_src_register src = {{0}}; 555bf215546Sopenharmony_ci 556bf215546Sopenharmony_ci src.Register.File = dst->DimIndirect.File; 557bf215546Sopenharmony_ci src.Register.Index = dst->DimIndirect.Index; 558bf215546Sopenharmony_ci 559bf215546Sopenharmony_ci scan_src_operand(info, fullinst, &src, -1, 560bf215546Sopenharmony_ci 1 << dst->DimIndirect.Swizzle, false, NULL); 561bf215546Sopenharmony_ci 562bf215546Sopenharmony_ci info->dim_indirect_files |= 1u << dst->Register.File; 563bf215546Sopenharmony_ci } 564bf215546Sopenharmony_ci 565bf215546Sopenharmony_ci if (is_memory_file(dst->Register.File)) { 566bf215546Sopenharmony_ci assert(fullinst->Instruction.Opcode == TGSI_OPCODE_STORE); 567bf215546Sopenharmony_ci 568bf215546Sopenharmony_ci is_mem_inst = true; 569bf215546Sopenharmony_ci info->writes_memory = TRUE; 570bf215546Sopenharmony_ci 571bf215546Sopenharmony_ci if (dst->Register.File == TGSI_FILE_IMAGE) { 572bf215546Sopenharmony_ci if (fullinst->Memory.Texture == TGSI_TEXTURE_2D_MSAA || 573bf215546Sopenharmony_ci fullinst->Memory.Texture == TGSI_TEXTURE_2D_ARRAY_MSAA) { 574bf215546Sopenharmony_ci if (dst->Register.Indirect) 575bf215546Sopenharmony_ci info->msaa_images_declared = info->images_declared; 576bf215546Sopenharmony_ci else 577bf215546Sopenharmony_ci info->msaa_images_declared |= 1 << dst->Register.Index; 578bf215546Sopenharmony_ci } 579bf215546Sopenharmony_ci 580bf215546Sopenharmony_ci if (dst->Register.Indirect) 581bf215546Sopenharmony_ci info->images_store = info->images_declared; 582bf215546Sopenharmony_ci else 583bf215546Sopenharmony_ci info->images_store |= 1 << dst->Register.Index; 584bf215546Sopenharmony_ci } else if (dst->Register.File == TGSI_FILE_BUFFER) { 585bf215546Sopenharmony_ci if (dst->Register.Indirect) 586bf215546Sopenharmony_ci info->shader_buffers_store = info->shader_buffers_declared; 587bf215546Sopenharmony_ci else 588bf215546Sopenharmony_ci info->shader_buffers_store |= 1 << dst->Register.Index; 589bf215546Sopenharmony_ci } 590bf215546Sopenharmony_ci } 591bf215546Sopenharmony_ci } 592bf215546Sopenharmony_ci 593bf215546Sopenharmony_ci if (is_mem_inst) 594bf215546Sopenharmony_ci info->num_memory_instructions++; 595bf215546Sopenharmony_ci 596bf215546Sopenharmony_ci if (computes_derivative(fullinst->Instruction.Opcode)) 597bf215546Sopenharmony_ci info->uses_derivatives = true; 598bf215546Sopenharmony_ci 599bf215546Sopenharmony_ci info->num_instructions++; 600bf215546Sopenharmony_ci} 601bf215546Sopenharmony_ci 602bf215546Sopenharmony_ci 603bf215546Sopenharmony_cistatic void 604bf215546Sopenharmony_ciscan_declaration(struct tgsi_shader_info *info, 605bf215546Sopenharmony_ci const struct tgsi_full_declaration *fulldecl) 606bf215546Sopenharmony_ci{ 607bf215546Sopenharmony_ci const uint file = fulldecl->Declaration.File; 608bf215546Sopenharmony_ci const unsigned procType = info->processor; 609bf215546Sopenharmony_ci uint reg; 610bf215546Sopenharmony_ci 611bf215546Sopenharmony_ci if (fulldecl->Declaration.Array) { 612bf215546Sopenharmony_ci unsigned array_id = fulldecl->Array.ArrayID; 613bf215546Sopenharmony_ci 614bf215546Sopenharmony_ci switch (file) { 615bf215546Sopenharmony_ci case TGSI_FILE_INPUT: 616bf215546Sopenharmony_ci assert(array_id < ARRAY_SIZE(info->input_array_first)); 617bf215546Sopenharmony_ci info->input_array_first[array_id] = fulldecl->Range.First; 618bf215546Sopenharmony_ci break; 619bf215546Sopenharmony_ci case TGSI_FILE_OUTPUT: 620bf215546Sopenharmony_ci assert(array_id < ARRAY_SIZE(info->output_array_first)); 621bf215546Sopenharmony_ci info->output_array_first[array_id] = fulldecl->Range.First; 622bf215546Sopenharmony_ci break; 623bf215546Sopenharmony_ci } 624bf215546Sopenharmony_ci info->array_max[file] = MAX2(info->array_max[file], array_id); 625bf215546Sopenharmony_ci } 626bf215546Sopenharmony_ci 627bf215546Sopenharmony_ci for (reg = fulldecl->Range.First; reg <= fulldecl->Range.Last; reg++) { 628bf215546Sopenharmony_ci unsigned semName = fulldecl->Semantic.Name; 629bf215546Sopenharmony_ci unsigned semIndex = fulldecl->Semantic.Index + 630bf215546Sopenharmony_ci (reg - fulldecl->Range.First); 631bf215546Sopenharmony_ci int buffer; 632bf215546Sopenharmony_ci unsigned index, target, type; 633bf215546Sopenharmony_ci 634bf215546Sopenharmony_ci /* 635bf215546Sopenharmony_ci * only first 32 regs will appear in this bitfield, if larger 636bf215546Sopenharmony_ci * bits will wrap around. 637bf215546Sopenharmony_ci */ 638bf215546Sopenharmony_ci info->file_mask[file] |= (1u << (reg & 31)); 639bf215546Sopenharmony_ci info->file_count[file]++; 640bf215546Sopenharmony_ci info->file_max[file] = MAX2(info->file_max[file], (int)reg); 641bf215546Sopenharmony_ci 642bf215546Sopenharmony_ci switch (file) { 643bf215546Sopenharmony_ci case TGSI_FILE_CONSTANT: 644bf215546Sopenharmony_ci buffer = 0; 645bf215546Sopenharmony_ci 646bf215546Sopenharmony_ci if (fulldecl->Declaration.Dimension) 647bf215546Sopenharmony_ci buffer = fulldecl->Dim.Index2D; 648bf215546Sopenharmony_ci 649bf215546Sopenharmony_ci info->const_file_max[buffer] = 650bf215546Sopenharmony_ci MAX2(info->const_file_max[buffer], (int)reg); 651bf215546Sopenharmony_ci info->const_buffers_declared |= 1u << buffer; 652bf215546Sopenharmony_ci break; 653bf215546Sopenharmony_ci 654bf215546Sopenharmony_ci case TGSI_FILE_IMAGE: 655bf215546Sopenharmony_ci info->images_declared |= 1u << reg; 656bf215546Sopenharmony_ci if (fulldecl->Image.Resource == TGSI_TEXTURE_BUFFER) 657bf215546Sopenharmony_ci info->images_buffers |= 1 << reg; 658bf215546Sopenharmony_ci break; 659bf215546Sopenharmony_ci 660bf215546Sopenharmony_ci case TGSI_FILE_BUFFER: 661bf215546Sopenharmony_ci info->shader_buffers_declared |= 1u << reg; 662bf215546Sopenharmony_ci break; 663bf215546Sopenharmony_ci 664bf215546Sopenharmony_ci case TGSI_FILE_HW_ATOMIC: 665bf215546Sopenharmony_ci info->hw_atomic_declared |= 1u << reg; 666bf215546Sopenharmony_ci break; 667bf215546Sopenharmony_ci 668bf215546Sopenharmony_ci case TGSI_FILE_INPUT: 669bf215546Sopenharmony_ci info->input_semantic_name[reg] = (ubyte) semName; 670bf215546Sopenharmony_ci info->input_semantic_index[reg] = (ubyte) semIndex; 671bf215546Sopenharmony_ci info->input_interpolate[reg] = (ubyte)fulldecl->Interp.Interpolate; 672bf215546Sopenharmony_ci info->input_interpolate_loc[reg] = (ubyte)fulldecl->Interp.Location; 673bf215546Sopenharmony_ci 674bf215546Sopenharmony_ci /* Vertex shaders can have inputs with holes between them. */ 675bf215546Sopenharmony_ci info->num_inputs = MAX2(info->num_inputs, reg + 1); 676bf215546Sopenharmony_ci 677bf215546Sopenharmony_ci switch (semName) { 678bf215546Sopenharmony_ci case TGSI_SEMANTIC_PRIMID: 679bf215546Sopenharmony_ci info->uses_primid = true; 680bf215546Sopenharmony_ci break; 681bf215546Sopenharmony_ci case TGSI_SEMANTIC_POSITION: 682bf215546Sopenharmony_ci info->reads_position = true; 683bf215546Sopenharmony_ci break; 684bf215546Sopenharmony_ci case TGSI_SEMANTIC_FACE: 685bf215546Sopenharmony_ci info->uses_frontface = true; 686bf215546Sopenharmony_ci break; 687bf215546Sopenharmony_ci } 688bf215546Sopenharmony_ci break; 689bf215546Sopenharmony_ci 690bf215546Sopenharmony_ci case TGSI_FILE_SYSTEM_VALUE: 691bf215546Sopenharmony_ci index = fulldecl->Range.First; 692bf215546Sopenharmony_ci 693bf215546Sopenharmony_ci info->system_value_semantic_name[index] = semName; 694bf215546Sopenharmony_ci info->num_system_values = MAX2(info->num_system_values, index + 1); 695bf215546Sopenharmony_ci 696bf215546Sopenharmony_ci switch (semName) { 697bf215546Sopenharmony_ci case TGSI_SEMANTIC_INSTANCEID: 698bf215546Sopenharmony_ci info->uses_instanceid = TRUE; 699bf215546Sopenharmony_ci break; 700bf215546Sopenharmony_ci case TGSI_SEMANTIC_VERTEXID: 701bf215546Sopenharmony_ci info->uses_vertexid = TRUE; 702bf215546Sopenharmony_ci break; 703bf215546Sopenharmony_ci case TGSI_SEMANTIC_VERTEXID_NOBASE: 704bf215546Sopenharmony_ci info->uses_vertexid_nobase = TRUE; 705bf215546Sopenharmony_ci break; 706bf215546Sopenharmony_ci case TGSI_SEMANTIC_BASEVERTEX: 707bf215546Sopenharmony_ci info->uses_basevertex = TRUE; 708bf215546Sopenharmony_ci break; 709bf215546Sopenharmony_ci case TGSI_SEMANTIC_DRAWID: 710bf215546Sopenharmony_ci info->uses_drawid = TRUE; 711bf215546Sopenharmony_ci break; 712bf215546Sopenharmony_ci case TGSI_SEMANTIC_PRIMID: 713bf215546Sopenharmony_ci info->uses_primid = TRUE; 714bf215546Sopenharmony_ci break; 715bf215546Sopenharmony_ci case TGSI_SEMANTIC_INVOCATIONID: 716bf215546Sopenharmony_ci info->uses_invocationid = TRUE; 717bf215546Sopenharmony_ci break; 718bf215546Sopenharmony_ci case TGSI_SEMANTIC_POSITION: 719bf215546Sopenharmony_ci info->reads_position = TRUE; 720bf215546Sopenharmony_ci break; 721bf215546Sopenharmony_ci case TGSI_SEMANTIC_FACE: 722bf215546Sopenharmony_ci info->uses_frontface = TRUE; 723bf215546Sopenharmony_ci break; 724bf215546Sopenharmony_ci case TGSI_SEMANTIC_SAMPLEMASK: 725bf215546Sopenharmony_ci info->reads_samplemask = TRUE; 726bf215546Sopenharmony_ci break; 727bf215546Sopenharmony_ci case TGSI_SEMANTIC_TESSINNER: 728bf215546Sopenharmony_ci case TGSI_SEMANTIC_TESSOUTER: 729bf215546Sopenharmony_ci info->reads_tess_factors = true; 730bf215546Sopenharmony_ci break; 731bf215546Sopenharmony_ci } 732bf215546Sopenharmony_ci break; 733bf215546Sopenharmony_ci 734bf215546Sopenharmony_ci case TGSI_FILE_OUTPUT: 735bf215546Sopenharmony_ci info->output_semantic_name[reg] = (ubyte) semName; 736bf215546Sopenharmony_ci info->output_semantic_index[reg] = (ubyte) semIndex; 737bf215546Sopenharmony_ci info->output_usagemask[reg] |= fulldecl->Declaration.UsageMask; 738bf215546Sopenharmony_ci info->num_outputs = MAX2(info->num_outputs, reg + 1); 739bf215546Sopenharmony_ci 740bf215546Sopenharmony_ci if (fulldecl->Declaration.UsageMask & TGSI_WRITEMASK_X) { 741bf215546Sopenharmony_ci info->output_streams[reg] |= (ubyte)fulldecl->Semantic.StreamX; 742bf215546Sopenharmony_ci info->num_stream_output_components[fulldecl->Semantic.StreamX]++; 743bf215546Sopenharmony_ci } 744bf215546Sopenharmony_ci if (fulldecl->Declaration.UsageMask & TGSI_WRITEMASK_Y) { 745bf215546Sopenharmony_ci info->output_streams[reg] |= (ubyte)fulldecl->Semantic.StreamY << 2; 746bf215546Sopenharmony_ci info->num_stream_output_components[fulldecl->Semantic.StreamY]++; 747bf215546Sopenharmony_ci } 748bf215546Sopenharmony_ci if (fulldecl->Declaration.UsageMask & TGSI_WRITEMASK_Z) { 749bf215546Sopenharmony_ci info->output_streams[reg] |= (ubyte)fulldecl->Semantic.StreamZ << 4; 750bf215546Sopenharmony_ci info->num_stream_output_components[fulldecl->Semantic.StreamZ]++; 751bf215546Sopenharmony_ci } 752bf215546Sopenharmony_ci if (fulldecl->Declaration.UsageMask & TGSI_WRITEMASK_W) { 753bf215546Sopenharmony_ci info->output_streams[reg] |= (ubyte)fulldecl->Semantic.StreamW << 6; 754bf215546Sopenharmony_ci info->num_stream_output_components[fulldecl->Semantic.StreamW]++; 755bf215546Sopenharmony_ci } 756bf215546Sopenharmony_ci 757bf215546Sopenharmony_ci switch (semName) { 758bf215546Sopenharmony_ci case TGSI_SEMANTIC_PRIMID: 759bf215546Sopenharmony_ci info->writes_primid = true; 760bf215546Sopenharmony_ci break; 761bf215546Sopenharmony_ci case TGSI_SEMANTIC_VIEWPORT_INDEX: 762bf215546Sopenharmony_ci info->writes_viewport_index = true; 763bf215546Sopenharmony_ci break; 764bf215546Sopenharmony_ci case TGSI_SEMANTIC_LAYER: 765bf215546Sopenharmony_ci info->writes_layer = true; 766bf215546Sopenharmony_ci break; 767bf215546Sopenharmony_ci case TGSI_SEMANTIC_PSIZE: 768bf215546Sopenharmony_ci info->writes_psize = true; 769bf215546Sopenharmony_ci break; 770bf215546Sopenharmony_ci case TGSI_SEMANTIC_CLIPVERTEX: 771bf215546Sopenharmony_ci info->writes_clipvertex = true; 772bf215546Sopenharmony_ci break; 773bf215546Sopenharmony_ci case TGSI_SEMANTIC_COLOR: 774bf215546Sopenharmony_ci info->colors_written |= 1 << semIndex; 775bf215546Sopenharmony_ci break; 776bf215546Sopenharmony_ci case TGSI_SEMANTIC_STENCIL: 777bf215546Sopenharmony_ci info->writes_stencil = true; 778bf215546Sopenharmony_ci break; 779bf215546Sopenharmony_ci case TGSI_SEMANTIC_SAMPLEMASK: 780bf215546Sopenharmony_ci info->writes_samplemask = true; 781bf215546Sopenharmony_ci break; 782bf215546Sopenharmony_ci case TGSI_SEMANTIC_EDGEFLAG: 783bf215546Sopenharmony_ci info->writes_edgeflag = true; 784bf215546Sopenharmony_ci break; 785bf215546Sopenharmony_ci case TGSI_SEMANTIC_POSITION: 786bf215546Sopenharmony_ci if (procType == PIPE_SHADER_FRAGMENT) 787bf215546Sopenharmony_ci info->writes_z = true; 788bf215546Sopenharmony_ci else 789bf215546Sopenharmony_ci info->writes_position = true; 790bf215546Sopenharmony_ci break; 791bf215546Sopenharmony_ci } 792bf215546Sopenharmony_ci break; 793bf215546Sopenharmony_ci 794bf215546Sopenharmony_ci case TGSI_FILE_SAMPLER: 795bf215546Sopenharmony_ci STATIC_ASSERT(sizeof(info->samplers_declared) * 8 >= PIPE_MAX_SAMPLERS); 796bf215546Sopenharmony_ci info->samplers_declared |= 1u << reg; 797bf215546Sopenharmony_ci break; 798bf215546Sopenharmony_ci 799bf215546Sopenharmony_ci case TGSI_FILE_SAMPLER_VIEW: 800bf215546Sopenharmony_ci target = fulldecl->SamplerView.Resource; 801bf215546Sopenharmony_ci type = fulldecl->SamplerView.ReturnTypeX; 802bf215546Sopenharmony_ci 803bf215546Sopenharmony_ci assert(target < TGSI_TEXTURE_UNKNOWN); 804bf215546Sopenharmony_ci if (info->sampler_targets[reg] == TGSI_TEXTURE_UNKNOWN) { 805bf215546Sopenharmony_ci /* Save sampler target for this sampler index */ 806bf215546Sopenharmony_ci info->sampler_targets[reg] = target; 807bf215546Sopenharmony_ci info->sampler_type[reg] = type; 808bf215546Sopenharmony_ci } else { 809bf215546Sopenharmony_ci /* if previously declared, make sure targets agree */ 810bf215546Sopenharmony_ci assert(info->sampler_targets[reg] == target); 811bf215546Sopenharmony_ci assert(info->sampler_type[reg] == type); 812bf215546Sopenharmony_ci } 813bf215546Sopenharmony_ci break; 814bf215546Sopenharmony_ci } 815bf215546Sopenharmony_ci } 816bf215546Sopenharmony_ci} 817bf215546Sopenharmony_ci 818bf215546Sopenharmony_ci 819bf215546Sopenharmony_cistatic void 820bf215546Sopenharmony_ciscan_immediate(struct tgsi_shader_info *info) 821bf215546Sopenharmony_ci{ 822bf215546Sopenharmony_ci uint reg = info->immediate_count++; 823bf215546Sopenharmony_ci uint file = TGSI_FILE_IMMEDIATE; 824bf215546Sopenharmony_ci 825bf215546Sopenharmony_ci info->file_mask[file] |= (1 << reg); 826bf215546Sopenharmony_ci info->file_count[file]++; 827bf215546Sopenharmony_ci info->file_max[file] = MAX2(info->file_max[file], (int)reg); 828bf215546Sopenharmony_ci} 829bf215546Sopenharmony_ci 830bf215546Sopenharmony_ci 831bf215546Sopenharmony_cistatic void 832bf215546Sopenharmony_ciscan_property(struct tgsi_shader_info *info, 833bf215546Sopenharmony_ci const struct tgsi_full_property *fullprop) 834bf215546Sopenharmony_ci{ 835bf215546Sopenharmony_ci unsigned name = fullprop->Property.PropertyName; 836bf215546Sopenharmony_ci unsigned value = fullprop->u[0].Data; 837bf215546Sopenharmony_ci 838bf215546Sopenharmony_ci assert(name < ARRAY_SIZE(info->properties)); 839bf215546Sopenharmony_ci info->properties[name] = value; 840bf215546Sopenharmony_ci 841bf215546Sopenharmony_ci switch (name) { 842bf215546Sopenharmony_ci case TGSI_PROPERTY_NUM_CLIPDIST_ENABLED: 843bf215546Sopenharmony_ci info->num_written_clipdistance = value; 844bf215546Sopenharmony_ci info->clipdist_writemask |= (1 << value) - 1; 845bf215546Sopenharmony_ci break; 846bf215546Sopenharmony_ci case TGSI_PROPERTY_NUM_CULLDIST_ENABLED: 847bf215546Sopenharmony_ci info->num_written_culldistance = value; 848bf215546Sopenharmony_ci info->culldist_writemask |= (1 << value) - 1; 849bf215546Sopenharmony_ci break; 850bf215546Sopenharmony_ci } 851bf215546Sopenharmony_ci} 852bf215546Sopenharmony_ci 853bf215546Sopenharmony_ci 854bf215546Sopenharmony_ci/** 855bf215546Sopenharmony_ci * Scan the given TGSI shader to collect information such as number of 856bf215546Sopenharmony_ci * registers used, special instructions used, etc. 857bf215546Sopenharmony_ci * \return info the result of the scan 858bf215546Sopenharmony_ci */ 859bf215546Sopenharmony_civoid 860bf215546Sopenharmony_citgsi_scan_shader(const struct tgsi_token *tokens, 861bf215546Sopenharmony_ci struct tgsi_shader_info *info) 862bf215546Sopenharmony_ci{ 863bf215546Sopenharmony_ci uint procType, i; 864bf215546Sopenharmony_ci struct tgsi_parse_context parse; 865bf215546Sopenharmony_ci unsigned current_depth = 0; 866bf215546Sopenharmony_ci 867bf215546Sopenharmony_ci memset(info, 0, sizeof(*info)); 868bf215546Sopenharmony_ci for (i = 0; i < TGSI_FILE_COUNT; i++) 869bf215546Sopenharmony_ci info->file_max[i] = -1; 870bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(info->const_file_max); i++) 871bf215546Sopenharmony_ci info->const_file_max[i] = -1; 872bf215546Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(info->sampler_targets); i++) 873bf215546Sopenharmony_ci info->sampler_targets[i] = TGSI_TEXTURE_UNKNOWN; 874bf215546Sopenharmony_ci 875bf215546Sopenharmony_ci /** 876bf215546Sopenharmony_ci ** Setup to begin parsing input shader 877bf215546Sopenharmony_ci **/ 878bf215546Sopenharmony_ci if (tgsi_parse_init( &parse, tokens ) != TGSI_PARSE_OK) { 879bf215546Sopenharmony_ci debug_printf("tgsi_parse_init() failed in tgsi_scan_shader()!\n"); 880bf215546Sopenharmony_ci return; 881bf215546Sopenharmony_ci } 882bf215546Sopenharmony_ci procType = parse.FullHeader.Processor.Processor; 883bf215546Sopenharmony_ci assert(procType == PIPE_SHADER_FRAGMENT || 884bf215546Sopenharmony_ci procType == PIPE_SHADER_VERTEX || 885bf215546Sopenharmony_ci procType == PIPE_SHADER_GEOMETRY || 886bf215546Sopenharmony_ci procType == PIPE_SHADER_TESS_CTRL || 887bf215546Sopenharmony_ci procType == PIPE_SHADER_TESS_EVAL || 888bf215546Sopenharmony_ci procType == PIPE_SHADER_COMPUTE); 889bf215546Sopenharmony_ci info->processor = procType; 890bf215546Sopenharmony_ci info->num_tokens = tgsi_num_tokens(parse.Tokens); 891bf215546Sopenharmony_ci 892bf215546Sopenharmony_ci if (procType == PIPE_SHADER_GEOMETRY) 893bf215546Sopenharmony_ci info->properties[TGSI_PROPERTY_GS_INVOCATIONS] = 1; 894bf215546Sopenharmony_ci 895bf215546Sopenharmony_ci /** 896bf215546Sopenharmony_ci ** Loop over incoming program tokens/instructions 897bf215546Sopenharmony_ci */ 898bf215546Sopenharmony_ci while (!tgsi_parse_end_of_tokens(&parse)) { 899bf215546Sopenharmony_ci tgsi_parse_token( &parse ); 900bf215546Sopenharmony_ci 901bf215546Sopenharmony_ci switch( parse.FullToken.Token.Type ) { 902bf215546Sopenharmony_ci case TGSI_TOKEN_TYPE_INSTRUCTION: 903bf215546Sopenharmony_ci scan_instruction(info, &parse.FullToken.FullInstruction, 904bf215546Sopenharmony_ci ¤t_depth); 905bf215546Sopenharmony_ci break; 906bf215546Sopenharmony_ci case TGSI_TOKEN_TYPE_DECLARATION: 907bf215546Sopenharmony_ci scan_declaration(info, &parse.FullToken.FullDeclaration); 908bf215546Sopenharmony_ci break; 909bf215546Sopenharmony_ci case TGSI_TOKEN_TYPE_IMMEDIATE: 910bf215546Sopenharmony_ci scan_immediate(info); 911bf215546Sopenharmony_ci break; 912bf215546Sopenharmony_ci case TGSI_TOKEN_TYPE_PROPERTY: 913bf215546Sopenharmony_ci scan_property(info, &parse.FullToken.FullProperty); 914bf215546Sopenharmony_ci break; 915bf215546Sopenharmony_ci default: 916bf215546Sopenharmony_ci assert(!"Unexpected TGSI token type"); 917bf215546Sopenharmony_ci } 918bf215546Sopenharmony_ci } 919bf215546Sopenharmony_ci 920bf215546Sopenharmony_ci info->uses_kill = (info->opcode_count[TGSI_OPCODE_KILL_IF] || 921bf215546Sopenharmony_ci info->opcode_count[TGSI_OPCODE_KILL]); 922bf215546Sopenharmony_ci 923bf215546Sopenharmony_ci /* The dimensions of the IN decleration in geometry shader have 924bf215546Sopenharmony_ci * to be deduced from the type of the input primitive. 925bf215546Sopenharmony_ci */ 926bf215546Sopenharmony_ci if (procType == PIPE_SHADER_GEOMETRY) { 927bf215546Sopenharmony_ci unsigned input_primitive = 928bf215546Sopenharmony_ci info->properties[TGSI_PROPERTY_GS_INPUT_PRIM]; 929bf215546Sopenharmony_ci int num_verts = u_vertices_per_prim(input_primitive); 930bf215546Sopenharmony_ci int j; 931bf215546Sopenharmony_ci info->file_count[TGSI_FILE_INPUT] = num_verts; 932bf215546Sopenharmony_ci info->file_max[TGSI_FILE_INPUT] = 933bf215546Sopenharmony_ci MAX2(info->file_max[TGSI_FILE_INPUT], num_verts - 1); 934bf215546Sopenharmony_ci for (j = 0; j < num_verts; ++j) { 935bf215546Sopenharmony_ci info->file_mask[TGSI_FILE_INPUT] |= (1 << j); 936bf215546Sopenharmony_ci } 937bf215546Sopenharmony_ci } 938bf215546Sopenharmony_ci 939bf215546Sopenharmony_ci tgsi_parse_free(&parse); 940bf215546Sopenharmony_ci} 941bf215546Sopenharmony_ci 942bf215546Sopenharmony_ci/** 943bf215546Sopenharmony_ci * Collect information about the arrays of a given register file. 944bf215546Sopenharmony_ci * 945bf215546Sopenharmony_ci * @param tokens TGSI shader 946bf215546Sopenharmony_ci * @param file the register file to scan through 947bf215546Sopenharmony_ci * @param max_array_id number of entries in @p arrays; should be equal to the 948bf215546Sopenharmony_ci * highest array id, i.e. tgsi_shader_info::array_max[file]. 949bf215546Sopenharmony_ci * @param arrays info for array of each ID will be written to arrays[ID - 1]. 950bf215546Sopenharmony_ci */ 951bf215546Sopenharmony_civoid 952bf215546Sopenharmony_citgsi_scan_arrays(const struct tgsi_token *tokens, 953bf215546Sopenharmony_ci unsigned file, 954bf215546Sopenharmony_ci unsigned max_array_id, 955bf215546Sopenharmony_ci struct tgsi_array_info *arrays) 956bf215546Sopenharmony_ci{ 957bf215546Sopenharmony_ci struct tgsi_parse_context parse; 958bf215546Sopenharmony_ci 959bf215546Sopenharmony_ci if (tgsi_parse_init(&parse, tokens) != TGSI_PARSE_OK) { 960bf215546Sopenharmony_ci debug_printf("tgsi_parse_init() failed in tgsi_scan_arrays()!\n"); 961bf215546Sopenharmony_ci return; 962bf215546Sopenharmony_ci } 963bf215546Sopenharmony_ci 964bf215546Sopenharmony_ci memset(arrays, 0, sizeof(arrays[0]) * max_array_id); 965bf215546Sopenharmony_ci 966bf215546Sopenharmony_ci while (!tgsi_parse_end_of_tokens(&parse)) { 967bf215546Sopenharmony_ci struct tgsi_full_instruction *inst; 968bf215546Sopenharmony_ci 969bf215546Sopenharmony_ci tgsi_parse_token(&parse); 970bf215546Sopenharmony_ci 971bf215546Sopenharmony_ci if (parse.FullToken.Token.Type == TGSI_TOKEN_TYPE_DECLARATION) { 972bf215546Sopenharmony_ci struct tgsi_full_declaration *decl = &parse.FullToken.FullDeclaration; 973bf215546Sopenharmony_ci 974bf215546Sopenharmony_ci if (decl->Declaration.Array && decl->Declaration.File == file && 975bf215546Sopenharmony_ci decl->Array.ArrayID > 0 && decl->Array.ArrayID <= max_array_id) { 976bf215546Sopenharmony_ci struct tgsi_array_info *array = &arrays[decl->Array.ArrayID - 1]; 977bf215546Sopenharmony_ci assert(!array->declared); 978bf215546Sopenharmony_ci array->declared = true; 979bf215546Sopenharmony_ci array->range = decl->Range; 980bf215546Sopenharmony_ci } 981bf215546Sopenharmony_ci } 982bf215546Sopenharmony_ci 983bf215546Sopenharmony_ci if (parse.FullToken.Token.Type != TGSI_TOKEN_TYPE_INSTRUCTION) 984bf215546Sopenharmony_ci continue; 985bf215546Sopenharmony_ci 986bf215546Sopenharmony_ci inst = &parse.FullToken.FullInstruction; 987bf215546Sopenharmony_ci for (unsigned i = 0; i < inst->Instruction.NumDstRegs; i++) { 988bf215546Sopenharmony_ci const struct tgsi_full_dst_register *dst = &inst->Dst[i]; 989bf215546Sopenharmony_ci if (dst->Register.File != file) 990bf215546Sopenharmony_ci continue; 991bf215546Sopenharmony_ci 992bf215546Sopenharmony_ci if (dst->Register.Indirect) { 993bf215546Sopenharmony_ci if (dst->Indirect.ArrayID > 0 && 994bf215546Sopenharmony_ci dst->Indirect.ArrayID <= max_array_id) { 995bf215546Sopenharmony_ci arrays[dst->Indirect.ArrayID - 1].writemask |= dst->Register.WriteMask; 996bf215546Sopenharmony_ci } else { 997bf215546Sopenharmony_ci /* Indirect writes without an ArrayID can write anywhere. */ 998bf215546Sopenharmony_ci for (unsigned j = 0; j < max_array_id; ++j) 999bf215546Sopenharmony_ci arrays[j].writemask |= dst->Register.WriteMask; 1000bf215546Sopenharmony_ci } 1001bf215546Sopenharmony_ci } else { 1002bf215546Sopenharmony_ci /* Check whether the write falls into any of the arrays anyway. */ 1003bf215546Sopenharmony_ci for (unsigned j = 0; j < max_array_id; ++j) { 1004bf215546Sopenharmony_ci struct tgsi_array_info *array = &arrays[j]; 1005bf215546Sopenharmony_ci if (array->declared && 1006bf215546Sopenharmony_ci dst->Register.Index >= array->range.First && 1007bf215546Sopenharmony_ci dst->Register.Index <= array->range.Last) 1008bf215546Sopenharmony_ci array->writemask |= dst->Register.WriteMask; 1009bf215546Sopenharmony_ci } 1010bf215546Sopenharmony_ci } 1011bf215546Sopenharmony_ci } 1012bf215546Sopenharmony_ci } 1013bf215546Sopenharmony_ci 1014bf215546Sopenharmony_ci tgsi_parse_free(&parse); 1015bf215546Sopenharmony_ci 1016bf215546Sopenharmony_ci return; 1017bf215546Sopenharmony_ci} 1018bf215546Sopenharmony_ci 1019bf215546Sopenharmony_cistatic void 1020bf215546Sopenharmony_cicheck_no_subroutines(const struct tgsi_full_instruction *inst) 1021bf215546Sopenharmony_ci{ 1022bf215546Sopenharmony_ci switch (inst->Instruction.Opcode) { 1023bf215546Sopenharmony_ci case TGSI_OPCODE_BGNSUB: 1024bf215546Sopenharmony_ci case TGSI_OPCODE_ENDSUB: 1025bf215546Sopenharmony_ci case TGSI_OPCODE_CAL: 1026bf215546Sopenharmony_ci unreachable("subroutines unhandled"); 1027bf215546Sopenharmony_ci } 1028bf215546Sopenharmony_ci} 1029bf215546Sopenharmony_ci 1030bf215546Sopenharmony_cistatic unsigned 1031bf215546Sopenharmony_ciget_inst_tessfactor_writemask(const struct tgsi_shader_info *info, 1032bf215546Sopenharmony_ci const struct tgsi_full_instruction *inst) 1033bf215546Sopenharmony_ci{ 1034bf215546Sopenharmony_ci unsigned writemask = 0; 1035bf215546Sopenharmony_ci 1036bf215546Sopenharmony_ci for (unsigned i = 0; i < inst->Instruction.NumDstRegs; i++) { 1037bf215546Sopenharmony_ci const struct tgsi_full_dst_register *dst = &inst->Dst[i]; 1038bf215546Sopenharmony_ci 1039bf215546Sopenharmony_ci if (dst->Register.File == TGSI_FILE_OUTPUT && 1040bf215546Sopenharmony_ci !dst->Register.Indirect) { 1041bf215546Sopenharmony_ci unsigned name = info->output_semantic_name[dst->Register.Index]; 1042bf215546Sopenharmony_ci 1043bf215546Sopenharmony_ci if (name == TGSI_SEMANTIC_TESSINNER) 1044bf215546Sopenharmony_ci writemask |= dst->Register.WriteMask; 1045bf215546Sopenharmony_ci else if (name == TGSI_SEMANTIC_TESSOUTER) 1046bf215546Sopenharmony_ci writemask |= dst->Register.WriteMask << 4; 1047bf215546Sopenharmony_ci } 1048bf215546Sopenharmony_ci } 1049bf215546Sopenharmony_ci return writemask; 1050bf215546Sopenharmony_ci} 1051bf215546Sopenharmony_ci 1052bf215546Sopenharmony_cistatic unsigned 1053bf215546Sopenharmony_ciget_block_tessfactor_writemask(const struct tgsi_shader_info *info, 1054bf215546Sopenharmony_ci struct tgsi_parse_context *parse, 1055bf215546Sopenharmony_ci unsigned end_opcode) 1056bf215546Sopenharmony_ci{ 1057bf215546Sopenharmony_ci struct tgsi_full_instruction *inst; 1058bf215546Sopenharmony_ci unsigned writemask = 0; 1059bf215546Sopenharmony_ci 1060bf215546Sopenharmony_ci tgsi_parse_token(parse); 1061bf215546Sopenharmony_ci assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION); 1062bf215546Sopenharmony_ci inst = &parse->FullToken.FullInstruction; 1063bf215546Sopenharmony_ci check_no_subroutines(inst); 1064bf215546Sopenharmony_ci 1065bf215546Sopenharmony_ci while (inst->Instruction.Opcode != end_opcode) { 1066bf215546Sopenharmony_ci 1067bf215546Sopenharmony_ci /* Recursively process nested blocks. */ 1068bf215546Sopenharmony_ci switch (inst->Instruction.Opcode) { 1069bf215546Sopenharmony_ci case TGSI_OPCODE_IF: 1070bf215546Sopenharmony_ci case TGSI_OPCODE_UIF: 1071bf215546Sopenharmony_ci writemask |= 1072bf215546Sopenharmony_ci get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDIF); 1073bf215546Sopenharmony_ci break; 1074bf215546Sopenharmony_ci 1075bf215546Sopenharmony_ci case TGSI_OPCODE_BGNLOOP: 1076bf215546Sopenharmony_ci writemask |= 1077bf215546Sopenharmony_ci get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDLOOP); 1078bf215546Sopenharmony_ci break; 1079bf215546Sopenharmony_ci 1080bf215546Sopenharmony_ci case TGSI_OPCODE_BARRIER: 1081bf215546Sopenharmony_ci unreachable("nested BARRIER is illegal"); 1082bf215546Sopenharmony_ci break; 1083bf215546Sopenharmony_ci 1084bf215546Sopenharmony_ci default: 1085bf215546Sopenharmony_ci writemask |= get_inst_tessfactor_writemask(info, inst); 1086bf215546Sopenharmony_ci } 1087bf215546Sopenharmony_ci 1088bf215546Sopenharmony_ci tgsi_parse_token(parse); 1089bf215546Sopenharmony_ci assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION); 1090bf215546Sopenharmony_ci inst = &parse->FullToken.FullInstruction; 1091bf215546Sopenharmony_ci check_no_subroutines(inst); 1092bf215546Sopenharmony_ci } 1093bf215546Sopenharmony_ci 1094bf215546Sopenharmony_ci return writemask; 1095bf215546Sopenharmony_ci} 1096bf215546Sopenharmony_ci 1097bf215546Sopenharmony_cistatic void 1098bf215546Sopenharmony_ciget_if_block_tessfactor_writemask(const struct tgsi_shader_info *info, 1099bf215546Sopenharmony_ci struct tgsi_parse_context *parse, 1100bf215546Sopenharmony_ci unsigned *upper_block_tf_writemask, 1101bf215546Sopenharmony_ci unsigned *cond_block_tf_writemask) 1102bf215546Sopenharmony_ci{ 1103bf215546Sopenharmony_ci struct tgsi_full_instruction *inst; 1104bf215546Sopenharmony_ci unsigned then_tessfactor_writemask = 0; 1105bf215546Sopenharmony_ci unsigned else_tessfactor_writemask = 0; 1106bf215546Sopenharmony_ci unsigned writemask; 1107bf215546Sopenharmony_ci bool is_then = true; 1108bf215546Sopenharmony_ci 1109bf215546Sopenharmony_ci tgsi_parse_token(parse); 1110bf215546Sopenharmony_ci assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION); 1111bf215546Sopenharmony_ci inst = &parse->FullToken.FullInstruction; 1112bf215546Sopenharmony_ci check_no_subroutines(inst); 1113bf215546Sopenharmony_ci 1114bf215546Sopenharmony_ci while (inst->Instruction.Opcode != TGSI_OPCODE_ENDIF) { 1115bf215546Sopenharmony_ci 1116bf215546Sopenharmony_ci switch (inst->Instruction.Opcode) { 1117bf215546Sopenharmony_ci case TGSI_OPCODE_ELSE: 1118bf215546Sopenharmony_ci is_then = false; 1119bf215546Sopenharmony_ci break; 1120bf215546Sopenharmony_ci 1121bf215546Sopenharmony_ci /* Recursively process nested blocks. */ 1122bf215546Sopenharmony_ci case TGSI_OPCODE_IF: 1123bf215546Sopenharmony_ci case TGSI_OPCODE_UIF: 1124bf215546Sopenharmony_ci get_if_block_tessfactor_writemask(info, parse, 1125bf215546Sopenharmony_ci is_then ? &then_tessfactor_writemask : 1126bf215546Sopenharmony_ci &else_tessfactor_writemask, 1127bf215546Sopenharmony_ci cond_block_tf_writemask); 1128bf215546Sopenharmony_ci break; 1129bf215546Sopenharmony_ci 1130bf215546Sopenharmony_ci case TGSI_OPCODE_BGNLOOP: 1131bf215546Sopenharmony_ci *cond_block_tf_writemask |= 1132bf215546Sopenharmony_ci get_block_tessfactor_writemask(info, parse, TGSI_OPCODE_ENDLOOP); 1133bf215546Sopenharmony_ci break; 1134bf215546Sopenharmony_ci 1135bf215546Sopenharmony_ci case TGSI_OPCODE_BARRIER: 1136bf215546Sopenharmony_ci unreachable("nested BARRIER is illegal"); 1137bf215546Sopenharmony_ci break; 1138bf215546Sopenharmony_ci default: 1139bf215546Sopenharmony_ci /* Process an instruction in the current block. */ 1140bf215546Sopenharmony_ci writemask = get_inst_tessfactor_writemask(info, inst); 1141bf215546Sopenharmony_ci 1142bf215546Sopenharmony_ci if (writemask) { 1143bf215546Sopenharmony_ci if (is_then) 1144bf215546Sopenharmony_ci then_tessfactor_writemask |= writemask; 1145bf215546Sopenharmony_ci else 1146bf215546Sopenharmony_ci else_tessfactor_writemask |= writemask; 1147bf215546Sopenharmony_ci } 1148bf215546Sopenharmony_ci } 1149bf215546Sopenharmony_ci 1150bf215546Sopenharmony_ci tgsi_parse_token(parse); 1151bf215546Sopenharmony_ci assert(parse->FullToken.Token.Type == TGSI_TOKEN_TYPE_INSTRUCTION); 1152bf215546Sopenharmony_ci inst = &parse->FullToken.FullInstruction; 1153bf215546Sopenharmony_ci check_no_subroutines(inst); 1154bf215546Sopenharmony_ci } 1155bf215546Sopenharmony_ci 1156bf215546Sopenharmony_ci if (then_tessfactor_writemask || else_tessfactor_writemask) { 1157bf215546Sopenharmony_ci /* If both statements write the same tess factor channels, 1158bf215546Sopenharmony_ci * we can say that the upper block writes them too. */ 1159bf215546Sopenharmony_ci *upper_block_tf_writemask |= then_tessfactor_writemask & 1160bf215546Sopenharmony_ci else_tessfactor_writemask; 1161bf215546Sopenharmony_ci *cond_block_tf_writemask |= then_tessfactor_writemask | 1162bf215546Sopenharmony_ci else_tessfactor_writemask; 1163bf215546Sopenharmony_ci } 1164bf215546Sopenharmony_ci} 1165bf215546Sopenharmony_ci 1166bf215546Sopenharmony_civoid 1167bf215546Sopenharmony_citgsi_scan_tess_ctrl(const struct tgsi_token *tokens, 1168bf215546Sopenharmony_ci const struct tgsi_shader_info *info, 1169bf215546Sopenharmony_ci struct tgsi_tessctrl_info *out) 1170bf215546Sopenharmony_ci{ 1171bf215546Sopenharmony_ci memset(out, 0, sizeof(*out)); 1172bf215546Sopenharmony_ci 1173bf215546Sopenharmony_ci if (info->processor != PIPE_SHADER_TESS_CTRL) 1174bf215546Sopenharmony_ci return; 1175bf215546Sopenharmony_ci 1176bf215546Sopenharmony_ci struct tgsi_parse_context parse; 1177bf215546Sopenharmony_ci if (tgsi_parse_init(&parse, tokens) != TGSI_PARSE_OK) { 1178bf215546Sopenharmony_ci debug_printf("tgsi_parse_init() failed in tgsi_scan_arrays()!\n"); 1179bf215546Sopenharmony_ci return; 1180bf215546Sopenharmony_ci } 1181bf215546Sopenharmony_ci 1182bf215546Sopenharmony_ci /* The pass works as follows: 1183bf215546Sopenharmony_ci * If all codepaths write tess factors, we can say that all invocations 1184bf215546Sopenharmony_ci * define tess factors. 1185bf215546Sopenharmony_ci * 1186bf215546Sopenharmony_ci * Each tess factor channel is tracked separately. 1187bf215546Sopenharmony_ci */ 1188bf215546Sopenharmony_ci unsigned main_block_tf_writemask = 0; /* if main block writes tess factors */ 1189bf215546Sopenharmony_ci unsigned cond_block_tf_writemask = 0; /* if cond block writes tess factors */ 1190bf215546Sopenharmony_ci 1191bf215546Sopenharmony_ci /* Initial value = true. Here the pass will accumulate results from multiple 1192bf215546Sopenharmony_ci * segments surrounded by barriers. If tess factors aren't written at all, 1193bf215546Sopenharmony_ci * it's a shader bug and we don't care if this will be true. 1194bf215546Sopenharmony_ci */ 1195bf215546Sopenharmony_ci out->tessfactors_are_def_in_all_invocs = true; 1196bf215546Sopenharmony_ci 1197bf215546Sopenharmony_ci while (!tgsi_parse_end_of_tokens(&parse)) { 1198bf215546Sopenharmony_ci tgsi_parse_token(&parse); 1199bf215546Sopenharmony_ci 1200bf215546Sopenharmony_ci if (parse.FullToken.Token.Type != TGSI_TOKEN_TYPE_INSTRUCTION) 1201bf215546Sopenharmony_ci continue; 1202bf215546Sopenharmony_ci 1203bf215546Sopenharmony_ci struct tgsi_full_instruction *inst = &parse.FullToken.FullInstruction; 1204bf215546Sopenharmony_ci check_no_subroutines(inst); 1205bf215546Sopenharmony_ci 1206bf215546Sopenharmony_ci /* Process nested blocks. */ 1207bf215546Sopenharmony_ci switch (inst->Instruction.Opcode) { 1208bf215546Sopenharmony_ci case TGSI_OPCODE_IF: 1209bf215546Sopenharmony_ci case TGSI_OPCODE_UIF: 1210bf215546Sopenharmony_ci get_if_block_tessfactor_writemask(info, &parse, 1211bf215546Sopenharmony_ci &main_block_tf_writemask, 1212bf215546Sopenharmony_ci &cond_block_tf_writemask); 1213bf215546Sopenharmony_ci continue; 1214bf215546Sopenharmony_ci 1215bf215546Sopenharmony_ci case TGSI_OPCODE_BGNLOOP: 1216bf215546Sopenharmony_ci cond_block_tf_writemask |= 1217bf215546Sopenharmony_ci get_block_tessfactor_writemask(info, &parse, TGSI_OPCODE_ENDLOOP); 1218bf215546Sopenharmony_ci continue; 1219bf215546Sopenharmony_ci 1220bf215546Sopenharmony_ci case TGSI_OPCODE_BARRIER: 1221bf215546Sopenharmony_ci /* The following case must be prevented: 1222bf215546Sopenharmony_ci * gl_TessLevelInner = ...; 1223bf215546Sopenharmony_ci * barrier(); 1224bf215546Sopenharmony_ci * if (gl_InvocationID == 1) 1225bf215546Sopenharmony_ci * gl_TessLevelInner = ...; 1226bf215546Sopenharmony_ci * 1227bf215546Sopenharmony_ci * If you consider disjoint code segments separated by barriers, each 1228bf215546Sopenharmony_ci * such segment that writes tess factor channels should write the same 1229bf215546Sopenharmony_ci * channels in all codepaths within that segment. 1230bf215546Sopenharmony_ci */ 1231bf215546Sopenharmony_ci if (main_block_tf_writemask || cond_block_tf_writemask) { 1232bf215546Sopenharmony_ci /* Accumulate the result: */ 1233bf215546Sopenharmony_ci out->tessfactors_are_def_in_all_invocs &= 1234bf215546Sopenharmony_ci !(cond_block_tf_writemask & ~main_block_tf_writemask); 1235bf215546Sopenharmony_ci 1236bf215546Sopenharmony_ci /* Analyze the next code segment from scratch. */ 1237bf215546Sopenharmony_ci main_block_tf_writemask = 0; 1238bf215546Sopenharmony_ci cond_block_tf_writemask = 0; 1239bf215546Sopenharmony_ci } 1240bf215546Sopenharmony_ci continue; 1241bf215546Sopenharmony_ci } 1242bf215546Sopenharmony_ci 1243bf215546Sopenharmony_ci main_block_tf_writemask |= get_inst_tessfactor_writemask(info, inst); 1244bf215546Sopenharmony_ci } 1245bf215546Sopenharmony_ci 1246bf215546Sopenharmony_ci /* Accumulate the result for the last code segment separated by a barrier. */ 1247bf215546Sopenharmony_ci if (main_block_tf_writemask || cond_block_tf_writemask) { 1248bf215546Sopenharmony_ci out->tessfactors_are_def_in_all_invocs &= 1249bf215546Sopenharmony_ci !(cond_block_tf_writemask & ~main_block_tf_writemask); 1250bf215546Sopenharmony_ci } 1251bf215546Sopenharmony_ci 1252bf215546Sopenharmony_ci tgsi_parse_free(&parse); 1253bf215546Sopenharmony_ci} 1254