2 * Copyright © 2009 Intel Corporation
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:
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
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.
25 * \file prog_parameter_layout.c
26 * \brief Helper functions to layout storage for program parameters
28 * \author Ian Romanick <ian.d.romanick@intel.com>
31 #include "main/mtypes.h"
32 #include "prog_parameter.h"
33 #include "prog_parameter_layout.h"
34 #include "prog_instruction.h"
35 #include "program_parser.h"
38 _mesa_combine_swizzles(unsigned base
, unsigned applied
)
43 for (i
= 0; i
< 4; i
++) {
44 const unsigned s
= GET_SWZ(applied
, i
);
46 swiz
|= ((s
<= SWIZZLE_W
) ? GET_SWZ(base
, s
) : s
) << (i
* 3);
54 * Copy indirect access array from one parameter list to another
56 * \param src Parameter array copied from
57 * \param dst Parameter array copied to
58 * \param first Index of first element in \c src to copy
59 * \param count Number of elements to copy
62 * The location in \c dst of the first element copied from \c src on
63 * success. -1 on failure.
66 * This function assumes that there is already enough space available in
67 * \c dst to hold all of the elements that will be copied over.
70 copy_indirect_accessed_array(struct gl_program_parameter_list
*src
,
71 struct gl_program_parameter_list
*dst
,
72 unsigned first
, unsigned count
)
74 const int base
= dst
->NumParameters
;
79 for (i
= first
; i
< (first
+ count
); i
++) {
80 struct gl_program_parameter
*curr
= & src
->Parameters
[i
];
83 if (curr
->Type
== PROGRAM_CONSTANT
) {
84 j
= dst
->NumParameters
;
86 for (j
= 0; j
< dst
->NumParameters
; j
++) {
87 if (memcmp(dst
->Parameters
[j
].StateIndexes
, curr
->StateIndexes
,
88 sizeof(curr
->StateIndexes
)) == 0) {
94 assert(j
== dst
->NumParameters
);
96 memcpy(& dst
->Parameters
[j
], curr
,
97 sizeof(dst
->Parameters
[j
]));
98 memcpy(dst
->ParameterValues
[j
], src
->ParameterValues
[i
],
102 dst
->NumParameters
++;
110 _mesa_layout_parameters(struct asm_parser_state
*state
)
112 struct gl_program_parameter_list
*layout
;
113 struct asm_instruction
*inst
;
118 _mesa_new_parameter_list_sized(state
->prog
->Parameters
->NumParameters
);
121 /* PASS 1: Move any parameters that are accessed indirectly from the
122 * original parameter list to the new parameter list.
124 for (inst
= state
->inst_head
; inst
!= NULL
; inst
= inst
->next
) {
125 for (i
= 0; i
< 3; i
++) {
126 if (inst
->SrcReg
[i
].Base
.RelAddr
) {
127 /* Only attempt to add the to the new parameter list once.
129 if (!inst
->SrcReg
[i
].Symbol
->pass1_done
) {
130 const int new_begin
=
131 copy_indirect_accessed_array(state
->prog
->Parameters
, layout
,
132 inst
->SrcReg
[i
].Symbol
->param_binding_begin
,
133 inst
->SrcReg
[i
].Symbol
->param_binding_length
);
139 inst
->SrcReg
[i
].Symbol
->param_binding_begin
= new_begin
;
140 inst
->SrcReg
[i
].Symbol
->pass1_done
= 1;
143 /* Previously the Index was just the offset from the parameter
144 * array. Now that the base of the parameter array is known, the
145 * index can be updated to its actual value.
147 inst
->Base
.SrcReg
[i
] = inst
->SrcReg
[i
].Base
;
148 inst
->Base
.SrcReg
[i
].Index
+=
149 inst
->SrcReg
[i
].Symbol
->param_binding_begin
;
155 /* PASS 2: Move any parameters that are not accessed indirectly from the
156 * original parameter list to the new parameter list.
158 for (inst
= state
->inst_head
; inst
!= NULL
; inst
= inst
->next
) {
159 for (i
= 0; i
< 3; i
++) {
160 const struct gl_program_parameter
*p
;
161 const int idx
= inst
->SrcReg
[i
].Base
.Index
;
162 unsigned swizzle
= SWIZZLE_NOOP
;
165 /* All relative addressed operands were processed on the first
166 * pass. Just skip them here.
168 if (inst
->SrcReg
[i
].Base
.RelAddr
) {
173 if ((inst
->SrcReg
[i
].Base
.File
<= PROGRAM_VARYING
)
174 || (inst
->SrcReg
[i
].Base
.File
>= PROGRAM_WRITE_ONLY
)) {
178 inst
->Base
.SrcReg
[i
] = inst
->SrcReg
[i
].Base
;
179 p
= & state
->prog
->Parameters
->Parameters
[idx
];
182 case PROGRAM_CONSTANT
: {
183 const float *const v
=
184 state
->prog
->Parameters
->ParameterValues
[idx
];
186 inst
->Base
.SrcReg
[i
].Index
=
187 _mesa_add_unnamed_constant(layout
, v
, p
->Size
, & swizzle
);
189 inst
->Base
.SrcReg
[i
].Swizzle
=
190 _mesa_combine_swizzles(swizzle
, inst
->Base
.SrcReg
[i
].Swizzle
);
194 case PROGRAM_STATE_VAR
:
195 inst
->Base
.SrcReg
[i
].Index
=
196 _mesa_add_state_reference(layout
, p
->StateIndexes
);
203 inst
->SrcReg
[i
].Base
.File
= p
->Type
;
204 inst
->Base
.SrcReg
[i
].File
= p
->Type
;
209 _mesa_free_parameter_list(state
->prog
->Parameters
);
210 state
->prog
->Parameters
= layout
;