~mmach/netext73/mesa-haswell

« back to all changes in this revision

Viewing changes to src/mesa/program/prog_parameter_layout.c

  • Committer: mmach
  • Date: 2022-09-22 19:56:13 UTC
  • Revision ID: netbit73@gmail.com-20220922195613-wtik9mmy20tmor0i
2022-09-22 21:17:09

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright © 2009 Intel Corporation
3
 
 *
4
 
 * Permission is hereby granted, free of charge, to any person obtaining a
5
 
 * copy of this software and associated documentation files (the "Software"),
6
 
 * to deal in the Software without restriction, including without limitation
7
 
 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8
 
 * and/or sell copies of the Software, and to permit persons to whom the
9
 
 * Software is furnished to do so, subject to the following conditions:
10
 
 *
11
 
 * The above copyright notice and this permission notice (including the next
12
 
 * paragraph) shall be included in all copies or substantial portions of the
13
 
 * Software.
14
 
 *
15
 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
 
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
 
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18
 
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
 
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
 
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
 
 * DEALINGS IN THE SOFTWARE.
22
 
 */
23
 
 
24
 
/**
25
 
 * \file prog_parameter_layout.c
26
 
 * \brief Helper functions to layout storage for program parameters
27
 
 *
28
 
 * \author Ian Romanick <ian.d.romanick@intel.com>
29
 
 */
30
 
 
31
 
 
32
 
#include "main/shader_types.h"
33
 
#include "prog_parameter.h"
34
 
#include "prog_parameter_layout.h"
35
 
#include "prog_instruction.h"
36
 
#include "program_parser.h"
37
 
 
38
 
unsigned
39
 
_mesa_combine_swizzles(unsigned base, unsigned applied)
40
 
{
41
 
   unsigned swiz = 0;
42
 
   unsigned i;
43
 
 
44
 
   for (i = 0; i < 4; i++) {
45
 
      const unsigned s = GET_SWZ(applied, i);
46
 
 
47
 
      swiz |= ((s <= SWIZZLE_W) ? GET_SWZ(base, s) : s) << (i * 3);
48
 
   }
49
 
 
50
 
   return swiz;
51
 
}
52
 
 
53
 
 
54
 
/**
55
 
 * Copy indirect access array from one parameter list to another
56
 
 *
57
 
 * \param src   Parameter array copied from
58
 
 * \param dst   Parameter array copied to
59
 
 * \param first Index of first element in \c src to copy
60
 
 * \param count Number of elements to copy
61
 
 *
62
 
 * \return
63
 
 * The location in \c dst of the first element copied from \c src on
64
 
 * success.  -1 on failure.
65
 
 *
66
 
 * \warning
67
 
 * This function assumes that there is already enough space available in
68
 
 * \c dst to hold all of the elements that will be copied over.
69
 
 */
70
 
static int
71
 
copy_indirect_accessed_array(struct gl_program_parameter_list *src,
72
 
                             struct gl_program_parameter_list *dst,
73
 
                             unsigned first, unsigned count)
74
 
{
75
 
   const int base = dst->NumParameters;
76
 
   unsigned i, j;
77
 
 
78
 
   for (i = first; i < (first + count); i++) {
79
 
      struct gl_program_parameter *curr = & src->Parameters[i];
80
 
 
81
 
      if (curr->Type == PROGRAM_CONSTANT) {
82
 
         j = dst->NumParameters;
83
 
      } else {
84
 
         for (j = 0; j < dst->NumParameters; j++) {
85
 
            if (memcmp(dst->Parameters[j].StateIndexes, curr->StateIndexes,
86
 
                       sizeof(curr->StateIndexes)) == 0) {
87
 
               return -1;
88
 
            }
89
 
         }
90
 
      }
91
 
 
92
 
      assert(j == dst->NumParameters);
93
 
 
94
 
      /* copy src parameter [i] to dest parameter [j] */
95
 
      memcpy(&dst->Parameters[j], curr,
96
 
             sizeof(dst->Parameters[j]));
97
 
 
98
 
      dst->Parameters[j].ValueOffset = dst->NumParameterValues;
99
 
 
100
 
      gl_constant_value *pv_dst =
101
 
         dst->ParameterValues + dst->Parameters[j].ValueOffset;
102
 
      gl_constant_value *pv_src =
103
 
         src->ParameterValues + src->Parameters[i].ValueOffset;
104
 
 
105
 
      memcpy(pv_dst, pv_src, MIN2(src->Parameters[i].Size, 4) *
106
 
             sizeof(GLfloat));
107
 
      dst->NumParameterValues += MIN2(dst->Parameters[j].Size, 4);
108
 
 
109
 
 
110
 
      /* Pointer to the string name was copied.  Null-out src param name
111
 
       * to prevent double free later.
112
 
       */
113
 
      curr->Name = NULL;
114
 
 
115
 
      dst->NumParameters++;
116
 
   }
117
 
 
118
 
   return base;
119
 
}
120
 
 
121
 
 
122
 
static int compare_state_var(const void *a1, const void *a2)
123
 
{
124
 
   const struct gl_program_parameter *p1 =
125
 
      (const struct gl_program_parameter *)a1;
126
 
   const struct gl_program_parameter *p2 =
127
 
      (const struct gl_program_parameter *)a2;
128
 
 
129
 
   for (unsigned i = 0; i < STATE_LENGTH; i++) {
130
 
      if (p1->StateIndexes[i] != p2->StateIndexes[i])
131
 
         return p1->StateIndexes[i] - p2->StateIndexes[i];
132
 
   }
133
 
   return 0;
134
 
}
135
 
 
136
 
 
137
 
/**
138
 
 * Create the final program parameter list in this order:
139
 
 * - constants and state variables with variable indexing are first
140
 
 * - other constants are next
141
 
 * - other state variables are last and sorted
142
 
 *
143
 
 * \return GL_TRUE for success, GL_FALSE for failure
144
 
 */
145
 
GLboolean
146
 
_mesa_layout_parameters(struct asm_parser_state *state)
147
 
{
148
 
   struct gl_program_parameter_list *layout;
149
 
   struct asm_instruction *inst;
150
 
 
151
 
   layout =
152
 
      _mesa_new_parameter_list_sized(state->prog->Parameters->NumParameters);
153
 
 
154
 
   /* PASS 1:  Move any parameters that are accessed indirectly from the
155
 
    * original parameter list to the new parameter list.
156
 
    */
157
 
   for (inst = state->inst_head; inst != NULL; inst = inst->next) {
158
 
      for (unsigned i = 0; i < 3; i++) {
159
 
         if (inst->SrcReg[i].Base.RelAddr) {
160
 
            /* Only attempt to add the to the new parameter list once.
161
 
             */
162
 
            if (!inst->SrcReg[i].Symbol->pass1_done) {
163
 
               const int new_begin =
164
 
                  copy_indirect_accessed_array(state->prog->Parameters, layout,
165
 
                                               inst->SrcReg[i].Symbol->param_binding_begin,
166
 
                                               inst->SrcReg[i].Symbol->param_binding_length);
167
 
 
168
 
               if (new_begin < 0) {
169
 
                  _mesa_free_parameter_list(layout);
170
 
                  return GL_FALSE;
171
 
               }
172
 
 
173
 
               inst->SrcReg[i].Symbol->param_binding_begin = new_begin;
174
 
               inst->SrcReg[i].Symbol->pass1_done = 1;
175
 
            }
176
 
 
177
 
            /* Previously the Index was just the offset from the parameter
178
 
             * array.  Now that the base of the parameter array is known, the
179
 
             * index can be updated to its actual value.
180
 
             */
181
 
            inst->Base.SrcReg[i] = inst->SrcReg[i].Base;
182
 
            inst->Base.SrcReg[i].Index +=
183
 
               inst->SrcReg[i].Symbol->param_binding_begin;
184
 
         }
185
 
      }
186
 
   }
187
 
 
188
 
   /* PASS 2: Move any constants that are not accessed indirectly from the
189
 
    * original parameter list to the new parameter list.
190
 
    */
191
 
   for (inst = state->inst_head; inst != NULL; inst = inst->next) {
192
 
      for (unsigned i = 0; i < 3; i++) {
193
 
         const int idx = inst->SrcReg[i].Base.Index;
194
 
         const struct gl_program_parameter *const p =
195
 
            &state->prog->Parameters->Parameters[idx];
196
 
         unsigned swizzle = SWIZZLE_NOOP;
197
 
 
198
 
         if (inst->SrcReg[i].Base.RelAddr ||
199
 
             inst->SrcReg[i].Base.File <= PROGRAM_OUTPUT ||
200
 
             inst->SrcReg[i].Base.File >= PROGRAM_WRITE_ONLY ||
201
 
             p->Type != PROGRAM_CONSTANT)
202
 
            continue;
203
 
 
204
 
         inst->Base.SrcReg[i] = inst->SrcReg[i].Base;
205
 
 
206
 
         unsigned pvo = state->prog->Parameters->Parameters[idx].ValueOffset;
207
 
         const gl_constant_value *const v =
208
 
            state->prog->Parameters->ParameterValues + pvo;
209
 
 
210
 
         inst->Base.SrcReg[i].Index =
211
 
            _mesa_add_unnamed_constant(layout, v, p->Size, &swizzle);
212
 
 
213
 
         inst->Base.SrcReg[i].Swizzle =
214
 
            _mesa_combine_swizzles(swizzle, inst->Base.SrcReg[i].Swizzle);
215
 
 
216
 
         inst->SrcReg[i].Base.File = p->Type;
217
 
         inst->Base.SrcReg[i].File = p->Type;
218
 
      }
219
 
   }
220
 
 
221
 
   /* PASS 3: Add sorted state variables.  NOTE: This pass does **not** modify
222
 
    * the instruction with the updated index.  The sorting step might
223
 
    * invalidate the index that was calculated by _mesa_add_state_reference.
224
 
    * Instead, it relies on PASS 4 to do this.
225
 
    */
226
 
   unsigned first_state_var = layout->NumParameters;
227
 
 
228
 
   for (inst = state->inst_head; inst != NULL; inst = inst->next) {
229
 
      for (unsigned i = 0; i < 3; i++) {
230
 
         const struct gl_program_parameter *p;
231
 
         const int idx = inst->SrcReg[i].Base.Index;
232
 
 
233
 
         p = &state->prog->Parameters->Parameters[idx];
234
 
 
235
 
         if (inst->SrcReg[i].Base.RelAddr ||
236
 
             inst->SrcReg[i].Base.File <= PROGRAM_OUTPUT ||
237
 
             inst->SrcReg[i].Base.File >= PROGRAM_WRITE_ONLY ||
238
 
             p->Type != PROGRAM_STATE_VAR)
239
 
            continue;
240
 
 
241
 
         _mesa_add_state_reference(layout, p->StateIndexes);
242
 
      }
243
 
   }
244
 
 
245
 
   /* Sort if we have added at least 2 state vars. */
246
 
   if (first_state_var + 2 <= layout->NumParameters) {
247
 
      /* All state vars should be vec4s. */
248
 
      for (unsigned i = first_state_var; i < layout->NumParameters; i++) {
249
 
         assert(layout->Parameters[i].Size == 4);
250
 
         assert(layout->Parameters[i].ValueOffset == i * 4);
251
 
      }
252
 
 
253
 
      qsort(layout->Parameters + first_state_var,
254
 
            layout->NumParameters - first_state_var,
255
 
            sizeof(layout->Parameters[0]), compare_state_var);
256
 
 
257
 
      /* Fix offsets. */
258
 
      for (unsigned i = first_state_var; i < layout->NumParameters; i++) {
259
 
         layout->Parameters[i].ValueOffset = i * 4;
260
 
      }
261
 
   }
262
 
 
263
 
   /* PASS 4: Fix up the index and file information for instructions whose
264
 
    * parameters were added to the parameter list in PASS 3.
265
 
    */
266
 
   for (inst = state->inst_head; inst != NULL; inst = inst->next) {
267
 
      for (unsigned i = 0; i < 3; i++) {
268
 
         const int idx = inst->SrcReg[i].Base.Index;
269
 
         const struct gl_program_parameter *const p =
270
 
            &state->prog->Parameters->Parameters[idx];
271
 
 
272
 
         if (inst->SrcReg[i].Base.RelAddr ||
273
 
             inst->SrcReg[i].Base.File <= PROGRAM_OUTPUT ||
274
 
             inst->SrcReg[i].Base.File >= PROGRAM_WRITE_ONLY ||
275
 
             p->Type != PROGRAM_STATE_VAR)
276
 
            continue;
277
 
 
278
 
         inst->Base.SrcReg[i] = inst->SrcReg[i].Base;
279
 
 
280
 
         inst->Base.SrcReg[i].Index =
281
 
            _mesa_add_state_reference(layout, p->StateIndexes);
282
 
 
283
 
         inst->SrcReg[i].Base.File = p->Type;
284
 
         inst->Base.SrcReg[i].File = p->Type;
285
 
      }
286
 
   }
287
 
 
288
 
   assert(layout->NumParameters <= state->prog->Parameters->NumParameters);
289
 
   _mesa_recompute_parameter_bounds(layout);
290
 
 
291
 
   layout->StateFlags = state->prog->Parameters->StateFlags;
292
 
   _mesa_free_parameter_list(state->prog->Parameters);
293
 
   state->prog->Parameters = layout;
294
 
 
295
 
   return GL_TRUE;
296
 
}