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

📄 ps_1_4.cpp

📁 使用stl技术,(还没看,是听说的)
💻 CPP
📖 第 1 页 / 共 5 页
字号:
		case sid_CMP:
		case sid_CND:
		case sid_DP2ADD:
		case sid_DP3:
		case sid_DP4:
			mOpType = (MachineInstID)(mi_COLOROP1 + mArgCnt - 1);

			// if context is ps.1.x and Macro not on or a phase marker was found then put all ALU ops in phase 2 ALU container
			if (((mActiveContexts & ckp_PS_1_1) && !mMacroOn) || mPhaseMarkerFound) mInstructionPhase = ptPHASE2ALU;
			else mInstructionPhase = ptPHASE1ALU;
			// check for alpha op in destination register which is OpParrams[0]
			// if no Mask for destination then make it .rgba
			if(mOpParrams[0].MaskRep == 0) mOpParrams[0].MaskRep =
			GL_RED_BIT_ATI | GL_GREEN_BIT_ATI | GL_BLUE_BIT_ATI | ALPHA_BIT;
			if (mOpParrams[0].MaskRep & ALPHA_BIT) {
				mDo_Alpha = true;
				mOpParrams[0].MaskRep -= ALPHA_BIT;
				if(mOpParrams[0].MaskRep == 0) mOpType = mi_NOP; // only do alpha op
			}
			break;

		case sid_TEXCRD:
			mOpType = mi_PASSTEXCOORD;
			if (mPhaseMarkerFound) mInstructionPhase = ptPHASE2TEX;
			else mInstructionPhase = ptPHASE1TEX;
			break;

		case sid_TEXLD:
			mOpType = mi_SAMPLEMAP;
			if (mPhaseMarkerFound) mInstructionPhase = ptPHASE2TEX;
			else mInstructionPhase = ptPHASE1TEX;
			break;

		case sid_TEX: // PS_1_1 emulation
			mOpType = mi_TEX;
			mInstructionPhase = ptPHASE1TEX;
			break;

		case sid_TEXCOORD: // PS_1_1 emulation
			mOpType = mi_TEXCOORD;
			mInstructionPhase = ptPHASE1TEX;
			break;

		case sid_TEXREG2AR:
			passed = expandMacro(texreg2ar_MacroMods);
			break;

		case sid_TEXREG2GB:
			passed = expandMacro(texreg2gb_MacroMods);
			break;

		case sid_TEXDP3:
			passed = expandMacro(texdp3_MacroMods);
			break;

		case sid_TEXDP3TEX:
			passed = expandMacro(texdp3tex_MacroMods);
			break;

		case sid_TEXM3X2PAD:
			passed = expandMacro(texm3x2pad_MacroMods);
			break;

		case sid_TEXM3X2TEX:
			passed = expandMacro(texm3x2tex_MacroMods);
			break;

		case sid_TEXM3X3PAD:
			// only 2 texm3x3pad instructions allowed
			// use count to modify macro to select which mask to use
			if(mTexm3x3padCount<2) {
				texm3x3pad[4].mID = sid_R + mTexm3x3padCount;
				mTexm3x3padCount++;
				passed = expandMacro(texm3x3pad_MacroMods);

			}
			else passed = false;

			break;

		case sid_TEXM3X3TEX:
			passed = expandMacro(texm3x3tex_MacroMods);
			break;

		case sid_DEF:
			mOpType = mi_SETCONSTANTS;
			mInstructionPhase = ptPHASE1TEX;
			break;

		case sid_PHASE: // PS_1_4 only
			mPhaseMarkerFound = true;
			break;

	} // end of switch

	if(passed) passed = expandMachineInstruction();

	return passed;
}


bool PS_1_4::expandMachineInstruction()
{
	// now push instructions onto MachineInstructions container
	// assume that an instruction will be expanded
	bool passed = true;

	if (mOpType != mi_NOP) {

		// a machine instruction will be built
		// this is currently the last one being built so keep track of it
		if (mInstructionPhase == ptPHASE2ALU) { 
			mSecondLastInstructionPos = mLastInstructionPos;
			mLastInstructionPos = mPhase2ALU_mi.size();
		}


		switch (mOpType) {
			case mi_COLOROP1:
			case mi_COLOROP2:
			case mi_COLOROP3:
				{
					addMachineInst(mInstructionPhase, mOpType);
					addMachineInst(mInstructionPhase, mSymbolTypeLib[mOpInst].mPass2Data);
					// send all parameters to machine inst container
					for(int i=0; i<=mArgCnt; i++) {
						addMachineInst(mInstructionPhase, mOpParrams[i].Arg);
						addMachineInst(mInstructionPhase, mOpParrams[i].MaskRep);
						addMachineInst(mInstructionPhase, mOpParrams[i].Mod);
						// check if source register read is valid in this phase
						passed &= isRegisterReadValid(mInstructionPhase, i);
					}

					// record which registers were written to and in which phase
					// mOpParrams[0].Arg is always the destination register r0 -> r5
					updateRegisterWriteState(mInstructionPhase);

				}
				break;

			case mi_SETCONSTANTS:
				addMachineInst(mInstructionPhase, mOpType);
				addMachineInst(mInstructionPhase, mOpParrams[0].Arg); // dst
				addMachineInst(mInstructionPhase, mConstantsPos); // index into constants array
				break;

			case mi_PASSTEXCOORD:
			case mi_SAMPLEMAP:
				// if source is a temp register than place instruction in phase 2 Texture ops
				if ((mOpParrams[1].Arg >= GL_REG_0_ATI) && (mOpParrams[1].Arg <= GL_REG_5_ATI)) {
					mInstructionPhase = ptPHASE2TEX;
				}

				addMachineInst(mInstructionPhase, mOpType);
				addMachineInst(mInstructionPhase, mOpParrams[0].Arg); // dst
				addMachineInst(mInstructionPhase, mOpParrams[1].Arg); // coord
				addMachineInst(mInstructionPhase, mOpParrams[1].MaskRep + GL_SWIZZLE_STR_ATI); // swizzle
				// record which registers were written to and in which phase
				// mOpParrams[0].Arg is always the destination register r0 -> r5
				updateRegisterWriteState(mInstructionPhase);
				break;

			case mi_TEX: // PS_1_1 emulation - turn CISC into RISC - phase 1
				addMachineInst(mInstructionPhase, mi_SAMPLEMAP);
				addMachineInst(mInstructionPhase, mOpParrams[0].Arg); // dst
				// tex tx becomes texld rx, tx with x: 0 - 3
				addMachineInst(mInstructionPhase, mOpParrams[0].Arg - GL_REG_0_ATI + GL_TEXTURE0_ARB); // interp
				// default to str which fills rgb of destination register
				addMachineInst(mInstructionPhase, GL_SWIZZLE_STR_ATI); // swizzle
				// record which registers were written to and in which phase
				// mOpParrams[0].Arg is always the destination register r0 -> r5
				updateRegisterWriteState(mInstructionPhase);
				break;

			case mi_TEXCOORD: // PS_1_1 emulation - turn CISC into RISC - phase 1
				addMachineInst(mInstructionPhase, mi_PASSTEXCOORD);
				addMachineInst(mInstructionPhase, mOpParrams[0].Arg); // dst
				// texcoord tx becomes texcrd rx, tx with x: 0 - 3
				addMachineInst(mInstructionPhase, mOpParrams[0].Arg - GL_REG_0_ATI + GL_TEXTURE0_ARB); // interp
				// default to str which fills rgb of destination register
				addMachineInst(mInstructionPhase, GL_SWIZZLE_STR_ATI); // swizzle
				// record which registers were written to and in which phase
				// mOpParrams[0].Arg is always the destination register r0 -> r5
				updateRegisterWriteState(mInstructionPhase);
				break;

	


		} // end of switch (mOpType)
	} // end of if (mOpType != mi_NOP)

	if(mDo_Alpha) {
		// process alpha channel
		//
		// a scaler machine instruction will be built
		// this is currently the last one being built so keep track of it
		if (mInstructionPhase == ptPHASE2ALU) { 
			mSecondLastInstructionPos = mLastInstructionPos;
			mLastInstructionPos = mPhase2ALU_mi.size();
		}

		MachineInstID alphaoptype = (MachineInstID)(mi_ALPHAOP1 + mArgCnt - 1);
		addMachineInst(mInstructionPhase, alphaoptype);
		addMachineInst(mInstructionPhase, mSymbolTypeLib[mOpInst].mPass2Data);
		// put all parameters in instruction que
		for(int i=0; i<=mArgCnt; i++) {
			addMachineInst(mInstructionPhase, mOpParrams[i].Arg);
			// destination parameter has no mask since it is the alpha channel
			// don't push mask for parrameter 0 (dst)
			if(i>0) addMachineInst(mInstructionPhase, mOpParrams[i].MaskRep);
			addMachineInst(mInstructionPhase, mOpParrams[i].Mod);
			// check if source register read is valid in this phase
			passed &= isRegisterReadValid(mInstructionPhase, i);
		}

		updateRegisterWriteState(mInstructionPhase);
	}

	// instruction passed on to machine instruction so clear the pipe
	clearMachineInstState();

	return passed;

}


void PS_1_4::updateRegisterWriteState(const PhaseType phase)
{
	int reg_offset = mOpParrams[0].Arg - GL_REG_0_ATI;

	switch(phase) {

		case ptPHASE1TEX:
		case ptPHASE1ALU:
			Phase_RegisterUsage[reg_offset].Phase1Write = true;
			break;

		case ptPHASE2TEX:
		case ptPHASE2ALU:
			Phase_RegisterUsage[reg_offset].Phase2Write = true;
			break;

	} // end switch(phase)

}


bool PS_1_4::isRegisterReadValid(const PhaseType phase, const int param)
{
	bool passed = true; // assume everything will go alright
	// if in phase 2 ALU and argument is a source
	if((phase == ptPHASE2ALU) && (param>0)) {
		// is source argument a temp register r0 - r5?
		if((mOpParrams[param].Arg >= GL_REG_0_ATI) && (mOpParrams[param].Arg <= GL_REG_5_ATI)) {
			int reg_offset = mOpParrams[param].Arg - GL_REG_0_ATI;
			// if register was not written to in phase 2 but was in phase 1
			if((Phase_RegisterUsage[reg_offset].Phase2Write == false) && Phase_RegisterUsage[reg_offset].Phase1Write) {
				// only perform register pass if there are ALU instructions in phase 1
				
				if(mPhase1ALU_mi.size() > 0) {
					// build machine instructions for passing a register from phase 1 to phase 2
					// NB: only rgb components of register will get passed

					addMachineInst(ptPHASE2TEX, mi_PASSTEXCOORD);
					addMachineInst(ptPHASE2TEX, mOpParrams[param].Arg); // dst
					addMachineInst(ptPHASE2TEX, mOpParrams[param].Arg); // coord
					addMachineInst(ptPHASE2TEX, GL_SWIZZLE_STR_ATI); // swizzle
					// mark register as being written to
					Phase_RegisterUsage[reg_offset].Phase2Write = true;
				}

			}
			// register can not be used because it has not been written to previously
			else passed = false;
		}

	}

	return passed;

}


void PS_1_4::optimize()
{
	// perform some optimizations on ps.1.1 machine instructions
	if (mActiveContexts & ckp_PS_1_1) {
		// need to check last few instructions to make sure r0 is set
		// ps.1.1 emulation uses r4 for r0 so last couple of instructions will probably require
		// changine destination register back to r0
		if (mLastInstructionPos < mPhase2ALU_mi.size()) {
			// first argument at mLastInstructionPos + 2 is destination register for all ps.1.1 ALU instructions
			mPhase2ALU_mi[mLastInstructionPos + 2] = GL_REG_0_ATI; 
			// if was an alpha op only then modify second last instruction destination register
			if ((mPhase2ALU_mi[mLastInstructionPos] == mi_ALPHAOP1) ||
				(mPhase2ALU_mi[mLastInstructionPos] == mi_ALPHAOP2) ||
				(mPhase2ALU_mi[mLastInstructionPos] == mi_ALPHAOP3)
				
				) {

				mPhase2ALU_mi[mSecondLastInstructionPos + 2] = GL_REG_0_ATI; 
			}

		}// end if (mLastInstructionPos < mMachineInstructions.size())

	}// end if (mActiveContexts & ckp_PS_1_1)

}


void PS_1_4::clearMachineInstState()
{
	// set current Machine Instruction State to baseline
	mOpType = mi_NOP;
	mOpInst = sid_INVALID;
	mDo_Alpha = false;
	mArgCnt = 0;

	for(int i=0; i<MAXOPPARRAMS; i++) {
		mOpParrams[i].Arg = GL_NONE;
		mOpParrams[i].Filled = false;
		mOpParrams[i].MaskRep = GL_NONE;
		mOpParrams[i].Mod = GL_NONE;
	}

}


void PS_1_4::clearAllMachineInst()
{

	mPhase1TEX_mi.clear();
	mPhase1ALU_mi.clear();
	mPhase2TEX_mi.clear();
	mPhase2ALU_mi.clear();

	// reset write state for all registers
	for(int i = 0; i<6; i++) {
		Phase_RegisterUsage[i].Phase1Write = false;
		Phase_RegisterUsage[i].Phase2Write = false;

	}

	mPhaseMarkerFound = false;
	mConstantsPos = -4;
	// keep track of the last instruction built
	// this info is used at the end of pass 2 to optimize the machine code
	mLastInstructionPos = 0;
	mSecondLastInstructionPos = 0;

	mMacroOn = false;  // macro's off at the beginning
	mTexm3x3padCount = 0;

}

bool PS_1_4::doPass2()
{
	clearAllMachineInst();
	// if pass 2 was successful, optimize the machine instructions
	bool passed = Pass2scan(&mTokenInstructions[0], mTokenInstructions.size());
	if (passed) optimize();  

	return passed;

}


bool PS_1_4::Pass2scan(const TokenInst * Tokens, const size_t size)
{

	// execute TokenInstructions to build MachineInstructions
	bool passed = true;
	SymbolDef* cursymboldef;
	uint ActiveNTTRuleID;

	clearMachineInstState();


	// iterate through all the tokens and build machine instruction
	// for each machine instruction need: optype, opinst, and up to 5 parameters
	for(uint i = 0; i < size; i++) {
		// lookup instruction type in library

		cursymboldef = &mSymbolTypeLib[Tokens[i].mID];
		ActiveNTTRuleID = Tokens[i].mNTTRuleID;
		mCurrentLine = Tokens[i].mLine;
		mCharPos = Tokens[i].mPos;

		switch(ActiveNTTRuleID) {

			case sid_CONSTANT:
			case sid_COLOR:
			case sid_REG_PS1_4:
			case sid_TEX_PS1_4:
			case sid_REG_PS1_1_3:
			case sid_TEX_PS1_1_3:
				// registars can be used for read and write so they can be used for dst and arg
				passed = setOpParram(cursymboldef);
				break;


			case sid_DEFCONST:
			case sid_UNARYOP:
			case sid_BINARYOP:
			case sid_TERNARYOP:
			case sid_TEXOP_PS1_1_3:
			case sid_TEXOP_PS1_4:
			case sid_PHASEMARKER:
			case sid_TEXCISCOP_PS1_1_3:
				// if the last instruction has not been passed on then do it now
				// make sure the pipe is clear for a new instruction
				BuildMachineInst();
				if(mOpInst == sid_INVALID) {
					mOpInst = cursymboldef->mID;
				}
				else passed = false;
				break;

			case sid_DSTMASK:
			case sid_SRCREP:
			case sid_TEXSWIZZLE:

⌨️ 快捷键说明

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