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/compiler.h"
32 #include "main/mtypes.h"
33 #include "prog_parameter.h"
34 #include "prog_parameter_layout.h"
35 #include "prog_instruction.h"
36 #include "program_parser.h"
39 _mesa_combine_swizzles(unsigned base
, unsigned applied
)
44 for (i
= 0; i
< 4; i
++) {
45 const unsigned s
= GET_SWZ(applied
, i
);
47 swiz
|= ((s
<= SWIZZLE_W
) ? GET_SWZ(base
, s
) : s
) << (i
* 3);
55 * Copy indirect access array from one parameter list to another
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
63 * The location in \c dst of the first element copied from \c src on
64 * success. -1 on failure.
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.
71 copy_indirect_accessed_array(struct gl_program_parameter_list
*src
,
72 struct gl_program_parameter_list
*dst
,
73 unsigned first
, unsigned count
)
75 const int base
= dst
->NumParameters
;
78 for (i
= first
; i
< (first
+ count
); i
++) {
79 struct gl_program_parameter
*curr
= & src
->Parameters
[i
];
81 if (curr
->Type
== PROGRAM_CONSTANT
) {
82 j
= dst
->NumParameters
;
84 for (j
= 0; j
< dst
->NumParameters
; j
++) {
85 if (memcmp(dst
->Parameters
[j
].StateIndexes
, curr
->StateIndexes
,
86 sizeof(curr
->StateIndexes
)) == 0) {
92 assert(j
== dst
->NumParameters
);
94 /* copy src parameter [i] to dest parameter [j] */
95 memcpy(& dst
->Parameters
[j
], curr
,
96 sizeof(dst
->Parameters
[j
]));
97 memcpy(dst
->ParameterValues
[j
], src
->ParameterValues
[i
],
100 /* Pointer to the string name was copied. Null-out src param name
101 * to prevent double free later.
105 dst
->NumParameters
++;
114 * \return GL_TRUE for success, GL_FALSE for failure
117 _mesa_layout_parameters(struct asm_parser_state
*state
)
119 struct gl_program_parameter_list
*layout
;
120 struct asm_instruction
*inst
;
124 _mesa_new_parameter_list_sized(state
->prog
->Parameters
->NumParameters
);
126 /* PASS 1: Move any parameters that are accessed indirectly from the
127 * original parameter list to the new parameter list.
129 for (inst
= state
->inst_head
; inst
!= NULL
; inst
= inst
->next
) {
130 for (i
= 0; i
< 3; i
++) {
131 if (inst
->SrcReg
[i
].Base
.RelAddr
) {
132 /* Only attempt to add the to the new parameter list once.
134 if (!inst
->SrcReg
[i
].Symbol
->pass1_done
) {
135 const int new_begin
=
136 copy_indirect_accessed_array(state
->prog
->Parameters
, layout
,
137 inst
->SrcReg
[i
].Symbol
->param_binding_begin
,
138 inst
->SrcReg
[i
].Symbol
->param_binding_length
);
141 _mesa_free_parameter_list(layout
);
145 inst
->SrcReg
[i
].Symbol
->param_binding_begin
= new_begin
;
146 inst
->SrcReg
[i
].Symbol
->pass1_done
= 1;
149 /* Previously the Index was just the offset from the parameter
150 * array. Now that the base of the parameter array is known, the
151 * index can be updated to its actual value.
153 inst
->Base
.SrcReg
[i
] = inst
->SrcReg
[i
].Base
;
154 inst
->Base
.SrcReg
[i
].Index
+=
155 inst
->SrcReg
[i
].Symbol
->param_binding_begin
;
160 /* PASS 2: Move any parameters that are not accessed indirectly from the
161 * original parameter list to the new parameter list.
163 for (inst
= state
->inst_head
; inst
!= NULL
; inst
= inst
->next
) {
164 for (i
= 0; i
< 3; i
++) {
165 const struct gl_program_parameter
*p
;
166 const int idx
= inst
->SrcReg
[i
].Base
.Index
;
167 unsigned swizzle
= SWIZZLE_NOOP
;
169 /* All relative addressed operands were processed on the first
170 * pass. Just skip them here.
172 if (inst
->SrcReg
[i
].Base
.RelAddr
) {
176 if ((inst
->SrcReg
[i
].Base
.File
<= PROGRAM_OUTPUT
)
177 || (inst
->SrcReg
[i
].Base
.File
>= PROGRAM_WRITE_ONLY
)) {
181 inst
->Base
.SrcReg
[i
] = inst
->SrcReg
[i
].Base
;
182 p
= & state
->prog
->Parameters
->Parameters
[idx
];
185 case PROGRAM_CONSTANT
: {
186 const gl_constant_value
*const v
=
187 state
->prog
->Parameters
->ParameterValues
[idx
];
189 inst
->Base
.SrcReg
[i
].Index
=
190 _mesa_add_unnamed_constant(layout
, v
, p
->Size
, & swizzle
);
192 inst
->Base
.SrcReg
[i
].Swizzle
=
193 _mesa_combine_swizzles(swizzle
, inst
->Base
.SrcReg
[i
].Swizzle
);
197 case PROGRAM_STATE_VAR
:
198 inst
->Base
.SrcReg
[i
].Index
=
199 _mesa_add_state_reference(layout
, p
->StateIndexes
);
206 inst
->SrcReg
[i
].Base
.File
= p
->Type
;
207 inst
->Base
.SrcReg
[i
].File
= p
->Type
;
211 layout
->StateFlags
= state
->prog
->Parameters
->StateFlags
;
212 _mesa_free_parameter_list(state
->prog
->Parameters
);
213 state
->prog
->Parameters
= layout
;