1bf215546Sopenharmony_ci/* 2bf215546Sopenharmony_ci * Copyright 2018 VMware, Inc. 3bf215546Sopenharmony_ci * All Rights Reserved. 4bf215546Sopenharmony_ci * 5bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 6bf215546Sopenharmony_ci * copy of this software and associated documentation files (the 7bf215546Sopenharmony_ci * "Software"), to deal in the Software without restriction, including 8bf215546Sopenharmony_ci * without limitation the rights to use, copy, modify, merge, publish, 9bf215546Sopenharmony_ci * distribute, sub license, and/or sell copies of the Software, and to 10bf215546Sopenharmony_ci * permit persons to whom the Software is furnished to do so, subject to 11bf215546Sopenharmony_ci * the following conditions: 12bf215546Sopenharmony_ci * 13bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the 14bf215546Sopenharmony_ci * next paragraph) shall be included in all copies or substantial portions 15bf215546Sopenharmony_ci * of the Software. 16bf215546Sopenharmony_ci * 17bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18bf215546Sopenharmony_ci * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19bf215546Sopenharmony_ci * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20bf215546Sopenharmony_ci * IN NO EVENT SHALL THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR 21bf215546Sopenharmony_ci * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22bf215546Sopenharmony_ci * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23bf215546Sopenharmony_ci * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24bf215546Sopenharmony_ci */ 25bf215546Sopenharmony_ci 26bf215546Sopenharmony_ci 27bf215546Sopenharmony_ci/** 28bf215546Sopenharmony_ci * This utility transforms the shader to support dynamic array indexing 29bf215546Sopenharmony_ci * for samplers and constant buffers. 30bf215546Sopenharmony_ci * It calculates dynamic array index first and then compare it with each 31bf215546Sopenharmony_ci * index and operation will be performed with matching index 32bf215546Sopenharmony_ci */ 33bf215546Sopenharmony_ci 34bf215546Sopenharmony_ci#include "util/u_debug.h" 35bf215546Sopenharmony_ci#include "util/u_math.h" 36bf215546Sopenharmony_ci#include "tgsi_info.h" 37bf215546Sopenharmony_ci#include "tgsi_dynamic_indexing.h" 38bf215546Sopenharmony_ci#include "tgsi_transform.h" 39bf215546Sopenharmony_ci#include "tgsi_dump.h" 40bf215546Sopenharmony_ci#include "pipe/p_state.h" 41bf215546Sopenharmony_ci 42bf215546Sopenharmony_ci 43bf215546Sopenharmony_cistruct dIndexing_transform_context 44bf215546Sopenharmony_ci{ 45bf215546Sopenharmony_ci struct tgsi_transform_context base; 46bf215546Sopenharmony_ci unsigned orig_num_tmp; 47bf215546Sopenharmony_ci unsigned orig_num_imm; 48bf215546Sopenharmony_ci unsigned num_const_bufs; 49bf215546Sopenharmony_ci unsigned num_samplers; 50bf215546Sopenharmony_ci unsigned num_iterations; 51bf215546Sopenharmony_ci unsigned const_buf_range[PIPE_MAX_CONSTANT_BUFFERS]; 52bf215546Sopenharmony_ci}; 53bf215546Sopenharmony_ci 54bf215546Sopenharmony_ci 55bf215546Sopenharmony_cistatic inline struct dIndexing_transform_context * 56bf215546Sopenharmony_cidIndexing_transform_context(struct tgsi_transform_context *ctx) 57bf215546Sopenharmony_ci{ 58bf215546Sopenharmony_ci return (struct dIndexing_transform_context *) ctx; 59bf215546Sopenharmony_ci} 60bf215546Sopenharmony_ci 61bf215546Sopenharmony_ci 62bf215546Sopenharmony_ci/** 63bf215546Sopenharmony_ci * TGSI declaration transform callback. 64bf215546Sopenharmony_ci */ 65bf215546Sopenharmony_cistatic void 66bf215546Sopenharmony_cidIndexing_decl(struct tgsi_transform_context *ctx, 67bf215546Sopenharmony_ci struct tgsi_full_declaration *decl) 68bf215546Sopenharmony_ci{ 69bf215546Sopenharmony_ci struct dIndexing_transform_context *dc = dIndexing_transform_context(ctx); 70bf215546Sopenharmony_ci 71bf215546Sopenharmony_ci if (decl->Declaration.File == TGSI_FILE_TEMPORARY) { 72bf215546Sopenharmony_ci /** 73bf215546Sopenharmony_ci * Emit some extra temporary register to use in keeping track of 74bf215546Sopenharmony_ci * dynamic index. 75bf215546Sopenharmony_ci */ 76bf215546Sopenharmony_ci dc->orig_num_tmp = decl->Range.Last; 77bf215546Sopenharmony_ci decl->Range.Last = decl->Range.Last + 3; 78bf215546Sopenharmony_ci } 79bf215546Sopenharmony_ci else if (decl->Declaration.File == TGSI_FILE_CONSTANT) { 80bf215546Sopenharmony_ci /* Keep track of number of constants in each buffer */ 81bf215546Sopenharmony_ci dc->const_buf_range[decl->Dim.Index2D] = decl->Range.Last; 82bf215546Sopenharmony_ci } 83bf215546Sopenharmony_ci ctx->emit_declaration(ctx, decl); 84bf215546Sopenharmony_ci} 85bf215546Sopenharmony_ci 86bf215546Sopenharmony_ci 87bf215546Sopenharmony_ci/** 88bf215546Sopenharmony_ci * TGSI transform prolog callback. 89bf215546Sopenharmony_ci */ 90bf215546Sopenharmony_cistatic void 91bf215546Sopenharmony_cidIndexing_prolog(struct tgsi_transform_context *ctx) 92bf215546Sopenharmony_ci{ 93bf215546Sopenharmony_ci tgsi_transform_immediate_int_decl(ctx, 0, 1, 2, 3); 94bf215546Sopenharmony_ci tgsi_transform_immediate_int_decl(ctx, 4, 5, 6, 7); 95bf215546Sopenharmony_ci} 96bf215546Sopenharmony_ci 97bf215546Sopenharmony_ci 98bf215546Sopenharmony_ci/** 99bf215546Sopenharmony_ci * This function emits some extra instruction to remove dynamic array 100bf215546Sopenharmony_ci * indexing of constant buffers / samplers from the shader. 101bf215546Sopenharmony_ci * It calculates dynamic array index first and compare it with each index for 102bf215546Sopenharmony_ci * declared constants/samplers. 103bf215546Sopenharmony_ci */ 104bf215546Sopenharmony_cistatic void 105bf215546Sopenharmony_ciremove_dynamic_indexes(struct tgsi_transform_context *ctx, 106bf215546Sopenharmony_ci struct tgsi_full_instruction *orig_inst, 107bf215546Sopenharmony_ci const struct tgsi_full_src_register *reg) 108bf215546Sopenharmony_ci{ 109bf215546Sopenharmony_ci struct dIndexing_transform_context *dc = dIndexing_transform_context(ctx); 110bf215546Sopenharmony_ci int i, j; 111bf215546Sopenharmony_ci int tmp_loopIdx = dc->orig_num_tmp + 1; 112bf215546Sopenharmony_ci int tmp_cond = dc->orig_num_tmp + 2; 113bf215546Sopenharmony_ci int tmp_arrayIdx = dc->orig_num_tmp + 3; 114bf215546Sopenharmony_ci int imm_index = dc->orig_num_imm; 115bf215546Sopenharmony_ci struct tgsi_full_instruction inst; 116bf215546Sopenharmony_ci unsigned INVALID_INDEX = 99999; 117bf215546Sopenharmony_ci unsigned file = TGSI_FILE_NULL, index = INVALID_INDEX; 118bf215546Sopenharmony_ci unsigned imm_swz_index = INVALID_INDEX; 119bf215546Sopenharmony_ci 120bf215546Sopenharmony_ci /* calculate dynamic array index store it in tmp_arrayIdx.x */ 121bf215546Sopenharmony_ci inst = tgsi_default_full_instruction(); 122bf215546Sopenharmony_ci inst.Instruction.Opcode = TGSI_OPCODE_UADD; 123bf215546Sopenharmony_ci inst.Instruction.NumDstRegs = 1; 124bf215546Sopenharmony_ci tgsi_transform_dst_reg(&inst.Dst[0], TGSI_FILE_TEMPORARY, 125bf215546Sopenharmony_ci tmp_arrayIdx, TGSI_WRITEMASK_X); 126bf215546Sopenharmony_ci inst.Instruction.NumSrcRegs = 2; 127bf215546Sopenharmony_ci if (reg->Register.File == TGSI_FILE_CONSTANT) { 128bf215546Sopenharmony_ci file = reg->DimIndirect.File; 129bf215546Sopenharmony_ci index = reg->DimIndirect.Index; 130bf215546Sopenharmony_ci imm_swz_index = reg->Dimension.Index; 131bf215546Sopenharmony_ci } 132bf215546Sopenharmony_ci else if (reg->Register.File == TGSI_FILE_SAMPLER) { 133bf215546Sopenharmony_ci file = reg->Indirect.File; 134bf215546Sopenharmony_ci index = reg->Indirect.Index; 135bf215546Sopenharmony_ci imm_swz_index = reg->Register.Index; 136bf215546Sopenharmony_ci } 137bf215546Sopenharmony_ci tgsi_transform_src_reg(&inst.Src[0], file, 138bf215546Sopenharmony_ci index, TGSI_SWIZZLE_X, 139bf215546Sopenharmony_ci TGSI_SWIZZLE_X, TGSI_SWIZZLE_X, TGSI_SWIZZLE_X); 140bf215546Sopenharmony_ci tgsi_transform_src_reg(&inst.Src[1], TGSI_FILE_IMMEDIATE, 141bf215546Sopenharmony_ci imm_index + (imm_swz_index / 4), 142bf215546Sopenharmony_ci imm_swz_index % 4, 143bf215546Sopenharmony_ci imm_swz_index % 4, 144bf215546Sopenharmony_ci imm_swz_index % 4, 145bf215546Sopenharmony_ci imm_swz_index % 4); 146bf215546Sopenharmony_ci ctx->emit_instruction(ctx, &inst); 147bf215546Sopenharmony_ci 148bf215546Sopenharmony_ci /* initialize counter to zero: tmp_loopIdx = 0 */ 149bf215546Sopenharmony_ci inst = tgsi_default_full_instruction(); 150bf215546Sopenharmony_ci inst.Instruction.Opcode = TGSI_OPCODE_MOV; 151bf215546Sopenharmony_ci inst.Instruction.NumDstRegs = 1; 152bf215546Sopenharmony_ci tgsi_transform_dst_reg(&inst.Dst[0], TGSI_FILE_TEMPORARY, 153bf215546Sopenharmony_ci tmp_loopIdx, TGSI_WRITEMASK_X); 154bf215546Sopenharmony_ci inst.Instruction.NumSrcRegs = 1; 155bf215546Sopenharmony_ci tgsi_transform_src_reg(&inst.Src[0], TGSI_FILE_IMMEDIATE, 156bf215546Sopenharmony_ci imm_index, TGSI_SWIZZLE_X, 157bf215546Sopenharmony_ci TGSI_SWIZZLE_X, TGSI_SWIZZLE_X, 158bf215546Sopenharmony_ci TGSI_SWIZZLE_X); 159bf215546Sopenharmony_ci ctx->emit_instruction(ctx, &inst); 160bf215546Sopenharmony_ci 161bf215546Sopenharmony_ci for (i = 0; i < dc->num_iterations; i++) { 162bf215546Sopenharmony_ci boolean out_of_bound_index = FALSE; 163bf215546Sopenharmony_ci /** 164bf215546Sopenharmony_ci * Make sure we are not exceeding index limit of constant buffer 165bf215546Sopenharmony_ci * 166bf215546Sopenharmony_ci * For example, In declaration, We have 167bf215546Sopenharmony_ci * 168bf215546Sopenharmony_ci * DCL CONST[0][0..1] 169bf215546Sopenharmony_ci * DCL CONST[1][0..2] 170bf215546Sopenharmony_ci * DCL CONST[2][0] 171bf215546Sopenharmony_ci * 172bf215546Sopenharmony_ci * and our dynamic index instruction is 173bf215546Sopenharmony_ci * MOV TEMP[0], CONST[ADDR[0].x][1] 174bf215546Sopenharmony_ci * 175bf215546Sopenharmony_ci * We have to make sure to skip unrolling for CONST[2] because 176bf215546Sopenharmony_ci * it has only one constant in the buffer 177bf215546Sopenharmony_ci */ 178bf215546Sopenharmony_ci if ((reg->Register.File == TGSI_FILE_CONSTANT) && 179bf215546Sopenharmony_ci (!reg->Register.Indirect && 180bf215546Sopenharmony_ci (reg->Register.Index > dc->const_buf_range[i]))) { 181bf215546Sopenharmony_ci out_of_bound_index = TRUE; 182bf215546Sopenharmony_ci } 183bf215546Sopenharmony_ci 184bf215546Sopenharmony_ci if (!out_of_bound_index) { 185bf215546Sopenharmony_ci /** 186bf215546Sopenharmony_ci * If we have an instruction of the format: 187bf215546Sopenharmony_ci * OPCODE dst, src..., CONST[K][foo], src... 188bf215546Sopenharmony_ci * where K is dynamic and tmp_loopIdx = i (loopcount), 189bf215546Sopenharmony_ci * replace it with: 190bf215546Sopenharmony_ci * 191bf215546Sopenharmony_ci * if (K == tmp_loopIdx) 192bf215546Sopenharmony_ci * OPCODE dst, src... where src is CONST[i][foo] and i is constant 193bf215546Sopenharmony_ci * } 194bf215546Sopenharmony_ci * 195bf215546Sopenharmony_ci * Similarly, If instruction uses dynamic array index for samplers 196bf215546Sopenharmony_ci * e.g. OPCODE dst, src, SAMPL[k] .. 197bf215546Sopenharmony_ci * replace it with: 198bf215546Sopenharmony_ci * if (K == tmp_loopIdx) 199bf215546Sopenharmony_ci * OPCODE dst, src, SAMPL[i][foo]... where i is constant. 200bf215546Sopenharmony_ci * } 201bf215546Sopenharmony_ci */ 202bf215546Sopenharmony_ci inst = tgsi_default_full_instruction(); 203bf215546Sopenharmony_ci inst.Instruction.Opcode = TGSI_OPCODE_USEQ; 204bf215546Sopenharmony_ci inst.Instruction.NumDstRegs = 1; 205bf215546Sopenharmony_ci tgsi_transform_dst_reg(&inst.Dst[0], TGSI_FILE_TEMPORARY, 206bf215546Sopenharmony_ci tmp_cond, TGSI_WRITEMASK_X); 207bf215546Sopenharmony_ci inst.Instruction.NumSrcRegs = 2; 208bf215546Sopenharmony_ci tgsi_transform_src_reg(&inst.Src[0], TGSI_FILE_TEMPORARY, 209bf215546Sopenharmony_ci tmp_arrayIdx, TGSI_SWIZZLE_X, 210bf215546Sopenharmony_ci TGSI_SWIZZLE_X, TGSI_SWIZZLE_X, 211bf215546Sopenharmony_ci TGSI_SWIZZLE_X); 212bf215546Sopenharmony_ci tgsi_transform_src_reg(&inst.Src[1], TGSI_FILE_TEMPORARY, 213bf215546Sopenharmony_ci tmp_loopIdx, TGSI_SWIZZLE_X, 214bf215546Sopenharmony_ci TGSI_SWIZZLE_X, TGSI_SWIZZLE_X, 215bf215546Sopenharmony_ci TGSI_SWIZZLE_X); 216bf215546Sopenharmony_ci ctx->emit_instruction(ctx, &inst); 217bf215546Sopenharmony_ci 218bf215546Sopenharmony_ci inst = tgsi_default_full_instruction(); 219bf215546Sopenharmony_ci inst.Instruction.Opcode = TGSI_OPCODE_UIF; 220bf215546Sopenharmony_ci inst.Instruction.NumDstRegs = 0; 221bf215546Sopenharmony_ci inst.Instruction.NumSrcRegs = 1; 222bf215546Sopenharmony_ci tgsi_transform_src_reg(&inst.Src[0], TGSI_FILE_TEMPORARY, 223bf215546Sopenharmony_ci tmp_cond, TGSI_SWIZZLE_X, 224bf215546Sopenharmony_ci TGSI_SWIZZLE_X, TGSI_SWIZZLE_X, 225bf215546Sopenharmony_ci TGSI_SWIZZLE_X); 226bf215546Sopenharmony_ci ctx->emit_instruction(ctx, &inst); 227bf215546Sopenharmony_ci 228bf215546Sopenharmony_ci /* emit instruction with new, non-dynamic source registers */ 229bf215546Sopenharmony_ci inst = *orig_inst; 230bf215546Sopenharmony_ci for (j = 0; j < inst.Instruction.NumSrcRegs; j++) { 231bf215546Sopenharmony_ci if (inst.Src[j].Dimension.Indirect && 232bf215546Sopenharmony_ci inst.Src[j].Register.File == TGSI_FILE_CONSTANT) { 233bf215546Sopenharmony_ci inst.Src[j].Register.Dimension = 1; 234bf215546Sopenharmony_ci inst.Src[j].Dimension.Index = i; 235bf215546Sopenharmony_ci inst.Src[j].Dimension.Indirect = 0; 236bf215546Sopenharmony_ci } 237bf215546Sopenharmony_ci else if (inst.Src[j].Register.Indirect && 238bf215546Sopenharmony_ci inst.Src[j].Register.File == TGSI_FILE_SAMPLER) { 239bf215546Sopenharmony_ci inst.Src[j].Register.Indirect = 0; 240bf215546Sopenharmony_ci inst.Src[j].Register.Index = i; 241bf215546Sopenharmony_ci } 242bf215546Sopenharmony_ci } 243bf215546Sopenharmony_ci ctx->emit_instruction(ctx, &inst); 244bf215546Sopenharmony_ci 245bf215546Sopenharmony_ci inst = tgsi_default_full_instruction(); 246bf215546Sopenharmony_ci inst.Instruction.Opcode = TGSI_OPCODE_ENDIF; 247bf215546Sopenharmony_ci inst.Instruction.NumDstRegs = 0; 248bf215546Sopenharmony_ci inst.Instruction.NumSrcRegs = 0; 249bf215546Sopenharmony_ci ctx->emit_instruction(ctx, &inst); 250bf215546Sopenharmony_ci } 251bf215546Sopenharmony_ci 252bf215546Sopenharmony_ci /** 253bf215546Sopenharmony_ci * Increment counter 254bf215546Sopenharmony_ci * UADD tmp_loopIdx.x tmp_loopIdx.x imm(1) 255bf215546Sopenharmony_ci */ 256bf215546Sopenharmony_ci inst = tgsi_default_full_instruction(); 257bf215546Sopenharmony_ci inst.Instruction.Opcode = TGSI_OPCODE_UADD; 258bf215546Sopenharmony_ci inst.Instruction.NumDstRegs = 1; 259bf215546Sopenharmony_ci tgsi_transform_dst_reg(&inst.Dst[0], TGSI_FILE_TEMPORARY, 260bf215546Sopenharmony_ci tmp_loopIdx, TGSI_WRITEMASK_X); 261bf215546Sopenharmony_ci inst.Instruction.NumSrcRegs = 2; 262bf215546Sopenharmony_ci tgsi_transform_src_reg(&inst.Src[0], TGSI_FILE_TEMPORARY, 263bf215546Sopenharmony_ci tmp_loopIdx, TGSI_SWIZZLE_X, 264bf215546Sopenharmony_ci TGSI_SWIZZLE_X, TGSI_SWIZZLE_X, TGSI_SWIZZLE_X); 265bf215546Sopenharmony_ci tgsi_transform_src_reg(&inst.Src[1], TGSI_FILE_IMMEDIATE, imm_index, 266bf215546Sopenharmony_ci TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y, 267bf215546Sopenharmony_ci TGSI_SWIZZLE_Y, TGSI_SWIZZLE_Y); 268bf215546Sopenharmony_ci 269bf215546Sopenharmony_ci ctx->emit_instruction(ctx, &inst); 270bf215546Sopenharmony_ci } 271bf215546Sopenharmony_ci} 272bf215546Sopenharmony_ci 273bf215546Sopenharmony_ci 274bf215546Sopenharmony_ci/** 275bf215546Sopenharmony_ci * TGSI instruction transform callback. 276bf215546Sopenharmony_ci */ 277bf215546Sopenharmony_cistatic void 278bf215546Sopenharmony_cidIndexing_inst(struct tgsi_transform_context *ctx, 279bf215546Sopenharmony_ci struct tgsi_full_instruction *inst) 280bf215546Sopenharmony_ci{ 281bf215546Sopenharmony_ci int i; 282bf215546Sopenharmony_ci boolean indexing = FALSE; 283bf215546Sopenharmony_ci struct dIndexing_transform_context *dc = dIndexing_transform_context(ctx); 284bf215546Sopenharmony_ci 285bf215546Sopenharmony_ci for (i = 0; i < inst->Instruction.NumSrcRegs; i++) { 286bf215546Sopenharmony_ci struct tgsi_full_src_register *src; 287bf215546Sopenharmony_ci src = &inst->Src[i]; 288bf215546Sopenharmony_ci /* check if constant buffer/sampler is using dynamic index */ 289bf215546Sopenharmony_ci if ((src->Dimension.Indirect && 290bf215546Sopenharmony_ci src->Register.File == TGSI_FILE_CONSTANT) || 291bf215546Sopenharmony_ci (src->Register.Indirect && 292bf215546Sopenharmony_ci src->Register.File == TGSI_FILE_SAMPLER)) { 293bf215546Sopenharmony_ci 294bf215546Sopenharmony_ci if (indexing) 295bf215546Sopenharmony_ci assert("More than one src has dynamic indexing"); 296bf215546Sopenharmony_ci 297bf215546Sopenharmony_ci if (src->Register.File == TGSI_FILE_CONSTANT) 298bf215546Sopenharmony_ci dc->num_iterations = dc->num_const_bufs; 299bf215546Sopenharmony_ci else 300bf215546Sopenharmony_ci dc->num_iterations = dc->num_samplers; 301bf215546Sopenharmony_ci 302bf215546Sopenharmony_ci remove_dynamic_indexes(ctx, inst, src); 303bf215546Sopenharmony_ci indexing = TRUE; 304bf215546Sopenharmony_ci } 305bf215546Sopenharmony_ci } 306bf215546Sopenharmony_ci 307bf215546Sopenharmony_ci if (!indexing) { 308bf215546Sopenharmony_ci ctx->emit_instruction(ctx, inst); 309bf215546Sopenharmony_ci } 310bf215546Sopenharmony_ci} 311bf215546Sopenharmony_ci 312bf215546Sopenharmony_ci/** 313bf215546Sopenharmony_ci * TGSI utility to remove dynamic array indexing for constant buffers and 314bf215546Sopenharmony_ci * samplers. 315bf215546Sopenharmony_ci * 316bf215546Sopenharmony_ci * This utility accepts bitmask of declared constant buffers and samplers, 317bf215546Sopenharmony_ci * number of immediates used in shader. 318bf215546Sopenharmony_ci * 319bf215546Sopenharmony_ci * If dynamic array index is used for constant buffers and samplers, this 320bf215546Sopenharmony_ci * utility removes those dynamic indexes from shader. It also makes sure 321bf215546Sopenharmony_ci * that it has same output as per original shader. 322bf215546Sopenharmony_ci * This is achieved by calculating dynamic array index first and then compare 323bf215546Sopenharmony_ci * it with each constant buffer/ sampler index and replace that dynamic index 324bf215546Sopenharmony_ci * with static index. 325bf215546Sopenharmony_ci */ 326bf215546Sopenharmony_cistruct tgsi_token * 327bf215546Sopenharmony_citgsi_remove_dynamic_indexing(const struct tgsi_token *tokens_in, 328bf215546Sopenharmony_ci unsigned const_buffers_declared_bitmask, 329bf215546Sopenharmony_ci unsigned samplers_declared_bitmask, 330bf215546Sopenharmony_ci unsigned imm_count) 331bf215546Sopenharmony_ci{ 332bf215546Sopenharmony_ci struct dIndexing_transform_context transform; 333bf215546Sopenharmony_ci const uint num_new_tokens = 1000; /* should be enough */ 334bf215546Sopenharmony_ci const uint new_len = tgsi_num_tokens(tokens_in) + num_new_tokens; 335bf215546Sopenharmony_ci 336bf215546Sopenharmony_ci /* setup transformation context */ 337bf215546Sopenharmony_ci memset(&transform, 0, sizeof(transform)); 338bf215546Sopenharmony_ci transform.base.transform_declaration = dIndexing_decl; 339bf215546Sopenharmony_ci transform.base.transform_instruction = dIndexing_inst; 340bf215546Sopenharmony_ci transform.base.prolog = dIndexing_prolog; 341bf215546Sopenharmony_ci 342bf215546Sopenharmony_ci transform.orig_num_tmp = 0; 343bf215546Sopenharmony_ci transform.orig_num_imm = imm_count; 344bf215546Sopenharmony_ci /* get count of declared const buffers and sampler from their bitmasks*/ 345bf215546Sopenharmony_ci transform.num_const_bufs = log2(const_buffers_declared_bitmask + 1); 346bf215546Sopenharmony_ci transform.num_samplers = log2(samplers_declared_bitmask + 1); 347bf215546Sopenharmony_ci transform.num_iterations = 0; 348bf215546Sopenharmony_ci 349bf215546Sopenharmony_ci return tgsi_transform_shader(tokens_in, new_len, &transform.base); 350bf215546Sopenharmony_ci} 351bf215546Sopenharmony_ci 352bf215546Sopenharmony_ci 353