Home | History | Annotate | Download | only in program
      1 /*
      2  * Mesa 3-D graphics library
      3  *
      4  * Copyright (C) 1999-2007  Brian Paul   All Rights Reserved.
      5  *
      6  * Permission is hereby granted, free of charge, to any person obtaining a
      7  * copy of this software and associated documentation files (the "Software"),
      8  * to deal in the Software without restriction, including without limitation
      9  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
     10  * and/or sell copies of the Software, and to permit persons to whom the
     11  * Software is furnished to do so, subject to the following conditions:
     12  *
     13  * The above copyright notice and this permission notice shall be included
     14  * in all copies or substantial portions of the Software.
     15  *
     16  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
     17  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     18  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     19  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
     20  * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
     21  * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
     22  * OTHER DEALINGS IN THE SOFTWARE.
     23  */
     24 
     25 /**
     26  * \file program.c
     27  * Vertex and fragment program support functions.
     28  * \author Brian Paul
     29  */
     30 
     31 
     32 #include "main/glheader.h"
     33 #include "main/context.h"
     34 #include "main/framebuffer.h"
     35 #include "main/hash.h"
     36 #include "main/macros.h"
     37 #include "main/shaderobj.h"
     38 #include "program.h"
     39 #include "prog_cache.h"
     40 #include "prog_parameter.h"
     41 #include "prog_instruction.h"
     42 #include "util/ralloc.h"
     43 
     44 
     45 /**
     46  * A pointer to this dummy program is put into the hash table when
     47  * glGenPrograms is called.
     48  */
     49 struct gl_program _mesa_DummyProgram;
     50 
     51 
     52 /**
     53  * Init context's vertex/fragment program state
     54  */
     55 void
     56 _mesa_init_program(struct gl_context *ctx)
     57 {
     58    /*
     59     * If this assertion fails, we need to increase the field
     60     * size for register indexes (see INST_INDEX_BITS).
     61     */
     62    assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents / 4
     63           <= (1 << INST_INDEX_BITS));
     64    assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents / 4
     65           <= (1 << INST_INDEX_BITS));
     66 
     67    assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxTemps <= (1 << INST_INDEX_BITS));
     68    assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxLocalParams <= (1 << INST_INDEX_BITS));
     69    assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxTemps <= (1 << INST_INDEX_BITS));
     70    assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxLocalParams <= (1 << INST_INDEX_BITS));
     71 
     72    assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxUniformComponents <= 4 * MAX_UNIFORMS);
     73    assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxUniformComponents <= 4 * MAX_UNIFORMS);
     74 
     75    assert(ctx->Const.Program[MESA_SHADER_VERTEX].MaxAddressOffset <= (1 << INST_INDEX_BITS));
     76    assert(ctx->Const.Program[MESA_SHADER_FRAGMENT].MaxAddressOffset <= (1 << INST_INDEX_BITS));
     77 
     78    /* If this fails, increase prog_instruction::TexSrcUnit size */
     79    STATIC_ASSERT(MAX_TEXTURE_UNITS <= (1 << 5));
     80 
     81    /* If this fails, increase prog_instruction::TexSrcTarget size */
     82    STATIC_ASSERT(NUM_TEXTURE_TARGETS <= (1 << 4));
     83 
     84    ctx->Program.ErrorPos = -1;
     85    ctx->Program.ErrorString = strdup("");
     86 
     87    ctx->VertexProgram.Enabled = GL_FALSE;
     88    ctx->VertexProgram.PointSizeEnabled =
     89       (ctx->API == API_OPENGLES2) ? GL_TRUE : GL_FALSE;
     90    ctx->VertexProgram.TwoSideEnabled = GL_FALSE;
     91    _mesa_reference_program(ctx, &ctx->VertexProgram.Current,
     92                            ctx->Shared->DefaultVertexProgram);
     93    assert(ctx->VertexProgram.Current);
     94    ctx->VertexProgram.Cache = _mesa_new_program_cache();
     95 
     96    ctx->FragmentProgram.Enabled = GL_FALSE;
     97    _mesa_reference_program(ctx, &ctx->FragmentProgram.Current,
     98                            ctx->Shared->DefaultFragmentProgram);
     99    assert(ctx->FragmentProgram.Current);
    100    ctx->FragmentProgram.Cache = _mesa_new_program_cache();
    101 
    102    /* XXX probably move this stuff */
    103    ctx->ATIFragmentShader.Enabled = GL_FALSE;
    104    ctx->ATIFragmentShader.Current = ctx->Shared->DefaultFragmentShader;
    105    assert(ctx->ATIFragmentShader.Current);
    106    ctx->ATIFragmentShader.Current->RefCount++;
    107 }
    108 
    109 
    110 /**
    111  * Free a context's vertex/fragment program state
    112  */
    113 void
    114 _mesa_free_program_data(struct gl_context *ctx)
    115 {
    116    _mesa_reference_program(ctx, &ctx->VertexProgram.Current, NULL);
    117    _mesa_delete_program_cache(ctx, ctx->VertexProgram.Cache);
    118    _mesa_reference_program(ctx, &ctx->FragmentProgram.Current, NULL);
    119    _mesa_delete_shader_cache(ctx, ctx->FragmentProgram.Cache);
    120 
    121    /* XXX probably move this stuff */
    122    if (ctx->ATIFragmentShader.Current) {
    123       ctx->ATIFragmentShader.Current->RefCount--;
    124       if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
    125          free(ctx->ATIFragmentShader.Current);
    126       }
    127    }
    128 
    129    free((void *) ctx->Program.ErrorString);
    130 }
    131 
    132 
    133 /**
    134  * Update the default program objects in the given context to reference those
    135  * specified in the shared state and release those referencing the old
    136  * shared state.
    137  */
    138 void
    139 _mesa_update_default_objects_program(struct gl_context *ctx)
    140 {
    141    _mesa_reference_program(ctx, &ctx->VertexProgram.Current,
    142                            ctx->Shared->DefaultVertexProgram);
    143    assert(ctx->VertexProgram.Current);
    144 
    145    _mesa_reference_program(ctx, &ctx->FragmentProgram.Current,
    146                             ctx->Shared->DefaultFragmentProgram);
    147    assert(ctx->FragmentProgram.Current);
    148 
    149    /* XXX probably move this stuff */
    150    if (ctx->ATIFragmentShader.Current) {
    151       ctx->ATIFragmentShader.Current->RefCount--;
    152       if (ctx->ATIFragmentShader.Current->RefCount <= 0) {
    153          free(ctx->ATIFragmentShader.Current);
    154       }
    155    }
    156    ctx->ATIFragmentShader.Current = (struct ati_fragment_shader *) ctx->Shared->DefaultFragmentShader;
    157    assert(ctx->ATIFragmentShader.Current);
    158    ctx->ATIFragmentShader.Current->RefCount++;
    159 }
    160 
    161 
    162 /**
    163  * Set the vertex/fragment program error state (position and error string).
    164  * This is generally called from within the parsers.
    165  */
    166 void
    167 _mesa_set_program_error(struct gl_context *ctx, GLint pos, const char *string)
    168 {
    169    ctx->Program.ErrorPos = pos;
    170    free((void *) ctx->Program.ErrorString);
    171    if (!string)
    172       string = "";
    173    ctx->Program.ErrorString = strdup(string);
    174 }
    175 
    176 
    177 /**
    178  * Initialize a new gl_program object.
    179  */
    180 struct gl_program *
    181 _mesa_init_gl_program(struct gl_program *prog, GLenum target, GLuint id,
    182                       bool is_arb_asm)
    183 {
    184    if (!prog)
    185       return NULL;
    186 
    187    memset(prog, 0, sizeof(*prog));
    188    mtx_init(&prog->Mutex, mtx_plain);
    189    prog->Id = id;
    190    prog->Target = target;
    191    prog->RefCount = 1;
    192    prog->Format = GL_PROGRAM_FORMAT_ASCII_ARB;
    193    prog->info.stage = _mesa_program_enum_to_shader_stage(target);
    194    prog->is_arb_asm = is_arb_asm;
    195 
    196    /* Uniforms that lack an initializer in the shader code have an initial
    197     * value of zero.  This includes sampler uniforms.
    198     *
    199     * Page 24 (page 30 of the PDF) of the GLSL 1.20 spec says:
    200     *
    201     *     "The link time initial value is either the value of the variable's
    202     *     initializer, if present, or 0 if no initializer is present. Sampler
    203     *     types cannot have initializers."
    204     *
    205     * So we only initialise ARB assembly style programs.
    206     */
    207    if (is_arb_asm) {
    208       /* default mapping from samplers to texture units */
    209       for (unsigned i = 0; i < MAX_SAMPLERS; i++)
    210          prog->SamplerUnits[i] = i;
    211    }
    212 
    213    return prog;
    214 }
    215 
    216 
    217 /**
    218  * Allocate and initialize a new fragment/vertex program object but
    219  * don't put it into the program hash table.  Called via
    220  * ctx->Driver.NewProgram.  May be overridden (ie. replaced) by a
    221  * device driver function to implement OO deriviation with additional
    222  * types not understood by this function.
    223  *
    224  * \param ctx  context
    225  * \param id   program id/number
    226  * \param target  program target/type
    227  * \return  pointer to new program object
    228  */
    229 struct gl_program *
    230 _mesa_new_program(struct gl_context *ctx, GLenum target, GLuint id,
    231                   bool is_arb_asm)
    232 {
    233    switch (target) {
    234    case GL_VERTEX_PROGRAM_ARB: /* == GL_VERTEX_PROGRAM_NV */
    235    case GL_GEOMETRY_PROGRAM_NV:
    236    case GL_TESS_CONTROL_PROGRAM_NV:
    237    case GL_TESS_EVALUATION_PROGRAM_NV:
    238    case GL_FRAGMENT_PROGRAM_ARB:
    239    case GL_COMPUTE_PROGRAM_NV: {
    240       struct gl_program *prog = rzalloc(NULL, struct gl_program);
    241       return _mesa_init_gl_program(prog, target, id, is_arb_asm);
    242    }
    243    default:
    244       _mesa_problem(ctx, "bad target in _mesa_new_program");
    245       return NULL;
    246    }
    247 }
    248 
    249 
    250 /**
    251  * Delete a program and remove it from the hash table, ignoring the
    252  * reference count.
    253  * Called via ctx->Driver.DeleteProgram.  May be wrapped (OO deriviation)
    254  * by a device driver function.
    255  */
    256 void
    257 _mesa_delete_program(struct gl_context *ctx, struct gl_program *prog)
    258 {
    259    (void) ctx;
    260    assert(prog);
    261    assert(prog->RefCount==0);
    262 
    263    if (prog == &_mesa_DummyProgram)
    264       return;
    265 
    266    if (prog->Parameters) {
    267       _mesa_free_parameter_list(prog->Parameters);
    268    }
    269 
    270    if (prog->nir) {
    271       ralloc_free(prog->nir);
    272    }
    273 
    274    mtx_destroy(&prog->Mutex);
    275    ralloc_free(prog);
    276 }
    277 
    278 
    279 /**
    280  * Return the gl_program object for a given ID.
    281  * Basically just a wrapper for _mesa_HashLookup() to avoid a lot of
    282  * casts elsewhere.
    283  */
    284 struct gl_program *
    285 _mesa_lookup_program(struct gl_context *ctx, GLuint id)
    286 {
    287    if (id)
    288       return (struct gl_program *) _mesa_HashLookup(ctx->Shared->Programs, id);
    289    else
    290       return NULL;
    291 }
    292 
    293 
    294 /**
    295  * Reference counting for vertex/fragment programs
    296  * This is normally only called from the _mesa_reference_program() macro
    297  * when there's a real pointer change.
    298  */
    299 void
    300 _mesa_reference_program_(struct gl_context *ctx,
    301                          struct gl_program **ptr,
    302                          struct gl_program *prog)
    303 {
    304 #ifndef NDEBUG
    305    assert(ptr);
    306    if (*ptr && prog) {
    307       /* sanity check */
    308       if ((*ptr)->Target == GL_VERTEX_PROGRAM_ARB)
    309          assert(prog->Target == GL_VERTEX_PROGRAM_ARB);
    310       else if ((*ptr)->Target == GL_FRAGMENT_PROGRAM_ARB)
    311          assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB ||
    312                 prog->Target == GL_FRAGMENT_PROGRAM_NV);
    313       else if ((*ptr)->Target == GL_GEOMETRY_PROGRAM_NV)
    314          assert(prog->Target == GL_GEOMETRY_PROGRAM_NV);
    315    }
    316 #endif
    317 
    318    if (*ptr) {
    319       GLboolean deleteFlag;
    320       struct gl_program *oldProg = *ptr;
    321 
    322       mtx_lock(&oldProg->Mutex);
    323       assert(oldProg->RefCount > 0);
    324       oldProg->RefCount--;
    325 
    326       deleteFlag = (oldProg->RefCount == 0);
    327       mtx_unlock(&oldProg->Mutex);
    328 
    329       if (deleteFlag) {
    330          assert(ctx);
    331          _mesa_reference_shader_program_data(ctx, &oldProg->sh.data, NULL);
    332          ctx->Driver.DeleteProgram(ctx, oldProg);
    333       }
    334 
    335       *ptr = NULL;
    336    }
    337 
    338    assert(!*ptr);
    339    if (prog) {
    340       mtx_lock(&prog->Mutex);
    341       prog->RefCount++;
    342       mtx_unlock(&prog->Mutex);
    343    }
    344 
    345    *ptr = prog;
    346 }
    347 
    348 
    349 /**
    350  * Insert 'count' NOP instructions at 'start' in the given program.
    351  * Adjust branch targets accordingly.
    352  */
    353 GLboolean
    354 _mesa_insert_instructions(struct gl_program *prog, GLuint start, GLuint count)
    355 {
    356    const GLuint origLen = prog->arb.NumInstructions;
    357    const GLuint newLen = origLen + count;
    358    struct prog_instruction *newInst;
    359    GLuint i;
    360 
    361    /* adjust branches */
    362    for (i = 0; i < prog->arb.NumInstructions; i++) {
    363       struct prog_instruction *inst = prog->arb.Instructions + i;
    364       if (inst->BranchTarget > 0) {
    365          if ((GLuint)inst->BranchTarget >= start) {
    366             inst->BranchTarget += count;
    367          }
    368       }
    369    }
    370 
    371    /* Alloc storage for new instructions */
    372    newInst = rzalloc_array(prog, struct prog_instruction, newLen);
    373    if (!newInst) {
    374       return GL_FALSE;
    375    }
    376 
    377    /* Copy 'start' instructions into new instruction buffer */
    378    _mesa_copy_instructions(newInst, prog->arb.Instructions, start);
    379 
    380    /* init the new instructions */
    381    _mesa_init_instructions(newInst + start, count);
    382 
    383    /* Copy the remaining/tail instructions to new inst buffer */
    384    _mesa_copy_instructions(newInst + start + count,
    385                            prog->arb.Instructions + start,
    386                            origLen - start);
    387 
    388    /* free old instructions */
    389    ralloc_free(prog->arb.Instructions);
    390 
    391    /* install new instructions */
    392    prog->arb.Instructions = newInst;
    393    prog->arb.NumInstructions = newLen;
    394 
    395    return GL_TRUE;
    396 }
    397 
    398 /**
    399  * Delete 'count' instructions at 'start' in the given program.
    400  * Adjust branch targets accordingly.
    401  */
    402 GLboolean
    403 _mesa_delete_instructions(struct gl_program *prog, GLuint start, GLuint count,
    404                           void *mem_ctx)
    405 {
    406    const GLuint origLen = prog->arb.NumInstructions;
    407    const GLuint newLen = origLen - count;
    408    struct prog_instruction *newInst;
    409    GLuint i;
    410 
    411    /* adjust branches */
    412    for (i = 0; i < prog->arb.NumInstructions; i++) {
    413       struct prog_instruction *inst = prog->arb.Instructions + i;
    414       if (inst->BranchTarget > 0) {
    415          if (inst->BranchTarget > (GLint) start) {
    416             inst->BranchTarget -= count;
    417          }
    418       }
    419    }
    420 
    421    /* Alloc storage for new instructions */
    422    newInst = rzalloc_array(mem_ctx, struct prog_instruction, newLen);
    423    if (!newInst) {
    424       return GL_FALSE;
    425    }
    426 
    427    /* Copy 'start' instructions into new instruction buffer */
    428    _mesa_copy_instructions(newInst, prog->arb.Instructions, start);
    429 
    430    /* Copy the remaining/tail instructions to new inst buffer */
    431    _mesa_copy_instructions(newInst + start,
    432                            prog->arb.Instructions + start + count,
    433                            newLen - start);
    434 
    435    /* free old instructions */
    436    ralloc_free(prog->arb.Instructions);
    437 
    438    /* install new instructions */
    439    prog->arb.Instructions = newInst;
    440    prog->arb.NumInstructions = newLen;
    441 
    442    return GL_TRUE;
    443 }
    444 
    445 
    446 /**
    447  * Populate the 'used' array with flags indicating which registers (TEMPs,
    448  * INPUTs, OUTPUTs, etc, are used by the given program.
    449  * \param file  type of register to scan for
    450  * \param used  returns true/false flags for in use / free
    451  * \param usedSize  size of the 'used' array
    452  */
    453 void
    454 _mesa_find_used_registers(const struct gl_program *prog,
    455                           gl_register_file file,
    456                           GLboolean used[], GLuint usedSize)
    457 {
    458    GLuint i, j;
    459 
    460    memset(used, 0, usedSize);
    461 
    462    for (i = 0; i < prog->arb.NumInstructions; i++) {
    463       const struct prog_instruction *inst = prog->arb.Instructions + i;
    464       const GLuint n = _mesa_num_inst_src_regs(inst->Opcode);
    465 
    466       if (inst->DstReg.File == file) {
    467          assert(inst->DstReg.Index < usedSize);
    468          if(inst->DstReg.Index < usedSize)
    469             used[inst->DstReg.Index] = GL_TRUE;
    470       }
    471 
    472       for (j = 0; j < n; j++) {
    473          if (inst->SrcReg[j].File == file) {
    474             assert(inst->SrcReg[j].Index < (GLint) usedSize);
    475             if (inst->SrcReg[j].Index < (GLint) usedSize)
    476                used[inst->SrcReg[j].Index] = GL_TRUE;
    477          }
    478       }
    479    }
    480 }
    481 
    482 
    483 /**
    484  * Scan the given 'used' register flag array for the first entry
    485  * that's >= firstReg.
    486  * \param used  vector of flags indicating registers in use (as returned
    487  *              by _mesa_find_used_registers())
    488  * \param usedSize  size of the 'used' array
    489  * \param firstReg  first register to start searching at
    490  * \return index of unused register, or -1 if none.
    491  */
    492 GLint
    493 _mesa_find_free_register(const GLboolean used[],
    494                          GLuint usedSize, GLuint firstReg)
    495 {
    496    GLuint i;
    497 
    498    assert(firstReg < usedSize);
    499 
    500    for (i = firstReg; i < usedSize; i++)
    501       if (!used[i])
    502          return i;
    503 
    504    return -1;
    505 }
    506 
    507 
    508 /* Gets the minimum number of shader invocations per fragment.
    509  * This function is useful to determine if we need to do per
    510  * sample shading or per fragment shading.
    511  */
    512 GLint
    513 _mesa_get_min_invocations_per_fragment(struct gl_context *ctx,
    514                                        const struct gl_program *prog,
    515                                        bool ignore_sample_qualifier)
    516 {
    517    /* From ARB_sample_shading specification:
    518     * "Using gl_SampleID in a fragment shader causes the entire shader
    519     *  to be evaluated per-sample."
    520     *
    521     * "Using gl_SamplePosition in a fragment shader causes the entire
    522     *  shader to be evaluated per-sample."
    523     *
    524     * "If MULTISAMPLE or SAMPLE_SHADING_ARB is disabled, sample shading
    525     *  has no effect."
    526     */
    527    if (ctx->Multisample.Enabled) {
    528       /* The ARB_gpu_shader5 specification says:
    529        *
    530        * "Use of the "sample" qualifier on a fragment shader input
    531        *  forces per-sample shading"
    532        */
    533       if (prog->info.fs.uses_sample_qualifier && !ignore_sample_qualifier)
    534          return MAX2(_mesa_geometric_samples(ctx->DrawBuffer), 1);
    535 
    536       if (prog->info.system_values_read & (SYSTEM_BIT_SAMPLE_ID |
    537                                            SYSTEM_BIT_SAMPLE_POS))
    538          return MAX2(_mesa_geometric_samples(ctx->DrawBuffer), 1);
    539       else if (ctx->Multisample.SampleShading)
    540          return MAX2(ceil(ctx->Multisample.MinSampleShadingValue *
    541                           _mesa_geometric_samples(ctx->DrawBuffer)), 1);
    542       else
    543          return 1;
    544    }
    545    return 1;
    546 }
    547