/////////////////////////////////////////////////////////////////////////////// // // ## ###### // ###### ### // ## ############### Shark 3D Engine (www.shark3d.com) // ########## # # # // ######## Copyright (c) 1996-2006 Spinor GmbH. // ######### # # # All rights reserved. // ## ########## // ## // /////////////////////////////////////////////////////////////////////////////// //@cpp #include "drv_d3d9_proghlsl.h" #include "drv_d3d9_progutil.h" #include "drv_d3d9_progincmgr.h" #include "drv_d3d9_progreport.h" #include "drv_d3d9_util.h" #include "drv/interf/drv_vartypes.h" #include "drv/util/drv_util_varutil.h" #include "drv/util/drv_util_varfetch.h" #include "drv/util/drv_util_gfxprog.h" #include "util/os/util_filesystem.h" #include "util/snk/util_snk_extractutil.h" #include "util/notif/util_multinotif.h" #include "util/cont/util_arrayalgo.h" /////////////////////////////////////////////////////////////////////////////// /*@{ @declare{shaderprog.param}{}{$ [chunk]} Parameters for d3d HLSL @ident{shaderprog}{d3d9.hlsl_vertshader} and @ident{shaderprog}{d3d9.hlsl_pixshader}. This is a pseudo chunk name. @}*/ /////////////////////////////////////////////////////////////////////////////// #define S3D_DRV_D3D9_RESOLVEVAR(Var, VarInfo, VarName)\ s3d_CDrvD3d9ProgHLSLUtil::ResolveVar(\ ProgCtx, VarInfo, CodeName, ConstTab, Var, VarName, VarSet); /////////////////////////////////////////////////////////////////////////////// s3d_CDrvD3d9ProgHLSL::s3d_CDrvD3d9ProgHLSL( s3d_CUtilNotifGather *NotifGather, s3d_CUtilStr_cr Info, s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilSnkChunk *ParamVert, s3d_CUtilSnkChunk *ParamPix) { m_ProgCtx = ProgCtx; m_Info = Info; s3d_CUtilMemPoolFrm MemPoolFrm(ProgCtx->m_MemPool); const s3d_CDrvD3d9Param *D3dParam = ProgCtx->m_D3dParam; if(D3dParam->m_ReportProg) m_ReportMsgHandler = ProgCtx->m_MsgHandler; if(ParamVert) { s3d_CDrvD3d9ProgHLSLUtil::CreateShader( NotifGather, ParamVert, ProgCtx, true, this, m_VertTrackBlk); } if(ParamPix) { s3d_CDrvD3d9ProgHLSLUtil::CreateShader( NotifGather, ParamPix, ProgCtx, false, this, m_PixTrackBlk); } } void s3d_CDrvD3d9ProgHLSL::TrackParams( s3d_CDrvGfxParam_cr GfxParam, const s3d_CDrvD3d9ParamBlk &ParamBlk, const s3d_CDrvD3d9ParamBlkState &ParamBlkState) { TrackParams(GfxParam, ParamBlk, ParamBlkState, m_VertTrackBlk); TrackParams(GfxParam, ParamBlk, ParamBlkState, m_PixTrackBlk); } void s3d_CDrvD3d9ProgHLSL::TrackTransfBone( s3d_CSysIntps BoneIdxCnt, const s3d_CSysInt32u *BoneIdxData, s3d_CSysIntps MatBoneCnt, const D3DXMATRIXA16 *MatBoneArray) { TrackTransfBone( BoneIdxCnt, BoneIdxData, MatBoneCnt, MatBoneArray, m_VertTrackBlk); TrackTransfBone( BoneIdxCnt, BoneIdxData, MatBoneCnt, MatBoneArray, m_PixTrackBlk); } void s3d_CDrvD3d9ProgHLSL::CalcVertBufDesc( const s3d_CDrvGfxCharge *Charge, s3d_CDrvD3d9VertBufDesc &VertBufDesc) const { s3d_CDrvD3d9ProgUtil::CalcVertBufDesc( m_ProgCtx, Charge, m_VertProgDecl.m_ProgUsage, m_VertComprFmt, VertBufDesc); } bool s3d_CDrvD3d9ProgHLSL::IsValid() { if(!m_VertTrackBlk.m_CodeName.IsEmpty() && !m_VertShader) return false; if(!m_PixTrackBlk.m_CodeName.IsEmpty() && !m_PixShader) return false; return true; } void s3d_CDrvD3d9ProgHLSL::GetVertProgCodeInfoName( s3d_CUtilStr &CodeInfo, s3d_CUtilStr &CodeName) const { CodeInfo = m_VertTrackBlk.m_CodeInfo; CodeName = m_VertTrackBlk.m_CodeName; } void s3d_CDrvD3d9ProgHLSL::GetPixProgCodeInfoName( s3d_CUtilStr &CodeInfo, s3d_CUtilStr &CodeName) const { CodeInfo = m_PixTrackBlk.m_CodeInfo; CodeName = m_PixTrackBlk.m_CodeName; } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9ProgHLSL::TrackMatTrans( const D3DXHANDLE &Var, int Trans, const D3DXMATRIXA16 *Mat, s3d_CSysIntps Cnt, const LPD3DXCONSTANTTABLE ConstTab, LPDIRECT3DDEVICE9 D3dDev) { switch(Trans) { case s3d_CDrvUtilGfxProg::TrackTrans_Identity: { S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetMatrixTransposeArray( D3dDev, Var, Mat, UINT(Cnt))); break; } case s3d_CDrvUtilGfxProg::TrackTrans_Inv: { if(Cnt > 1) { D3DXMATRIXA16 *InvMat = reinterpret_cast (alloca(Cnt * S3D_SYS_SIZEOFS(D3DXMATRIXA16))); s3d_CSysIntps i; for(i = 0; i < Cnt; i++) D3DXMatrixInverse(&InvMat[i], 0, Mat); S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetMatrixTransposeArray( D3dDev, Var, InvMat, UINT(Cnt))); } else { D3DXMATRIXA16 InvMat; D3DXMatrixInverse(&InvMat, 0, Mat); S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetMatrixTranspose(D3dDev, Var, &InvMat)); } break; } case s3d_CDrvUtilGfxProg::TrackTrans_Transp: { S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetMatrixArray( D3dDev, Var, Mat, UINT(Cnt))); break; } case s3d_CDrvUtilGfxProg::TrackTrans_InvTransp: { if(Cnt > 1) { D3DXMATRIXA16 *InvMat = reinterpret_cast (alloca(Cnt * S3D_SYS_SIZEOFS(D3DXMATRIXA16))); s3d_CSysIntps i; for(i = 0; i < Cnt; i++) D3DXMatrixInverse(&InvMat[i], 0, Mat); S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetMatrixArray( D3dDev, Var, InvMat, UINT(Cnt))); } else { D3DXMATRIXA16 InvMat; D3DXMatrixInverse(&InvMat, 0, Mat); S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetMatrix( D3dDev, Var, &InvMat)); } break; } default: S3D_SYS_ASSERT(0); break; } } void s3d_CDrvD3d9ProgHLSL::TrackParams( s3d_CDrvGfxParam_cr GfxParam, const s3d_CDrvD3d9ParamBlk &ParamBlk, const s3d_CDrvD3d9ParamBlkState &ParamBlkState, s3d_CDrvD3d9ProgHLSLTrackBlk &TrackBlk) { LPDIRECT3DDEVICE9 D3dDev = m_ProgCtx->m_D3dDev; if(!D3dDev) return; LPD3DXCONSTANTTABLE ConstTab = TrackBlk.m_ConstTab; if(!ConstTab) return; S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetDefaults(D3dDev)); const s3d_CSysChar *Info = TrackBlk.m_CodeInfo.GetChars(); const s3d_CDrvD3d9ProgHLSLTrackMatArray *TrackMatArray = &TrackBlk.m_MatTrackArray; s3d_CSysIntps nTrackMat = TrackMatArray->GetCnt(); s3d_CSysIntps iTrackMat; for(iTrackMat = 0; iTrackMat < nTrackMat; iTrackMat++) { const s3d_CDrvD3d9ProgHLSLTrackMat *TrackMat = &TrackMatArray->RefAtRaw(iTrackMat); D3DXHANDLE Var = TrackMat->m_Var; if(!Var) continue; int Trans = TrackMat->m_Trans; switch(TrackMat->m_Chan) { case s3d_CDrvUtilGfxProg::TrackChan_View: { if(ParamBlkState.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_MatView) { TrackMatTrans( Var, Trans, &ParamBlk.m_MatView, 1, ConstTab, D3dDev); } break; } case s3d_CDrvUtilGfxProg::TrackChan_Proj: { if(ParamBlkState.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_MatProj) { TrackMatTrans( Var, Trans, &ParamBlk.m_MatProj, 1, ConstTab, D3dDev); } break; } case s3d_CDrvUtilGfxProg::TrackChan_ProjView: { if((ParamBlkState.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_MatView) || (ParamBlkState.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_MatProj)) { D3DXMATRIXA16 ProjView; D3DXMatrixMultiply( &ProjView, &ParamBlk.m_MatProj, &ParamBlk.m_MatView); TrackMatTrans( Var, Trans, &ProjView, 1, ConstTab, D3dDev); } break; } case s3d_CDrvUtilGfxProg::TrackChan_Attr: { if(ParamBlkState.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_MatGen) { int Slot = TrackMat->m_Slot; const D3DXMATRIXA16 *Mat = &ParamBlk.m_MatGenArray[Slot]; TrackMatTrans( Var, Trans, Mat, 1, ConstTab, D3dDev); } break; } default: break; } } if(ParamBlk.m_UseConstColorAlpha) TrackNoLighting(ParamBlk, ParamBlkState, TrackBlk); else TrackLighting(ParamBlk, ParamBlkState, TrackBlk); D3DXHANDLE Var = TrackBlk.m_FogVar; if(Var && (ParamBlkState.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_Fog)) { S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector( D3dDev, Var, &ParamBlk.m_FogColDensity)); } const s3d_CDrvD3d9TexObjBasePtr *SampTexArray = ParamBlk.m_SampTexArray; const s3d_CDrvD3d9ProgHLSLVarArray *TexSizeArray = &TrackBlk.m_TexSizeArray; s3d_CSysIntps nTex = TexSizeArray->GetCnt(); s3d_CSysIntps iTex; for(iTex = 0; iTex < nTex; iTex++) { D3DXHANDLE Var = TexSizeArray->GetAtRaw(iTex); if(Var) { D3DXVECTOR4 Val(0, 0, 0, 0); s3d_CDrvD3d9TexObjBase *Tex = 0; if(iTex < m_ProgCtx->m_MaxSampCnt) Tex = SampTexArray[iTex]; if(Tex) { Val.x = s3d_SysFloatOfInt(Tex->m_Width); Val.y = s3d_SysFloatOfInt(Tex->m_Height); Val.z = s3d_SysFloatOfInt(Tex->m_Depth); Val.w = 0; } S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector(D3dDev, Var, &Val)); } } const s3d_CDrvD3d9ProgHLSLVarArray *TexRcpSizeArray = &TrackBlk.m_TexRcpSizeArray; nTex = TexRcpSizeArray->GetCnt(); for(iTex = 0; iTex < nTex; iTex++) { D3DXHANDLE Var = TexRcpSizeArray->GetAtRaw(iTex); if(Var) { D3DXVECTOR4 Val(0, 0, 0, 0); s3d_CDrvD3d9TexObjBase *Tex = 0; if(iTex < m_ProgCtx->m_MaxSampCnt) Tex = SampTexArray[iTex]; if(Tex) { Val.x = 1 / s3d_SysFloatOfInt(Tex->m_Width); Val.y = 1 / s3d_SysFloatOfInt(Tex->m_Height); Val.z = 1 / s3d_SysFloatOfInt(Tex->m_Depth); Val.w = 0; } S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector(D3dDev, Var, &Val)); } } s3d_CDrvUtilVarFetch VarFetch( m_ProgCtx->m_MsgHandler, GfxParam.m_Blk); s3d_CDrvD3d9ProgHLSLParamEntry *ParamArray = TrackBlk.m_ParamArray.GetPtrRaw(); s3d_CSysIntps nParam = TrackBlk.m_ParamArray.GetCnt(); s3d_CSysIntps iParam; for(iParam = 0; iParam < nParam; iParam++) { s3d_CDrvD3d9ProgHLSLParamEntry *Param = &ParamArray[iParam]; s3d_CDrvVarSlot *VarSlot = VarFetch.FetchNextSlot( Param->m_Val.m_Info.GetChars(), Param->m_Key, Param->m_Val.m_HadError, Param->m_Val.m_HadError); s3d_CUtilRecogBase *VarRecog = s3d_DrvVarFetchWary(m_ProgCtx->m_MsgHandler, Info, GfxParam.m_Blk, *VarSlot); if(!VarRecog) continue; const s3d_CDrvD3d9ProgHLSLParam *ParamEntry = &Param->m_Val; D3DXHANDLE ParamVar = ParamEntry->m_Var; if(!ParamVar) continue; const s3d_CSysChar *ParamInfo = ParamEntry->m_Info.GetChars(); switch(ParamEntry->m_Type) { case s3d_CDrvUtilGfxProg::ParamType_Float4: { const s3d_CDrvVarVec4f *DrvVar = s3d_DrvVarCast( m_ProgCtx->m_MsgHandler, ParamInfo, GfxParam.m_Blk, *VarSlot, VarRecog); if(DrvVar) { const float *fD3dVal = reinterpret_cast(&DrvVar->m_Val); S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetFloatArray( D3dDev, ParamVar, fD3dVal, 4)); } break; } case s3d_CDrvUtilGfxProg::ParamType_Float4x4: case s3d_CDrvUtilGfxProg::ParamType_Float4x4_Transp: case s3d_CDrvUtilGfxProg::ParamType_Float4x4_Inv: case s3d_CDrvUtilGfxProg::ParamType_Float4x4_InvTransp: { const s3d_CDrvVarMat4x4f *DrvVar; DrvVar = s3d_DrvVarCast( m_ProgCtx->m_MsgHandler, ParamInfo, GfxParam.m_Blk, *VarSlot, VarRecog); if(DrvVar) { D3DXMATRIXA16 Mat; const s3d_CUtilMat4x4f *EngMat = &DrvVar->m_Val; Mat._11 = EngMat->m_xx; Mat._21 = EngMat->m_yx; Mat._31 = EngMat->m_zx; Mat._41 = EngMat->m_wx; Mat._12 = EngMat->m_xy; Mat._22 = EngMat->m_yy; Mat._32 = EngMat->m_zy; Mat._42 = EngMat->m_wy; Mat._13 = EngMat->m_xz; Mat._23 = EngMat->m_yz; Mat._33 = EngMat->m_zz; Mat._43 = EngMat->m_wz; Mat._14 = EngMat->m_xw; Mat._24 = EngMat->m_yw; Mat._34 = EngMat->m_zw; Mat._44 = EngMat->m_ww; int Trans = ParamEntry->m_Type; /*s3d_CDrvUtilGfxProg::TransOfParamType( ParamEntry->m_Type);*/ TrackMatTrans( ParamVar, Trans, &Mat, 1, ConstTab, D3dDev); } break; } default: S3D_SYS_ASSERT(0); break; } } } void s3d_CDrvD3d9ProgHLSL::TrackNoLighting( const s3d_CDrvD3d9ParamBlk &ParamBlk, const s3d_CDrvD3d9ParamBlkState &ParamBlkState, s3d_CDrvD3d9ProgHLSLTrackBlk &TrackBlk) { LPDIRECT3DDEVICE9 D3dDev = m_ProgCtx->m_D3dDev; LPD3DXCONSTANTTABLE ConstTab = TrackBlk.m_ConstTab; D3DXHANDLE Var = TrackBlk.m_Mtl.m_EmissiveVar; if(Var) { const D3DXVECTOR4 *Vec4 = reinterpret_cast( &ParamBlk.m_ColorAlphaVal); S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector(D3dDev, Var, Vec4)); } Var = TrackBlk.m_ActiveLightCntVar; if(Var) { S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetInt( D3dDev, Var, 0)); } s3d_CSysIntps FromLight = 0; TrackLightingBlack(ParamBlk, ParamBlkState, TrackBlk, FromLight); } void s3d_CDrvD3d9ProgHLSL::TrackLighting( const s3d_CDrvD3d9ParamBlk &ParamBlk, const s3d_CDrvD3d9ParamBlkState &ParamBlkState, s3d_CDrvD3d9ProgHLSLTrackBlk &TrackBlk) { LPDIRECT3DDEVICE9 D3dDev = m_ProgCtx->m_D3dDev; LPD3DXCONSTANTTABLE ConstTab = TrackBlk.m_ConstTab; if(ParamBlkState.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_Mtl) { D3DXHANDLE Var = TrackBlk.m_Mtl.m_EmissiveVar; if(Var) { const D3DXVECTOR4 *Vec4 = reinterpret_cast( &ParamBlk.m_Mtl.Emissive); S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector(D3dDev, Var, Vec4)); } Var = TrackBlk.m_Mtl.m_PowerVar; if(Var) { D3DXVECTOR4 Vec4; Vec4.x = ParamBlk.m_Mtl.Power; Vec4.y = ParamBlk.m_Mtl.Power; Vec4.z = ParamBlk.m_Mtl.Power; Vec4.w = ParamBlk.m_Mtl.Power; S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector(D3dDev, Var, &Vec4)); } } if(ParamBlkState.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_Light) { const s3d_CDrvD3d9ProgHLSLLightArray *LightTrackArray = &TrackBlk.m_LightTrackArray; s3d_CSysIntps MaxProgLightCnt = LightTrackArray->GetCnt(); s3d_CSysIntps nLightCnt = ParamBlk.m_CurLightCnt; const D3DLIGHT9 *Light = ParamBlk.m_LightArray; if(nLightCnt > MaxProgLightCnt) nLightCnt = MaxProgLightCnt; const s3d_CDrvD3d9ProgHLSLLight *ProgLight = LightTrackArray->GetPtrRaw(); s3d_CSysIntps iLight; for(iLight = 0; iLight < nLightCnt; iLight++) { D3DXHANDLE Var = ProgLight->m_AmbientVar; if(Var) { const D3DXVECTOR4 *Vec4 = reinterpret_cast( &Light->Ambient); S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector( D3dDev, Var, Vec4)); } Var = ProgLight->m_DiffuseVar; if(Var) { const D3DXVECTOR4 *Vec4 = reinterpret_cast( &Light->Diffuse); S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector( D3dDev, Var, Vec4)); } Var = ProgLight->m_SpecularVar; if(Var) { const D3DXVECTOR4 *Vec4 = reinterpret_cast( &Light->Specular); S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector( D3dDev, Var, Vec4)); } Var = ProgLight->m_PosVar; if(Var) { const D3DXVECTOR4 *Vec4 = reinterpret_cast( &Light->Position); S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector( D3dDev, Var, Vec4)); } Var = ProgLight->m_DirVar; if(Var) { const D3DXVECTOR4 *Vec4 = reinterpret_cast( &Light->Direction); S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector( D3dDev, Var, Vec4)); } Var = ProgLight->m_AttenVar; if(Var) { float Atten[4]; Atten[0] = Light->Attenuation0; //AttenConst Atten[1] = Light->Attenuation1; //AttenLinear Atten[2] = Light->Attenuation2; //AttenQuadr Atten[3] = Light->Range; S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetFloatArray( D3dDev, Var, Atten, 4)); } Light++; ProgLight++; } D3DXHANDLE Var = TrackBlk.m_ActiveLightCntVar; if(Var) { S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetInt( D3dDev, Var, INT(nLightCnt))); } if(nLightCnt < MaxProgLightCnt) { TrackLightingBlack( ParamBlk, ParamBlkState, TrackBlk, nLightCnt); } } } void s3d_CDrvD3d9ProgHLSL::TrackLightingBlack( const s3d_CDrvD3d9ParamBlk &ParamBlk, const s3d_CDrvD3d9ParamBlkState &ParamBlkState, s3d_CDrvD3d9ProgHLSLTrackBlk &TrackBlk, s3d_CSysIntps FromLight) { LPDIRECT3DDEVICE9 D3dDev = m_ProgCtx->m_D3dDev; LPD3DXCONSTANTTABLE ConstTab = TrackBlk.m_ConstTab; const s3d_CDrvD3d9ProgHLSLLightArray *LightArray = &TrackBlk.m_LightTrackArray; s3d_CSysIntps nLightCnt = LightArray->GetCnt(); s3d_CSysIntps iLight; for(iLight = FromLight; iLight < nLightCnt; iLight++) { const s3d_CDrvD3d9ProgHLSLLight *ProgLight = &LightArray->RefAtRaw(iLight); const D3DXVECTOR4 Vec4(0, 0, 0, 0); D3DXHANDLE Var = ProgLight->m_AmbientVar; if(Var) { S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector( D3dDev, Var, &Vec4)); } Var = ProgLight->m_DiffuseVar; if(Var) { S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector( D3dDev, Var, &Vec4)); } Var = ProgLight->m_SpecularVar; if(Var) { S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector( D3dDev, Var, &Vec4)); } Var = ProgLight->m_PosVar; if(Var) { S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector( D3dDev, Var, &Vec4)); } Var = ProgLight->m_DirVar; if(Var) { S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector( D3dDev, Var, &Vec4)); } Var = ProgLight->m_AttenVar; if(Var) { S3D_DRV_D3D9_CHECK( m_ProgCtx->m_Env, ConstTab->SetVector( D3dDev, Var, &Vec4)); } } } void s3d_CDrvD3d9ProgHLSL::TrackTransfBone( s3d_CSysIntps BoneIdxCnt, const s3d_CSysInt32u *BoneIdxData, s3d_CSysIntps MatBoneCnt, const D3DXMATRIXA16 *MatBoneArray, s3d_CDrvD3d9ProgHLSLTrackBlk &TrackBlk) { if(!BoneIdxData) return; if(!MatBoneArray) return; LPDIRECT3DDEVICE9 D3dDev = m_ProgCtx->m_D3dDev; LPD3DXCONSTANTTABLE ConstTab = TrackBlk.m_ConstTab; if(!ConstTab) return; const s3d_CSysChar *Info = TrackBlk.m_CodeInfo.GetChars(); const s3d_CDrvD3d9ProgHLSLTrackMatArray *TrackMatArray = &TrackBlk.m_BoneTrackArray; LPD3DXMATRIXA16 BoneMatData = reinterpret_cast( alloca(S3D_SYS_SIZEOFS(D3DXMATRIXA16) * BoneIdxCnt)); s3d_CSysIntps iBoneIdx; for(iBoneIdx = 0; iBoneIdx < BoneIdxCnt; iBoneIdx++) { s3d_CSysIntps MatBoneIdx = BoneIdxData[iBoneIdx]; if(MatBoneIdx >= MatBoneCnt) D3DXMatrixIdentity(&BoneMatData[iBoneIdx]); else BoneMatData[iBoneIdx] = MatBoneArray[MatBoneIdx]; } const s3d_CDrvD3d9ProgHLSLTrackMat *TrackMat = TrackMatArray->GetPtrRaw(); s3d_CSysIntps nTrackMat = TrackMatArray->GetCnt(); s3d_CSysIntps iTrackMat; for(iTrackMat = 0; iTrackMat < nTrackMat; iTrackMat++) { D3DXHANDLE Var = TrackMat->m_Var; if(!Var) continue; int Trans = TrackMat->m_Trans; switch(TrackMat->m_Chan) { case s3d_CDrvUtilGfxProg::TrackChan_Bone: { int TrackCnt = TrackMat->m_Cnt; if(BoneIdxCnt < TrackCnt) TrackCnt = BoneIdxCnt; TrackMatTrans( Var, Trans, BoneMatData, TrackCnt, ConstTab, D3dDev); break; } default: { S3D_SYS_ASSERT(0); } } TrackMat++; } } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9ProgHLSLUtil::CreateShader( s3d_CUtilNotifGather *NotifGather, s3d_CUtilSnkChunk *Param, s3d_CDrvD3d9ProgCtx *ProgCtx, bool VertShader, s3d_CDrvD3d9Prog *Prog, s3d_CDrvD3d9ProgHLSLTrackBlk &TrackBlk) { if(!ProgCtx) return; s3d_CUtilMsgHandler *MsgHandler = ProgCtx->m_MsgHandler; s3d_CUtilSnkExtract SnkExtract; SnkExtract.Assign(MsgHandler, Param); s3d_CLibStreamPreproStatePtr PreproState = S3D_SYS_NEW s3d_CLibStreamPreproState; s3d_CDrvD3d9ProgHLSLUtil::ExtractPredefine( ProgCtx, PreproState, SnkExtract); /*@{ @declare{shaderprog.param}{.code_variant_array} {$ [chunk]...[chunk]} Each chunk specifies a D3D HLSL shader source code file for a specific shader version. If there is more than one @code{code_variant} the one that first successfully compiles is taken. @}*/ s3d_CUtilSnkChunkArray CodeArray; s3d_CUtilStr CodeArrayInfo; SnkExtract.ExtractChunkArray( CodeArrayInfo, CodeArray, "code_variant_array", true); s3d_CUtilStr CodeName, CodeInfo; s3d_CSysIntps nCode = CodeArray.GetCnt(); s3d_CSysIntps iCode; for(iCode = 0; iCode < nCode; iCode++) { s3d_CUtilSnkExtract CodeSnkExtract; s3d_CUtilSnkChunk *CodeChunk = CodeArray.GetAt(iCode); CodeSnkExtract.Assign(MsgHandler, CodeChunk); /*@{ @declare{shaderprog.param} {.code_variant_array.profile}{$ [str]} Shader profile which should be used to compile shader program. Use empty string for highest profile supported by gfx hardware. @}*/ s3d_CUtilStr ReqVer = CodeSnkExtract.ExtractStr("profile", false); /* if(!s3d_CDrvD3d9ProgUtil::IsVersAllowed(MaxMajor, MaxMinor, ReqVer)) continue; */ /*@{ @declare{shaderprog.param} {.code_variant_array.code}{$ [str]} Specifies the D3D HLSL shader source code file. @}*/ CodeSnkExtract.ExtractStr(CodeInfo, CodeName, "code", true); /*@{ @declare{shaderprog.param} {.code_variant_array.debug_code_file} {$ [str]} Specifies the shader source file that is used for debugging. @}*/ s3d_CUtilStr DbgCodeName = CodeSnkExtract.ExtractStr("debug_code_file", false); /*@{ @declare{shaderprog.param} {.code_variant_array.entry_point} {$ [str]} Function name which is executed, usually something like main_vs_2x0 or main_fs_2x0. @}*/ s3d_CUtilStr EntryPoint = CodeSnkExtract.ExtractStr("entry_point", true); s3d_CUtilStr Profile; if(VertShader) { if(ReqVer.IsEmpty()) Profile = D3DXGetVertexShaderProfile(ProgCtx->m_D3dDev); else Profile = s3d_CDrvD3d9ProgUtil::GenProfileString(ReqVer, "vs"); } else { if(ReqVer.IsEmpty()) Profile = D3DXGetPixelShaderProfile(ProgCtx->m_D3dDev); else Profile = s3d_CDrvD3d9ProgUtil::GenProfileString(ReqVer, "ps"); } CodeSnkExtract.CheckForUnknown(); s3d_CDrvD3d9Buf CodeBuf; if(ProgCtx->m_D3dParam->m_ShaderDebug && !DbgCodeName.IsEmpty()) { s3d_CDrvD3d9ProgHLSLUtil::CompileFromFile( NotifGather, ProgCtx, CodeInfo, DbgCodeName, EntryPoint, Profile, PreproState, CodeBuf, TrackBlk.m_ConstTab); } else { s3d_CDrvD3d9ProgHLSLUtil::CompileFromRes( NotifGather, ProgCtx, CodeInfo, CodeName, EntryPoint, Profile, PreproState, CodeBuf, TrackBlk.m_ConstTab); } if(!CodeBuf) continue; const DWORD *Function = reinterpret_cast( CodeBuf->GetBufferPointer()); DWORD ShaderVers = D3DXGetShaderVersion(Function); HRESULT Result = D3DERR_INVALIDCALL; LPDIRECT3DDEVICE9 D3dDev = ProgCtx->m_D3dDev; if(VertShader) { if(ShaderVers <= ProgCtx->m_MaxVS) { S3D_DRV_D3D9_CALLCHECK( ProgCtx->m_Env, Result, D3dDev->CreateVertexShader( Function, &Prog->m_VertShader.EmptyRef())); } else { s3d_CUtilMsg m; m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_proghlsl.vsvers"; m.m_StdTempl = "D3D: " "HLSL program '[1]' requires GPU with vertex shader " "version '[2]' but GPU has only '[3]'."; m.AddInfo(CodeInfo); m.AddInfo(CodeName); m.AddInfo(s3d_CDrvD3d9ProgUtil::StrOfVers(ShaderVers)); m.AddInfo(s3d_CDrvD3d9ProgUtil::StrOfVers(ProgCtx->m_MaxVS)); s3d_UtilMsgReportNote(ProgCtx->m_MsgHandler, m); } } else { if(ShaderVers <= ProgCtx->m_MaxPS) { S3D_DRV_D3D9_CALLCHECK( ProgCtx->m_Env, Result, D3dDev->CreatePixelShader( Function, &Prog->m_PixShader.EmptyRef())); } else { s3d_CUtilMsg m; m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_proghlsl.psvers"; m.m_StdTempl = "D3D: " "HLSL program '[1]' requires GPU with pixel shader " "version '[2]' but GPU has only '[3]'."; m.AddInfo(CodeInfo); m.AddInfo(CodeName); m.AddInfo(s3d_CDrvD3d9ProgUtil::StrOfVers(ShaderVers)); m.AddInfo(s3d_CDrvD3d9ProgUtil::StrOfVers(ProgCtx->m_MaxPS)); s3d_UtilMsgReportNote(ProgCtx->m_MsgHandler, m); } } if(FAILED(Result)) { TrackBlk.m_ConstTab.Reset(); continue; } if(VertShader) { s3d_CDrvD3d9ProgUtil::GetProgDecl( ProgCtx, Prog->m_VertProgDecl, CodeBuf->GetBufferSize(), Function); s3d_CDrvD3d9ProgUtil::ExtractComprFmt( ProgCtx, CodeInfo, CodeName, Prog, SnkExtract); } s3d_CDrvD3d9ProgHLSLUtil::InitTrackBlk( ProgCtx, CodeInfo, CodeName, TrackBlk, SnkExtract); SnkExtract.CheckForUnknown(); break; } } void s3d_CDrvD3d9ProgHLSLUtil::ExtractPredefine( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CLibStreamPreproState *PreproState, s3d_CUtilSnkExtract &SnkExtract) { /*@{ @declare{shaderprog.param} {.predefine_array}{$ [chunk]...[chunk]} Array of chunks defining macros used at compile time. @listing { @sident{shaderprog}{.predefine_array} { @sident{shaderprog}{.predefine_array@$ .name} "S3D_FEATURE_MF" } { @sident{shaderprog}{.predefine_array@$ .name} "S3D_FEATURE_MF_CNT" @sident{shaderprog}{.predefine_array@$ .val} "5" } } @}*/ s3d_CUtilSnkChunkArray ChunkArray; SnkExtract.ExtractChunkArray(ChunkArray, "predefine_array", false); int i; for(i = 0; i < ChunkArray.GetCntInt(); i++) { s3d_CUtilSnkExtract SnkExtract; s3d_CUtilSnkChunk *Chunk = ChunkArray.GetAt(i); SnkExtract.Assign(ProgCtx->m_MsgHandler, Chunk); /*@{ @declare{shaderprog.param} {.predefine_array.name}{$ [str]} Name of macro. @}*/ s3d_CUtilStr Name, NameInfo; SnkExtract.ExtractStr(NameInfo, Name, "name", true); /*@{ @declare{shaderprog.param} {.predefine_array.val}{$ [str]} Value of macro. @}*/ s3d_CUtilStr Def = SnkExtract.ExtractStr("val", false); PreproState->DefineSimple(ProgCtx->m_MsgHandler, NameInfo, Name, Def); SnkExtract.CheckForUnknown(); } } void s3d_CDrvD3d9ProgHLSLUtil::ExtractParamArray( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, const LPD3DXCONSTANTTABLE ConstTab, s3d_CDrvD3d9ProgHLSLParamArray &ParamArray, s3d_CDrvD3d9ProgHLSLVarSet &VarSet, s3d_CUtilSnkExtract &SnkExtract) { ParamArray.Reset(); /*@{ @declare{shaderprog.param} {.param_array}{$ [chunk]...[chunk]} Each entry maps @ident{comp}{.dest_progvar} to shader code variable. See also @ident{comp}{}. @listing { @sident{shaderprog}{.param_array} { @sident{shaderprog}{.param_array@$ .src_progvar} "prog_cenrange" @sident{shaderprog}{.param_array@$ .dest_codevar} "lightCenRange" @sident{shaderprog}{.param_array@$ .type} "float4" } } @}*/ s3d_CUtilSnkChunkArray ParamChunkArray; SnkExtract.ExtractChunkArray(ParamChunkArray, "param_array", false); s3d_CSysIntps nParamChunk = ParamChunkArray.GetCnt(); s3d_CSysIntps iParamChunk; for(iParamChunk = 0; iParamChunk < nParamChunk; iParamChunk++) { s3d_CUtilSnkExtract SnkExtract; SnkExtract.Assign(ProgCtx->m_MsgHandler, ParamChunkArray[iParamChunk]); s3d_CUtilStr ParamInfo; s3d_CUtilAtomPtr ParamAtom; /*@{ @declare{shaderprog.param} {.param_array.src_progvar}{$ [str]} Shader source variable. See @ident{comp}{.dest_progvar}. @}*/ s3d_CUtilSnkExtractUtil::ExtractAtom( ParamInfo, ParamAtom, ProgCtx->m_AtomMgr, SnkExtract, "src_progvar", true); /*@{ @declare{shaderprog.param} {.param_array.dest_codevar}{$ [str]} Shader code destination variable. @}*/ s3d_CUtilStr ParamDestVar = SnkExtract.ExtractStr("dest_codevar", true); /*@{ @declare{shaderprog.param} {.param_array.type}{$ [str]} Type of shader code variable. Can be one of @code{float4}, @code{float4x4[_transp|_inv|_invtransp]}. @}*/ s3d_CUtilStr TypeStr; s3d_CUtilStr TypeInfo; SnkExtract.ExtractStr(TypeInfo, TypeStr, "type", true); s3d_CUtilSnkExtractEnum SnkExtractEnum; SnkExtractEnum.Assign(ProgCtx->m_MsgHandler, TypeInfo, TypeStr); int Type = -1; if(SnkExtractEnum.Check("float4")) Type = s3d_CDrvUtilGfxProg::ParamType_Float4; else if(SnkExtractEnum.Check("float4x4")) Type = s3d_CDrvUtilGfxProg::ParamType_Float4x4; else if(SnkExtractEnum.Check("float4x4_transp")) Type = s3d_CDrvUtilGfxProg::ParamType_Float4x4_Transp; else if(SnkExtractEnum.Check("float4x4_inv")) Type = s3d_CDrvUtilGfxProg::ParamType_Float4x4_Inv; else if(SnkExtractEnum.Check("float4x4_invtransp")) Type = s3d_CDrvUtilGfxProg::ParamType_Float4x4_InvTransp; else SnkExtractEnum.ErrorUnknown(); SnkExtract.CheckForUnknown(); s3d_CDrvD3d9ProgHLSLParam Param; Param.m_Info = ParamInfo; S3D_DRV_D3D9_RESOLVEVAR(Param.m_Var, ParamInfo, ParamDestVar); Param.m_Type = Type; ParamArray.InsertBack( s3d_CDrvD3d9ProgHLSLParamEntry(ParamAtom, Param)); } s3d_UtilArraySortDefault(ParamArray); ParamArray.Compactify(); } void s3d_CDrvD3d9ProgHLSLUtil::ExtractTexSize( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, const LPD3DXCONSTANTTABLE ConstTab, s3d_CDrvD3d9ProgHLSLVarArray &TexSizeArray, s3d_CDrvD3d9ProgHLSLVarArray &TexRcpSizeArray, s3d_CDrvD3d9ProgHLSLVarSet &VarSet, s3d_CUtilSnkExtract &SnkExtract) { /*@{ @declare{shaderprog.param} {.tex_size_codevar_array}{$ [str]...[str]} Array of shader code variables to upload texture dimensions to. @table { { @code{texsize_codevar.x} } { Width } } { { @code{texsize_codevar.y} } { Height } } { { @code{texsize_codevar.z} } { Depth } } { { @code{texsize_codevar.w} } { } } For example: @listing { @sident{shaderprog}{@$ .tex_size_codevar_array} "tex00_size" "" "tex02_size" } Uploads size of texture currently bound to sampler 0 and 2, @it{""} disables upload of texture bound to sampler 1. @}*/ s3d_CUtilStrArray TexSizeStrArray; s3d_CUtilStr TexSizeInfo; SnkExtract.ExtractStrArray( TexSizeInfo, TexSizeStrArray, "tex_size_codevar_array", false); /*@{ @declare{shaderprog.param} {.tex_rcpsize_codevar_array}{$ [str]...[str]} Array of shader code variables to upload reciprocal texture dimensions to. See also @ident{shaderprog}{.tex_size_codevar_array}. @table { { @code{texrcpsize_codevar.x} } { 1 / Width } } { { @code{texrcpsize_codevar.y} } { 1 / Height } } { { @code{texrcpsize_codevar.z} } { 1 / Depth } } { { @code{texrcpsize_codevar.w} } { } } @}*/ s3d_CUtilStrArray TexRcpStrSizeArray; s3d_CUtilStr TexRcpSizeInfo; SnkExtract.ExtractStrArray( TexRcpSizeInfo, TexRcpStrSizeArray, "tex_rcpsize_codevar_array", false); TexSizeArray.Reset(); s3d_CSysIntps nTexSize = TexSizeStrArray.GetCnt(); if(nTexSize >= ProgCtx->m_MaxSampCnt) { s3d_CDrvDxError e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_proghlsl.invalid_tex_size_cnt."; e.m_StdTempl = "Too many HLSL tex_size_codevar_array entries '[1]'." " Must be less than or equal to [2]."; e.AddInfo(TexSizeInfo); e.AddInfo(s3d_CUtilStrUtil::StrOfInt(nTexSize)); e.AddInfo(s3d_CUtilStrUtil::StrOfInt(ProgCtx->m_MaxSampCnt)); s3d_UtilMsgReportError(ProgCtx->m_MsgHandler, e); } int iTexSize; for(iTexSize = 0; iTexSize < nTexSize; iTexSize++) { s3d_CUtilStr VarName = TexSizeStrArray.GetAt(iTexSize); D3DXHANDLE TexSizeVar = 0; S3D_DRV_D3D9_RESOLVEVAR(TexSizeVar, TexSizeInfo, VarName); TexSizeArray.InsertBack(TexSizeVar); } TexRcpSizeArray.Reset(); s3d_CSysIntps nRcpTexSize = TexRcpStrSizeArray.GetCnt(); if(nRcpTexSize >= ProgCtx->m_MaxSampCnt) { s3d_CDrvDxError e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_proghlsl" ".invalid_tex_rcpsize_cnt."; e.m_StdTempl = "Too many HLSL tex_rcpsize_codevar_array entries '[1]'." " Must be less than or equal to [2]."; e.AddInfo(TexSizeInfo); e.AddInfo(s3d_CUtilStrUtil::StrOfInt(nRcpTexSize)); e.AddInfo(s3d_CUtilStrUtil::StrOfInt(ProgCtx->m_MaxSampCnt)); s3d_UtilMsgReportError(ProgCtx->m_MsgHandler, e); } int iRcpTexSize; for(iRcpTexSize = 0; iRcpTexSize < nRcpTexSize; iRcpTexSize++) { s3d_CUtilStr VarName = TexRcpStrSizeArray.GetAt(iRcpTexSize); D3DXHANDLE TexRcpSizeVar = 0; S3D_DRV_D3D9_RESOLVEVAR(TexRcpSizeVar, TexRcpSizeInfo, VarName); TexRcpSizeArray.InsertBack(TexRcpSizeVar); } TexSizeArray.Compactify(); TexRcpSizeArray.Compactify(); } void s3d_CDrvD3d9ProgHLSLUtil::ExtractTrackArray( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, const LPD3DXCONSTANTTABLE ConstTab, s3d_CDrvD3d9ProgHLSLTrackMatArray &MatTrackArray, s3d_CDrvD3d9ProgHLSLTrackMatArray &BoneTrackArray, s3d_CDrvD3d9ProgHLSLVarSet &VarSet, s3d_CUtilSnkExtract &SnkExtract) { /*@{ @declare{shaderprog.param} {.tracking}{$ [chunk]...[chunk]} Track matrices to shader code variables. @listing { @sident{shaderprog}{.tracking} { @sident{shaderprog}{.tracking@$ .codevar} "matProj" @sident{shaderprog}{.tracking@$ .slot} 0 @sident{shaderprog}{.tracking@$ .chan} "proj" @sident{shaderprog}{.tracking@$ .trans} "identity" } } @}*/ s3d_CUtilSnkChunkArray TrackArray; s3d_CUtilStr TrackInfo; SnkExtract.ExtractChunkArray( TrackInfo, TrackArray, "tracking", false); MatTrackArray.Reset(); BoneTrackArray.Reset(); int iTrack; for(iTrack = 0; iTrack < TrackArray.GetCnt(); iTrack++) { s3d_CUtilSnkChunk *TrackChunk = TrackArray.GetAt(iTrack); s3d_CUtilSnkExtractEnum SnkExtractEnum; s3d_CUtilSnkExtract SnkExtract; SnkExtract.Assign(ProgCtx->m_MsgHandler, TrackChunk); s3d_CDrvD3d9ProgHLSLTrackMat Track; /*@{ @declare{shaderprog.param} {.tracking.chan}{$ [str]} chan can be one of: @table { { [ identity | proj | view | projview | tex | bone ] } } @}*/ s3d_CUtilStr ChanName, ChanInfo; SnkExtract.ExtractStr(ChanInfo, ChanName, "chan", true, ""); SnkExtractEnum.Assign(ProgCtx->m_MsgHandler, ChanInfo, ChanName); Track.m_Chan = s3d_CDrvUtilGfxProg::TrackChan_Identity; if(SnkExtractEnum.Check("view")) Track.m_Chan = s3d_CDrvUtilGfxProg::TrackChan_View; else if(SnkExtractEnum.Check("proj")) Track.m_Chan = s3d_CDrvUtilGfxProg::TrackChan_Proj; else if(SnkExtractEnum.Check("projview")) Track.m_Chan = s3d_CDrvUtilGfxProg::TrackChan_ProjView; else if(SnkExtractEnum.Check("identity")) Track.m_Chan = s3d_CDrvUtilGfxProg::TrackChan_Identity; else if(SnkExtractEnum.Check("attr")) Track.m_Chan = s3d_CDrvUtilGfxProg::TrackChan_Attr; else if(SnkExtractEnum.Check("bone")) Track.m_Chan = s3d_CDrvUtilGfxProg::TrackChan_Bone; else SnkExtractEnum.ErrorUnknown(); /*@{ @declare{shaderprog.param} {.tracking.slot}{$ [int]} Used for selecting texture matrix for the texture that is bound to sampler @it{slot}. Has no effect on matrices other than texture or bone. Default is 0. @}*/ s3d_CUtilStr TrackSlotInfo; SnkExtract.ExtractInt(TrackSlotInfo, Track.m_Slot, "slot", false, 0); if(Track.m_Slot < 0 || Track.m_Slot >= ProgCtx->m_MaxAttrCnt) { s3d_CDrvDxError e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_proghlsl.invalid_slot."; e.m_StdTempl = "Invalid HLSL tracking slot value '[1]'. " "Must be greater or equal 0 and less than [2]."; e.AddInfo(TrackSlotInfo); e.AddInfo(s3d_CUtilStrUtil::StrOfInt(Track.m_Slot)); e.AddInfo(s3d_CUtilStrUtil::StrOfInt(ProgCtx->m_MaxAttrCnt)); s3d_UtilMsgReportError(ProgCtx->m_MsgHandler, e); Track.m_Slot = 0; } /*@{ @declare{shaderprog.param} {.tracking.trans}{$ [str]} trans can be one of: @table { { [ identity | inv | transp | invtransp ] } } @}*/ s3d_CUtilStr TransName, TransInfo; SnkExtract.ExtractStr(TransInfo, TransName, "trans", true, ""); SnkExtractEnum.Assign( ProgCtx->m_MsgHandler, TransInfo, TransName); if(SnkExtractEnum.Check("identity")) Track.m_Trans = s3d_CDrvUtilGfxProg::TrackTrans_Identity; else if(SnkExtractEnum.Check("inv")) Track.m_Trans = s3d_CDrvUtilGfxProg::TrackTrans_Inv; else if(SnkExtractEnum.Check("transp")) Track.m_Trans = s3d_CDrvUtilGfxProg::TrackTrans_Transp; else if(SnkExtractEnum.Check("invtransp")) Track.m_Trans = s3d_CDrvUtilGfxProg::TrackTrans_InvTransp; else { Track.m_Trans = s3d_CDrvUtilGfxProg::TrackTrans_Identity; SnkExtractEnum.ErrorUnknown(); } /*@{ @declare{shaderprog.param} {.tracking.codevar}{$ [str]} Shader code variable where matrix is uploaded to. @}*/ s3d_CUtilStr VarName, VarInfo; SnkExtract.ExtractStr(VarInfo, VarName, "codevar", true); S3D_DRV_D3D9_RESOLVEVAR(Track.m_Var, VarInfo, VarName); if(Track.m_Var) { D3DXCONSTANT_DESC ConstDesc; s3d_SysMemset(&ConstDesc, 0, S3D_SYS_SIZEOFS(ConstDesc)); UINT ConstDescCnt = 1; S3D_DRV_D3D9_CHECK( ProgCtx->m_Env, ConstTab->GetConstantDesc( Track.m_Var, &ConstDesc, &ConstDescCnt)); Track.m_Cnt = s3d_SysMax(UINT(1), ConstDesc.Elements); if(Track.m_Chan == s3d_CDrvUtilGfxProg::TrackChan_Bone) BoneTrackArray.InsertBack(Track); else MatTrackArray.InsertBack(Track); } SnkExtract.CheckForUnknown(); } MatTrackArray.Compactify(); BoneTrackArray.Compactify(); } void s3d_CDrvD3d9ProgHLSLUtil::ExtractLightArray( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, const LPD3DXCONSTANTTABLE ConstTab, D3DXHANDLE &ActiveLightCntVar, s3d_CDrvD3d9ProgHLSLLightArray &LightTrackArray, s3d_CDrvD3d9ProgHLSLVarSet &VarSet, s3d_CUtilSnkExtract &SnkExtract) { /*@{ @declare{shaderprog.param} {.light_array}{$ [chunk]...[chunk]} Specifies how many lights a shader can handle and the shader code variable names where to upload light values. Typical @ident{shaderprog}{.light_array} entry. @listing { @sident{shaderprog}{.light_array} { @sident{shaderprog}{.light_array@$ .cnt} 2 @sident{shaderprog}{.light_array@$ .pos_codevar} "lightArray[$].pos" @sident{shaderprog}{.light_array@$ .dir_codevar} "lightArray[$].dir" @sident{shaderprog}{.light_array@$ .ambient_codevar} "lightArray[$].ambient" @sident{shaderprog}{.light_array@$ .diffuse_codevar} "lightArray[$].diffuse" @sident{shaderprog}{.light_array@$ .specular_codevar} "lightArray[$].specular" @sident{shaderprog}{.light_array@$ .atten_codevar} "lightArray[$].atten" } } This chunk e.g. will be 2 (cnt) times replicated. '$' is a placeholder, which is replaced in this case with index 0 and 1 so it can be used in the shader as lightArray[0].pos and lightArray[1].pos. @}*/ s3d_CUtilSnkChunkPtr LightChunk; s3d_CUtilStr LightInfo; SnkExtract.ExtractChunk( LightInfo, LightChunk, "light_array", false); /*@{ @declare{shaderprog.param} {.light_activecnt_codevar}{$ [str]} In D3D shader version >= 2.0. this var is used for uploading the currently active light count. @}*/ s3d_CUtilStr VarName, VarInfo; SnkExtract.ExtractStr(VarInfo, VarName, "light_activecnt_codevar", false); ActiveLightCntVar = 0; if(!VarName.IsEmpty()) { S3D_DRV_D3D9_RESOLVEVAR(ActiveLightCntVar, VarInfo, VarName); } LightTrackArray.Reset(); if(!LightChunk) return; s3d_CUtilSnkExtract SnkLightExtract; SnkLightExtract.Assign(ProgCtx->m_MsgHandler, LightChunk); /*@{ @declare{shaderprog.param} {.light_array.cnt}{$ [int]} Number of lights supported by this shader program. @}*/ s3d_CUtilStr LightCntInfo; int LightCnt; SnkLightExtract.ExtractInt(LightCntInfo, LightCnt, "cnt", true, 0); if(LightCnt > ProgCtx->m_MaxLightCnt) { s3d_CDrvDxError e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_proghlsl.invalid_lightcnt."; e.m_StdTempl = "Invalid HLSL tracking light count value '[1]'. " "Must be greater or equal 0 and less than [2]."; e.AddInfo(LightCntInfo); e.AddInfo(s3d_CUtilStrUtil::StrOfInt(LightCnt)); e.AddInfo(s3d_CUtilStrUtil::StrOfInt(ProgCtx->m_MaxLightCnt)); s3d_UtilMsgReportError(ProgCtx->m_MsgHandler, e); LightCnt = ProgCtx->m_MaxLightCnt; } /*@{ @declare{shaderprog.param} {.light_array.pos_codevar}{$ [str]} Light position (in viewspace) shader code variable. @}*/ s3d_CUtilStr Pos, PosInfo; SnkLightExtract.ExtractStr(PosInfo, Pos, "pos_codevar", true); /*@{ @declare{shaderprog.param} {.light_array.dir_codevar}{$ [str]} Light direction (in viewspace) shader code variable. @}*/ s3d_CUtilStr Dir, DirInfo; SnkLightExtract.ExtractStr(DirInfo, Dir, "dir_codevar", true); /*@{ @declare{shaderprog.param} {.light_array.ambient_codevar}{$ [str]} Light ambient color shader code variable. @}*/ s3d_CUtilStr Ambient, AmbientInfo; SnkLightExtract.ExtractStr(AmbientInfo, Ambient, "ambient_codevar", true); /*@{ @declare{shaderprog.param} {.light_array.diffuse_codevar}{$ [str]} Light diffuse color shader code variable. @}*/ s3d_CUtilStr Diffuse, DiffuseInfo; SnkLightExtract.ExtractStr( DiffuseInfo, Diffuse, "diffuse_codevar", true); /*@{ @declare{shaderprog.param} {.light_array.specular_codevar}{$ [str]} Light specular color shader code variable. @}*/ s3d_CUtilStr Specular, SpecularInfo; SnkLightExtract.ExtractStr( SpecularInfo, Specular, "specular_codevar", true); /*@{ @declare{shaderprog.param} {.light_array.atten_codevar}{$ [str]} Light attenuation shader code variable. @table { { @code{atten_codevar.x} } { AttenConst } } { { @code{atten_codevar.y} } { AttenLinear } } { { @code{atten_codevar.z} } { AttenQuadr } } { { @code{atten_codevar.w} } { Range } } @}*/ s3d_CUtilStr Atten, AttenInfo; SnkLightExtract.ExtractStr( AttenInfo, Atten, "atten_codevar", true); SnkLightExtract.CheckForUnknown(); s3d_CUtilStrBuf ParamName; s3d_CUtilStrBuf StrIdx; int iLightParam; for(iLightParam = 0; iLightParam < LightCnt; iLightParam++) { s3d_CDrvD3d9ProgHLSLLight Light; StrIdx.Clear(); StrIdx.AppendInt(iLightParam); ParamName.Assign(Pos); ParamName.Replace("$", StrIdx.GetChars()); S3D_DRV_D3D9_RESOLVEVAR(Light.m_PosVar, PosInfo, ParamName); ParamName.Assign(Dir); ParamName.Replace("$", StrIdx.GetChars()); S3D_DRV_D3D9_RESOLVEVAR(Light.m_DirVar, DirInfo, ParamName); ParamName.Assign(Ambient); ParamName.Replace("$", StrIdx.GetChars()); S3D_DRV_D3D9_RESOLVEVAR(Light.m_AmbientVar, AmbientInfo, ParamName); ParamName.Assign(Diffuse); ParamName.Replace("$", StrIdx.GetChars()); S3D_DRV_D3D9_RESOLVEVAR(Light.m_DiffuseVar, DiffuseInfo, ParamName); ParamName.Assign(Specular); ParamName.Replace("$", StrIdx.GetChars()); S3D_DRV_D3D9_RESOLVEVAR(Light.m_SpecularVar, SpecularInfo, ParamName); ParamName.Assign(Atten); ParamName.Replace("$", StrIdx.GetChars()); S3D_DRV_D3D9_RESOLVEVAR(Light.m_AttenVar, AttenInfo, ParamName); LightTrackArray.InsertBack(Light); } LightTrackArray.Compactify(); } void s3d_CDrvD3d9ProgHLSLUtil::ExtractMtl( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, const LPD3DXCONSTANTTABLE ConstTab, s3d_CDrvD3d9ProgHLSLTrackMtrl &Mtl, s3d_CDrvD3d9ProgHLSLVarSet &VarSet, s3d_CUtilSnkExtract &SnkExtract) { /*@{ @declare{shaderprog.param} {.mtl}{$ [chunk]} @}*/ s3d_CUtilSnkChunkPtr MtlChunk; MtlChunk = SnkExtract.ExtractChunk("mtl", false); s3d_CUtilSnkExtract MtrlSnkExtract; MtrlSnkExtract.Assign(ProgCtx->m_MsgHandler, MtlChunk); /*@{ @declare{shaderprog.param} {.mtl.power_codevar}{$ [str]} Mtl power variable. @table { { @code{power_codevar.x} } { MtlPower } } { { @code{power_codevar.y} } { MtlPower } } { { @code{power_codevar.z} } { MtlPower } } { { @code{power_codevar.w} } { MtlPower } } @}*/ s3d_CUtilStr VarName, VarInfo; MtrlSnkExtract.ExtractStr(VarInfo, VarName, "power_codevar", false); D3DXHANDLE PowerVar = 0; if(!VarName.IsEmpty()) { S3D_DRV_D3D9_RESOLVEVAR(PowerVar, VarInfo, VarName); } /*@{ @declare{shaderprog.param} {.mtl.emissive_codevar}{$ [str]} Mtl emissive color variable. @table { { @code{emissive_codevar.x} } { MtlEmissive.r } } { { @code{emissive_codevar.y} } { MtlEmissive.g } } { { @code{emissive_codevar.z} } { MtlEmissive.b } } { { @code{emissive_codevar.w} } { MtlEmissive.a } } @}*/ MtrlSnkExtract.ExtractStr( VarInfo, VarName, "emissive_codevar", false); D3DXHANDLE EmissiveVar = 0; if(!VarName.IsEmpty()) { S3D_DRV_D3D9_RESOLVEVAR(EmissiveVar, VarInfo, VarName); } Mtl.m_PowerVar = PowerVar; Mtl.m_EmissiveVar = EmissiveVar; MtrlSnkExtract.CheckForUnknown(); } void s3d_CDrvD3d9ProgHLSLUtil::ExtractFog( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, const LPD3DXCONSTANTTABLE ConstTab, D3DXHANDLE &FogVar, s3d_CDrvD3d9ProgHLSLVarSet &VarSet, s3d_CUtilSnkExtract &SnkExtract) { /*@{ @declare{shaderprog.param} {.fog_codevar}{$ [str]} Fog color and denisity variable. @table { { @code{fog_codevar.x} } { FogColor.r } } { { @code{fog_codevar.y} } { FogColor.g } } { { @code{fog_codevar.z} } { FogColor.b } } { { @code{fog_codevar.w} } { FogDensity } } @}*/ s3d_CUtilStr VarName, VarInfo; SnkExtract.ExtractStr(VarInfo, VarName, "fog_codevar", false); FogVar = 0; if(!VarName.IsEmpty()) { S3D_DRV_D3D9_RESOLVEVAR(FogVar, VarInfo, VarName); } } void s3d_CDrvD3d9ProgHLSLUtil::InitTrackBlk( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, s3d_CDrvD3d9ProgHLSLTrackBlk &TrackBlk, s3d_CUtilSnkExtract &SnkExtract) { TrackBlk.m_CodeInfo = CodeInfo; TrackBlk.m_CodeName = CodeName; const LPD3DXCONSTANTTABLE ConstTab = TrackBlk.m_ConstTab; s3d_CDrvD3d9ProgHLSLVarSet VarSet; s3d_CDrvD3d9ProgHLSLUtil::ExtractParamArray( ProgCtx, CodeInfo, CodeName, ConstTab, TrackBlk.m_ParamArray, VarSet, SnkExtract); s3d_CDrvD3d9ProgHLSLUtil::ExtractTexSize( ProgCtx, CodeInfo, CodeName, ConstTab, TrackBlk.m_TexSizeArray, TrackBlk.m_TexRcpSizeArray, VarSet, SnkExtract); s3d_CDrvD3d9ProgHLSLUtil::ExtractTrackArray( ProgCtx, CodeInfo, CodeName, ConstTab, TrackBlk.m_MatTrackArray, TrackBlk.m_BoneTrackArray, VarSet, SnkExtract); s3d_CDrvD3d9ProgHLSLUtil::ExtractLightArray( ProgCtx, CodeInfo, CodeName, ConstTab, TrackBlk.m_ActiveLightCntVar, TrackBlk.m_LightTrackArray, VarSet, SnkExtract); s3d_CDrvD3d9ProgHLSLUtil::ExtractMtl( ProgCtx, CodeInfo, CodeName, ConstTab, TrackBlk.m_Mtl, VarSet, SnkExtract); s3d_CDrvD3d9ProgHLSLUtil::ExtractFog( ProgCtx, CodeInfo, CodeName, ConstTab, TrackBlk.m_FogVar, VarSet, SnkExtract); s3d_CDrvD3d9ProgHLSLUtil::EnumAllVars( ProgCtx, CodeInfo, CodeName, ConstTab, VarSet); } bool s3d_CDrvD3d9ProgHLSLUtil::CompileFromRes( s3d_CUtilNotifGather *NotifGather, const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, s3d_CUtilStr_cr EntryPoint, s3d_CUtilStr_cr Profile, s3d_CLibStreamPreproState *PreproState, s3d_CDrvD3d9Buf &CodeBuf, s3d_CDrvD3d9ConstTable &ConstTab) { if(!ProgCtx) return false; s3d_CUtilMsgHandler *MsgHandler = ProgCtx->m_MsgHandler; s3d_CCompResMgr *ResMgr = ProgCtx->m_ResMgr; s3d_CUtilMemPool *MemPool = ProgCtx->m_MemPool; s3d_CUtilMemPoolFrm MemPoolFrm(MemPool); int Generosity = s3d_CCompResMgr::Generosity_AllowMissing; s3d_CUtilStr ResInfo; s3d_CUtilStreamPtr ResStream; bool Final = false; s3d_CUtilNotifEntryPtr NotifEntry = S3D_SYS_NEW s3d_CUtilNotifEntry; ResMgr->GetResource( CodeInfo, CodeName, true, Generosity, ResInfo, ResStream, Final, NotifEntry); if(NotifGather) NotifGather->AddNotifEntry(NotifEntry); if(!ResStream) return false; s3d_CUtilStreamPos ResSize = ResStream->GetSize(); if(ResSize == 0) return false; UINT D3dStreamLen = UINT(ResSize); s3d_CSysIntm *ResData = new(MemPool) s3d_CSysIntm[D3dStreamLen + 1]; ResStream->Read(D3dStreamLen, ResData); ResData[ResSize] = 0; if(s3d_CDrvD3d9ProgUtil::CreateCodeBufOfBinData( ProgCtx, CodeBuf, D3dStreamLen, ResData)) return true; s3d_CUtilMap StreamNameMap; // Errors contain no filename for the main file: StreamNameMap.SetAt("", ResInfo); s3d_CDrvD3d9ProgIncMgr ProgIncMgr( MsgHandler, CodeInfo, MemPool, ResMgr, NotifGather, &StreamNameMap); s3d_CUtilOwnArray D3dMacroArray; s3d_CDrvD3d9ProgUtil::D3dMarcoArrayOfPreprocArray( D3dMacroArray, PreproState); s3d_CDrvD3d9Buf ErrBuf; const char *D3dStream = reinterpret_cast(ResData); DWORD Flags = 0; int DxResult = D3DXCompileShader( D3dStream, D3dStreamLen, D3dMacroArray.Get(), &ProgIncMgr, EntryPoint.GetChars(), Profile.GetChars(), Flags, &CodeBuf.EmptyRef(), &ErrBuf.EmptyRef(), &ConstTab.EmptyRef()); // ErrBuf can be valid even if assembling was successful, e.g. warnings. s3d_CDrvD3d9ProgReportMap Report(0, 0, &StreamNameMap); if(!Report.ReportCompilingBuffer( ProgCtx->m_Env, CodeInfo, ErrBuf, DxResult)) return false; return true; } bool s3d_CDrvD3d9ProgHLSLUtil::CompileFromFile( s3d_CUtilNotifGather *NotifGather, const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, s3d_CUtilStr_cr EntryPoint, s3d_CUtilStr_cr Profile, s3d_CLibStreamPreproState *PreproState, s3d_CDrvD3d9Buf &CodeBuf, s3d_CDrvD3d9ConstTable &ConstTab) { if(!ProgCtx) return false; s3d_CUtilMsgHandler *MsgHandler = ProgCtx->m_MsgHandler; s3d_CCompResMgr *ResMgr = ProgCtx->m_ResMgr; s3d_CUtilMemPool *MemPool = ProgCtx->m_MemPool; s3d_CDrvD3d9Buf ErrBuf; s3d_CUtilMap StreamNameMap; // Errors contain no filename for the main file: StreamNameMap.SetAt("", CodeName); int DxResult = 0; // Own scope for MemPoolFrm, used by ProgIncMgr { s3d_CUtilMemPoolFrm MemPoolFrm(ProgCtx->m_MemPool); s3d_CDrvD3d9ProgIncMgr ProgIncMgr( MsgHandler, CodeInfo, MemPool, ResMgr, NotifGather, &StreamNameMap); s3d_CUtilOwnArray D3dMacroArray; s3d_CDrvD3d9ProgUtil::D3dMarcoArrayOfPreprocArray( D3dMacroArray, PreproState); DWORD Flags = D3DXSHADER_DEBUG; DxResult = D3DXCompileShaderFromFile( CodeName.GetChars(), D3dMacroArray.Get(), &ProgIncMgr, EntryPoint.GetChars(), Profile.GetChars(), Flags, &CodeBuf.EmptyRef(), &ErrBuf.EmptyRef(), 0); } // ErrBuf can be valid even if assembling was successful, e.g. warnings. s3d_CDrvD3d9ProgReportMap Report(0, 0, &StreamNameMap); if(!Report.ReportCompilingBuffer( ProgCtx->m_Env, CodeInfo, ErrBuf, DxResult)) return false; return true; } void s3d_CDrvD3d9ProgHLSLUtil::ResolveVar( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr Info, s3d_CUtilStr_cr CodeName, LPD3DXCONSTANTTABLE ConstTab, D3DXHANDLE &Var, s3d_CUtilStr_cr VarName, s3d_CDrvD3d9ProgHLSLVarSet &VarSet) { Var = 0; if(!ProgCtx) return; if(VarName.IsEmpty()) return; if(ConstTab) Var = ConstTab->GetConstantByName(0, VarName.GetChars()); if(!Var) { /* s3d_CDrvDxError e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_proghlsl.unused_codevar."; e.m_StdTempl = "Unused tracking variable '[1]' for " "D3D HLSL shader \"[2]\" "; e.AddInfo(Info); e.AddInfo(VarName); e.AddInfo(CodeName); s3d_UtilMsgReportError(ProgCtx->m_MsgHandler, e); */ return; } bool AlreadyDefined = VarSet.DefineAt(Var); if(AlreadyDefined) { s3d_CDrvDxError e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_proghlsl.multiple_tracked."; e.m_StdTempl = "Variable '[1]' is tracked more than once in" "D3D HLSL shader \"[2]\" "; e.AddInfo(Info); e.AddInfo(VarName); e.AddInfo(CodeName); s3d_UtilMsgReportError(ProgCtx->m_MsgHandler, e); } } void s3d_CDrvD3d9ProgHLSLUtil::EnumAllVars( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, LPD3DXCONSTANTTABLE ConstTab, const s3d_CDrvD3d9ProgHLSLVarSet &VarSet) { D3DXCONSTANTTABLE_DESC ConstTabDesc; S3D_DRV_D3D9_CHECK( ProgCtx->m_Env, ConstTab->GetDesc(&ConstTabDesc)); UINT nConst = ConstTabDesc.Constants; UINT iConst; for(iConst = 0; iConst < nConst; iConst++) { D3DXHANDLE Var = 0; S3D_DRV_D3D9_HRESCALL( ProgCtx->m_Env, Var, ConstTab->GetConstant( 0, iConst)); EnumVar( ProgCtx, CodeInfo, CodeName, ConstTab, Var, 0, VarSet); } } void s3d_CDrvD3d9ProgHLSLUtil::EnumVar( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, LPD3DXCONSTANTTABLE ConstTab, D3DXHANDLE Var, s3d_CUtilStr_cr VarName, const s3d_CDrvD3d9ProgHLSLVarSet &VarSet) { if(!ProgCtx) return; if(!ConstTab) return; D3DXCONSTANT_DESC ConstDesc; s3d_SysMemset(&ConstDesc, 0, S3D_SYS_SIZEOFS(ConstDesc)); UINT ConstDescCnt = 1; S3D_DRV_D3D9_CHECK( ProgCtx->m_Env, ConstTab->GetConstantDesc( Var, &ConstDesc, &ConstDescCnt)); s3d_CUtilStrBuf VarNameBuf; VarNameBuf.Append(VarName); VarNameBuf.Append(ConstDesc.Name); s3d_CDrvD3d9ProgHLSLUtil::CheckVarInitialized( ProgCtx, CodeInfo, CodeName, Var, VarNameBuf, ConstDesc, VarSet); UINT nElem = ConstDesc.Elements; UINT iElem; for(iElem = 0; iElem < nElem; iElem++) { D3DXHANDLE ElemVar = 0; S3D_DRV_D3D9_HRESCALL( ProgCtx->m_Env, ElemVar, ConstTab->GetConstantElement( Var, iElem)); UINT nStruct = ConstDesc.StructMembers; UINT iStruct; for(iStruct = 0; iStruct < nStruct; iStruct++) { D3DXHANDLE StructVar = 0; S3D_DRV_D3D9_HRESCALL( ProgCtx->m_Env, StructVar, ConstTab->GetConstant( ElemVar, iStruct)); D3DXCONSTANT_DESC ElemConstDesc; s3d_SysMemset(&ElemConstDesc, 0, S3D_SYS_SIZEOFS(ElemConstDesc)); UINT ElemConstDescCnt = 1; S3D_DRV_D3D9_CHECK( ProgCtx->m_Env, ConstTab->GetConstantDesc( StructVar, &ElemConstDesc, &ElemConstDescCnt)); VarNameBuf.Reset(); VarNameBuf = VarName; VarNameBuf.Append(ConstDesc.Name); VarNameBuf.Append("["); VarNameBuf.Append(s3d_CUtilStrUtil::StrOfInt(iElem)); VarNameBuf.Append("]."); EnumVar( ProgCtx, CodeInfo, CodeName, ConstTab, StructVar, VarNameBuf, VarSet); } D3DXCONSTANT_DESC ElemConstDesc; s3d_SysMemset(&ElemConstDesc, 0, S3D_SYS_SIZEOFS(ElemConstDesc)); UINT ElemConstDescCnt = 1; S3D_DRV_D3D9_CHECK( ProgCtx->m_Env, ConstTab->GetConstantDesc( ElemVar, &ElemConstDesc, &ElemConstDescCnt)); VarNameBuf.Reset(); VarNameBuf = VarName; VarNameBuf.Append(ElemConstDesc.Name); VarNameBuf.Append("["); VarNameBuf.Append(s3d_CUtilStrUtil::StrOfInt(iElem)); VarNameBuf.Append("]"); s3d_CDrvD3d9ProgHLSLUtil::CheckVarInitialized( ProgCtx, CodeInfo, CodeName, Var, VarNameBuf, ElemConstDesc, VarSet); } } void s3d_CDrvD3d9ProgHLSLUtil::CheckVarInitialized( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, D3DXHANDLE Var, s3d_CUtilStr_cr VarName, const D3DXCONSTANT_DESC &VarDesc, const s3d_CDrvD3d9ProgHLSLVarSet &VarSet) { if(!VarDesc.DefaultValue && !VarSet.IsDefined(Var)) { if(VarDesc.RegisterSet != D3DXRS_SAMPLER && VarDesc.Class != D3DXPC_STRUCT) { s3d_CDrvD3d9Error e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_proghlsl.undef_codevar."; e.m_StdTempl = "Uninitialized code variable '[1]' for " "D3D HLSL shader \"[2]\" "; e.AddInfo(CodeInfo); e.AddInfo(VarName); e.AddInfo(CodeName); s3d_UtilMsgReportError(ProgCtx->m_MsgHandler, e); } } } ///////////////////////////////////////////////////////////////////////////////