📄 brw_vs_emit.c
字号:
}/* Post-vertex-program processing. Send the results to the URB. */static void emit_vertex_write( struct brw_vs_compile *c){ struct brw_compile *p = &c->func; struct brw_reg m0 = brw_message_reg(0); struct brw_reg pos = c->regs[PROGRAM_OUTPUT][VERT_RESULT_HPOS]; struct brw_reg ndc; if (c->key.copy_edgeflag) { brw_MOV(p, get_reg(c, PROGRAM_OUTPUT, VERT_RESULT_EDGE), get_reg(c, PROGRAM_INPUT, VERT_ATTRIB_EDGEFLAG)); } /* Build ndc coords? TODO: Shortcircuit when w is known to be one. */ if (!c->key.know_w_is_one) { ndc = get_tmp(c); emit_math1(c, BRW_MATH_FUNCTION_INV, ndc, brw_swizzle1(pos, 3), BRW_MATH_PRECISION_FULL); brw_MUL(p, brw_writemask(ndc, WRITEMASK_XYZ), pos, ndc); } else { ndc = pos; } /* This includes the workaround for -ve rhw, so is no longer an * optional step: */ if ((c->prog_data.outputs_written & (1<<VERT_RESULT_PSIZ)) || c->key.nr_userclip || !c->key.know_w_is_one) { struct brw_reg header1 = retype(get_tmp(c), BRW_REGISTER_TYPE_UD); GLuint i; brw_MOV(p, header1, brw_imm_ud(0)); brw_set_access_mode(p, BRW_ALIGN_16); if (c->prog_data.outputs_written & (1<<VERT_RESULT_PSIZ)) { struct brw_reg psiz = c->regs[PROGRAM_OUTPUT][VERT_RESULT_PSIZ]; brw_MUL(p, brw_writemask(header1, WRITEMASK_W), brw_swizzle1(psiz, 0), brw_imm_f(1<<11)); brw_AND(p, brw_writemask(header1, WRITEMASK_W), header1, brw_imm_ud(0x7ff<<8)); } for (i = 0; i < c->key.nr_userclip; i++) { brw_set_conditionalmod(p, BRW_CONDITIONAL_L); brw_DP4(p, brw_null_reg(), pos, c->userplane[i]); brw_OR(p, brw_writemask(header1, WRITEMASK_W), header1, brw_imm_ud(1<<i)); brw_set_predicate_control(p, BRW_PREDICATE_NONE); } /* i965 clipping workaround: * 1) Test for -ve rhw * 2) If set, * set ndc = (0,0,0,0) * set ucp[6] = 1 * * Later, clipping will detect ucp[6] and ensure the primitive is * clipped against all fixed planes. */ if (!(BRW_IS_GM45(p->brw) || BRW_IS_G4X(p->brw)) && !c->key.know_w_is_one) { brw_CMP(p, vec8(brw_null_reg()), BRW_CONDITIONAL_L, brw_swizzle1(ndc, 3), brw_imm_f(0)); brw_OR(p, brw_writemask(header1, WRITEMASK_W), header1, brw_imm_ud(1<<6)); brw_MOV(p, ndc, brw_imm_f(0)); brw_set_predicate_control(p, BRW_PREDICATE_NONE); } brw_set_access_mode(p, BRW_ALIGN_1); /* why? */ brw_MOV(p, retype(brw_message_reg(1), BRW_REGISTER_TYPE_UD), header1); brw_set_access_mode(p, BRW_ALIGN_16); release_tmp(c, header1); } else { brw_MOV(p, retype(brw_message_reg(1), BRW_REGISTER_TYPE_UD), brw_imm_ud(0)); } /* Emit the (interleaved) headers for the two vertices - an 8-reg * of zeros followed by two sets of NDC coordinates: */ brw_set_access_mode(p, BRW_ALIGN_1); brw_MOV(p, offset(m0, 2), ndc); brw_MOV(p, offset(m0, 3), pos); brw_urb_WRITE(p, brw_null_reg(), /* dest */ 0, /* starting mrf reg nr */ c->r0, /* src */ 0, /* allocate */ 1, /* used */ c->nr_outputs + 3, /* msg len */ 0, /* response len */ 1, /* eot */ 1, /* writes complete */ 0, /* urb destination offset */ BRW_URB_SWIZZLE_INTERLEAVE);}static void post_vs_emit( struct brw_vs_compile *c, struct brw_instruction *end_inst ){ GLuint nr_insns = c->vp->program.Base.NumInstructions; GLuint insn, target_insn; struct prog_instruction *inst1, *inst2; struct brw_instruction *brw_inst1, *brw_inst2; int offset; for (insn = 0; insn < nr_insns; insn++) { inst1 = &c->vp->program.Base.Instructions[insn]; brw_inst1 = inst1->Data; switch (inst1->Opcode) { case OPCODE_CAL: case OPCODE_BRA: target_insn = inst1->BranchTarget; inst2 = &c->vp->program.Base.Instructions[target_insn]; brw_inst2 = inst2->Data; offset = brw_inst2 - brw_inst1; brw_set_src1(brw_inst1, brw_imm_d(offset*16)); break; case OPCODE_END: offset = end_inst - brw_inst1; brw_set_src1(brw_inst1, brw_imm_d(offset*16)); break; default: break; } }}/* Emit the fragment program instructions here. */void brw_vs_emit(struct brw_vs_compile *c ){#define MAX_IFSN 32 struct brw_compile *p = &c->func; GLuint nr_insns = c->vp->program.Base.NumInstructions; GLuint insn, if_insn = 0; struct brw_instruction *end_inst; struct brw_instruction *if_inst[MAX_IFSN]; struct brw_indirect stack_index = brw_indirect(0, 0); GLuint index; GLuint file; if (INTEL_DEBUG & DEBUG_VS) { _mesa_printf("\n\n\nvs-emit:\n"); _mesa_print_program(&c->vp->program.Base); _mesa_printf("\n"); } brw_set_compression_control(p, BRW_COMPRESSION_NONE); brw_set_access_mode(p, BRW_ALIGN_16); /* Message registers can't be read, so copy the output into GRF register if they are used in source registers */ for (insn = 0; insn < nr_insns; insn++) { GLuint i; struct prog_instruction *inst = &c->vp->program.Base.Instructions[insn]; for (i = 0; i < 3; i++) { struct prog_src_register *src = &inst->SrcReg[i]; GLuint index = src->Index; GLuint file = src->File; if (file == PROGRAM_OUTPUT && index != VERT_RESULT_HPOS) c->output_regs[index].used_in_src = GL_TRUE; } } /* Static register allocation */ brw_vs_alloc_regs(c); brw_MOV(p, get_addr_reg(stack_index), brw_address(c->stack)); for (insn = 0; insn < nr_insns; insn++) { struct prog_instruction *inst = &c->vp->program.Base.Instructions[insn]; struct brw_reg args[3], dst; GLuint i; /* Get argument regs. SWZ is special and does this itself. */ inst->Data = &p->store[p->nr_insn]; if (inst->Opcode != OPCODE_SWZ) for (i = 0; i < 3; i++) { struct prog_src_register *src = &inst->SrcReg[i]; index = src->Index; file = src->File; if (file == PROGRAM_OUTPUT&&c->output_regs[index].used_in_src) args[i] = c->output_regs[index].reg; else args[i] = get_arg(c, src); } /* Get dest regs. Note that it is possible for a reg to be both * dst and arg, given the static allocation of registers. So * care needs to be taken emitting multi-operation instructions. */ index = inst->DstReg.Index; file = inst->DstReg.File; if (file == PROGRAM_OUTPUT && c->output_regs[index].used_in_src) dst = c->output_regs[index].reg; else dst = get_dst(c, inst->DstReg); switch (inst->Opcode) { case OPCODE_ABS: brw_MOV(p, dst, brw_abs(args[0])); break; case OPCODE_ADD: brw_ADD(p, dst, args[0], args[1]); break; case OPCODE_DP3: brw_DP3(p, dst, args[0], args[1]); break; case OPCODE_DP4: brw_DP4(p, dst, args[0], args[1]); break; case OPCODE_DPH: brw_DPH(p, dst, args[0], args[1]); break; case OPCODE_DST: unalias2(c, dst, args[0], args[1], emit_dst_noalias); break; case OPCODE_EXP: unalias1(c, dst, args[0], emit_exp_noalias); break; case OPCODE_EX2: emit_math1(c, BRW_MATH_FUNCTION_EXP, dst, args[0], BRW_MATH_PRECISION_FULL); break; case OPCODE_ARL: emit_arl(c, dst, args[0]); break; case OPCODE_FLR: brw_RNDD(p, dst, args[0]); break; case OPCODE_FRC: brw_FRC(p, dst, args[0]); break; case OPCODE_LOG: unalias1(c, dst, args[0], emit_log_noalias); break; case OPCODE_LG2: emit_math1(c, BRW_MATH_FUNCTION_LOG, dst, args[0], BRW_MATH_PRECISION_FULL); break; case OPCODE_LIT: unalias1(c, dst, args[0], emit_lit_noalias); break; case OPCODE_MAD: brw_MOV(p, brw_acc_reg(), args[2]); brw_MAC(p, dst, args[0], args[1]); break; case OPCODE_MAX: emit_max(p, dst, args[0], args[1]); break; case OPCODE_MIN: emit_min(p, dst, args[0], args[1]); break; case OPCODE_MOV: brw_MOV(p, dst, args[0]); break; case OPCODE_MUL: brw_MUL(p, dst, args[0], args[1]); break; case OPCODE_POW: emit_math2(c, BRW_MATH_FUNCTION_POW, dst, args[0], args[1], BRW_MATH_PRECISION_FULL); break; case OPCODE_RCP: emit_math1(c, BRW_MATH_FUNCTION_INV, dst, args[0], BRW_MATH_PRECISION_FULL); break; case OPCODE_RSQ: emit_math1(c, BRW_MATH_FUNCTION_RSQ, dst, args[0], BRW_MATH_PRECISION_FULL); break; case OPCODE_SEQ: emit_seq(p, dst, args[0], args[1]); break; case OPCODE_SNE: emit_sne(p, dst, args[0], args[1]); break; case OPCODE_SGE: emit_sge(p, dst, args[0], args[1]); break; case OPCODE_SGT: emit_sgt(p, dst, args[0], args[1]); break; case OPCODE_SLT: emit_slt(p, dst, args[0], args[1]); break; case OPCODE_SLE: emit_sle(p, dst, args[0], args[1]); break; case OPCODE_SUB: brw_ADD(p, dst, args[0], negate(args[1])); break; case OPCODE_SWZ: /* The args[0] value can't be used here as it won't have * correctly encoded the full swizzle: */ emit_swz(c, dst, inst->SrcReg[0] ); break; case OPCODE_XPD: emit_xpd(p, dst, args[0], args[1]); break; case OPCODE_IF: assert(if_insn < MAX_IFSN); if_inst[if_insn++] = brw_IF(p, BRW_EXECUTE_8); break; case OPCODE_ELSE: if_inst[if_insn-1] = brw_ELSE(p, if_inst[if_insn-1]); break; case OPCODE_ENDIF: assert(if_insn > 0); brw_ENDIF(p, if_inst[--if_insn]); break; case OPCODE_BRA: brw_set_predicate_control(p, BRW_PREDICATE_NORMAL); brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16)); brw_set_predicate_control_flag_value(p, 0xff); break; case OPCODE_CAL: brw_set_access_mode(p, BRW_ALIGN_1); brw_ADD(p, deref_1d(stack_index, 0), brw_ip_reg(), brw_imm_d(3*16)); brw_set_access_mode(p, BRW_ALIGN_16); brw_ADD(p, get_addr_reg(stack_index), get_addr_reg(stack_index), brw_imm_d(4)); inst->Data = &p->store[p->nr_insn]; brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16)); break; case OPCODE_RET: brw_ADD(p, get_addr_reg(stack_index), get_addr_reg(stack_index), brw_imm_d(-4)); brw_set_access_mode(p, BRW_ALIGN_1); brw_MOV(p, brw_ip_reg(), deref_1d(stack_index, 0)); brw_set_access_mode(p, BRW_ALIGN_16); case OPCODE_END: brw_ADD(p, brw_ip_reg(), brw_ip_reg(), brw_imm_d(1*16)); break; case OPCODE_PRINT: case OPCODE_BGNSUB: case OPCODE_ENDSUB: break; default: _mesa_printf("Unsupport opcode %d in vertex shader\n", inst->Opcode); break; } if ((inst->DstReg.File == PROGRAM_OUTPUT) && (inst->DstReg.Index != VERT_RESULT_HPOS) && c->output_regs[inst->DstReg.Index].used_in_src) { brw_MOV(p, get_dst(c, inst->DstReg), dst); } /* Result color clamping. * * When destination register is an output register and * it's primary/secondary front/back color, we have to clamp * the result to [0,1]. This is done by enabling the * saturation bit for the last instruction. * * We don't use brw_set_saturate() as it modifies * p->current->header.saturate, which affects all the subsequent * instructions. Instead, we directly modify the header * of the last (already stored) instruction. */ if (inst->DstReg.File == PROGRAM_OUTPUT) { if ((inst->DstReg.Index == VERT_RESULT_COL0) || (inst->DstReg.Index == VERT_RESULT_COL1) || (inst->DstReg.Index == VERT_RESULT_BFC0) || (inst->DstReg.Index == VERT_RESULT_BFC1)) { p->store[p->nr_insn-1].header.saturate = 1; } } release_tmps(c); } end_inst = &p->store[p->nr_insn]; emit_vertex_write(c); post_vs_emit(c, end_inst); for (insn = 0; insn < nr_insns; insn++) c->vp->program.Base.Instructions[insn].Data = NULL;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -