mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1673 lines
82 KiB
1673 lines
82 KiB
///////////////////////////////////////////////////////////////////////////////
|
|
// Copyright (C) Microsoft Corporation, 2000.
|
|
//
|
|
// pixshade.cpp
|
|
//
|
|
// Direct3D Reference Device - Pixel Shader
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
//-----------------------------------------------------------------------------
|
|
RDPShader::RDPShader(void)
|
|
{
|
|
m_pRD = NULL;
|
|
m_pCode = NULL;
|
|
m_CodeSize = 0;
|
|
m_cActiveTextureStages = 0;
|
|
m_ReferencedTexCoordMask = 0;
|
|
m_cInst = 0;
|
|
m_pInst = NULL;
|
|
m_cConstDefs = 0;
|
|
m_pConstDefs = NULL;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
RDPShader::~RDPShader()
|
|
{
|
|
if (NULL != m_pCode) delete[] m_pCode;
|
|
if (NULL != m_pInst) delete[] m_pInst;
|
|
if (NULL != m_pConstDefs) delete[] m_pConstDefs;
|
|
}
|
|
|
|
#define _DWordCount() (pToken - pCode)
|
|
|
|
#define _RegisterNeedsToBeInitializedWithTexcoords(Reg) (*pReferencedTexCoordMask)|=(1<<Reg);
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// UpdateReferencedTexCoords
|
|
//
|
|
// Called for each instruction while parsing a 1.3 pixelshader.
|
|
// Updates pReferencedTexCoordMask (bitfield) to represent
|
|
// which texture coordinate sets are actually used by the shader.
|
|
// This is used to eliminate unnecessary attribute setup/sampling during
|
|
// primitive rasterization.
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
void UpdateReferencedTexCoords(PixelShaderInstruction* pInst,
|
|
DWORD* pReferencedTexCoordMask )
|
|
{
|
|
switch( pInst->Opcode & D3DSI_OPCODE_MASK )
|
|
{
|
|
case D3DSIO_TEX:
|
|
case D3DSIO_TEXCOORD:
|
|
case D3DSIO_TEXDEPTH:
|
|
{
|
|
for( UINT i = 0; i < 3; i++ )
|
|
{
|
|
UINT RegNum = pInst->SrcParam[i] & 0xFF;
|
|
if( D3DSPR_TEXTURE == (pInst->SrcParam[i] & D3DSP_REGTYPE_MASK) )
|
|
_RegisterNeedsToBeInitializedWithTexcoords(RegNum);
|
|
}
|
|
}
|
|
break;
|
|
case D3DSIO_TEXKILL: // treat dest param as source
|
|
{
|
|
UINT RegNum = pInst->DstParam & 0xFF;
|
|
if( D3DSPR_TEXTURE == (pInst->DstParam & D3DSP_REGTYPE_MASK) )
|
|
_RegisterNeedsToBeInitializedWithTexcoords(RegNum);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
void CalculateSourceReadMasks(PixelShaderInstruction* pInst, BYTE* pSourceReadMasks, BOOL bAfterSwizzle, DWORD dwVersion)
|
|
{
|
|
UINT i, j;
|
|
DWORD Opcode = pInst->Opcode & D3DSI_OPCODE_MASK;
|
|
BYTE ComponentMask[4]= {RDPS_COMPONENTMASK_0, RDPS_COMPONENTMASK_1, RDPS_COMPONENTMASK_2, RDPS_COMPONENTMASK_3};
|
|
|
|
for( i = 0; i < pInst->SrcParamCount; i++ )
|
|
{
|
|
BYTE NeededComponents;
|
|
BYTE ReadComponents = 0;
|
|
|
|
switch( Opcode )
|
|
{
|
|
case D3DSIO_TEX: // only in ps.1.4 does texld have source parameter
|
|
if( D3DPS_VERSION(1,4) == dwVersion )
|
|
{
|
|
// for ps.1.4, texld has a source parameter
|
|
NeededComponents = RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1 | RDPS_COMPONENTMASK_2;
|
|
}
|
|
else // versions < ps.1.4 don't have a src param on tex, so we shouldn't get here. But maybe in ps.2.0...
|
|
{
|
|
NeededComponents = RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1 | RDPS_COMPONENTMASK_2 | RDPS_COMPONENTMASK_3;
|
|
}
|
|
break;
|
|
case D3DSIO_TEXCOORD:
|
|
if( D3DPS_VERSION(1,4) == dwVersion )
|
|
{
|
|
// for ps.1.4, texcrd has a source parameter
|
|
NeededComponents = RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1 | RDPS_COMPONENTMASK_2;
|
|
}
|
|
else // versions < ps.1.4 don't have a src param on texcoord, so we shouldn't get here. But maybe in ps.2.0...
|
|
{
|
|
NeededComponents = RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1 | RDPS_COMPONENTMASK_2 | RDPS_COMPONENTMASK_3;
|
|
}
|
|
break;
|
|
case D3DSIO_TEXBEM:
|
|
case D3DSIO_TEXBEML:
|
|
NeededComponents = RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1;
|
|
break;
|
|
case D3DSIO_DP3:
|
|
NeededComponents = RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1 | RDPS_COMPONENTMASK_2;
|
|
break;
|
|
case D3DSIO_DP4:
|
|
NeededComponents = RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1 | RDPS_COMPONENTMASK_2 | RDPS_COMPONENTMASK_3;
|
|
break;
|
|
case D3DSIO_BEM: // ps.1.4
|
|
NeededComponents = RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1;
|
|
break;
|
|
default:
|
|
// standard component-wise instruction,
|
|
// OR an op we know reads .rgba and we also know it will be validated to .rgba writemask
|
|
NeededComponents = (pInst->DstParam & D3DSP_WRITEMASK_ALL) >> RDPS_COMPONENTMASK_SHIFT;
|
|
break;
|
|
}
|
|
|
|
if( bAfterSwizzle )
|
|
{
|
|
pSourceReadMasks[i] = NeededComponents;
|
|
}
|
|
else
|
|
{
|
|
// Figure out which components of this source parameter are read (taking into account swizzle)
|
|
for(j = 0; j < 4; j++)
|
|
{
|
|
if( NeededComponents & ComponentMask[j] )
|
|
ReadComponents |= ComponentMask[((pInst->SrcParam[i] & D3DSP_SWIZZLE_MASK) >> (D3DVS_SWIZZLE_SHIFT + 2*j)) & 0x3];
|
|
}
|
|
pSourceReadMasks[i] = ReadComponents;
|
|
}
|
|
}
|
|
}
|
|
|
|
void RDPSRegister::Set(RDPS_REGISTER_TYPE RegType, UINT RegNum, RefRast* pRast)
|
|
{
|
|
m_RegType = RegType;
|
|
m_RegNum = RegNum;
|
|
|
|
UINT MaxRegNum = 0;
|
|
|
|
switch( RegType )
|
|
{
|
|
case RDPSREG_INPUT:
|
|
MaxRegNum = RDPS_MAX_NUMINPUTREG - 1;
|
|
m_pReg = pRast->m_InputReg[RegNum];
|
|
break;
|
|
case RDPSREG_TEMP:
|
|
MaxRegNum = RDPS_MAX_NUMTEMPREG - 1;
|
|
m_pReg = pRast->m_TempReg[RegNum];
|
|
break;
|
|
case RDPSREG_CONST:
|
|
MaxRegNum = RDPS_MAX_NUMCONSTREG - 1;
|
|
m_pReg = pRast->m_ConstReg[RegNum];
|
|
break;
|
|
case RDPSREG_TEXTURE:
|
|
MaxRegNum = RDPS_MAX_NUMTEXTUREREG - 1;
|
|
m_pReg = pRast->m_TextReg[RegNum];
|
|
break;
|
|
case RDPSREG_POSTMODSRC:
|
|
MaxRegNum = RDPS_MAX_NUMPOSTMODSRCREG - 1;
|
|
m_pReg = pRast->m_PostModSrcReg[RegNum];
|
|
break;
|
|
case RDPSREG_SCRATCH:
|
|
MaxRegNum = RDPS_MAX_NUMSCRATCHREG - 1;
|
|
m_pReg = pRast->m_ScratchReg[RegNum];
|
|
break;
|
|
case RDPSREG_QUEUEDWRITE:
|
|
MaxRegNum = RDPS_MAX_NUMQUEUEDWRITEREG - 1;
|
|
m_pReg = pRast->m_QueuedWriteReg[RegNum];
|
|
break;
|
|
case RDPSREG_ZERO:
|
|
MaxRegNum = 0;
|
|
m_pReg = pRast->m_ZeroReg;
|
|
break;
|
|
case RDPSREG_ONE:
|
|
MaxRegNum = 0;
|
|
m_pReg = pRast->m_OneReg;
|
|
break;
|
|
case RDPSREG_TWO:
|
|
MaxRegNum = 0;
|
|
m_pReg = pRast->m_TwoReg;
|
|
break;
|
|
default:
|
|
m_pReg = NULL;
|
|
_ASSERT(FALSE,"RDPSRegister::SetReg - Unknown register type.");
|
|
break;
|
|
}
|
|
if( RegNum > MaxRegNum )
|
|
{
|
|
_ASSERT(FALSE,"RDPSRegister::SetReg - Register number too high.");
|
|
}
|
|
return;
|
|
}
|
|
|
|
//-----------------------------------------------------------------------------
|
|
//
|
|
// Initialize
|
|
//
|
|
// - Copies pixel shader token stream from DDI token stream.
|
|
// - Counts the number of active texture stages for m_cActiveTextureStages.
|
|
// - Translates shader into "RISC" instruction set to be executed
|
|
// by refrast's shader VM
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
HRESULT
|
|
RDPShader::Initialize(
|
|
RefDev* pRD, DWORD* pCode, DWORD ByteCodeSize, D3DCAPS8* pCaps )
|
|
{
|
|
m_pRD = pRD;
|
|
m_CodeSize = ByteCodeSize/4; // bytecount -> dword count
|
|
|
|
FLOAT fMin = -(pCaps->MaxPixelShaderValue);
|
|
FLOAT fMax = (pCaps->MaxPixelShaderValue);
|
|
|
|
// ------------------------------------------------------------------------
|
|
//
|
|
// First pass through shader to find the number of instructions,
|
|
// figure out how many constants there are.
|
|
//
|
|
// ------------------------------------------------------------------------
|
|
{
|
|
DWORD* pToken = pCode;
|
|
pToken++; // version token
|
|
while (*pToken != D3DPS_END())
|
|
{
|
|
DWORD Inst = *pToken;
|
|
if (*pToken++ & (1L<<31)) // instruction token
|
|
{
|
|
DPFERR("PixelShader Token #%d: instruction token error",_DWordCount());
|
|
return E_FAIL;
|
|
}
|
|
if ( (Inst & D3DSI_OPCODE_MASK) == D3DSIO_COMMENT )
|
|
{
|
|
pToken += (Inst & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
|
|
m_cInst++;
|
|
}
|
|
else if( (Inst & D3DSI_OPCODE_MASK) == D3DSIO_DEF )
|
|
{
|
|
m_cConstDefs++;
|
|
pToken += 5;
|
|
}
|
|
else
|
|
{
|
|
if (*pToken & (1L<<31)) pToken++; // destination param token
|
|
while (*pToken & (1L<<31)) pToken++; // source param tokens
|
|
m_cInst++;
|
|
}
|
|
if (_DWordCount() > (int)m_CodeSize)
|
|
{
|
|
DPFERR("PixelShader(%d tokens, %d expected): count error",_DWordCount(),m_CodeSize);
|
|
return E_FAIL;
|
|
}
|
|
}
|
|
pToken++; // step over END token
|
|
if (_DWordCount() != (int)m_CodeSize)
|
|
{
|
|
DPFERR("PixelShader(%d tokens, %d expected): count error",_DWordCount(),m_CodeSize);
|
|
return E_FAIL;
|
|
}
|
|
|
|
// make copy of original shader
|
|
m_pCode = new DWORD[m_CodeSize];
|
|
if (NULL == m_pCode)
|
|
return E_OUTOFMEMORY;
|
|
memcpy( m_pCode, pCode, ByteCodeSize );
|
|
|
|
// allocate instruction array
|
|
m_pInst = new PixelShaderInstruction[m_cInst];
|
|
if (NULL == m_pInst)
|
|
return E_OUTOFMEMORY;
|
|
memset( m_pInst, 0x0, sizeof(PixelShaderInstruction)*m_cInst );
|
|
|
|
m_pConstDefs = new ConstDef[m_cConstDefs];
|
|
if (NULL == m_pConstDefs)
|
|
return E_OUTOFMEMORY;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------
|
|
//
|
|
// Second pass through shader to:
|
|
// - produce a list of instructions, each one including opcodes,
|
|
// comments, and disassembled text for access by shader debuggers.
|
|
// - figure out the TSS # used (if any) by each instruction
|
|
// - figure out the max texture stage # used
|
|
// - figure out when the ref. pixel shader executor should
|
|
// queue writes up and when to flush the queue, in order to
|
|
// simulate co-issue.
|
|
// - figure out which texture coordinate sets get used
|
|
// - process constant DEF instructions into a list that can be
|
|
// executed whenever SetPixelShader is done.
|
|
//
|
|
// ------------------------------------------------------------------------
|
|
{
|
|
DWORD* pToken = m_pCode;
|
|
PixelShaderInstruction* pInst = m_pInst;
|
|
PixelShaderInstruction* pPrevious_NonTrivial_Inst = NULL;
|
|
pToken++; // skip over version
|
|
|
|
BOOL bMinimizeReferencedTexCoords;
|
|
|
|
if( (D3DPS_VERSION(1,3) >= *pCode) ||
|
|
(D3DPS_VERSION(254,254) == *pCode ) )//legacy
|
|
{
|
|
bMinimizeReferencedTexCoords = FALSE;
|
|
}
|
|
else
|
|
{
|
|
bMinimizeReferencedTexCoords = TRUE;
|
|
}
|
|
|
|
|
|
UINT CurrConstDef = 0;
|
|
|
|
while (*pToken != D3DPS_END())
|
|
{
|
|
switch( (*pToken) & D3DSI_OPCODE_MASK )
|
|
{
|
|
case D3DSIO_COMMENT:
|
|
pInst->Opcode = *pToken;
|
|
pInst->pComment = (pToken+1);
|
|
pInst->CommentSize = ((*pToken) & D3DSI_COMMENTSIZE_MASK) >> D3DSI_COMMENTSIZE_SHIFT;
|
|
pToken += (pInst->CommentSize+1);
|
|
pInst++;
|
|
continue;
|
|
case D3DSIO_DEF:
|
|
{
|
|
pToken++;
|
|
m_pConstDefs[CurrConstDef].RegNum = (*pToken++) & D3DSP_REGNUM_MASK;
|
|
|
|
// clamp constants on input to range of values in pixel shaders
|
|
for( UINT i = 0; i < 4; i++ )
|
|
{
|
|
m_pConstDefs[CurrConstDef].f[i] = MAX( fMin, MIN( fMax, *(FLOAT*)pToken));
|
|
pToken++;
|
|
}
|
|
|
|
CurrConstDef++;
|
|
continue;
|
|
}
|
|
case D3DSIO_NOP:
|
|
// get disasm string
|
|
PixelShaderInstDisAsm( pInst->Text, 128, pToken, 0x0 );
|
|
pInst->Opcode = *pToken++;
|
|
pInst++;
|
|
continue;
|
|
}
|
|
|
|
// get disasm string
|
|
PixelShaderInstDisAsm( pInst->Text, 128, pToken, 0x0 );
|
|
|
|
// get next instruction and parameters
|
|
pInst->Opcode = *pToken++;
|
|
|
|
pInst->SrcParamCount = 0;
|
|
if (*pToken & (1L<<31))
|
|
{
|
|
pInst->DstParam = *pToken++;
|
|
}
|
|
while (*pToken & (1L<<31))
|
|
{
|
|
pInst->SrcParam[pInst->SrcParamCount++] = *pToken++;
|
|
}
|
|
|
|
|
|
// process TEX ops
|
|
//
|
|
BOOL bLegacyTexOp = FALSE;
|
|
switch (pInst->Opcode & D3DSI_OPCODE_MASK)
|
|
{
|
|
default: break;
|
|
case D3DSIO_TEXBEM_LEGACY:
|
|
case D3DSIO_TEXBEML_LEGACY:
|
|
bLegacyTexOp = TRUE;
|
|
// fall through
|
|
case D3DSIO_TEXCOORD:
|
|
case D3DSIO_TEXKILL:
|
|
case D3DSIO_TEX:
|
|
case D3DSIO_TEXBEM:
|
|
case D3DSIO_TEXBEML:
|
|
case D3DSIO_TEXREG2AR:
|
|
case D3DSIO_TEXREG2GB:
|
|
case D3DSIO_TEXM3x2PAD:
|
|
case D3DSIO_TEXM3x2TEX:
|
|
case D3DSIO_TEXM3x3PAD:
|
|
case D3DSIO_TEXM3x3TEX:
|
|
case D3DSIO_TEXM3x3SPEC:
|
|
case D3DSIO_TEXM3x3VSPEC:
|
|
case D3DSIO_TEXM3x2DEPTH:
|
|
case D3DSIO_TEXDP3:
|
|
case D3DSIO_TEXREG2RGB:
|
|
case D3DSIO_TEXDEPTH:
|
|
case D3DSIO_TEXDP3TEX:
|
|
case D3DSIO_TEXM3x3:
|
|
pInst->bTexOp = TRUE;
|
|
break;
|
|
}
|
|
if (pInst->bTexOp)
|
|
{
|
|
// update stage count and assign ptr to TSS for this op
|
|
if (bLegacyTexOp)
|
|
{
|
|
m_cActiveTextureStages =
|
|
max(m_cActiveTextureStages,(pInst->DstParam&D3DSP_REGNUM_MASK)+1);
|
|
pInst->uiTSSNum = (pInst->DstParam&D3DSP_REGNUM_MASK)-1;
|
|
}
|
|
else
|
|
{
|
|
UINT Stage;
|
|
BOOL bStageUsed = TRUE;
|
|
|
|
switch(pInst->Opcode & D3DSI_OPCODE_MASK)
|
|
{
|
|
case D3DSIO_TEXCOORD:
|
|
case D3DSIO_TEXDEPTH:
|
|
case D3DSIO_TEXKILL:
|
|
if( bMinimizeReferencedTexCoords )
|
|
{
|
|
bStageUsed = FALSE;
|
|
break;
|
|
}
|
|
// falling through
|
|
case D3DSIO_TEX:
|
|
default:
|
|
Stage = pInst->DstParam&D3DSP_REGNUM_MASK;
|
|
break;
|
|
}
|
|
|
|
if( bStageUsed )
|
|
{
|
|
m_cActiveTextureStages = max(m_cActiveTextureStages,Stage+1);
|
|
pInst->uiTSSNum = Stage;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( pPrevious_NonTrivial_Inst )
|
|
{
|
|
// Queue write of last instruction if the current instruction has the
|
|
// COISSUE flag.
|
|
if( pInst->Opcode & D3DSI_COISSUE )
|
|
{
|
|
pPrevious_NonTrivial_Inst->bQueueWrite = TRUE;
|
|
}
|
|
|
|
// Flush writes after the previous instruction if it had the COISSUE
|
|
// flag and the current instruction doesn't have it.
|
|
if( !(pInst->Opcode & D3DSI_COISSUE) && (pPrevious_NonTrivial_Inst->Opcode & D3DSI_COISSUE) )
|
|
{
|
|
pPrevious_NonTrivial_Inst->bFlushQueue = TRUE;
|
|
}
|
|
}
|
|
|
|
pPrevious_NonTrivial_Inst = pInst;
|
|
|
|
if( bMinimizeReferencedTexCoords )
|
|
{
|
|
UpdateReferencedTexCoords(pInst, &m_ReferencedTexCoordMask);
|
|
}
|
|
|
|
pInst++;
|
|
}
|
|
|
|
if( !bMinimizeReferencedTexCoords )
|
|
{
|
|
m_ReferencedTexCoordMask = (1<<m_cActiveTextureStages) - 1;
|
|
}
|
|
}
|
|
|
|
// ------------------------------------------------------------------------
|
|
//
|
|
// Third pass through the shader (through the list of instructions made
|
|
// in the last pass) to translate instructions into a more basic ("RISC")
|
|
// instruction set for the refrast executor.
|
|
//
|
|
// ------------------------------------------------------------------------
|
|
{
|
|
#define _Set(RegType, RegNum) Set(RegType,RegNum,pRast)
|
|
|
|
#define _NewPSInst(__INST) \
|
|
{ \
|
|
RDPSOffset = pRDPSInst - pRDPSInstBuffer + LastRDPSInstSize; \
|
|
m_RDPSInstBuffer.SetGrowSize(MAX(512,RDPSOffset)); \
|
|
if( FAILED(m_RDPSInstBuffer.Grow(RDPSOffset + sizeof(__INST##_PARAMS)))) \
|
|
{return E_OUTOFMEMORY;} \
|
|
pRDPSInstBuffer = &m_RDPSInstBuffer[0]; \
|
|
pRDPSInst = pRDPSInstBuffer + RDPSOffset; \
|
|
((__INST##_PARAMS UNALIGNED64*)pRDPSInst)->Inst = __INST; \
|
|
LastRDPSInstSize = sizeof(__INST##_PARAMS); \
|
|
}
|
|
|
|
#define _InstParam(__INST) (*(__INST##_PARAMS UNALIGNED64*)pRDPSInst)
|
|
|
|
#define _NoteInstructionEvent _NewPSInst(RDPSINST_NEXTD3DPSINST); \
|
|
_InstParam(RDPSINST_NEXTD3DPSINST).pInst = pInst;
|
|
|
|
#define _EnterQuadPixelLoop if(!bInQuadPixelLoop) \
|
|
{ \
|
|
_NewPSInst(RDPSINST_QUADLOOPBEGIN); \
|
|
RDPSLoopOffset = RDPSOffset + sizeof(RDPSINST_QUADLOOPBEGIN_PARAMS); \
|
|
bInQuadPixelLoop = TRUE; \
|
|
}
|
|
|
|
#define _LeaveQuadPixelLoop if(bInQuadPixelLoop) \
|
|
{ \
|
|
_NewPSInst(RDPSINST_QUADLOOPEND); \
|
|
_InstParam(RDPSINST_QUADLOOPEND).JumpBackByOffset = \
|
|
RDPSOffset - RDPSLoopOffset;\
|
|
bInQuadPixelLoop = FALSE; \
|
|
}
|
|
|
|
#define _EmitDstMod(__dstReg,__mask) _NewPSInst(RDPSINST_DSTMOD); \
|
|
_InstParam(RDPSINST_DSTMOD).DstReg = __dstReg; \
|
|
_InstParam(RDPSINST_DSTMOD).WriteMask = __mask; \
|
|
_InstParam(RDPSINST_DSTMOD).fScale = DstScale; \
|
|
_InstParam(RDPSINST_DSTMOD).fRangeMin = DstRange[0]; \
|
|
_InstParam(RDPSINST_DSTMOD).fRangeMax = DstRange[1];
|
|
|
|
|
|
// Th macro _EmitProj emits instructions to do the following:
|
|
// - Put reciprocal of source (x,y,z,w) component __COMPONENT (ex. w) into scratch register 0 component (for w example:) 4
|
|
// - Replicate reciprocal to rgb components of scratch register 0 (w example yields: 1/,1/w,1/w, <--1/w)
|
|
// - Multiply source register register by scratch register (x/w,y/w,z/w,1) and put the result into the dest register.
|
|
#define _EmitProj(__DESTTYPE,__DESTNUM,__SRCTYPE,__SRCNUM,__COMPONENT) \
|
|
_NewPSInst(RDPSINST_RCP); \
|
|
_InstParam(RDPSINST_RCP).DstReg._Set(RDPSREG_SCRATCH,0); \
|
|
_InstParam(RDPSINST_RCP).SrcReg0._Set(__SRCTYPE,__SRCNUM); \
|
|
_InstParam(RDPSINST_RCP).bSrcReg0_Negate = FALSE; \
|
|
_InstParam(RDPSINST_RCP).WriteMask = __COMPONENT; \
|
|
\
|
|
_NewPSInst(RDPSINST_SWIZZLE); \
|
|
_InstParam(RDPSINST_SWIZZLE).DstReg._Set(RDPSREG_SCRATCH,0); \
|
|
_InstParam(RDPSINST_SWIZZLE).SrcReg0._Set(RDPSREG_SCRATCH,0); \
|
|
_InstParam(RDPSINST_SWIZZLE).WriteMask = RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1 \
|
|
| RDPS_COMPONENTMASK_2 | RDPS_COMPONENTMASK_3; \
|
|
_InstParam(RDPSINST_SWIZZLE).Swizzle = \
|
|
(RDPS_COMPONENTMASK_0 == __COMPONENT) ? RDPS_REPLICATERED : \
|
|
(RDPS_COMPONENTMASK_1 == __COMPONENT) ? RDPS_REPLICATEGREEN : \
|
|
(RDPS_COMPONENTMASK_2 == __COMPONENT) ? RDPS_REPLICATEBLUE : RDPS_REPLICATEALPHA; \
|
|
\
|
|
_NewPSInst(RDPSINST_MUL); \
|
|
_InstParam(RDPSINST_MUL).DstReg._Set(__DESTTYPE,__DESTNUM); \
|
|
_InstParam(RDPSINST_MUL).SrcReg0._Set(RDPSREG_SCRATCH,0); \
|
|
_InstParam(RDPSINST_MUL).SrcReg1._Set(__SRCTYPE,__SRCNUM); \
|
|
_InstParam(RDPSINST_MUL).bSrcReg0_Negate = FALSE; \
|
|
_InstParam(RDPSINST_MUL).bSrcReg1_Negate = FALSE; \
|
|
_InstParam(RDPSINST_MUL).WriteMask = \
|
|
(RDPS_COMPONENTMASK_0 == __COMPONENT) ? RDPS_COMPONENTMASK_0 : \
|
|
(RDPS_COMPONENTMASK_1 == __COMPONENT) ? RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1 : \
|
|
(RDPS_COMPONENTMASK_2 == __COMPONENT) ? RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1 | \
|
|
RDPS_COMPONENTMASK_2 : RDPS_COMPONENTMASK_ALL;
|
|
|
|
BYTE ComponentSwizzle[4] = {RDPS_REPLICATERED, RDPS_REPLICATEGREEN, RDPS_REPLICATEBLUE, RDPS_REPLICATEALPHA};
|
|
BYTE ComponentMask[4] = {RDPS_COMPONENTMASK_0, RDPS_COMPONENTMASK_1, RDPS_COMPONENTMASK_2, RDPS_COMPONENTMASK_3};
|
|
int QueueIndex = -1; // current queue location (for staging results when simulating coissue)
|
|
UINT i;
|
|
BOOL bInQuadPixelLoop = FALSE;
|
|
|
|
RefRast* pRast = &m_pRD->m_Rast;
|
|
|
|
RDPSRegister ZeroReg; ZeroReg._Set(RDPSREG_ZERO,0);
|
|
RDPSRegister OneReg; OneReg._Set(RDPSREG_ONE,0);
|
|
RDPSRegister TwoReg; TwoReg._Set(RDPSREG_TWO,0);
|
|
|
|
// destination parameter controls
|
|
RDPSRegister DstReg;
|
|
FLOAT DstScale; // Result Shift Scale - +/- 2**n only
|
|
FLOAT DstRange[2]; // clamp dest to this range
|
|
BYTE DstWriteMask; // per-component write mask
|
|
PRGBAVEC pDstReg; // address of dest register
|
|
|
|
// source parameter controls
|
|
RDPSRegister SrcReg[3];
|
|
|
|
BYTE* pRDPSInstBuffer = NULL;
|
|
BYTE* pRDPSInst = pRDPSInstBuffer;
|
|
size_t RDPSOffset, RDPSLoopOffset;
|
|
size_t LastRDPSInstSize = 0;
|
|
|
|
DWORD Version = *m_pCode;
|
|
|
|
for (UINT CurrentPSInst=0; CurrentPSInst < m_cInst; CurrentPSInst++)
|
|
{
|
|
PixelShaderInstruction* pInst = m_pInst + CurrentPSInst;
|
|
DWORD Opcode = pInst->Opcode & D3DSI_OPCODE_MASK;
|
|
DWORD SrcSwizzle[3];
|
|
BYTE SourceReadMasks[3];
|
|
BYTE SourceReadMasksAfterSwizzle[3];
|
|
BOOL bForceNeg1To1Clamp[3] = {FALSE, FALSE, FALSE};
|
|
BOOL bEmitQueueWrite = FALSE;
|
|
RDPSRegister QueuedWriteDstReg;
|
|
BYTE QueuedWriteDstWriteMask;
|
|
BYTE ProjComponent[3] = {0,0,0};
|
|
BOOL bEmitProj[3] = {FALSE, FALSE, FALSE};
|
|
BOOL bProjOnEval[3] = {FALSE, FALSE, FALSE};
|
|
BOOL bEmitSrcMod[3] = {FALSE, FALSE, FALSE};
|
|
BOOL bEmitSwizzle[3] = {FALSE, FALSE, FALSE};
|
|
BOOL bSrcNegate[3] = {FALSE, FALSE, FALSE};
|
|
BOOL bSrcBias[3] = {FALSE, FALSE, FALSE};
|
|
BOOL bSrcTimes2[3] = {FALSE, FALSE, FALSE};
|
|
BOOL bSrcComplement[3] = {FALSE, FALSE, FALSE};
|
|
|
|
switch( Opcode )
|
|
{
|
|
continue;
|
|
case D3DSIO_DEF:
|
|
// nothing to do -> DEF has already been processed out and is not an true instruction
|
|
continue;
|
|
case D3DSIO_COMMENT:
|
|
continue;
|
|
case D3DSIO_PHASE:
|
|
case D3DSIO_NOP:
|
|
#if DBG
|
|
_NoteInstructionEvent
|
|
#endif
|
|
continue;
|
|
}
|
|
|
|
#if DBG
|
|
_NoteInstructionEvent
|
|
#endif
|
|
|
|
// do some preliminary setup for this instruction
|
|
|
|
UINT RegNum = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
switch (pInst->DstParam & D3DSP_REGTYPE_MASK)
|
|
{
|
|
case D3DSPR_TEXTURE:
|
|
DstReg._Set(RDPSREG_TEXTURE, RegNum); break;
|
|
case D3DSPR_TEMP:
|
|
DstReg._Set(RDPSREG_TEMP, RegNum); break;
|
|
default:
|
|
_ASSERT( FALSE, "RDPShader::Initialize - Unexpected destination register type." );
|
|
break;
|
|
}
|
|
|
|
DstWriteMask = (pInst->DstParam & D3DSP_WRITEMASK_ALL) >> RDPS_COMPONENTMASK_SHIFT;
|
|
|
|
if( pInst->bQueueWrite )
|
|
{
|
|
QueueIndex++;
|
|
|
|
QueuedWriteDstReg = DstReg;
|
|
QueuedWriteDstWriteMask = DstWriteMask;
|
|
DstReg._Set(RDPSREG_QUEUEDWRITE,QueueIndex);
|
|
_ASSERT(QueueIndex <= RDPS_MAX_NUMQUEUEDWRITEREG, "Too many queued writes in pixelshader (improperly handled co-issue)." );
|
|
bEmitQueueWrite = TRUE;
|
|
}
|
|
|
|
CalculateSourceReadMasks(pInst, SourceReadMasks, FALSE,Version);
|
|
CalculateSourceReadMasks(pInst, SourceReadMasksAfterSwizzle, TRUE,Version);
|
|
for (i=0; i < pInst->SrcParamCount; i++)
|
|
{
|
|
RegNum = pInst->SrcParam[i]&D3DSP_REGNUM_MASK;
|
|
switch (pInst->SrcParam[i] & D3DSP_REGTYPE_MASK)
|
|
{
|
|
case D3DSPR_TEMP:
|
|
SrcReg[i]._Set(RDPSREG_TEMP, RegNum); break;
|
|
case D3DSPR_TEXTURE:
|
|
SrcReg[i]._Set(RDPSREG_TEXTURE, RegNum); break;
|
|
case D3DSPR_INPUT:
|
|
SrcReg[i]._Set(RDPSREG_INPUT, RegNum); break;
|
|
case D3DSPR_CONST:
|
|
SrcReg[i]._Set(RDPSREG_CONST, RegNum);
|
|
// Force a [-1,1] clamp after applying modifier (for constants only)
|
|
// This overrides the the standard [-MaxPixelShaderValue,MaxPixelShaderValue] clamp.
|
|
// An IHV that supports MaxPixelShaderValue > 1 forgot to do this for constants.
|
|
bForceNeg1To1Clamp[i] = TRUE;
|
|
break;
|
|
default:
|
|
_ASSERT( FALSE, "RDPShader::Initialize - Unexpected source register type." );
|
|
break;
|
|
}
|
|
|
|
if( (D3DSPSM_DZ == (pInst->SrcParam[i] & D3DSP_SRCMOD_MASK)) ||
|
|
(D3DSPSM_DW == (pInst->SrcParam[i] & D3DSP_SRCMOD_MASK)) )
|
|
{
|
|
if( D3DSPSM_DZ == (pInst->SrcParam[i] & D3DSP_SRCMOD_MASK))
|
|
{
|
|
ProjComponent[i] = RDPS_COMPONENTMASK_2;
|
|
}
|
|
else // _DW
|
|
{
|
|
if( D3DPS_VERSION(1,4) == Version )
|
|
ProjComponent[i] = RDPS_COMPONENTMASK_2;
|
|
else
|
|
ProjComponent[i] = RDPS_COMPONENTMASK_3;
|
|
}
|
|
|
|
|
|
if( D3DSPR_TEXTURE == (pInst->SrcParam[i] & D3DSP_REGTYPE_MASK ) ) // t# register being used to represent evaluated texcoord.
|
|
{
|
|
bProjOnEval[i] = TRUE;
|
|
}
|
|
else
|
|
bEmitProj[i] = TRUE;
|
|
}
|
|
else
|
|
{
|
|
bEmitSrcMod[i] = TRUE;
|
|
|
|
switch (pInst->SrcParam[i] & D3DSP_SRCMOD_MASK)
|
|
{
|
|
default:
|
|
case D3DSPSM_NONE:
|
|
if( !bForceNeg1To1Clamp[i] )
|
|
bEmitSrcMod[i] = FALSE;
|
|
break;
|
|
case D3DSPSM_NEG:
|
|
bSrcNegate[i] = TRUE; // negate is not part of source modifier
|
|
if( !bForceNeg1To1Clamp[i] )
|
|
bEmitSrcMod[i] = FALSE;
|
|
break;
|
|
case D3DSPSM_BIAS:
|
|
bSrcBias[i] = TRUE;
|
|
break;
|
|
case D3DSPSM_BIASNEG:
|
|
bSrcNegate[i] = TRUE;
|
|
bSrcBias[i] = TRUE;
|
|
break;
|
|
case D3DSPSM_SIGN: // _bx2
|
|
bSrcBias[i] = TRUE;
|
|
bSrcTimes2[i] = TRUE;
|
|
break;
|
|
case D3DSPSM_SIGNNEG: // negative _bx2
|
|
bSrcNegate[i] = TRUE; // negate is not part of source modifier
|
|
bSrcBias[i] = TRUE;
|
|
bSrcTimes2[i] = TRUE;
|
|
break;
|
|
case D3DSPSM_COMP:
|
|
bSrcComplement[i] = TRUE;
|
|
break;
|
|
case D3DSPSM_X2:
|
|
bSrcTimes2[i] = TRUE;
|
|
break;
|
|
case D3DSPSM_X2NEG:
|
|
bSrcNegate[i] = TRUE; // negate is not part of source modifier
|
|
bSrcTimes2[i] = TRUE;
|
|
break;
|
|
}
|
|
|
|
_ASSERT(!(bSrcComplement[i] && (bSrcTimes2[i]||bSrcBias[i]||bSrcNegate[i])),"RDPShader::Initialize - Complement cannot be combined with other modifiers.");
|
|
}
|
|
|
|
SrcSwizzle[i] = (pInst->SrcParam[i] & D3DSP_SWIZZLE_MASK) >> D3DSP_SWIZZLE_SHIFT;
|
|
bEmitSwizzle[i] = (D3DSP_NOSWIZZLE != (pInst->SrcParam[i] & D3DSP_SWIZZLE_MASK));
|
|
}
|
|
|
|
// set clamp values
|
|
switch (pInst->DstParam & D3DSP_DSTMOD_MASK)
|
|
{
|
|
default:
|
|
case D3DSPDM_NONE:
|
|
if(pInst->bTexOp)
|
|
{
|
|
DstRange[0] = -FLT_MAX;
|
|
DstRange[1] = FLT_MAX;
|
|
}
|
|
else
|
|
{
|
|
DstRange[0] = fMin;
|
|
DstRange[1] = fMax;
|
|
}
|
|
break;
|
|
case D3DSPDM_SATURATE:
|
|
DstRange[0] = 0.F;
|
|
DstRange[1] = 1.F;
|
|
break;
|
|
}
|
|
|
|
UINT ShiftScale =
|
|
(pInst->DstParam & D3DSP_DSTSHIFT_MASK) >> D3DSP_DSTSHIFT_SHIFT;
|
|
if (ShiftScale & 0x8)
|
|
{
|
|
ShiftScale = ((~ShiftScale)&0x7)+1; // negative magnitude
|
|
DstScale = 1.f/(FLOAT)(1<<ShiftScale);
|
|
}
|
|
else
|
|
{
|
|
DstScale = (FLOAT)(1<<ShiftScale);
|
|
}
|
|
|
|
// finished preliminary setup, now start emitting ops...
|
|
|
|
_EnterQuadPixelLoop
|
|
|
|
if( bEmitQueueWrite )
|
|
{
|
|
_NewPSInst(RDPSINST_QUEUEWRITE);
|
|
_InstParam(RDPSINST_QUEUEWRITE).DstReg = QueuedWriteDstReg;
|
|
_InstParam(RDPSINST_QUEUEWRITE).WriteMask = QueuedWriteDstWriteMask;
|
|
}
|
|
|
|
for (i=0; i < pInst->SrcParamCount; i++)
|
|
{
|
|
if( bEmitProj[i] )
|
|
{
|
|
_EmitProj(RDPSREG_POSTMODSRC,i,SrcReg[i].GetRegType(),SrcReg[i].GetRegNum(),ProjComponent[i]);
|
|
SrcReg[i]._Set(RDPSREG_POSTMODSRC,i);
|
|
}
|
|
|
|
if( bEmitSrcMod[i] )
|
|
{
|
|
_NewPSInst(RDPSINST_SRCMOD);
|
|
_InstParam(RDPSINST_SRCMOD).DstReg._Set(RDPSREG_POSTMODSRC,i);
|
|
_InstParam(RDPSINST_SRCMOD).SrcReg0 = SrcReg[i];
|
|
_InstParam(RDPSINST_SRCMOD).WriteMask = SourceReadMasks[i];
|
|
_InstParam(RDPSINST_SRCMOD).bBias = bSrcBias[i];
|
|
_InstParam(RDPSINST_SRCMOD).bTimes2 = bSrcTimes2[i];
|
|
_InstParam(RDPSINST_SRCMOD).bComplement = bSrcComplement[i];
|
|
_InstParam(RDPSINST_SRCMOD).fRangeMin = bForceNeg1To1Clamp[i] ? -1.0f : fMin;
|
|
_InstParam(RDPSINST_SRCMOD).fRangeMax = bForceNeg1To1Clamp[i] ? 1.0f : fMax;
|
|
SrcReg[i]._Set(RDPSREG_POSTMODSRC,i);
|
|
}
|
|
|
|
if( bEmitSwizzle[i] && !bProjOnEval[i] )
|
|
{
|
|
_NewPSInst(RDPSINST_SWIZZLE);
|
|
_InstParam(RDPSINST_SWIZZLE).DstReg._Set(RDPSREG_POSTMODSRC,i);
|
|
_InstParam(RDPSINST_SWIZZLE).SrcReg0 = SrcReg[i];
|
|
_InstParam(RDPSINST_SWIZZLE).WriteMask = SourceReadMasksAfterSwizzle[i];
|
|
_InstParam(RDPSINST_SWIZZLE).Swizzle = SrcSwizzle[i];
|
|
SrcReg[i]._Set(RDPSREG_POSTMODSRC,i);
|
|
}
|
|
}
|
|
|
|
switch(Opcode)
|
|
{
|
|
case D3DSIO_TEXCOORD:
|
|
case D3DSIO_TEXKILL:
|
|
{
|
|
if( !( (D3DSIO_TEXKILL == Opcode) &&
|
|
(D3DSPR_TEMP == (pInst->DstParam & D3DSP_REGTYPE_MASK))
|
|
)
|
|
)
|
|
{
|
|
UINT CoordSet = pInst->SrcParam[0] ? (pInst->SrcParam[0] & D3DSP_REGNUM_MASK) :
|
|
(pInst->DstParam & D3DSP_REGNUM_MASK);
|
|
|
|
RDPSRegister CoordReg;
|
|
if(bProjOnEval[0])
|
|
CoordReg._Set(RDPSREG_POSTMODSRC,0);
|
|
else
|
|
CoordReg = DstReg;
|
|
|
|
// For TEXCOORD, clamp 0. to 1 only there is no source parameter (ps.1.0, ps.1.1)
|
|
// For TEXKILL, never clamp
|
|
// NOTE: the TEXCOORD clamp is a temporary limitation for DX8 shader models
|
|
BOOL bTexCoordClamp = ((D3DSIO_TEXCOORD == Opcode) && (!pInst->SrcParam[0])) ? TRUE : FALSE;
|
|
|
|
_NewPSInst(RDPSINST_EVAL);
|
|
_InstParam(RDPSINST_EVAL).DstReg = CoordReg;
|
|
_InstParam(RDPSINST_EVAL).uiCoordSet = CoordSet;
|
|
_InstParam(RDPSINST_EVAL).bIgnoreD3DTTFF_PROJECTED = TRUE; // projection disabled (unless _p modifier used -> _EmitProj below)
|
|
_InstParam(RDPSINST_EVAL).bClamp = bTexCoordClamp;
|
|
|
|
if( bProjOnEval[0] )
|
|
{
|
|
if( bEmitSwizzle[0] )
|
|
{
|
|
_NewPSInst(RDPSINST_SWIZZLE);
|
|
_InstParam(RDPSINST_SWIZZLE).DstReg = DstReg;
|
|
_InstParam(RDPSINST_SWIZZLE).SrcReg0 = CoordReg;
|
|
_InstParam(RDPSINST_SWIZZLE).WriteMask = SourceReadMasksAfterSwizzle[0];
|
|
_InstParam(RDPSINST_SWIZZLE).Swizzle = SrcSwizzle[0];
|
|
}
|
|
_EmitProj(DstReg.GetRegType(),DstReg.GetRegNum(),DstReg.GetRegType(),DstReg.GetRegNum(),ProjComponent[0]);
|
|
}
|
|
|
|
// check version (first DWORD of code token stream), and always
|
|
// set 4th component to 1.0 for ps.1.3 or earlier
|
|
if ( D3DPS_VERSION(1,3) >= Version )
|
|
{
|
|
_NewPSInst(RDPSINST_MOV);
|
|
_InstParam(RDPSINST_MOV).DstReg = DstReg;
|
|
_InstParam(RDPSINST_MOV).SrcReg0 = OneReg; // 1.0f
|
|
_InstParam(RDPSINST_MOV).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_MOV).WriteMask = RDPS_COMPONENTMASK_3;
|
|
}
|
|
}
|
|
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
|
|
if( D3DSIO_TEXKILL == Opcode )
|
|
{
|
|
_NewPSInst(RDPSINST_KILL);
|
|
_InstParam(RDPSINST_KILL).DstReg = DstReg;
|
|
}
|
|
}
|
|
break;
|
|
case D3DSIO_TEX:
|
|
{
|
|
RDPSRegister CoordReg;
|
|
BOOL bDoSampleCoords = TRUE;
|
|
|
|
UINT CoordSet = pInst->SrcParam[0] ? (pInst->SrcParam[0] & D3DSP_REGNUM_MASK) :
|
|
(pInst->DstParam & D3DSP_REGNUM_MASK);
|
|
|
|
if( pInst->SrcParam[0] )
|
|
{
|
|
CoordReg = SrcReg[0];
|
|
if( D3DSPR_TEMP == (pInst->SrcParam[0] & D3DSP_REGTYPE_MASK) )
|
|
bDoSampleCoords = FALSE;
|
|
}
|
|
else // no source param.
|
|
{
|
|
CoordReg._Set(RDPSREG_SCRATCH,0);
|
|
}
|
|
|
|
if( bDoSampleCoords )
|
|
{
|
|
_NewPSInst(RDPSINST_EVAL);
|
|
_InstParam(RDPSINST_EVAL).DstReg = CoordReg;
|
|
_InstParam(RDPSINST_EVAL).uiCoordSet = CoordSet;
|
|
_InstParam(RDPSINST_EVAL).bIgnoreD3DTTFF_PROJECTED = bProjOnEval[0]; // if we have _p modifier, we do _EmitProj below
|
|
_InstParam(RDPSINST_EVAL).bClamp = FALSE;
|
|
}
|
|
|
|
if( bProjOnEval[0] )
|
|
{
|
|
if( bEmitSwizzle[0] )
|
|
{
|
|
_NewPSInst(RDPSINST_SWIZZLE);
|
|
_InstParam(RDPSINST_SWIZZLE).DstReg._Set(RDPSREG_POSTMODSRC,0);
|
|
_InstParam(RDPSINST_SWIZZLE).SrcReg0 = CoordReg;
|
|
_InstParam(RDPSINST_SWIZZLE).WriteMask = SourceReadMasksAfterSwizzle[0];
|
|
_InstParam(RDPSINST_SWIZZLE).Swizzle = SrcSwizzle[0];
|
|
CoordReg._Set(RDPSREG_POSTMODSRC,0);
|
|
}
|
|
_EmitProj(RDPSREG_POSTMODSRC,0,CoordReg.GetRegType(),CoordReg.GetRegNum(),ProjComponent[0]);
|
|
CoordReg._Set(RDPSREG_POSTMODSRC,0);
|
|
}
|
|
|
|
_LeaveQuadPixelLoop
|
|
|
|
PRGBAVEC pCoordReg = CoordReg.GetRegPtr();
|
|
|
|
_NewPSInst(RDPSINST_TEXCOVERAGE);
|
|
_InstParam(RDPSINST_TEXCOVERAGE).uiStage = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pGradients = pRast->m_Gradients; // where to store gradients
|
|
// data from which to compute gradients. i.e.: du/dx = DUDX_0 - DUDX_1
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDX_0 = &pCoordReg[1][0]; // du/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDX_1 = &pCoordReg[0][0];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDY_0 = &pCoordReg[2][0]; // du/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDY_1 = &pCoordReg[0][0];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDX_0 = &pCoordReg[1][1]; // dv/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDX_1 = &pCoordReg[0][1];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDY_0 = &pCoordReg[2][1]; // dv/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDY_1 = &pCoordReg[0][1];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_0 = &pCoordReg[1][2]; // dw/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_1 = &pCoordReg[0][2];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_0 = &pCoordReg[2][2]; // dw/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_1 = &pCoordReg[0][2];
|
|
|
|
_EnterQuadPixelLoop
|
|
|
|
_NewPSInst(RDPSINST_SAMPLE);
|
|
_InstParam(RDPSINST_SAMPLE).DstReg = DstReg;
|
|
_InstParam(RDPSINST_SAMPLE).CoordReg = CoordReg;
|
|
_InstParam(RDPSINST_SAMPLE).uiStage = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
}
|
|
break;
|
|
case D3DSIO_TEXDP3:
|
|
case D3DSIO_TEXDP3TEX:
|
|
{
|
|
RDPSRegister CoordReg;
|
|
CoordReg._Set(RDPSREG_SCRATCH,0);
|
|
|
|
_NewPSInst(RDPSINST_EVAL);
|
|
_InstParam(RDPSINST_EVAL).DstReg = CoordReg;
|
|
_InstParam(RDPSINST_EVAL).uiCoordSet = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
_InstParam(RDPSINST_EVAL).bIgnoreD3DTTFF_PROJECTED = TRUE; // no projection
|
|
_InstParam(RDPSINST_EVAL).bClamp = FALSE;
|
|
|
|
if( D3DSIO_TEXDP3 == Opcode )
|
|
{
|
|
_NewPSInst(RDPSINST_DP3);
|
|
_InstParam(RDPSINST_DP3).DstReg = DstReg;
|
|
_InstParam(RDPSINST_DP3).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_DP3).SrcReg1 = CoordReg;
|
|
_InstParam(RDPSINST_DP3).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_DP3).bSrcReg1_Negate = FALSE;
|
|
_InstParam(RDPSINST_DP3).WriteMask = RDPS_COMPONENTMASK_ALL;
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
}
|
|
else // D3DSIO_TEXDP3TEX
|
|
{
|
|
_NewPSInst(RDPSINST_DP3);
|
|
_InstParam(RDPSINST_DP3).DstReg = CoordReg;
|
|
_InstParam(RDPSINST_DP3).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_DP3).SrcReg1 = CoordReg;
|
|
_InstParam(RDPSINST_DP3).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_DP3).bSrcReg1_Negate = FALSE;
|
|
_InstParam(RDPSINST_DP3).WriteMask = RDPS_COMPONENTMASK_0;
|
|
|
|
_NewPSInst(RDPSINST_MOV);
|
|
_InstParam(RDPSINST_MOV).DstReg = CoordReg;
|
|
_InstParam(RDPSINST_MOV).SrcReg0 = ZeroReg; // 0.0f
|
|
_InstParam(RDPSINST_MOV).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_MOV).WriteMask = RDPS_COMPONENTMASK_1 | RDPS_COMPONENTMASK_2;
|
|
|
|
_LeaveQuadPixelLoop
|
|
|
|
PRGBAVEC pCoordReg = CoordReg.GetRegPtr();
|
|
|
|
_NewPSInst(RDPSINST_TEXCOVERAGE);
|
|
_InstParam(RDPSINST_TEXCOVERAGE).uiStage = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pGradients = pRast->m_Gradients; // where to store gradients
|
|
// data from which to compute gradients. i.e.: du/dx = DUDX_0 - DUDX_1
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDX_0 = &pCoordReg[1][0]; // du/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDX_1 = &pCoordReg[0][0];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDY_0 = &pCoordReg[2][0]; // du/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDY_1 = &pCoordReg[0][0];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDX_0 = // dv/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDX_1 =
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDY_0 = // dv/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDY_1 =
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_0 = // dw/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_1 =
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_0 = // dw/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_1 = &ZeroReg.GetRegPtr()[0][0]; // 0.0f
|
|
|
|
_EnterQuadPixelLoop
|
|
|
|
_NewPSInst(RDPSINST_SAMPLE);
|
|
_InstParam(RDPSINST_SAMPLE).DstReg = DstReg;
|
|
_InstParam(RDPSINST_SAMPLE).CoordReg = CoordReg;
|
|
_InstParam(RDPSINST_SAMPLE).uiStage = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
}
|
|
}
|
|
break;
|
|
case D3DSIO_TEXREG2AR:
|
|
case D3DSIO_TEXREG2GB:
|
|
case D3DSIO_TEXREG2RGB:
|
|
{
|
|
UINT I0, I1;
|
|
PRGBAVEC pSrcReg0 = SrcReg[0].GetRegPtr();
|
|
|
|
switch( Opcode )
|
|
{
|
|
case D3DSIO_TEXREG2AR:
|
|
I0 = 3;
|
|
I1 = 0;
|
|
break;
|
|
case D3DSIO_TEXREG2GB:
|
|
I0 = 1;
|
|
I1 = 2;
|
|
break;
|
|
case D3DSIO_TEXREG2RGB:
|
|
I0 = 0;
|
|
I1 = 1;
|
|
break;
|
|
}
|
|
|
|
_LeaveQuadPixelLoop
|
|
|
|
_NewPSInst(RDPSINST_TEXCOVERAGE);
|
|
_InstParam(RDPSINST_TEXCOVERAGE).uiStage = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pGradients = pRast->m_Gradients; // where to store gradients
|
|
// data from which to compute gradients. i.e.: du/dx = DUDX_0 - DUDX_1
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDX_0 = &pSrcReg0[1][I0]; // du/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDX_1 = &pSrcReg0[0][I0];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDY_0 = &pSrcReg0[2][I0]; // du/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDY_1 = &pSrcReg0[0][I0];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDX_0 = &pSrcReg0[1][I1]; // dv/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDX_1 = &pSrcReg0[0][I1];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDY_0 = &pSrcReg0[2][I1]; // dv/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDY_1 = &pSrcReg0[0][I1];
|
|
switch( Opcode )
|
|
{
|
|
case D3DSIO_TEXREG2AR:
|
|
case D3DSIO_TEXREG2GB:
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_0 = // dw/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_1 =
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_0 = // dw/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_1 = &ZeroReg.GetRegPtr()[0][0]; // 0.0f
|
|
break;
|
|
case D3DSIO_TEXREG2RGB:
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_0 = &pSrcReg0[1][2]; // dw/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_1 = &pSrcReg0[0][2];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_0 = &pSrcReg0[2][2]; // dw/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_1 = &pSrcReg0[0][2];
|
|
break;
|
|
}
|
|
|
|
_EnterQuadPixelLoop
|
|
|
|
RDPSRegister CoordReg;
|
|
CoordReg._Set(RDPSREG_SCRATCH,0);
|
|
|
|
_NewPSInst(RDPSINST_SWIZZLE);
|
|
_InstParam(RDPSINST_SWIZZLE).DstReg = CoordReg;
|
|
_InstParam(RDPSINST_SWIZZLE).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_SWIZZLE).WriteMask = RDPS_COMPONENTMASK_0;
|
|
_InstParam(RDPSINST_SWIZZLE).Swizzle = ComponentSwizzle[I0];
|
|
|
|
_NewPSInst(RDPSINST_SWIZZLE);
|
|
_InstParam(RDPSINST_SWIZZLE).DstReg = CoordReg;
|
|
_InstParam(RDPSINST_SWIZZLE).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_SWIZZLE).WriteMask = RDPS_COMPONENTMASK_1;
|
|
_InstParam(RDPSINST_SWIZZLE).Swizzle = ComponentSwizzle[I1];
|
|
|
|
_NewPSInst(RDPSINST_MOV);
|
|
_InstParam(RDPSINST_MOV).DstReg = CoordReg;
|
|
_InstParam(RDPSINST_MOV).SrcReg0 = (D3DSIO_TEXREG2RGB == Opcode ? SrcReg[0] : ZeroReg );
|
|
_InstParam(RDPSINST_MOV).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_MOV).WriteMask = RDPS_COMPONENTMASK_2;
|
|
|
|
_NewPSInst(RDPSINST_SAMPLE);
|
|
_InstParam(RDPSINST_SAMPLE).DstReg = DstReg;
|
|
_InstParam(RDPSINST_SAMPLE).CoordReg = CoordReg;
|
|
_InstParam(RDPSINST_SAMPLE).uiStage = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
}
|
|
break;
|
|
case D3DSIO_TEXBEM:
|
|
case D3DSIO_TEXBEML:
|
|
case D3DSIO_TEXBEM_LEGACY: // refrast only -> used with legacy fixed function rasterizer
|
|
case D3DSIO_TEXBEML_LEGACY: // refrast only -> used with legacy fixed function rasterizer
|
|
{
|
|
BOOL bDoLuminance = ((D3DSIO_TEXBEML == Opcode) || (D3DSIO_TEXBEML_LEGACY == Opcode));
|
|
RDPSRegister CoordReg;
|
|
CoordReg._Set(RDPSREG_SCRATCH,0);
|
|
|
|
_NewPSInst(RDPSINST_EVAL);
|
|
_InstParam(RDPSINST_EVAL).DstReg = CoordReg;
|
|
_InstParam(RDPSINST_EVAL).uiCoordSet = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
_InstParam(RDPSINST_EVAL).bIgnoreD3DTTFF_PROJECTED = FALSE;
|
|
_InstParam(RDPSINST_EVAL).bClamp = FALSE;
|
|
|
|
_NewPSInst(RDPSINST_BEM);
|
|
_InstParam(RDPSINST_BEM).DstReg = CoordReg;
|
|
_InstParam(RDPSINST_BEM).SrcReg0 = CoordReg;
|
|
_InstParam(RDPSINST_BEM).SrcReg1 = SrcReg[0];
|
|
_InstParam(RDPSINST_BEM).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_BEM).bSrcReg1_Negate = FALSE;
|
|
_InstParam(RDPSINST_BEM).WriteMask = RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1;
|
|
_InstParam(RDPSINST_BEM).uiStage = pInst->uiTSSNum;
|
|
|
|
_EmitDstMod(CoordReg,RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1)
|
|
|
|
_LeaveQuadPixelLoop
|
|
|
|
PRGBAVEC pCoordReg = CoordReg.GetRegPtr();
|
|
|
|
_NewPSInst(RDPSINST_TEXCOVERAGE);
|
|
_InstParam(RDPSINST_TEXCOVERAGE).uiStage = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pGradients = pRast->m_Gradients; // where to store gradients
|
|
// data from which to compute gradients. i.e.: du/dx = DUDX_0 - DUDX_1
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDX_0 = &pCoordReg[1][0]; // du/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDX_1 = &pCoordReg[0][0];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDY_0 = &pCoordReg[2][0]; // du/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDY_1 = &pCoordReg[0][0];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDX_0 = &pCoordReg[1][1]; // dv/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDX_1 = &pCoordReg[0][1];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDY_0 = &pCoordReg[2][1]; // dv/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDY_1 = &pCoordReg[0][1];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_0 = // dw/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_1 =
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_0 = // dw/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_1 = &ZeroReg.GetRegPtr()[0][0]; // 0.0f
|
|
|
|
_EnterQuadPixelLoop
|
|
|
|
_NewPSInst(RDPSINST_SAMPLE);
|
|
_InstParam(RDPSINST_SAMPLE).DstReg = DstReg;
|
|
_InstParam(RDPSINST_SAMPLE).CoordReg = CoordReg;
|
|
_InstParam(RDPSINST_SAMPLE).uiStage = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
|
|
if( bDoLuminance )
|
|
{
|
|
_NewPSInst(RDPSINST_LUMINANCE);
|
|
_InstParam(RDPSINST_LUMINANCE).DstReg = DstReg;
|
|
_InstParam(RDPSINST_LUMINANCE).SrcReg0 = DstReg;
|
|
_InstParam(RDPSINST_LUMINANCE).SrcReg1 = SrcReg[0];
|
|
_InstParam(RDPSINST_LUMINANCE).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_LUMINANCE).bSrcReg1_Negate = FALSE;
|
|
_InstParam(RDPSINST_LUMINANCE).uiStage = pInst->uiTSSNum;
|
|
}
|
|
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
}
|
|
break;
|
|
case D3DSIO_TEXDEPTH:
|
|
_NewPSInst(RDPSINST_DEPTH);
|
|
_InstParam(RDPSINST_DEPTH).DstReg = DstReg;
|
|
break;
|
|
case D3DSIO_TEXM3x2PAD:
|
|
{
|
|
RDPSRegister CoordReg;
|
|
CoordReg._Set(RDPSREG_SCRATCH,0);
|
|
|
|
// do dot product for first row of matrix multiply
|
|
|
|
// evaluate texture coordinate; projection disabled
|
|
_NewPSInst(RDPSINST_EVAL);
|
|
_InstParam(RDPSINST_EVAL).DstReg = CoordReg;
|
|
_InstParam(RDPSINST_EVAL).uiCoordSet = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
_InstParam(RDPSINST_EVAL).bIgnoreD3DTTFF_PROJECTED = TRUE; // no projection
|
|
_InstParam(RDPSINST_EVAL).bClamp = FALSE;
|
|
|
|
// do row of transform - tex coord * vector loaded from texture (on previous stage)
|
|
_NewPSInst(RDPSINST_DP3);
|
|
_InstParam(RDPSINST_DP3).DstReg._Set(DstReg.GetRegType(),DstReg.GetRegNum()+1);
|
|
_InstParam(RDPSINST_DP3).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_DP3).SrcReg1 = CoordReg;
|
|
_InstParam(RDPSINST_DP3).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_DP3).bSrcReg1_Negate = FALSE;
|
|
_InstParam(RDPSINST_DP3).WriteMask = RDPS_COMPONENTMASK_0;
|
|
}
|
|
break;
|
|
case D3DSIO_TEXM3x3PAD:
|
|
{
|
|
BOOL bSecondPad = (D3DSIO_TEXM3x3PAD != ((pInst + 1)->Opcode & D3DSI_OPCODE_MASK));
|
|
BOOL bInVSPECSequence = (D3DSIO_TEXM3x3VSPEC == (((pInst + (bSecondPad?1:2))->Opcode) & D3DSI_OPCODE_MASK));
|
|
RDPSRegister CoordReg, EyeReg;
|
|
CoordReg._Set(RDPSREG_SCRATCH,0);
|
|
EyeReg._Set(RDPSREG_SCRATCH,1);
|
|
|
|
// do dot product for first row of matrix multiply
|
|
|
|
// evaluate texture coordinate; projection disabled
|
|
_NewPSInst(RDPSINST_EVAL);
|
|
_InstParam(RDPSINST_EVAL).DstReg = CoordReg;
|
|
_InstParam(RDPSINST_EVAL).uiCoordSet = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
_InstParam(RDPSINST_EVAL).bIgnoreD3DTTFF_PROJECTED = TRUE; // no projection
|
|
_InstParam(RDPSINST_EVAL).bClamp = FALSE;
|
|
|
|
// do row of transform - tex coord * vector loaded from texture (on previous stage)
|
|
_NewPSInst(RDPSINST_DP3);
|
|
_InstParam(RDPSINST_DP3).DstReg._Set(DstReg.GetRegType(),DstReg.GetRegNum()+(bSecondPad?1:2));
|
|
_InstParam(RDPSINST_DP3).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_DP3).SrcReg1 = CoordReg;
|
|
_InstParam(RDPSINST_DP3).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_DP3).bSrcReg1_Negate = FALSE;
|
|
_InstParam(RDPSINST_DP3).WriteMask = bSecondPad?RDPS_COMPONENTMASK_1:RDPS_COMPONENTMASK_0;
|
|
|
|
if(bInVSPECSequence)
|
|
{
|
|
// eye vector encoded in 4th element of texture coordinates
|
|
_NewPSInst(RDPSINST_SWIZZLE);
|
|
_InstParam(RDPSINST_SWIZZLE).DstReg = EyeReg;
|
|
_InstParam(RDPSINST_SWIZZLE).SrcReg0 = CoordReg;
|
|
_InstParam(RDPSINST_SWIZZLE).WriteMask = bSecondPad?RDPS_COMPONENTMASK_1:RDPS_COMPONENTMASK_0;
|
|
_InstParam(RDPSINST_SWIZZLE).Swizzle = RDPS_REPLICATEALPHA;
|
|
}
|
|
}
|
|
break;
|
|
case D3DSIO_TEXM3x2TEX:
|
|
case D3DSIO_TEXM3x3:
|
|
case D3DSIO_TEXM3x3TEX:
|
|
case D3DSIO_TEXM3x3SPEC:
|
|
case D3DSIO_TEXM3x3VSPEC:
|
|
case D3DSIO_TEXM3x2DEPTH:
|
|
{
|
|
BOOL bIs3D = (D3DSIO_TEXM3x2TEX != Opcode) && (D3DSIO_TEXM3x2DEPTH != Opcode);
|
|
RDPSRegister CoordReg, EyeReg;
|
|
CoordReg._Set(RDPSREG_SCRATCH,0);
|
|
EyeReg._Set(RDPSREG_SCRATCH,1);
|
|
|
|
// do dot product for last row of matrix multiply
|
|
|
|
// evaluate texture coordinate; projection disabled
|
|
_NewPSInst(RDPSINST_EVAL);
|
|
_InstParam(RDPSINST_EVAL).DstReg = CoordReg;
|
|
_InstParam(RDPSINST_EVAL).uiCoordSet = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
_InstParam(RDPSINST_EVAL).bIgnoreD3DTTFF_PROJECTED = TRUE; // no projection
|
|
_InstParam(RDPSINST_EVAL).bClamp = FALSE;
|
|
|
|
// do row of transform - tex coord * vector loaded from texture (on previous stage)
|
|
_NewPSInst(RDPSINST_DP3);
|
|
_InstParam(RDPSINST_DP3).DstReg = DstReg;
|
|
_InstParam(RDPSINST_DP3).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_DP3).SrcReg1 = CoordReg;
|
|
_InstParam(RDPSINST_DP3).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_DP3).bSrcReg1_Negate = FALSE;
|
|
_InstParam(RDPSINST_DP3).WriteMask = bIs3D ? RDPS_COMPONENTMASK_2 : RDPS_COMPONENTMASK_1;
|
|
|
|
if(D3DSIO_TEXM3x3VSPEC == Opcode)
|
|
{
|
|
// eye vector encoded in 4th element of texture coordinates
|
|
_NewPSInst(RDPSINST_SWIZZLE);
|
|
_InstParam(RDPSINST_SWIZZLE).DstReg = EyeReg;
|
|
_InstParam(RDPSINST_SWIZZLE).SrcReg0 = CoordReg;
|
|
_InstParam(RDPSINST_SWIZZLE).WriteMask = RDPS_COMPONENTMASK_2;
|
|
_InstParam(RDPSINST_SWIZZLE).Swizzle = RDPS_REPLICATEALPHA;
|
|
}
|
|
|
|
// Now do stuff that depends on which TEXM3x* instruction this is...
|
|
|
|
if( D3DSIO_TEXM3x3 == Opcode )
|
|
{
|
|
_NewPSInst(RDPSINST_MOV);
|
|
_InstParam(RDPSINST_MOV).DstReg = DstReg;
|
|
_InstParam(RDPSINST_MOV).SrcReg0 = OneReg; // 1.0f
|
|
_InstParam(RDPSINST_MOV).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_MOV).WriteMask = RDPS_COMPONENTMASK_3;
|
|
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
}
|
|
else if ( (D3DSIO_TEXM3x2TEX == Opcode) ||
|
|
(D3DSIO_TEXM3x3TEX == Opcode) )
|
|
{
|
|
// do straight lookup with transformed tex coords - this
|
|
// vector is not normalized, but normalization is not necessary
|
|
// for a cubemap lookup
|
|
|
|
// compute gradients for diffuse lookup
|
|
_LeaveQuadPixelLoop
|
|
|
|
PRGBAVEC pDstReg = DstReg.GetRegPtr();
|
|
|
|
_NewPSInst(RDPSINST_TEXCOVERAGE);
|
|
_InstParam(RDPSINST_TEXCOVERAGE).uiStage = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pGradients = pRast->m_Gradients; // where to store gradients
|
|
// data from which to compute gradients. i.e.: du/dx = DUDX_0 - DUDX_1
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDX_0 = &pDstReg[1][0]; // du/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDX_1 = &pDstReg[0][0];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDY_0 = &pDstReg[2][0]; // du/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDY_1 = &pDstReg[0][0];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDX_0 = &pDstReg[1][1]; // dv/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDX_1 = &pDstReg[0][1];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDY_0 = &pDstReg[2][1]; // dv/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDY_1 = &pDstReg[0][1];
|
|
if( bIs3D )
|
|
{
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_0 = &pDstReg[1][2]; // dw/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_1 = &pDstReg[0][2];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_0 = &pDstReg[2][2]; // dw/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_1 = &pDstReg[0][2];
|
|
}
|
|
else
|
|
{
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_0 = // dw/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_1 =
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_0 = // dw/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_1 = &ZeroReg.GetRegPtr()[0][0]; // 0.0f
|
|
}
|
|
|
|
_EnterQuadPixelLoop
|
|
|
|
// do lookup
|
|
if( !bIs3D )
|
|
{
|
|
_NewPSInst(RDPSINST_MOV);
|
|
_InstParam(RDPSINST_MOV).DstReg = DstReg;
|
|
_InstParam(RDPSINST_MOV).SrcReg0 = ZeroReg; // 0.0f
|
|
_InstParam(RDPSINST_MOV).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_MOV).WriteMask = RDPS_COMPONENTMASK_2;
|
|
}
|
|
|
|
_NewPSInst(RDPSINST_SAMPLE);
|
|
_InstParam(RDPSINST_SAMPLE).DstReg = DstReg;
|
|
_InstParam(RDPSINST_SAMPLE).CoordReg = DstReg;
|
|
_InstParam(RDPSINST_SAMPLE).uiStage = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
}
|
|
else if ( Opcode == D3DSIO_TEXM3x2DEPTH )
|
|
{
|
|
// Take resulting u,v values and compute u/v, which
|
|
// can be interpreted is z/w = perspective correct depth.
|
|
// Then perturb the z coord for the pixel.
|
|
_NewPSInst(RDPSINST_DEPTH);
|
|
_InstParam(RDPSINST_DEPTH).DstReg = DstReg;
|
|
}
|
|
else if ( (Opcode == D3DSIO_TEXM3x3SPEC) ||
|
|
(Opcode == D3DSIO_TEXM3x3VSPEC) )
|
|
{
|
|
RDPSRegister NdotE, NdotN, RCPNdotN, Scale, ReflReg;
|
|
NdotE._Set(RDPSREG_SCRATCH,2);
|
|
NdotN._Set(RDPSREG_SCRATCH,3);
|
|
RCPNdotN = NdotN; // reuse same register
|
|
Scale = NdotE; // reuse same register
|
|
ReflReg = CoordReg; // reuse same register
|
|
|
|
// compute reflection vector and do lookup - the normal needs
|
|
// to be normalized here, which is included in this expression
|
|
if (D3DSIO_TEXM3x3SPEC == Opcode)
|
|
{
|
|
// eye vector is constant register
|
|
EyeReg = SrcReg[1];
|
|
} // else (TEXM3x3VSPEC) -> eye is what was copied out of the 4th component of 3 texcoords
|
|
|
|
|
|
// Compute reflection vector: 2(NdotE/NdotN) * N - E ...
|
|
|
|
// Calculate NdotE
|
|
_NewPSInst(RDPSINST_DP3);
|
|
_InstParam(RDPSINST_DP3).DstReg = NdotE;
|
|
_InstParam(RDPSINST_DP3).SrcReg0 = DstReg; // N
|
|
_InstParam(RDPSINST_DP3).SrcReg1 = EyeReg; // E
|
|
_InstParam(RDPSINST_DP3).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_DP3).bSrcReg1_Negate = FALSE;
|
|
_InstParam(RDPSINST_DP3).WriteMask = RDPS_COMPONENTMASK_3;
|
|
|
|
// Calculate NdotN
|
|
_NewPSInst(RDPSINST_DP3);
|
|
_InstParam(RDPSINST_DP3).DstReg = NdotN;
|
|
_InstParam(RDPSINST_DP3).SrcReg0 = DstReg; // N
|
|
_InstParam(RDPSINST_DP3).SrcReg1 = DstReg; // N
|
|
_InstParam(RDPSINST_DP3).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_DP3).bSrcReg1_Negate = FALSE;
|
|
_InstParam(RDPSINST_DP3).WriteMask = RDPS_COMPONENTMASK_3;
|
|
|
|
// Calculate scale = 2(NdotE/NdotN):
|
|
|
|
// a) Calculate reciprocal of NdotN
|
|
_NewPSInst(RDPSINST_RCP);
|
|
_InstParam(RDPSINST_RCP).DstReg = RCPNdotN;
|
|
_InstParam(RDPSINST_RCP).SrcReg0 = NdotN;
|
|
_InstParam(RDPSINST_RCP).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_RCP).WriteMask = RDPS_COMPONENTMASK_3;
|
|
|
|
// b) Multiply NdotE by reciprocal NdotN
|
|
_NewPSInst(RDPSINST_MUL);
|
|
_InstParam(RDPSINST_MUL).DstReg = Scale;
|
|
_InstParam(RDPSINST_MUL).SrcReg0 = NdotE;
|
|
_InstParam(RDPSINST_MUL).SrcReg1 = RCPNdotN;
|
|
_InstParam(RDPSINST_MUL).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_MUL).bSrcReg1_Negate = FALSE;
|
|
_InstParam(RDPSINST_MUL).WriteMask = RDPS_COMPONENTMASK_3;
|
|
|
|
// c) Multiply by 2
|
|
_NewPSInst(RDPSINST_MUL);
|
|
_InstParam(RDPSINST_MUL).DstReg = Scale;
|
|
_InstParam(RDPSINST_MUL).SrcReg0 = Scale;
|
|
_InstParam(RDPSINST_MUL).SrcReg1 = TwoReg; // 2.0f
|
|
_InstParam(RDPSINST_MUL).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_MUL).bSrcReg1_Negate = FALSE;
|
|
_InstParam(RDPSINST_MUL).WriteMask = RDPS_COMPONENTMASK_3;
|
|
|
|
// d) Replicate result to rgb
|
|
_NewPSInst(RDPSINST_SWIZZLE);
|
|
_InstParam(RDPSINST_SWIZZLE).DstReg = Scale;
|
|
_InstParam(RDPSINST_SWIZZLE).SrcReg0 = Scale;
|
|
_InstParam(RDPSINST_SWIZZLE).WriteMask = RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1 | RDPS_COMPONENTMASK_2;
|
|
_InstParam(RDPSINST_SWIZZLE).Swizzle = RDPS_REPLICATEALPHA;
|
|
|
|
// Calculate reflection = scale * N - E
|
|
|
|
_NewPSInst(RDPSINST_MUL);
|
|
_InstParam(RDPSINST_MUL).DstReg = ReflReg;
|
|
_InstParam(RDPSINST_MUL).SrcReg0 = Scale; // scale *
|
|
_InstParam(RDPSINST_MUL).SrcReg1 = DstReg; // N
|
|
_InstParam(RDPSINST_MUL).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_MUL).bSrcReg1_Negate = FALSE;
|
|
_InstParam(RDPSINST_MUL).WriteMask = RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1 | RDPS_COMPONENTMASK_2;
|
|
|
|
_NewPSInst(RDPSINST_SUB);
|
|
_InstParam(RDPSINST_SUB).DstReg = ReflReg;
|
|
_InstParam(RDPSINST_SUB).SrcReg0 = ReflReg; // (scale * N) -
|
|
_InstParam(RDPSINST_SUB).SrcReg1 = EyeReg; // E
|
|
_InstParam(RDPSINST_SUB).bSrcReg0_Negate = FALSE;
|
|
_InstParam(RDPSINST_SUB).bSrcReg1_Negate = FALSE;
|
|
_InstParam(RDPSINST_SUB).WriteMask = RDPS_COMPONENTMASK_0 | RDPS_COMPONENTMASK_1 | RDPS_COMPONENTMASK_2;
|
|
|
|
// compute gradients for reflection lookup
|
|
_LeaveQuadPixelLoop
|
|
|
|
PRGBAVEC pReflReg = ReflReg.GetRegPtr();
|
|
|
|
_NewPSInst(RDPSINST_TEXCOVERAGE);
|
|
_InstParam(RDPSINST_TEXCOVERAGE).uiStage = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pGradients = pRast->m_Gradients; // where to store gradients
|
|
// data from which to compute gradients. i.e.: du/dx = DUDX_0 - DUDX_1
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDX_0 = &pReflReg[1][0]; // du/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDX_1 = &pReflReg[0][0];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDY_0 = &pReflReg[2][0]; // du/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDUDY_1 = &pReflReg[0][0];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDX_0 = &pReflReg[1][1]; // dv/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDX_1 = &pReflReg[0][1];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDY_0 = &pReflReg[2][1]; // dv/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDVDY_1 = &pReflReg[0][1];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_0 = &pReflReg[1][2]; // dw/dx
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDX_1 = &pReflReg[0][2];
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_0 = &pReflReg[2][2]; // dw/dy
|
|
_InstParam(RDPSINST_TEXCOVERAGE).pDWDY_1 = &pReflReg[0][2];
|
|
|
|
_EnterQuadPixelLoop
|
|
|
|
// do lookup
|
|
_NewPSInst(RDPSINST_SAMPLE);
|
|
_InstParam(RDPSINST_SAMPLE).DstReg = DstReg;
|
|
_InstParam(RDPSINST_SAMPLE).CoordReg = ReflReg;
|
|
_InstParam(RDPSINST_SAMPLE).uiStage = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
}
|
|
}
|
|
break;
|
|
case D3DSIO_BEM:
|
|
_NewPSInst(RDPSINST_BEM);
|
|
_InstParam(RDPSINST_BEM).DstReg = DstReg;
|
|
_InstParam(RDPSINST_BEM).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_BEM).SrcReg1 = SrcReg[1];
|
|
_InstParam(RDPSINST_BEM).bSrcReg0_Negate = bSrcNegate[0];
|
|
_InstParam(RDPSINST_BEM).bSrcReg1_Negate = bSrcNegate[1];
|
|
_InstParam(RDPSINST_BEM).WriteMask = DstWriteMask;
|
|
_InstParam(RDPSINST_BEM).uiStage = pInst->DstParam & D3DSP_REGNUM_MASK;
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
break;
|
|
case D3DSIO_MOV:
|
|
_NewPSInst(RDPSINST_MOV);
|
|
_InstParam(RDPSINST_MOV).DstReg = DstReg;
|
|
_InstParam(RDPSINST_MOV).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_MOV).bSrcReg0_Negate = bSrcNegate[0];
|
|
_InstParam(RDPSINST_MOV).WriteMask = DstWriteMask;
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
break;
|
|
case D3DSIO_FRC:
|
|
_NewPSInst(RDPSINST_FRC);
|
|
_InstParam(RDPSINST_FRC).DstReg = DstReg;
|
|
_InstParam(RDPSINST_FRC).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_FRC).bSrcReg0_Negate = bSrcNegate[0];
|
|
_InstParam(RDPSINST_FRC).WriteMask = DstWriteMask;
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
break;
|
|
case D3DSIO_ADD:
|
|
_NewPSInst(RDPSINST_ADD);
|
|
_InstParam(RDPSINST_ADD).DstReg = DstReg;
|
|
_InstParam(RDPSINST_ADD).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_ADD).SrcReg1 = SrcReg[1];
|
|
_InstParam(RDPSINST_ADD).bSrcReg0_Negate = bSrcNegate[0];
|
|
_InstParam(RDPSINST_ADD).bSrcReg1_Negate = bSrcNegate[1];
|
|
_InstParam(RDPSINST_ADD).WriteMask = DstWriteMask;
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
break;
|
|
case D3DSIO_SUB:
|
|
_NewPSInst(RDPSINST_SUB);
|
|
_InstParam(RDPSINST_SUB).DstReg = DstReg;
|
|
_InstParam(RDPSINST_SUB).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_SUB).SrcReg1 = SrcReg[1];
|
|
_InstParam(RDPSINST_SUB).bSrcReg0_Negate = bSrcNegate[0];
|
|
_InstParam(RDPSINST_SUB).bSrcReg1_Negate = bSrcNegate[1];
|
|
_InstParam(RDPSINST_SUB).WriteMask = DstWriteMask;
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
break;
|
|
case D3DSIO_MUL:
|
|
_NewPSInst(RDPSINST_MUL);
|
|
_InstParam(RDPSINST_MUL).DstReg = DstReg;
|
|
_InstParam(RDPSINST_MUL).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_MUL).SrcReg1 = SrcReg[1];
|
|
_InstParam(RDPSINST_MUL).bSrcReg0_Negate = bSrcNegate[0];
|
|
_InstParam(RDPSINST_MUL).bSrcReg1_Negate = bSrcNegate[1];
|
|
_InstParam(RDPSINST_MUL).WriteMask = DstWriteMask;
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
break;
|
|
case D3DSIO_DP3:
|
|
_NewPSInst(RDPSINST_DP3);
|
|
_InstParam(RDPSINST_DP3).DstReg = DstReg;
|
|
_InstParam(RDPSINST_DP3).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_DP3).SrcReg1 = SrcReg[1];
|
|
_InstParam(RDPSINST_DP3).bSrcReg0_Negate = bSrcNegate[0];
|
|
_InstParam(RDPSINST_DP3).bSrcReg1_Negate = bSrcNegate[1];
|
|
_InstParam(RDPSINST_DP3).WriteMask = DstWriteMask;
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
break;
|
|
case D3DSIO_DP4:
|
|
_NewPSInst(RDPSINST_DP4);
|
|
_InstParam(RDPSINST_DP4).DstReg = DstReg;
|
|
_InstParam(RDPSINST_DP4).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_DP4).SrcReg1 = SrcReg[1];
|
|
_InstParam(RDPSINST_DP4).bSrcReg0_Negate = bSrcNegate[0];
|
|
_InstParam(RDPSINST_DP4).bSrcReg1_Negate = bSrcNegate[1];
|
|
_InstParam(RDPSINST_DP4).WriteMask = DstWriteMask;
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
break;
|
|
case D3DSIO_MAD:
|
|
_NewPSInst(RDPSINST_MAD);
|
|
_InstParam(RDPSINST_MAD).DstReg = DstReg;
|
|
_InstParam(RDPSINST_MAD).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_MAD).SrcReg1 = SrcReg[1];
|
|
_InstParam(RDPSINST_MAD).SrcReg2 = SrcReg[2];
|
|
_InstParam(RDPSINST_MAD).bSrcReg0_Negate = bSrcNegate[0];
|
|
_InstParam(RDPSINST_MAD).bSrcReg1_Negate = bSrcNegate[1];
|
|
_InstParam(RDPSINST_MAD).bSrcReg2_Negate = bSrcNegate[2];
|
|
_InstParam(RDPSINST_MAD).WriteMask = DstWriteMask;
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
break;
|
|
case D3DSIO_LRP:
|
|
_NewPSInst(RDPSINST_LRP);
|
|
_InstParam(RDPSINST_LRP).DstReg = DstReg;
|
|
_InstParam(RDPSINST_LRP).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_LRP).SrcReg1 = SrcReg[1];
|
|
_InstParam(RDPSINST_LRP).SrcReg2 = SrcReg[2];
|
|
_InstParam(RDPSINST_LRP).bSrcReg0_Negate = bSrcNegate[0];
|
|
_InstParam(RDPSINST_LRP).bSrcReg1_Negate = bSrcNegate[1];
|
|
_InstParam(RDPSINST_LRP).bSrcReg2_Negate = bSrcNegate[2];
|
|
_InstParam(RDPSINST_LRP).WriteMask = DstWriteMask;
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
break;
|
|
case D3DSIO_CND:
|
|
_NewPSInst(RDPSINST_CND);
|
|
_InstParam(RDPSINST_CND).DstReg = DstReg;
|
|
_InstParam(RDPSINST_CND).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_CND).SrcReg1 = SrcReg[1];
|
|
_InstParam(RDPSINST_CND).SrcReg2 = SrcReg[2];
|
|
_InstParam(RDPSINST_CND).bSrcReg0_Negate = bSrcNegate[0];
|
|
_InstParam(RDPSINST_CND).bSrcReg1_Negate = bSrcNegate[1];
|
|
_InstParam(RDPSINST_CND).bSrcReg2_Negate = bSrcNegate[2];
|
|
_InstParam(RDPSINST_CND).WriteMask = DstWriteMask;
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
break;
|
|
case D3DSIO_CMP:
|
|
_NewPSInst(RDPSINST_CMP);
|
|
_InstParam(RDPSINST_CMP).DstReg = DstReg;
|
|
_InstParam(RDPSINST_CMP).SrcReg0 = SrcReg[0];
|
|
_InstParam(RDPSINST_CMP).SrcReg1 = SrcReg[1];
|
|
_InstParam(RDPSINST_CMP).SrcReg2 = SrcReg[2];
|
|
_InstParam(RDPSINST_CMP).bSrcReg0_Negate = bSrcNegate[0];
|
|
_InstParam(RDPSINST_CMP).bSrcReg1_Negate = bSrcNegate[1];
|
|
_InstParam(RDPSINST_CMP).bSrcReg2_Negate = bSrcNegate[2];
|
|
_InstParam(RDPSINST_CMP).WriteMask = DstWriteMask;
|
|
_EmitDstMod(DstReg,DstWriteMask)
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if( pInst->bFlushQueue )
|
|
{
|
|
_EnterQuadPixelLoop
|
|
_NewPSInst(RDPSINST_FLUSHQUEUE);
|
|
QueueIndex = -1;
|
|
}
|
|
|
|
#if DBG
|
|
_LeaveQuadPixelLoop
|
|
#endif
|
|
}
|
|
|
|
// Flush queue at end of shader if there is anything on it
|
|
if( -1 != QueueIndex )
|
|
{
|
|
_EnterQuadPixelLoop
|
|
_NewPSInst(RDPSINST_FLUSHQUEUE);
|
|
QueueIndex = -1;
|
|
}
|
|
|
|
_LeaveQuadPixelLoop
|
|
|
|
_NewPSInst(RDPSINST_END);
|
|
|
|
#if DBG
|
|
if( pRast->m_bDebugPrintTranslatedPixelShaderTokens )
|
|
RDPSDisAsm(pRDPSInstBuffer, m_pConstDefs, m_cConstDefs,pCaps->MaxPixelShaderValue, Version);
|
|
#endif
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
// end
|