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

📄 slang_emit.c

📁 Mesa is an open-source implementation of the OpenGL specification - a system for rendering interacti
💻 C
📖 第 1 页 / 共 4 页
字号:
static struct prog_instruction *emit_swizzle(slang_emit_info *emitInfo, slang_ir_node *n){   struct prog_instruction *inst;   inst = emit(emitInfo, n->Children[0]);   /* setup storage info, if needed */   if (!n->Store->Parent)      n->Store->Parent = n->Children[0]->Store;   assert(n->Store->Parent);   return inst;}/** * Dereference array element.  Just resolve storage for the array * element represented by this node. */static struct prog_instruction *emit_array_element(slang_emit_info *emitInfo, slang_ir_node *n){   slang_ir_storage *root;   assert(n->Opcode == IR_ELEMENT);   assert(n->Store);   assert(n->Store->File == PROGRAM_UNDEFINED);   assert(n->Store->Parent);   assert(n->Store->Size > 0);   root = n->Store;   while (root->Parent)      root = root->Parent;   if (root->File == PROGRAM_STATE_VAR) {      GLint index = _slang_alloc_statevar(n, emitInfo->prog->Parameters);      assert(n->Store->Index == index);      return NULL;   }   /* do codegen for array */   emit(emitInfo, n->Children[0]);   if (n->Children[1]->Opcode == IR_FLOAT) {      /* Constant array index.       * Set Store's index to be the offset of the array element in       * the register file.       */      const GLint element = (GLint) n->Children[1]->Value[0];      const GLint sz = (n->Store->Size + 3) / 4; /* size in slots/registers */      n->Store->Index = sz * element;      assert(n->Store->Parent);   }   else {      /* Variable array index */      struct prog_instruction *inst;      /* do codegen for array index expression */      emit(emitInfo, n->Children[1]);      inst = new_instruction(emitInfo, OPCODE_ARL);      storage_to_dst_reg(&inst->DstReg, n->Store, n->Writemask);      storage_to_src_reg(&inst->SrcReg[0], n->Children[1]->Store);      inst->DstReg.File = PROGRAM_ADDRESS;      inst->DstReg.Index = 0; /* always address register [0] */      inst->Comment = _mesa_strdup("ARL ADDR");      n->Store->RelAddr = GL_TRUE;   }   /* if array element size is one, make sure we only access X */   if (n->Store->Size == 1)      n->Store->Swizzle = SWIZZLE_XXXX;   return NULL; /* no instruction */}/** * Resolve storage for accessing a structure field. */static struct prog_instruction *emit_struct_field(slang_emit_info *emitInfo, slang_ir_node *n){   slang_ir_storage *root = n->Store;   assert(n->Opcode == IR_FIELD);   while (root->Parent)      root = root->Parent;   /* If this is the field of a state var, allocate constant/uniform    * storage for it now if we haven't already.    * Note that we allocate storage (uniform/constant slots) for state    * variables here rather than at declaration time so we only allocate    * space for the ones that we actually use!    */   if (root->File == PROGRAM_STATE_VAR) {      root->Index = _slang_alloc_statevar(n, emitInfo->prog->Parameters);      if (root->Index < 0) {         slang_info_log_error(emitInfo->log, "Error parsing state variable");         return NULL;      }   }   else {      /* do codegen for struct */      emit(emitInfo, n->Children[0]);   }   return NULL; /* no instruction */}/** * Emit code for a variable declaration. * This usually doesn't result in any code generation, but just * memory allocation. */static struct prog_instruction *emit_var_decl(slang_emit_info *emitInfo, slang_ir_node *n){   struct prog_instruction *inst;   assert(n->Store);   assert(n->Store->File != PROGRAM_UNDEFINED);   assert(n->Store->Size > 0);   /*assert(n->Store->Index < 0);*/   if (!n->Var || n->Var->isTemp) {      /* a nameless/temporary variable, will be freed after first use */      /*NEW*/      if (n->Store->Index < 0 && !_slang_alloc_temp(emitInfo->vt, n->Store)) {         slang_info_log_error(emitInfo->log,                              "Ran out of registers, too many temporaries");         return NULL;      }   }   else {      /* a regular variable */      _slang_add_variable(emitInfo->vt, n->Var);      if (!_slang_alloc_var(emitInfo->vt, n->Store)) {         slang_info_log_error(emitInfo->log,                              "Ran out of registers, too many variables");         return NULL;      }      /*        printf("IR_VAR_DECL %s %d store %p\n",        (char*) n->Var->a_name, n->Store->Index, (void*) n->Store);      */      assert(n->Var->aux == n->Store);   }   if (emitInfo->EmitComments) {      /* emit NOP with comment describing the variable's storage location */      char s[1000];      sprintf(s, "TEMP[%d]%s = variable %s (size %d)",              n->Store->Index,              _mesa_swizzle_string(n->Store->Swizzle, 0, GL_FALSE),               (n->Var ? (char *) n->Var->a_name : "anonymous"),              n->Store->Size);      inst = emit_comment(emitInfo, s);      return inst;   }   return NULL;}/** * Emit code for a reference to a variable. * Actually, no code is generated but we may do some memory alloation. * In particular, state vars (uniforms) are allocated on an as-needed basis. */static struct prog_instruction *emit_var_ref(slang_emit_info *emitInfo, slang_ir_node *n){   assert(n->Store);   assert(n->Store->File != PROGRAM_UNDEFINED);   if (n->Store->File == PROGRAM_STATE_VAR && n->Store->Index < 0) {      n->Store->Index = _slang_alloc_statevar(n, emitInfo->prog->Parameters);   }   else if (n->Store->File == PROGRAM_UNIFORM) {      /* mark var as used */      _mesa_use_uniform(emitInfo->prog->Parameters, (char *) n->Var->a_name);   }   if (n->Store->Index < 0) {      /* probably ran out of registers */      return NULL;   }   assert(n->Store->Size > 0);   return NULL;}static struct prog_instruction *emit(slang_emit_info *emitInfo, slang_ir_node *n){   struct prog_instruction *inst;   if (!n)      return NULL;   if (emitInfo->log->error_flag) {      return NULL;   }   switch (n->Opcode) {   case IR_SEQ:      /* sequence of two sub-trees */      assert(n->Children[0]);      assert(n->Children[1]);      emit(emitInfo, n->Children[0]);      if (emitInfo->log->error_flag)         return NULL;      inst = emit(emitInfo, n->Children[1]);#if 0      assert(!n->Store);#endif      n->Store = n->Children[1]->Store;      return inst;   case IR_SCOPE:      /* new variable scope */      _slang_push_var_table(emitInfo->vt);      inst = emit(emitInfo, n->Children[0]);      _slang_pop_var_table(emitInfo->vt);      return inst;   case IR_VAR_DECL:      /* Variable declaration - allocate a register for it */      inst = emit_var_decl(emitInfo, n);      return inst;   case IR_VAR:      /* Reference to a variable       * Storage should have already been resolved/allocated.       */      return emit_var_ref(emitInfo, n);   case IR_ELEMENT:      return emit_array_element(emitInfo, n);   case IR_FIELD:      return emit_struct_field(emitInfo, n);   case IR_SWIZZLE:      return emit_swizzle(emitInfo, n);   /* Simple arithmetic */   /* unary */   case IR_MOVE:   case IR_RSQ:   case IR_RCP:   case IR_FLOOR:   case IR_FRAC:   case IR_F_TO_I:   case IR_I_TO_F:   case IR_ABS:   case IR_SIN:   case IR_COS:   case IR_DDX:   case IR_DDY:   case IR_EXP:   case IR_EXP2:   case IR_LOG2:   case IR_NOISE1:   case IR_NOISE2:   case IR_NOISE3:   case IR_NOISE4:   /* binary */   case IR_ADD:   case IR_SUB:   case IR_MUL:   case IR_DOT4:   case IR_DOT3:   case IR_CROSS:   case IR_MIN:   case IR_MAX:   case IR_SEQUAL:   case IR_SNEQUAL:   case IR_SGE:   case IR_SGT:   case IR_SLE:   case IR_SLT:   case IR_POW:   /* trinary operators */   case IR_LRP:      return emit_arith(emitInfo, n);   case IR_EQUAL:   case IR_NOTEQUAL:      return emit_compare(emitInfo, n);   case IR_CLAMP:      return emit_clamp(emitInfo, n);   case IR_TEX:   case IR_TEXB:   case IR_TEXP:      return emit_tex(emitInfo, n);   case IR_NEG:      return emit_negation(emitInfo, n);   case IR_FLOAT:      /* find storage location for this float constant */      n->Store->Index = _mesa_add_unnamed_constant(emitInfo->prog->Parameters,                                                   n->Value,                                                   n->Store->Size,                                                   &n->Store->Swizzle);      if (n->Store->Index < 0) {         slang_info_log_error(emitInfo->log, "Ran out of space for constants");         return NULL;      }      return NULL;   case IR_COPY:      return emit_copy(emitInfo, n);   case IR_COND:      return emit_cond(emitInfo, n);   case IR_NOT:      return emit_not(emitInfo, n);   case IR_LABEL:      return emit_label(emitInfo, n);   case IR_KILL:      return emit_kill(emitInfo);   case IR_CALL:      /* new variable scope for subroutines/function calls */      _slang_push_var_table(emitInfo->vt);      inst = emit_fcall(emitInfo, n);      _slang_pop_var_table(emitInfo->vt);      return inst;   case IR_IF:      return emit_if(emitInfo, n);   case IR_LOOP:      return emit_loop(emitInfo, n);   case IR_BREAK_IF_TRUE:   case IR_CONT_IF_TRUE:      return emit_cont_break_if_true(emitInfo, n);   case IR_BREAK:      /* fall-through */   case IR_CONT:      return emit_cont_break(emitInfo, n);   case IR_BEGIN_SUB:      return new_instruction(emitInfo, OPCODE_BGNSUB);   case IR_END_SUB:      return new_instruction(emitInfo, OPCODE_ENDSUB);   case IR_RETURN:      return emit_return(emitInfo, n);   case IR_NOP:      return NULL;   default:      _mesa_problem(NULL, "Unexpected IR opcode in emit()\n");   }   return NULL;}/** * After code generation, any subroutines will be in separate program * objects.  This function appends all the subroutines onto the main * program and resolves the linking of all the branch/call instructions. * XXX this logic should really be part of the linking process... */static void_slang_resolve_subroutines(slang_emit_info *emitInfo){   GET_CURRENT_CONTEXT(ctx);   struct gl_program *mainP = emitInfo->prog;   GLuint *subroutineLoc, i, total;   subroutineLoc      = (GLuint *) _mesa_malloc(emitInfo->NumSubroutines * sizeof(GLuint));   /* total number of instructions */   total = mainP->NumInstructions;   for (i = 0; i < emitInfo->NumSubroutines; i++) {      subroutineLoc[i] = total;      total += emitInfo->Subroutines[i]->NumInstructions;   }   /* adjust BrancTargets within the functions */   for (i = 0; i < emitInfo->NumSubroutines; i++) {      struct gl_program *sub = emitInfo->Subroutines[i];      GLuint j;      for (j = 0; j < sub->NumInstructions; j++) {         struct prog_instruction *inst = sub->Instructions + j;         if (inst->Opcode != OPCODE_CAL && inst->BranchTarget >= 0) {            inst->BranchTarget += subroutineLoc[i];         }      }   }   /* append subroutines' instructions after main's instructions */   mainP->Instructions = _mesa_realloc_instructions(mainP->Instructions,                                                    mainP->NumInstructions,                                                    total);   mainP->NumInstructions = total;   for (i = 0; i < emitInfo->NumSubroutines; i++) {      struct gl_program *sub = emitInfo->Subroutines[i];      _mesa_copy_instructions(mainP->Instructions + subroutineLoc[i],                              sub->Instructions,                              sub->NumInstructions);      /* delete subroutine code */      sub->Parameters = NULL; /* prevent double-free */      _mesa_reference_program(ctx, &emitInfo->Subroutines[i], NULL);   }   /* free subroutine list */   if (emitInfo->Subroutines) {      _mesa_free(emitInfo->Subroutines);      emitInfo->Subroutines = NULL;   }   emitInfo->NumSubroutines = 0;   /* Examine CAL instructions.    * At this point, the BranchTarget field of the CAL instruction is    * the number/id of the subroutine to call (an index into the    * emitInfo->Subroutines list).    * Translate that into an actual instruction location now.    */   for (i = 0; i < mainP->NumInstructions; i++) {      struct prog_instruction *inst = mainP->Instructions + i;      if (inst->Opcode == OPCODE_CAL) {         const GLuint f = inst->BranchTarget;         inst->BranchTarget = subroutineLoc[f];      }   }   _mesa_free(subroutineLoc);}GLboolean_slang_emit_code(slang_ir_node *n, slang_var_table *vt,                 struct gl_program *prog, GLboolean withEnd,                 slang_info_log *log){   GET_CURRENT_CONTEXT(ctx);   GLboolean success;   slang_emit_info emitInfo;   GLuint maxUniforms;   emitInfo.log = log;   emitInfo.vt = vt;   emitInfo.prog = prog;   emitInfo.Subroutines = NULL;   emitInfo.NumSubroutines = 0;   emitInfo.EmitHighLevelInstructions = ctx->Shader.EmitHighLevelInstructions;   emitInfo.EmitCondCodes = ctx->Shader.EmitCondCodes;   emitInfo.EmitComments = ctx->Shader.EmitComments;   emitInfo.EmitBeginEndSub = GL_TRUE;   if (!emitInfo.EmitCondCodes) {      emitInfo.EmitHighLevelInstructions = GL_TRUE;   }         /* Check uniform/constant limits */   if (prog->Target == GL_FRAGMENT_PROGRAM_ARB) {      maxUniforms = ctx->Const.FragmentProgram.MaxUniformComponents / 4;   }   else {      assert(prog->Target == GL_VERTEX_PROGRAM_ARB);      maxUniforms = ctx->Const.VertexProgram.MaxUniformComponents / 4;   }   if (prog->Parameters->NumParameters > maxUniforms) {      slang_info_log_error(log, "Constant/uniform register limit exceeded");      return GL_FALSE;   }   (void) emit(&emitInfo, n);   /* finish up by adding the END opcode to program */   if (withEnd) {      struct prog_instruction *inst;      inst = new_instruction(&emitInfo, OPCODE_END);   }   _slang_resolve_subroutines(&emitInfo);   success = GL_TRUE;#if 0   printf("*********** End emit code (%u inst):\n", prog->NumInstructions);   _mesa_print_program(prog);   _mesa_print_program_parameters(ctx,prog);#endif   return success;}

⌨️ 快捷键说明

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