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

📄 slang_link.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 2 页
字号:
               else {                  /* No user-defined binding, choose our own attribute number.                   * Start at 1 since generic attribute 0 always aliases                   * glVertex/position.                   */                  for (attr = 1; attr < MAX_VERTEX_ATTRIBS; attr++) {                     if (((1 << attr) & usedAttributes) == 0)                        break;                  }                  if (attr == MAX_VERTEX_ATTRIBS) {                     link_error(shProg, "Too many vertex attributes");                     return GL_FALSE;                  }                  /* mark this attribute as used */                  usedAttributes |= (1 << attr);               }               attribMap[k] = attr;               /* Save the final name->attrib binding so it can be queried                * with glGetAttributeLocation().                */               _mesa_add_attribute(linkedProg->Attributes, name,                                   size, type, attr);            }            assert(attr >= 0);            /* update the instruction's src reg */            inst->SrcReg[j].Index = VERT_ATTRIB_GENERIC0 + attr;         }      }   }   return GL_TRUE;}/** * Scan program instructions to update the program's NumTemporaries field. * Note: this implemenation relies on the code generator allocating * temps in increasing order (0, 1, 2, ... ). */static void_slang_count_temporaries(struct gl_program *prog){   GLuint i, j;   GLint maxIndex = -1;   for (i = 0; i < prog->NumInstructions; i++) {      const struct prog_instruction *inst = prog->Instructions + i;      const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);      for (j = 0; j < numSrc; j++) {         if (inst->SrcReg[j].File == PROGRAM_TEMPORARY) {            if (maxIndex < inst->SrcReg[j].Index)               maxIndex = inst->SrcReg[j].Index;         }         if (inst->DstReg.File == PROGRAM_TEMPORARY) {            if (maxIndex < (GLint) inst->DstReg.Index)               maxIndex = inst->DstReg.Index;         }      }   }   prog->NumTemporaries = (GLuint) (maxIndex + 1);}/** * Scan program instructions to update the program's InputsRead and * OutputsWritten fields. */static void_slang_update_inputs_outputs(struct gl_program *prog){   GLuint i, j;   prog->InputsRead = 0x0;   prog->OutputsWritten = 0x0;   for (i = 0; i < prog->NumInstructions; i++) {      const struct prog_instruction *inst = prog->Instructions + i;      const GLuint numSrc = _mesa_num_inst_src_regs(inst->Opcode);      for (j = 0; j < numSrc; j++) {         if (inst->SrcReg[j].File == PROGRAM_INPUT) {            prog->InputsRead |= 1 << inst->SrcReg[j].Index;         }      }      if (inst->DstReg.File == PROGRAM_OUTPUT) {         prog->OutputsWritten |= 1 << inst->DstReg.Index;      }   }}/** cast wrapper */static struct gl_vertex_program *vertex_program(struct gl_program *prog){   assert(prog->Target == GL_VERTEX_PROGRAM_ARB);   return (struct gl_vertex_program *) prog;}/** cast wrapper */static struct gl_fragment_program *fragment_program(struct gl_program *prog){   assert(prog->Target == GL_FRAGMENT_PROGRAM_ARB);   return (struct gl_fragment_program *) prog;}/** * Shader linker.  Currently: * * 1. The last attached vertex shader and fragment shader are linked. * 2. Varying vars in the two shaders are combined so their locations *    agree between the vertex and fragment stages.  They're treated as *    vertex program output attribs and as fragment program input attribs. * 3. The vertex and fragment programs are cloned and modified to update *    src/dst register references so they use the new, linked varying *    storage locations. */void_slang_link(GLcontext *ctx,            GLhandleARB programObj,            struct gl_shader_program *shProg){   const struct gl_vertex_program *vertProg;   const struct gl_fragment_program *fragProg;   GLuint numSamplers = 0;   GLuint i;   _mesa_clear_shader_program_data(ctx, shProg);   /* check that all programs compiled successfully */   for (i = 0; i < shProg->NumShaders; i++) {      if (!shProg->Shaders[i]->CompileStatus) {         link_error(shProg, "linking with uncompiled shader\n");         return;      }   }   shProg->Uniforms = _mesa_new_uniform_list();   shProg->Varying = _mesa_new_parameter_list();   /**    * Find attached vertex, fragment shaders defining main()    */   vertProg = NULL;   fragProg = NULL;   for (i = 0; i < shProg->NumShaders; i++) {      struct gl_shader *shader = shProg->Shaders[i];      if (shader->Type == GL_VERTEX_SHADER && shader->Main)         vertProg = vertex_program(shader->Program);      else if (shader->Type == GL_FRAGMENT_SHADER && shader->Main)         fragProg = fragment_program(shader->Program);      else         _mesa_problem(ctx, "unexpected shader target in slang_link()");   }#if FEATURE_es2_glsl   /* must have both a vertex and fragment program for ES2 */   if (!vertProg) {      link_error(shProg, "missing vertex shader\n");      return;   }   if (!fragProg) {      link_error(shProg, "missing fragment shader\n");      return;   }#endif   /*    * Make copies of the vertex/fragment programs now since we'll be    * changing src/dst registers after merging the uniforms and varying vars.    */   _mesa_reference_vertprog(ctx, &shProg->VertexProgram, NULL);   if (vertProg) {      struct gl_vertex_program *linked_vprog =         vertex_program(_mesa_clone_program(ctx, &vertProg->Base));      shProg->VertexProgram = linked_vprog; /* refcount OK */      ASSERT(shProg->VertexProgram->Base.RefCount == 1);   }   _mesa_reference_fragprog(ctx, &shProg->FragmentProgram, NULL);   if (fragProg) {      struct gl_fragment_program *linked_fprog =          fragment_program(_mesa_clone_program(ctx, &fragProg->Base));      shProg->FragmentProgram = linked_fprog; /* refcount OK */      ASSERT(shProg->FragmentProgram->Base.RefCount == 1);   }   /* link varying vars */   if (shProg->VertexProgram) {      if (!link_varying_vars(shProg, &shProg->VertexProgram->Base))         return;   }   if (shProg->FragmentProgram) {      if (!link_varying_vars(shProg, &shProg->FragmentProgram->Base))         return;   }   /* link uniform vars */   if (shProg->VertexProgram)      link_uniform_vars(shProg, &shProg->VertexProgram->Base, &numSamplers);   if (shProg->FragmentProgram)      link_uniform_vars(shProg, &shProg->FragmentProgram->Base, &numSamplers);   /*_mesa_print_uniforms(shProg->Uniforms);*/   if (shProg->VertexProgram) {      if (!_slang_resolve_attributes(shProg, &vertProg->Base,                                     &shProg->VertexProgram->Base)) {         return;      }   }   if (shProg->VertexProgram) {      _slang_update_inputs_outputs(&shProg->VertexProgram->Base);      _slang_count_temporaries(&shProg->VertexProgram->Base);      if (!(shProg->VertexProgram->Base.OutputsWritten & (1 << VERT_RESULT_HPOS))) {         /* the vertex program did not compute a vertex position */         link_error(shProg,                    "gl_Position was not written by vertex shader\n");         return;      }   }   if (shProg->FragmentProgram) {      _slang_count_temporaries(&shProg->FragmentProgram->Base);      _slang_update_inputs_outputs(&shProg->FragmentProgram->Base);   }   /* Check that all the varying vars needed by the fragment shader are    * actually produced by the vertex shader.    */   if (shProg->FragmentProgram) {      const GLbitfield varyingRead         = shProg->FragmentProgram->Base.InputsRead >> FRAG_ATTRIB_VAR0;      const GLbitfield varyingWritten = shProg->VertexProgram ?         shProg->VertexProgram->Base.OutputsWritten >> VERT_RESULT_VAR0 : 0x0;      if ((varyingRead & varyingWritten) != varyingRead) {         link_error(shProg,          "Fragment program using varying vars not written by vertex shader\n");         return;      }            }   if (fragProg && shProg->FragmentProgram) {      /* notify driver that a new fragment program has been compiled/linked */      ctx->Driver.ProgramStringNotify(ctx, GL_FRAGMENT_PROGRAM_ARB,                                      &shProg->FragmentProgram->Base);#if 0      printf("************** original fragment program\n");      _mesa_print_program(&fragProg->Base);      _mesa_print_program_parameters(ctx, &fragProg->Base);#endif#if 0      printf("************** linked fragment prog\n");      _mesa_print_program(&shProg->FragmentProgram->Base);      _mesa_print_program_parameters(ctx, &shProg->FragmentProgram->Base);#endif   }   if (vertProg && shProg->VertexProgram) {      /* notify driver that a new vertex program has been compiled/linked */      ctx->Driver.ProgramStringNotify(ctx, GL_VERTEX_PROGRAM_ARB,                                      &shProg->VertexProgram->Base);#if 0      printf("************** original vertex program\n");      _mesa_print_program(&vertProg->Base);      _mesa_print_program_parameters(ctx, &vertProg->Base);#endif#if 0      printf("************** linked vertex prog\n");      _mesa_print_program(&shProg->VertexProgram->Base);      _mesa_print_program_parameters(ctx, &shProg->VertexProgram->Base);#endif   }   shProg->LinkStatus = (shProg->VertexProgram || shProg->FragmentProgram);}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -