⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 slang_link.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * 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 + -