📄 slang_link.c
字号:
/* * Mesa 3-D graphics library * Version: 7.2 * * Copyright (C) 2008 Brian Paul All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), * to deal in the Software without restriction, including without limitation * the rights to use, copy, modify, merge, publish, distribute, sublicense, * and/or sell copies of the Software, and to permit persons to whom the * Software is furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included * in all copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *//** * \file slang_link.c * GLSL linker * \author Brian Paul */#include "main/imports.h"#include "main/context.h"#include "main/hash.h"#include "main/macros.h"#include "shader/program.h"#include "shader/prog_instruction.h"#include "shader/prog_parameter.h"#include "shader/prog_print.h"#include "shader/prog_statevars.h"#include "shader/prog_uniform.h"#include "shader/shader_api.h"#include "slang_link.h"/** * Record a linking error. */static voidlink_error(struct gl_shader_program *shProg, const char *msg){ if (shProg->InfoLog) { _mesa_free(shProg->InfoLog); } shProg->InfoLog = _mesa_strdup(msg); shProg->LinkStatus = GL_FALSE;}/** * Linking varying vars involves rearranging varying vars so that the * vertex program's output varyings matches the order of the fragment * program's input varyings. */static GLbooleanlink_varying_vars(struct gl_shader_program *shProg, struct gl_program *prog){ GLuint *map, i, firstVarying, newFile; map = (GLuint *) malloc(prog->Varying->NumParameters * sizeof(GLuint)); if (!map) return GL_FALSE; for (i = 0; i < prog->Varying->NumParameters; i++) { /* see if this varying is in the linked varying list */ const struct gl_program_parameter *var = prog->Varying->Parameters + i; GLint j = _mesa_lookup_parameter_index(shProg->Varying, -1, var->Name); if (j >= 0) { /* already in list, check size */ if (var->Size != shProg->Varying->Parameters[j].Size) { /* error */ link_error(shProg, "mismatched varying variable types"); return GL_FALSE; } } else { /* not already in linked list */ j = _mesa_add_varying(shProg->Varying, var->Name, var->Size); } /* map varying[i] to varying[j]. * Note: the loop here takes care of arrays or large (sz>4) vars. */ { GLint sz = var->Size; while (sz > 0) { /*printf("Link varying from %d to %d\n", i, j);*/ map[i++] = j++; sz -= 4; } i--; /* go back one */ } } /* Varying variables are treated like other vertex program outputs * (and like other fragment program inputs). The position of the * first varying differs for vertex/fragment programs... * Also, replace File=PROGRAM_VARYING with File=PROGRAM_INPUT/OUTPUT. */ if (prog->Target == GL_VERTEX_PROGRAM_ARB) { firstVarying = VERT_RESULT_VAR0; newFile = PROGRAM_OUTPUT; } else { assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB); firstVarying = FRAG_ATTRIB_VAR0; newFile = PROGRAM_INPUT; } /* OK, now scan the program/shader instructions looking for varying vars, * replacing the old index with the new index. */ for (i = 0; i < prog->NumInstructions; i++) { struct prog_instruction *inst = prog->Instructions + i; GLuint j; if (inst->DstReg.File == PROGRAM_VARYING) { inst->DstReg.File = newFile; inst->DstReg.Index = map[ inst->DstReg.Index ] + firstVarying; } for (j = 0; j < 3; j++) { if (inst->SrcReg[j].File == PROGRAM_VARYING) { inst->SrcReg[j].File = newFile; inst->SrcReg[j].Index = map[ inst->SrcReg[j].Index ] + firstVarying; } } } free(map); /* these will get recomputed before linking is completed */ prog->InputsRead = 0x0; prog->OutputsWritten = 0x0; return GL_TRUE;}/** * Build the shProg->Uniforms list. * This is basically a list/index of all uniforms found in either/both of * the vertex and fragment shaders. */static voidlink_uniform_vars(struct gl_shader_program *shProg, struct gl_program *prog, GLuint *numSamplers){ GLuint samplerMap[MAX_SAMPLERS]; GLuint i; for (i = 0; i < prog->Parameters->NumParameters; i++) { const struct gl_program_parameter *p = prog->Parameters->Parameters + i; /* * XXX FIX NEEDED HERE * We should also be adding a uniform if p->Type == PROGRAM_STATE_VAR. * For example, modelview matrix, light pos, etc. * Also, we need to update the state-var name-generator code to * generate GLSL-style names, like "gl_LightSource[0].position". * Furthermore, we'll need to fix the state-var's size/datatype info. */ if ((p->Type == PROGRAM_UNIFORM && p->Used) || p->Type == PROGRAM_SAMPLER) { _mesa_append_uniform(shProg->Uniforms, p->Name, prog->Target, i); } if (p->Type == PROGRAM_SAMPLER) { /* Allocate a new sampler index */ GLuint sampNum = *numSamplers; GLuint oldSampNum = (GLuint) prog->Parameters->ParameterValues[i][0]; assert(oldSampNum < MAX_SAMPLERS); samplerMap[oldSampNum] = sampNum; (*numSamplers)++; } } /* OK, now scan the program/shader instructions looking for sampler vars, * replacing the old index with the new index. */ prog->SamplersUsed = 0x0; for (i = 0; i < prog->NumInstructions; i++) { struct prog_instruction *inst = prog->Instructions + i; if (_mesa_is_tex_instruction(inst->Opcode)) { /* printf("====== remap sampler from %d to %d\n", inst->Sampler, map[ inst->Sampler ]); */ /* here, texUnit is really samplerUnit */ inst->TexSrcUnit = samplerMap[inst->TexSrcUnit]; prog->SamplerTargets[inst->TexSrcUnit] = inst->TexSrcTarget; prog->SamplersUsed |= (1 << inst->TexSrcUnit); } }}/** * Resolve binding of generic vertex attributes. * For example, if the vertex shader declared "attribute vec4 foobar" we'll * allocate a generic vertex attribute for "foobar" and plug that value into * the vertex program instructions. * But if the user called glBindAttributeLocation(), those bindings will * have priority. */static GLboolean_slang_resolve_attributes(struct gl_shader_program *shProg, const struct gl_program *origProg, struct gl_program *linkedProg){ GLint attribMap[MAX_VERTEX_ATTRIBS]; GLuint i, j; GLbitfield usedAttributes; assert(origProg != linkedProg); assert(origProg->Target == GL_VERTEX_PROGRAM_ARB); assert(linkedProg->Target == GL_VERTEX_PROGRAM_ARB); if (!shProg->Attributes) shProg->Attributes = _mesa_new_parameter_list(); if (linkedProg->Attributes) { _mesa_free_parameter_list(linkedProg->Attributes); } linkedProg->Attributes = _mesa_new_parameter_list(); /* Build a bitmask indicating which attribute indexes have been * explicitly bound by the user with glBindAttributeLocation(). */ usedAttributes = 0x0; for (i = 0; i < shProg->Attributes->NumParameters; i++) { GLint attr = shProg->Attributes->Parameters[i].StateIndexes[0]; usedAttributes |= (1 << attr); } /* initialize the generic attribute map entries to -1 */ for (i = 0; i < MAX_VERTEX_ATTRIBS; i++) { attribMap[i] = -1; } /* * Scan program for generic attribute references */ for (i = 0; i < linkedProg->NumInstructions; i++) { struct prog_instruction *inst = linkedProg->Instructions + i; for (j = 0; j < 3; j++) { if (inst->SrcReg[j].File == PROGRAM_INPUT && inst->SrcReg[j].Index >= VERT_ATTRIB_GENERIC0) { /* * OK, we've found a generic vertex attribute reference. */ const GLint k = inst->SrcReg[j].Index - VERT_ATTRIB_GENERIC0; GLint attr = attribMap[k]; if (attr < 0) { /* Need to figure out attribute mapping now. */ const char *name = origProg->Attributes->Parameters[k].Name; const GLint size = origProg->Attributes->Parameters[k].Size; const GLenum type =origProg->Attributes->Parameters[k].DataType; GLint index; /* See if there's a user-defined attribute binding for * this name. */ index = _mesa_lookup_parameter_index(shProg->Attributes, -1, name); if (index >= 0) { /* Found a user-defined binding */ attr = shProg->Attributes->Parameters[index].StateIndexes[0]; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -