1848b8605Smrg/* 2848b8605Smrg * Copyright © 2009 Intel Corporation 3848b8605Smrg * 4848b8605Smrg * Permission is hereby granted, free of charge, to any person obtaining a 5848b8605Smrg * copy of this software and associated documentation files (the "Software"), 6848b8605Smrg * to deal in the Software without restriction, including without limitation 7848b8605Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8848b8605Smrg * and/or sell copies of the Software, and to permit persons to whom the 9848b8605Smrg * Software is furnished to do so, subject to the following conditions: 10848b8605Smrg * 11848b8605Smrg * The above copyright notice and this permission notice (including the next 12848b8605Smrg * paragraph) shall be included in all copies or substantial portions of the 13848b8605Smrg * Software. 14848b8605Smrg * 15848b8605Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16848b8605Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17848b8605Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18848b8605Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19848b8605Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20848b8605Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21848b8605Smrg * DEALINGS IN THE SOFTWARE. 22848b8605Smrg */ 23848b8605Smrg 24848b8605Smrg/** 25848b8605Smrg * \file prog_parameter_layout.c 26848b8605Smrg * \brief Helper functions to layout storage for program parameters 27848b8605Smrg * 28848b8605Smrg * \author Ian Romanick <ian.d.romanick@intel.com> 29848b8605Smrg */ 30848b8605Smrg 31b8e80941Smrg#include "main/imports.h" 32848b8605Smrg#include "main/mtypes.h" 33848b8605Smrg#include "prog_parameter.h" 34848b8605Smrg#include "prog_parameter_layout.h" 35848b8605Smrg#include "prog_instruction.h" 36848b8605Smrg#include "program_parser.h" 37848b8605Smrg 38848b8605Smrgunsigned 39848b8605Smrg_mesa_combine_swizzles(unsigned base, unsigned applied) 40848b8605Smrg{ 41848b8605Smrg unsigned swiz = 0; 42848b8605Smrg unsigned i; 43848b8605Smrg 44848b8605Smrg for (i = 0; i < 4; i++) { 45848b8605Smrg const unsigned s = GET_SWZ(applied, i); 46848b8605Smrg 47848b8605Smrg swiz |= ((s <= SWIZZLE_W) ? GET_SWZ(base, s) : s) << (i * 3); 48848b8605Smrg } 49848b8605Smrg 50848b8605Smrg return swiz; 51848b8605Smrg} 52848b8605Smrg 53848b8605Smrg 54848b8605Smrg/** 55848b8605Smrg * Copy indirect access array from one parameter list to another 56848b8605Smrg * 57848b8605Smrg * \param src Parameter array copied from 58848b8605Smrg * \param dst Parameter array copied to 59848b8605Smrg * \param first Index of first element in \c src to copy 60848b8605Smrg * \param count Number of elements to copy 61848b8605Smrg * 62848b8605Smrg * \return 63848b8605Smrg * The location in \c dst of the first element copied from \c src on 64848b8605Smrg * success. -1 on failure. 65848b8605Smrg * 66848b8605Smrg * \warning 67848b8605Smrg * This function assumes that there is already enough space available in 68848b8605Smrg * \c dst to hold all of the elements that will be copied over. 69848b8605Smrg */ 70848b8605Smrgstatic int 71848b8605Smrgcopy_indirect_accessed_array(struct gl_program_parameter_list *src, 72848b8605Smrg struct gl_program_parameter_list *dst, 73848b8605Smrg unsigned first, unsigned count) 74848b8605Smrg{ 75848b8605Smrg const int base = dst->NumParameters; 76848b8605Smrg unsigned i, j; 77848b8605Smrg 78848b8605Smrg for (i = first; i < (first + count); i++) { 79848b8605Smrg struct gl_program_parameter *curr = & src->Parameters[i]; 80848b8605Smrg 81848b8605Smrg if (curr->Type == PROGRAM_CONSTANT) { 82848b8605Smrg j = dst->NumParameters; 83848b8605Smrg } else { 84848b8605Smrg for (j = 0; j < dst->NumParameters; j++) { 85848b8605Smrg if (memcmp(dst->Parameters[j].StateIndexes, curr->StateIndexes, 86848b8605Smrg sizeof(curr->StateIndexes)) == 0) { 87848b8605Smrg return -1; 88848b8605Smrg } 89848b8605Smrg } 90848b8605Smrg } 91848b8605Smrg 92848b8605Smrg assert(j == dst->NumParameters); 93848b8605Smrg 94848b8605Smrg /* copy src parameter [i] to dest parameter [j] */ 95b8e80941Smrg memcpy(&dst->Parameters[j], curr, 96848b8605Smrg sizeof(dst->Parameters[j])); 97b8e80941Smrg 98b8e80941Smrg dst->ParameterValueOffset[j] = dst->NumParameterValues; 99b8e80941Smrg 100b8e80941Smrg gl_constant_value *pv_dst = 101b8e80941Smrg dst->ParameterValues + dst->ParameterValueOffset[j]; 102b8e80941Smrg gl_constant_value *pv_src = 103b8e80941Smrg src->ParameterValues + src->ParameterValueOffset[i]; 104b8e80941Smrg 105b8e80941Smrg memcpy(pv_dst, pv_src, MIN2(src->Parameters[i].Size, 4) * 106b8e80941Smrg sizeof(GLfloat)); 107b8e80941Smrg dst->NumParameterValues += MIN2(dst->Parameters[j].Size, 4); 108b8e80941Smrg 109848b8605Smrg 110848b8605Smrg /* Pointer to the string name was copied. Null-out src param name 111848b8605Smrg * to prevent double free later. 112848b8605Smrg */ 113848b8605Smrg curr->Name = NULL; 114848b8605Smrg 115848b8605Smrg dst->NumParameters++; 116848b8605Smrg } 117848b8605Smrg 118848b8605Smrg return base; 119848b8605Smrg} 120848b8605Smrg 121848b8605Smrg 122848b8605Smrg/** 123848b8605Smrg * XXX description??? 124848b8605Smrg * \return GL_TRUE for success, GL_FALSE for failure 125848b8605Smrg */ 126848b8605SmrgGLboolean 127848b8605Smrg_mesa_layout_parameters(struct asm_parser_state *state) 128848b8605Smrg{ 129848b8605Smrg struct gl_program_parameter_list *layout; 130848b8605Smrg struct asm_instruction *inst; 131848b8605Smrg unsigned i; 132848b8605Smrg 133848b8605Smrg layout = 134848b8605Smrg _mesa_new_parameter_list_sized(state->prog->Parameters->NumParameters); 135848b8605Smrg 136848b8605Smrg /* PASS 1: Move any parameters that are accessed indirectly from the 137848b8605Smrg * original parameter list to the new parameter list. 138848b8605Smrg */ 139848b8605Smrg for (inst = state->inst_head; inst != NULL; inst = inst->next) { 140848b8605Smrg for (i = 0; i < 3; i++) { 141848b8605Smrg if (inst->SrcReg[i].Base.RelAddr) { 142848b8605Smrg /* Only attempt to add the to the new parameter list once. 143848b8605Smrg */ 144848b8605Smrg if (!inst->SrcReg[i].Symbol->pass1_done) { 145848b8605Smrg const int new_begin = 146848b8605Smrg copy_indirect_accessed_array(state->prog->Parameters, layout, 147848b8605Smrg inst->SrcReg[i].Symbol->param_binding_begin, 148848b8605Smrg inst->SrcReg[i].Symbol->param_binding_length); 149848b8605Smrg 150848b8605Smrg if (new_begin < 0) { 151848b8605Smrg _mesa_free_parameter_list(layout); 152848b8605Smrg return GL_FALSE; 153848b8605Smrg } 154848b8605Smrg 155848b8605Smrg inst->SrcReg[i].Symbol->param_binding_begin = new_begin; 156848b8605Smrg inst->SrcReg[i].Symbol->pass1_done = 1; 157848b8605Smrg } 158848b8605Smrg 159848b8605Smrg /* Previously the Index was just the offset from the parameter 160848b8605Smrg * array. Now that the base of the parameter array is known, the 161848b8605Smrg * index can be updated to its actual value. 162848b8605Smrg */ 163848b8605Smrg inst->Base.SrcReg[i] = inst->SrcReg[i].Base; 164848b8605Smrg inst->Base.SrcReg[i].Index += 165848b8605Smrg inst->SrcReg[i].Symbol->param_binding_begin; 166848b8605Smrg } 167848b8605Smrg } 168848b8605Smrg } 169848b8605Smrg 170848b8605Smrg /* PASS 2: Move any parameters that are not accessed indirectly from the 171848b8605Smrg * original parameter list to the new parameter list. 172848b8605Smrg */ 173848b8605Smrg for (inst = state->inst_head; inst != NULL; inst = inst->next) { 174848b8605Smrg for (i = 0; i < 3; i++) { 175848b8605Smrg const struct gl_program_parameter *p; 176848b8605Smrg const int idx = inst->SrcReg[i].Base.Index; 177848b8605Smrg unsigned swizzle = SWIZZLE_NOOP; 178848b8605Smrg 179848b8605Smrg /* All relative addressed operands were processed on the first 180848b8605Smrg * pass. Just skip them here. 181848b8605Smrg */ 182848b8605Smrg if (inst->SrcReg[i].Base.RelAddr) { 183848b8605Smrg continue; 184848b8605Smrg } 185848b8605Smrg 186848b8605Smrg if ((inst->SrcReg[i].Base.File <= PROGRAM_OUTPUT) 187848b8605Smrg || (inst->SrcReg[i].Base.File >= PROGRAM_WRITE_ONLY)) { 188848b8605Smrg continue; 189848b8605Smrg } 190848b8605Smrg 191848b8605Smrg inst->Base.SrcReg[i] = inst->SrcReg[i].Base; 192848b8605Smrg p = & state->prog->Parameters->Parameters[idx]; 193848b8605Smrg 194848b8605Smrg switch (p->Type) { 195848b8605Smrg case PROGRAM_CONSTANT: { 196b8e80941Smrg unsigned pvo = state->prog->Parameters->ParameterValueOffset[idx]; 197b8e80941Smrg const gl_constant_value *const v = 198b8e80941Smrg state->prog->Parameters->ParameterValues + pvo; 199848b8605Smrg 200848b8605Smrg inst->Base.SrcReg[i].Index = 201848b8605Smrg _mesa_add_unnamed_constant(layout, v, p->Size, & swizzle); 202848b8605Smrg 203848b8605Smrg inst->Base.SrcReg[i].Swizzle = 204848b8605Smrg _mesa_combine_swizzles(swizzle, inst->Base.SrcReg[i].Swizzle); 205848b8605Smrg break; 206848b8605Smrg } 207848b8605Smrg 208848b8605Smrg case PROGRAM_STATE_VAR: 209848b8605Smrg inst->Base.SrcReg[i].Index = 210848b8605Smrg _mesa_add_state_reference(layout, p->StateIndexes); 211848b8605Smrg break; 212848b8605Smrg 213848b8605Smrg default: 214848b8605Smrg break; 215848b8605Smrg } 216848b8605Smrg 217848b8605Smrg inst->SrcReg[i].Base.File = p->Type; 218848b8605Smrg inst->Base.SrcReg[i].File = p->Type; 219848b8605Smrg } 220848b8605Smrg } 221848b8605Smrg 222848b8605Smrg layout->StateFlags = state->prog->Parameters->StateFlags; 223848b8605Smrg _mesa_free_parameter_list(state->prog->Parameters); 224848b8605Smrg state->prog->Parameters = layout; 225848b8605Smrg 226848b8605Smrg return GL_TRUE; 227848b8605Smrg} 228