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#include "main/imports.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" 37 38unsigned 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 */ 70static int 71copy_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->ParameterValueOffset[j] = dst->NumParameterValues; 99 100 gl_constant_value *pv_dst = 101 dst->ParameterValues + dst->ParameterValueOffset[j]; 102 gl_constant_value *pv_src = 103 src->ParameterValues + src->ParameterValueOffset[i]; 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/** 123 * XXX description??? 124 * \return GL_TRUE for success, GL_FALSE for failure 125 */ 126GLboolean 127_mesa_layout_parameters(struct asm_parser_state *state) 128{ 129 struct gl_program_parameter_list *layout; 130 struct asm_instruction *inst; 131 unsigned i; 132 133 layout = 134 _mesa_new_parameter_list_sized(state->prog->Parameters->NumParameters); 135 136 /* PASS 1: Move any parameters that are accessed indirectly from the 137 * original parameter list to the new parameter list. 138 */ 139 for (inst = state->inst_head; inst != NULL; inst = inst->next) { 140 for (i = 0; i < 3; i++) { 141 if (inst->SrcReg[i].Base.RelAddr) { 142 /* Only attempt to add the to the new parameter list once. 143 */ 144 if (!inst->SrcReg[i].Symbol->pass1_done) { 145 const int new_begin = 146 copy_indirect_accessed_array(state->prog->Parameters, layout, 147 inst->SrcReg[i].Symbol->param_binding_begin, 148 inst->SrcReg[i].Symbol->param_binding_length); 149 150 if (new_begin < 0) { 151 _mesa_free_parameter_list(layout); 152 return GL_FALSE; 153 } 154 155 inst->SrcReg[i].Symbol->param_binding_begin = new_begin; 156 inst->SrcReg[i].Symbol->pass1_done = 1; 157 } 158 159 /* Previously the Index was just the offset from the parameter 160 * array. Now that the base of the parameter array is known, the 161 * index can be updated to its actual value. 162 */ 163 inst->Base.SrcReg[i] = inst->SrcReg[i].Base; 164 inst->Base.SrcReg[i].Index += 165 inst->SrcReg[i].Symbol->param_binding_begin; 166 } 167 } 168 } 169 170 /* PASS 2: Move any parameters that are not accessed indirectly from the 171 * original parameter list to the new parameter list. 172 */ 173 for (inst = state->inst_head; inst != NULL; inst = inst->next) { 174 for (i = 0; i < 3; i++) { 175 const struct gl_program_parameter *p; 176 const int idx = inst->SrcReg[i].Base.Index; 177 unsigned swizzle = SWIZZLE_NOOP; 178 179 /* All relative addressed operands were processed on the first 180 * pass. Just skip them here. 181 */ 182 if (inst->SrcReg[i].Base.RelAddr) { 183 continue; 184 } 185 186 if ((inst->SrcReg[i].Base.File <= PROGRAM_OUTPUT) 187 || (inst->SrcReg[i].Base.File >= PROGRAM_WRITE_ONLY)) { 188 continue; 189 } 190 191 inst->Base.SrcReg[i] = inst->SrcReg[i].Base; 192 p = & state->prog->Parameters->Parameters[idx]; 193 194 switch (p->Type) { 195 case PROGRAM_CONSTANT: { 196 unsigned pvo = state->prog->Parameters->ParameterValueOffset[idx]; 197 const gl_constant_value *const v = 198 state->prog->Parameters->ParameterValues + pvo; 199 200 inst->Base.SrcReg[i].Index = 201 _mesa_add_unnamed_constant(layout, v, p->Size, & swizzle); 202 203 inst->Base.SrcReg[i].Swizzle = 204 _mesa_combine_swizzles(swizzle, inst->Base.SrcReg[i].Swizzle); 205 break; 206 } 207 208 case PROGRAM_STATE_VAR: 209 inst->Base.SrcReg[i].Index = 210 _mesa_add_state_reference(layout, p->StateIndexes); 211 break; 212 213 default: 214 break; 215 } 216 217 inst->SrcReg[i].Base.File = p->Type; 218 inst->Base.SrcReg[i].File = p->Type; 219 } 220 } 221 222 layout->StateFlags = state->prog->Parameters->StateFlags; 223 _mesa_free_parameter_list(state->prog->Parameters); 224 state->prog->Parameters = layout; 225 226 return GL_TRUE; 227} 228