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

📄 slang_emit.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 4 页
字号:
/* * Mesa 3-D graphics library * Version:  7.1 * * Copyright (C) 2005-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_emit.c * Emit program instructions (PI code) from IR trees. * \author Brian Paul *//*** *** NOTES *** *** To emit GPU instructions, we basically just do an in-order traversal *** of the IR tree. ***/#include "main/imports.h"#include "main/context.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 "slang_builtin.h"#include "slang_emit.h"#include "slang_mem.h"#define PEEPHOLE_OPTIMIZATIONS 1#define ANNOTATE 0typedef struct{   slang_info_log *log;   slang_var_table *vt;   struct gl_program *prog;   struct gl_program **Subroutines;   GLuint NumSubroutines;   /* code-gen options */   GLboolean EmitHighLevelInstructions;   GLboolean EmitCondCodes;   GLboolean EmitComments;   GLboolean EmitBeginEndSub; /* XXX TEMPORARY */} slang_emit_info;static struct gl_program *new_subroutine(slang_emit_info *emitInfo, GLuint *id){   GET_CURRENT_CONTEXT(ctx);   const GLuint n = emitInfo->NumSubroutines;   emitInfo->Subroutines = (struct gl_program **)      _mesa_realloc(emitInfo->Subroutines,                    n * sizeof(struct gl_program),                    (n + 1) * sizeof(struct gl_program));   emitInfo->Subroutines[n] = ctx->Driver.NewProgram(ctx, emitInfo->prog->Target, 0);   emitInfo->Subroutines[n]->Parameters = emitInfo->prog->Parameters;   emitInfo->NumSubroutines++;   *id = n;   return emitInfo->Subroutines[n];}/** * Convert a writemask to a swizzle.  Used for testing cond codes because * we only want to test the cond code component(s) that was set by the * previous instruction. */static GLuintwritemask_to_swizzle(GLuint writemask){   if (writemask == WRITEMASK_X)      return SWIZZLE_XXXX;   if (writemask == WRITEMASK_Y)      return SWIZZLE_YYYY;   if (writemask == WRITEMASK_Z)      return SWIZZLE_ZZZZ;   if (writemask == WRITEMASK_W)      return SWIZZLE_WWWW;   return SWIZZLE_XYZW;  /* shouldn't be hit */}/** * Swizzle a swizzle (function composition). * That is, return swz2(swz1), or said another way: swz1.szw2 * Example: swizzle_swizzle(".zwxx", ".xxyw") yields ".zzwx" */GLuint_slang_swizzle_swizzle(GLuint swz1, GLuint swz2){   GLuint i, swz, s[4];   for (i = 0; i < 4; i++) {      GLuint c = GET_SWZ(swz2, i);      if (c <= SWIZZLE_W)         s[i] = GET_SWZ(swz1, c);      else         s[i] = c;   }   swz = MAKE_SWIZZLE4(s[0], s[1], s[2], s[3]);   return swz;}/** * Allocate storage for the given node (if it hasn't already been allocated). * * Typically this is temporary storage for an intermediate result (such as * for a multiply or add, etc). * * If n->Store does not exist it will be created and will be of the size * specified by defaultSize. */static GLbooleanalloc_node_storage(slang_emit_info *emitInfo, slang_ir_node *n,                   GLint defaultSize){   assert(!n->Var);   if (!n->Store) {      assert(defaultSize > 0);      n->Store = _slang_new_ir_storage(PROGRAM_TEMPORARY, -1, defaultSize);   }   /* now allocate actual register(s).  I.e. set n->Store->Index >= 0 */   if (n->Store->Index < 0) {      if (!_slang_alloc_temp(emitInfo->vt, n->Store)) {         slang_info_log_error(emitInfo->log,                              "Ran out of registers, too many temporaries");         _slang_free(n->Store);         n->Store = NULL;         return GL_FALSE;      }   }   return GL_TRUE;}/** * Free temporary storage, if n->Store is, in fact, temp storage. * Otherwise, no-op. */static voidfree_node_storage(slang_var_table *vt, slang_ir_node *n){   if (n->Store->File == PROGRAM_TEMPORARY &&       n->Store->Index >= 0 &&       n->Opcode != IR_SWIZZLE) {      if (_slang_is_temp(vt, n->Store)) {         _slang_free_temp(vt, n->Store);         n->Store->Index = -1;         n->Store = NULL; /* XXX this may not be needed */      }   }}/** * Helper function to allocate a short-term temporary. * Free it with _slang_free_temp(). */static GLbooleanalloc_local_temp(slang_emit_info *emitInfo, slang_ir_storage *temp, GLint size){   assert(size >= 1);   assert(size <= 4);   _mesa_bzero(temp, sizeof(*temp));   temp->Size = size;   temp->File = PROGRAM_TEMPORARY;   temp->Index = -1;   return _slang_alloc_temp(emitInfo->vt, temp);}/** * Remove any SWIZZLE_NIL terms from given swizzle mask. * For a swizzle like .z??? generate .zzzz (replicate single component). * Else, for .wx?? generate .wxzw (insert default component for the position). */static GLuintfix_swizzle(GLuint swizzle){   GLuint c0 = GET_SWZ(swizzle, 0),      c1 = GET_SWZ(swizzle, 1),      c2 = GET_SWZ(swizzle, 2),      c3 = GET_SWZ(swizzle, 3);   if (c1 == SWIZZLE_NIL && c2 == SWIZZLE_NIL && c3 == SWIZZLE_NIL) {      /* smear first component across all positions */      c1 = c2 = c3 = c0;   }   else {      /* insert default swizzle components */      if (c0 == SWIZZLE_NIL)         c0 = SWIZZLE_X;      if (c1 == SWIZZLE_NIL)         c1 = SWIZZLE_Y;      if (c2 == SWIZZLE_NIL)         c2 = SWIZZLE_Z;      if (c3 == SWIZZLE_NIL)         c3 = SWIZZLE_W;   }   return MAKE_SWIZZLE4(c0, c1, c2, c3);}/** * Convert IR storage to an instruction dst register. */static voidstorage_to_dst_reg(struct prog_dst_register *dst, const slang_ir_storage *st,                   GLuint writemask){   const GLint size = st->Size;   GLint index = st->Index;   GLuint swizzle = st->Swizzle;   /* if this is storage relative to some parent storage, walk up the tree */   while (st->Parent) {      st = st->Parent;      index += st->Index;      swizzle = _slang_swizzle_swizzle(st->Swizzle, swizzle);   }   assert(st->File != PROGRAM_UNDEFINED);   dst->File = st->File;   assert(index >= 0);   dst->Index = index;   assert(size >= 1);   assert(size <= 4);   if (size == 1) {      GLuint comp = GET_SWZ(swizzle, 0);      assert(comp < 4);      dst->WriteMask = WRITEMASK_X << comp;   }   else {      dst->WriteMask = writemask;   }}/** * Convert IR storage to an instruction src register. */static voidstorage_to_src_reg(struct prog_src_register *src, const slang_ir_storage *st){   const GLboolean relAddr = st->RelAddr;   GLint index = st->Index;   GLuint swizzle = st->Swizzle;   /* if this is storage relative to some parent storage, walk up the tree */   while (st->Parent) {      st = st->Parent;      index += st->Index;      swizzle = _slang_swizzle_swizzle(fix_swizzle(st->Swizzle), swizzle);   }   assert(st->File >= 0);#if 1 /* XXX temporary */   if (st->File == PROGRAM_UNDEFINED) {      slang_ir_storage *st0 = (slang_ir_storage *) st;      st0->File = PROGRAM_TEMPORARY;   }#endif   assert(st->File < PROGRAM_UNDEFINED);   src->File = st->File;   assert(index >= 0);   src->Index = index;   swizzle = fix_swizzle(swizzle);   assert(GET_SWZ(swizzle, 0) <= SWIZZLE_W);   assert(GET_SWZ(swizzle, 1) <= SWIZZLE_W);   assert(GET_SWZ(swizzle, 2) <= SWIZZLE_W);   assert(GET_SWZ(swizzle, 3) <= SWIZZLE_W);   src->Swizzle = swizzle;   src->RelAddr = relAddr;}/* * Setup an instrucion src register to point to a scalar constant. */static voidconstant_to_src_reg(struct prog_src_register *src, GLfloat val,                    slang_emit_info *emitInfo){   GLuint zeroSwizzle;   GLint zeroReg;   GLfloat value[4];   value[0] = val;   zeroReg = _mesa_add_unnamed_constant(emitInfo->prog->Parameters,                                        value, 1, &zeroSwizzle);   assert(zeroReg >= 0);   src->File = PROGRAM_CONSTANT;   src->Index = zeroReg;   src->Swizzle = zeroSwizzle;}/** * Add new instruction at end of given program. * \param prog  the program to append instruction onto * \param opcode  opcode for the new instruction * \return pointer to the new instruction */static struct prog_instruction *new_instruction(slang_emit_info *emitInfo, gl_inst_opcode opcode){   struct gl_program *prog = emitInfo->prog;   struct prog_instruction *inst;#if 0   /* print prev inst */   if (prog->NumInstructions > 0) {      _mesa_print_instruction(prog->Instructions + prog->NumInstructions - 1);   }#endif   prog->Instructions = _mesa_realloc_instructions(prog->Instructions,                                                   prog->NumInstructions,                                                   prog->NumInstructions + 1);   inst = prog->Instructions + prog->NumInstructions;   prog->NumInstructions++;   _mesa_init_instructions(inst, 1);   inst->Opcode = opcode;   inst->BranchTarget = -1; /* invalid */   /*   printf("New inst %d: %p %s\n", prog->NumInstructions-1,(void*)inst,          _mesa_opcode_string(inst->Opcode));   */   return inst;}/** * Return pointer to last instruction in program. */static struct prog_instruction *prev_instruction(slang_emit_info *emitInfo){   struct gl_program *prog = emitInfo->prog;   if (prog->NumInstructions == 0)      return NULL;   else      return prog->Instructions + prog->NumInstructions - 1;}static struct prog_instruction *emit(slang_emit_info *emitInfo, slang_ir_node *n);/** * Return an annotation string for given node's storage. */static char *storage_annotation(const slang_ir_node *n, const struct gl_program *prog){#if ANNOTATE   const slang_ir_storage *st = n->Store;   static char s[100] = "";   if (!st)      return _mesa_strdup("");   switch (st->File) {   case PROGRAM_CONSTANT:      if (st->Index >= 0) {         const GLfloat *val = prog->Parameters->ParameterValues[st->Index];         if (st->Swizzle == SWIZZLE_NOOP)            sprintf(s, "{%g, %g, %g, %g}", val[0], val[1], val[2], val[3]);         else {            sprintf(s, "%g", val[GET_SWZ(st->Swizzle, 0)]);         }      }      break;   case PROGRAM_TEMPORARY:      if (n->Var)         sprintf(s, "%s", (char *) n->Var->a_name);      else         sprintf(s, "t[%d]", st->Index);      break;   case PROGRAM_STATE_VAR:   case PROGRAM_UNIFORM:      sprintf(s, "%s", prog->Parameters->Parameters[st->Index].Name);      break;   case PROGRAM_VARYING:      sprintf(s, "%s", prog->Varying->Parameters[st->Index].Name);      break;   case PROGRAM_INPUT:      sprintf(s, "input[%d]", st->Index);      break;   case PROGRAM_OUTPUT:      sprintf(s, "output[%d]", st->Index);      break;   default:      s[0] = 0;   }   return _mesa_strdup(s);#else   return NULL;#endif}/** * Return an annotation string for an instruction. */static char *instruction_annotation(gl_inst_opcode opcode, char *dstAnnot,                       char *srcAnnot0, char *srcAnnot1, char *srcAnnot2){#if ANNOTATE   const char *operator;   char *s;   int len = 50;   if (dstAnnot)      len += strlen(dstAnnot);   else      dstAnnot = _mesa_strdup("");   if (srcAnnot0)      len += strlen(srcAnnot0);   else      srcAnnot0 = _mesa_strdup("");   if (srcAnnot1)      len += strlen(srcAnnot1);   else      srcAnnot1 = _mesa_strdup("");   if (srcAnnot2)      len += strlen(srcAnnot2);   else      srcAnnot2 = _mesa_strdup("");   switch (opcode) {   case OPCODE_ADD:      operator = "+";      break;   case OPCODE_SUB:      operator = "-";      break;   case OPCODE_MUL:      operator = "*";      break;   case OPCODE_DP3:      operator = "DP3";      break;   case OPCODE_DP4:      operator = "DP4";      break;   case OPCODE_XPD:      operator = "XPD";      break;   case OPCODE_RSQ:      operator = "RSQ";      break;   case OPCODE_SGT:      operator = ">";      break;   default:      operator = ",";   }   s = (char *) malloc(len);   sprintf(s, "%s = %s %s %s %s", dstAnnot,           srcAnnot0, operator, srcAnnot1, srcAnnot2);   assert(_mesa_strlen(s) < len);   free(dstAnnot);   free(srcAnnot0);   free(srcAnnot1);   free(srcAnnot2);

⌨️ 快捷键说明

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