|
|
///////////////////////////////////////////////////////////////////////////////
// Copyright (C) Microsoft Corporation, 2000.
//
// valbase.hpp
//
// Direct3D Reference Device - Vertex/PixelShader validation common infrastructure
//
///////////////////////////////////////////////////////////////////////////////
#ifndef __VALBASE_HPP__
#define __VALBASE_HPP__
#define NUM_COMPONENTS_IN_REGISTER 4
#define SHADER_INSTRUCTION_MAX_PARAMS 4
#define SHADER_INSTRUCTION_MAX_SRCPARAMS (SHADER_INSTRUCTION_MAX_PARAMS - 1)
typedef enum _SPEW_TYPE { SPEW_INSTRUCTION_ERROR, SPEW_INSTRUCTION_WARNING, SPEW_GLOBAL_ERROR, SPEW_GLOBAL_WARNING } SPEW_TYPE;
typedef enum _SHADER_VALIDATOR_FLAGS { SHADER_VALIDATOR_LOG_ERRORS = 0x1, SHADER_VALIDATOR_OPTIMIZE_WRITEMASKS = 0x2 } SHADER_VALIDATOR_FLAGS;
typedef enum _DSTSHIFT { DSTSHIFT_NONE = 0x0, DSTSHIFT_X2 = 0x1, DSTSHIFT_X4 = 0x2, DSTSHIFT_X8 = 0x3, DSTSHIFT_D2 = 0xF, DSTSHIFT_D4 = 0xE, DSTSHIFT_D8 = 0xD } DSTSHIFT;
const DWORD COMPONENT_MASKS[4] = {D3DSP_WRITEMASK_0, D3DSP_WRITEMASK_1, D3DSP_WRITEMASK_2, D3DSP_WRITEMASK_3};
//-----------------------------------------------------------------------------
// DSTPARAM - part of CBaseInstruction
//-----------------------------------------------------------------------------
class DSTPARAM { public: DSTPARAM();
BOOL m_bParamUsed; // Does instruction have dest param?
UINT m_RegNum; DWORD m_WriteMask; // writemasks (D3DSP_WRITEMASK_*)
D3DSHADER_PARAM_DSTMOD_TYPE m_DstMod; // D3DSPDM_NONE, D3DSPDM_SATURATE (PShader)
DSTSHIFT m_DstShift; // _x2, _x4, etc. (PShader)
D3DSHADER_PARAM_REGISTER_TYPE m_RegType; // _TEMP, _ADDRESS, etc.
DWORD m_ComponentReadMask; // Which components instruction needs to read
// This seems strage, but in ps.2.0 there are some ops
// that have one parameter (dest), but they read from it, and write back to it.
};
//-----------------------------------------------------------------------------
// SRCPARAM - part of CBaseInstruction
//-----------------------------------------------------------------------------
class SRCPARAM { public: SRCPARAM();
BOOL m_bParamUsed; // Does instruction have this src param?
UINT m_RegNum; DWORD m_SwizzleShift; // D3DVS_*_*, or D3DSP_NOSWIZZLE/
// D3DSP_REPLICATERED/GREEN/BLUE/ALPHA
D3DVS_ADDRESSMODE_TYPE m_AddressMode; // D3DVS_ADDRMODE_ABSOLUTE / _RELATIVE (VShader)
DWORD m_RelativeAddrComponent; // One of D3DSP_WRITEMASK_0, 1, 2, or 3. (VShader)
D3DSHADER_PARAM_SRCMOD_TYPE m_SrcMod; // _NEG, _BIAS, etc.
D3DSHADER_PARAM_REGISTER_TYPE m_RegType; // _TEMP, _CONST, etc.
DWORD m_ComponentReadMask; // Which components instruction needs to read
};
//-----------------------------------------------------------------------------
// CBaseInstruction
//-----------------------------------------------------------------------------
class CBaseInstruction { public: CBaseInstruction(CBaseInstruction* pPrevInst); // Append to linked list
void SetSpewFileNameAndLineNumber(const char* pFileName, const DWORD* pLineNumber); char* MakeInstructionLocatorString(); virtual void CalculateComponentReadMasks(DWORD dwVersion) = 0; // which components to each source read?
// Instruction Description
D3DSHADER_INSTRUCTION_OPCODE_TYPE m_Type; UINT m_DstParamCount; UINT m_SrcParamCount; CBaseInstruction* m_pPrevInst; CBaseInstruction* m_pNextInst; const DWORD* m_pSpewLineNumber; // points to line number embedded in shader by assembler (if present)
const char* m_pSpewFileName; // points to file name embedded in shader (if present)
UINT m_SpewInstructionCount; // only used for spew, not for any limit checking
// Destination Parameter Description
DSTPARAM m_DstParam; // Source Parameters
SRCPARAM m_SrcParam[SHADER_INSTRUCTION_MAX_SRCPARAMS]; };
//-----------------------------------------------------------------------------
// CAccessHistoryNode
//-----------------------------------------------------------------------------
class CAccessHistoryNode { public: CAccessHistoryNode(CAccessHistoryNode* pPreviousAccess, CAccessHistoryNode* pPreviousWriter, CAccessHistoryNode* pPreviousReader, CBaseInstruction* pInst, BOOL bWrite );
CAccessHistoryNode* m_pPreviousAccess; CAccessHistoryNode* m_pNextAccess; CAccessHistoryNode* m_pPreviousWriter; CAccessHistoryNode* m_pPreviousReader; CBaseInstruction* m_pInst; BOOL m_bWrite; BOOL m_bRead; };
//-----------------------------------------------------------------------------
// CAccessHistory
//-----------------------------------------------------------------------------
class CAccessHistory { public: CAccessHistory(); ~CAccessHistory(); CAccessHistoryNode* m_pFirstAccess; CAccessHistoryNode* m_pMostRecentAccess; CAccessHistoryNode* m_pMostRecentWriter; CAccessHistoryNode* m_pMostRecentReader; BOOL m_bPreShaderInitialized;
BOOL NewAccess(CBaseInstruction* pInst, BOOL bWrite ); BOOL InsertReadBeforeWrite(CAccessHistoryNode* pWriteNode, CBaseInstruction* pInst); };
//-----------------------------------------------------------------------------
// CRegisterFile
//-----------------------------------------------------------------------------
class CRegisterFile { UINT m_NumRegisters; BOOL m_bWritable; UINT m_NumReadPorts; BOOL m_bInitOk; public: CRegisterFile(UINT NumRegisters, BOOL bWritable, UINT NumReadPorts, BOOL bPreShaderInitialized ); ~CRegisterFile();
inline UINT GetNumRegs() {return m_NumRegisters;}; inline BOOL IsWritable() {return m_bWritable;}; inline UINT GetNumReadPorts() {return m_NumReadPorts;}; inline BOOL InitOk() {return m_bInitOk;}; CAccessHistory* m_pAccessHistory[NUM_COMPONENTS_IN_REGISTER]; };
//-----------------------------------------------------------------------------
// CBaseShaderValidator
//-----------------------------------------------------------------------------
class CBaseShaderValidator { protected: BOOL m_bBaseInitOk; DWORD m_Version; UINT m_SpewInstructionCount; // only used for spew, not for any limit checking
CBaseInstruction* m_pInstructionList; const DWORD* m_pCurrToken; HRESULT m_ReturnCode; BOOL m_bSeenAllInstructions; DWORD m_ErrorCount; CErrorLog* m_pLog; CBaseInstruction* m_pCurrInst; const D3DCAPS8* m_pCaps; // can be NULL if not provided.
const DWORD* m_pLatestSpewLineNumber; // points to latest line number sent in comment from D3DX Assembler
const char* m_pLatestSpewFileName; // points to latest file name sent in comment from D3DX Assembler
// m_bSrcParamError needed by Rule_SrcInitialized (in both vshader and pshader)
BOOL m_bSrcParamError[SHADER_INSTRUCTION_MAX_SRCPARAMS];
virtual BOOL DecodeNextInstruction() = 0; void DecodeDstParam( DSTPARAM* pDstParam, DWORD Token ); void DecodeSrcParam( SRCPARAM* pSrcParam, DWORD Token ); virtual BOOL InitValidation() = 0; void ValidateShader(); virtual BOOL ApplyPerInstructionRules() = 0; virtual void ApplyPostInstructionsRules() = 0; virtual CBaseInstruction* AllocateNewInstruction(CBaseInstruction* pPrevInst) = 0; void ParseCommentForAssemblerMessages(const DWORD* pComment); void Spew( SPEW_TYPE SpewType, CBaseInstruction* pInst /* can be NULL */, const char* pszFormat, ... ); char* MakeAffectedComponentsText( DWORD ComponentMask, BOOL bColorLabels = TRUE, BOOL bPositionLabels = TRUE);
public: CBaseShaderValidator( const DWORD* pCode, const D3DCAPS8* pCaps, DWORD Flags ); ~CBaseShaderValidator();
DWORD GetRequiredLogBufferSize() { if( m_pLog ) return m_pLog->GetRequiredLogBufferSize(); else return 0; }
void WriteLogToBuffer( char* pBuffer ) { if( m_pLog ) m_pLog->WriteLogToBuffer( pBuffer ); }
HRESULT GetStatus() { return m_ReturnCode; }; };
#endif //__VALBASE_HPP__
|