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