Home | History | Annotate | Download | only in program
      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 (at) 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 
     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       memcpy(dst->ParameterValues[j], src->ParameterValues[i],
     98 	     sizeof(GLfloat) * 4);
     99 
    100       /* Pointer to the string name was copied.  Null-out src param name
    101        * to prevent double free later.
    102        */
    103       curr->Name = NULL;
    104 
    105       dst->NumParameters++;
    106    }
    107 
    108    return base;
    109 }
    110 
    111 
    112 /**
    113  * XXX description???
    114  * \return GL_TRUE for success, GL_FALSE for failure
    115  */
    116 GLboolean
    117 _mesa_layout_parameters(struct asm_parser_state *state)
    118 {
    119    struct gl_program_parameter_list *layout;
    120    struct asm_instruction *inst;
    121    unsigned i;
    122 
    123    layout =
    124       _mesa_new_parameter_list_sized(state->prog->Parameters->NumParameters);
    125 
    126    /* PASS 1:  Move any parameters that are accessed indirectly from the
    127     * original parameter list to the new parameter list.
    128     */
    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.
    133 	     */
    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);
    139 
    140 	       if (new_begin < 0) {
    141 		  _mesa_free_parameter_list(layout);
    142 		  return GL_FALSE;
    143 	       }
    144 
    145 	       inst->SrcReg[i].Symbol->param_binding_begin = new_begin;
    146 	       inst->SrcReg[i].Symbol->pass1_done = 1;
    147 	    }
    148 
    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.
    152 	     */
    153 	    inst->Base.SrcReg[i] = inst->SrcReg[i].Base;
    154 	    inst->Base.SrcReg[i].Index +=
    155 	       inst->SrcReg[i].Symbol->param_binding_begin;
    156 	 }
    157       }
    158    }
    159 
    160    /* PASS 2:  Move any parameters that are not accessed indirectly from the
    161     * original parameter list to the new parameter list.
    162     */
    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;
    168 
    169 	 /* All relative addressed operands were processed on the first
    170 	  * pass.  Just skip them here.
    171 	  */
    172 	 if (inst->SrcReg[i].Base.RelAddr) {
    173 	    continue;
    174 	 }
    175 
    176 	 if ((inst->SrcReg[i].Base.File <= PROGRAM_OUTPUT)
    177 	     || (inst->SrcReg[i].Base.File >= PROGRAM_WRITE_ONLY)) {
    178 	    continue;
    179 	 }
    180 
    181 	 inst->Base.SrcReg[i] = inst->SrcReg[i].Base;
    182 	 p = & state->prog->Parameters->Parameters[idx];
    183 
    184 	 switch (p->Type) {
    185 	 case PROGRAM_CONSTANT: {
    186 	    const gl_constant_value *const v =
    187 	       state->prog->Parameters->ParameterValues[idx];
    188 
    189 	    inst->Base.SrcReg[i].Index =
    190 	       _mesa_add_unnamed_constant(layout, v, p->Size, & swizzle);
    191 
    192 	    inst->Base.SrcReg[i].Swizzle =
    193 	       _mesa_combine_swizzles(swizzle, inst->Base.SrcReg[i].Swizzle);
    194 	    break;
    195 	 }
    196 
    197 	 case PROGRAM_STATE_VAR:
    198 	    inst->Base.SrcReg[i].Index =
    199 	       _mesa_add_state_reference(layout, p->StateIndexes);
    200 	    break;
    201 
    202 	 default:
    203 	    break;
    204 	 }
    205 
    206 	 inst->SrcReg[i].Base.File = p->Type;
    207 	 inst->Base.SrcReg[i].File = p->Type;
    208       }
    209    }
    210 
    211    layout->StateFlags = state->prog->Parameters->StateFlags;
    212    _mesa_free_parameter_list(state->prog->Parameters);
    213    state->prog->Parameters = layout;
    214 
    215    return GL_TRUE;
    216 }
    217