/////////////////////////////////////////////////////////////////////////////// // // ## ###### // ###### ### // ## ############### Shark 3D Engine (www.shark3d.com) // ########## # # # // ######## Copyright (c) 1996-2006 Spinor GmbH. // ######### # # # All rights reserved. // ## ########## // ## // /////////////////////////////////////////////////////////////////////////////// //@cpp #include "drv_d3d9_progasm.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" #include /////////////////////////////////////////////////////////////////////////////// /*@{ @declare{shaderprog.param}{}{$ [chunk]} Parameters for d3d assembly @ident{shaderprog}{d3d9.asm_vertshader} and @ident{shaderprog}{d3d9.asm_pixshader}. This is a pseudo chunk name. @}*/ /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9ProgAsmTrackBlkVert::SetShaderConstF( s3d_CDrvD3d9ProgCtx *ProgCtx, UINT ConstAddr, const float *ConstVal, UINT ConstCnt) const { S3D_DRV_D3D9_CHECK( ProgCtx->m_Env, ProgCtx->m_D3dDev->SetVertexShaderConstantF( ConstAddr, ConstVal, ConstCnt)); } void s3d_CDrvD3d9ProgAsmTrackBlkVert::SetShaderConstI( s3d_CDrvD3d9ProgCtx *ProgCtx, UINT ConstAddr, const int *ConstVal, UINT ConstCnt) const { S3D_DRV_D3D9_CHECK( ProgCtx->m_Env, ProgCtx->m_D3dDev->SetVertexShaderConstantI( ConstAddr, ConstVal, ConstCnt)); } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9ProgAsmTrackBlkPix::SetShaderConstF( s3d_CDrvD3d9ProgCtx *ProgCtx, UINT ConstAddr, const float *ConstVal, UINT ConstCnt) const { S3D_DRV_D3D9_CHECK( ProgCtx->m_Env, ProgCtx->m_D3dDev->SetPixelShaderConstantF( ConstAddr, ConstVal, ConstCnt)); } void s3d_CDrvD3d9ProgAsmTrackBlkPix::SetShaderConstI( s3d_CDrvD3d9ProgCtx *ProgCtx, UINT ConstAddr, const int *ConstVal, UINT ConstCnt) const { S3D_DRV_D3D9_CHECK( ProgCtx->m_Env, ProgCtx->m_D3dDev->SetPixelShaderConstantI( ConstAddr, ConstVal, ConstCnt)); } /////////////////////////////////////////////////////////////////////////////// s3d_CDrvD3d9ProgAsm::s3d_CDrvD3d9ProgAsm( s3d_CUtilNotifGather *NotifGather, s3d_CUtilStr_cr Info, s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilSnkChunk *ParamVert, s3d_CUtilSnkChunk *ParamPix) { m_ProgCtx = ProgCtx; m_Info = Info; const s3d_CDrvD3d9Param *D3dParam = ProgCtx->m_D3dParam; if(D3dParam->m_ReportProg) m_ReportMsgHandler = ProgCtx->m_MsgHandler; if(ParamVert) { s3d_CDrvD3d9ProgAsmUtil::CreateShader( NotifGather, ParamVert, ProgCtx, true, this, m_VertTrackBlk); } if(ParamPix) { s3d_CDrvD3d9ProgAsmUtil::CreateShader( NotifGather, ParamPix, ProgCtx, false, this, m_PixTrackBlk); } } void s3d_CDrvD3d9ProgAsm::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_CDrvD3d9ProgAsm::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_CDrvD3d9ProgAsm::CalcVertBufDesc( const s3d_CDrvGfxCharge *Charge, s3d_CDrvD3d9VertBufDesc &VertBufDesc) const { s3d_CDrvD3d9ProgUtil::CalcVertBufDesc( m_ProgCtx, Charge, m_VertProgDecl.m_ProgUsage, m_VertComprFmt, VertBufDesc); } bool s3d_CDrvD3d9ProgAsm::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_CDrvD3d9ProgAsm::GetVertProgCodeInfoName( s3d_CUtilStr &CodeInfo, s3d_CUtilStr &CodeName) const { CodeInfo = m_VertTrackBlk.m_CodeInfo; CodeName = m_VertTrackBlk.m_CodeName; } void s3d_CDrvD3d9ProgAsm::GetPixProgCodeInfoName( s3d_CUtilStr &CodeInfo, s3d_CUtilStr &CodeName) const { CodeInfo = m_PixTrackBlk.m_CodeInfo; CodeName = m_PixTrackBlk.m_CodeName; } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9ProgAsm::TrackMatTrans( const int &Addr, int Trans, const D3DXMATRIXA16 *Mat, s3d_CSysIntps Cnt, s3d_CDrvD3d9ProgAsmTrackBlk &TrackBlk) { UINT ConstCnt = UINT(Cnt << 2); switch(Trans) { case s3d_CDrvUtilGfxProg::TrackTrans_Identity: { const float *ConstVal = reinterpret_cast(Mat); TrackBlk.SetShaderConstF(m_ProgCtx, Addr, ConstVal, ConstCnt); break; } case s3d_CDrvUtilGfxProg::TrackTrans_Inv: { D3DXMATRIXA16 *InvMat = reinterpret_cast (alloca(Cnt * S3D_SYS_SIZEOFS(D3DXMATRIXA16))); s3d_CSysIntps i; for(i = 0; i < Cnt; i++) D3DXMatrixInverse(&InvMat[i], 0, Mat); const float *ConstVal = reinterpret_cast(InvMat); TrackBlk.SetShaderConstF(m_ProgCtx, Addr, ConstVal, ConstCnt); break; } case s3d_CDrvUtilGfxProg::TrackTrans_Transp: { D3DXMATRIXA16 *TranspMat = reinterpret_cast (alloca(Cnt * S3D_SYS_SIZEOFS(D3DXMATRIXA16))); s3d_CSysIntps i; for(i = 0; i < Cnt; i++) D3DXMatrixTranspose(&TranspMat[i], Mat); const float *ConstVal = reinterpret_cast(TranspMat); TrackBlk.SetShaderConstF(m_ProgCtx, Addr, ConstVal, ConstCnt); break; } case s3d_CDrvUtilGfxProg::TrackTrans_InvTransp: { D3DXMATRIXA16 *InvTranspMat = reinterpret_cast (alloca(Cnt * S3D_SYS_SIZEOFS(D3DXMATRIXA16))); D3DXMATRIXA16 *TranspMat = reinterpret_cast (alloca(Cnt * S3D_SYS_SIZEOFS(D3DXMATRIXA16))); s3d_CSysIntps i; for(i = 0; i < Cnt; i++) { D3DXMatrixTranspose(&TranspMat[i], Mat); D3DXMatrixInverse(&InvTranspMat[i], 0, &TranspMat[i]); } const float *ConstVal = reinterpret_cast( InvTranspMat); TrackBlk.SetShaderConstF(m_ProgCtx, Addr, ConstVal, ConstCnt); break; } default: S3D_SYS_ASSERT(0); break; } } void s3d_CDrvD3d9ProgAsm::TrackParams( s3d_CDrvGfxParam_cr GfxParam, const s3d_CDrvD3d9ParamBlk &ParamBlk, const s3d_CDrvD3d9ParamBlkState &ParamBlkState, s3d_CDrvD3d9ProgAsmTrackBlk &TrackBlk) { LPDIRECT3DDEVICE9 D3dDev = m_ProgCtx->m_D3dDev; if(!D3dDev) return; const s3d_CSysChar *Info = TrackBlk.m_CodeInfo.GetChars(); const s3d_CDrvD3d9ProgAsmTrackMatArray *TrackMatArray = &TrackBlk.m_MatTrackArray; s3d_CSysIntps nTrackMat = TrackMatArray->GetCnt(); s3d_CSysIntps iTrackMat; for(iTrackMat = 0; iTrackMat < nTrackMat; iTrackMat++) { const s3d_CDrvD3d9ProgAsmTrackMat *TrackMat = &TrackMatArray->RefAtRaw(iTrackMat); int Addr = TrackMat->m_Addr; if(Addr < 0) continue; int Trans = TrackMat->m_Trans; switch(TrackMat->m_Chan) { case s3d_CDrvUtilGfxProg::TrackChan_View: { if(ParamBlkState.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_MatView) { TrackMatTrans( Addr, Trans, &ParamBlk.m_MatView, 1, TrackBlk); } break; } case s3d_CDrvUtilGfxProg::TrackChan_Proj: { if(ParamBlkState.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_MatProj) { TrackMatTrans( Addr, Trans, &ParamBlk.m_MatProj, 1, TrackBlk); } 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(Addr, Trans, &ProjView, 1, TrackBlk); } break; } case s3d_CDrvUtilGfxProg::TrackChan_Identity: { S3D_SYS_ASSERT(0); break; } case s3d_CDrvUtilGfxProg::TrackChan_Attr: { if(ParamBlkState.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_MatGen) { int Slot = TrackMat->m_Slot; int Cnt = s3d_SysMin( TrackMat->m_Cnt, m_ProgCtx->m_MaxAttrCnt); const D3DXMATRIXA16 *Mat = &ParamBlk.m_MatGenArray[Slot]; TrackMatTrans(Addr, Trans, Mat, Cnt, TrackBlk); } break; } default: break; } } if(ParamBlk.m_UseConstColorAlpha) TrackNoLighting(ParamBlk, ParamBlkState, TrackBlk); else TrackLighting(ParamBlk, ParamBlkState, TrackBlk); if(TrackBlk.m_FogAddr >= 0 && (ParamBlkState.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_Fog)) { TrackBlk.SetShaderConstF( m_ProgCtx, TrackBlk.m_FogAddr, ParamBlk.m_FogColDensity, 1); } const s3d_CDrvD3d9TexObjBasePtr *SampTexArray = ParamBlk.m_SampTexArray; const s3d_CDrvD3d9ProgAsmAddrArray *TexSizeArray = &TrackBlk.m_TexSizeArray; s3d_CSysIntps nTex = TexSizeArray->GetCnt(); s3d_CSysIntps iTex; for(iTex = 0; iTex < nTex; iTex++) { const int Addr = TexSizeArray->GetAtRaw(iTex); if(Addr >= 0) { float Vec4[4] = {0,0,0,0}; s3d_CDrvD3d9TexObjBase *Tex = 0; if(iTex < m_ProgCtx->m_MaxSampCnt) Tex = SampTexArray[iTex]; if(Tex) { Vec4[0] = s3d_SysFloatOfInt(Tex->m_Width); Vec4[1] = s3d_SysFloatOfInt(Tex->m_Height); Vec4[2] = s3d_SysFloatOfInt(Tex->m_Depth); Vec4[3] = 0; } TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); } } const s3d_CDrvD3d9ProgAsmAddrArray *TexRcpSizeArray = &TrackBlk.m_TexRcpSizeArray; nTex = TexRcpSizeArray->GetCnt(); for(iTex = 0; iTex < nTex; iTex++) { int Addr = TexRcpSizeArray->GetAtRaw(iTex); if(Addr >= 0) { float Vec4[4] = {0,0,0,0}; s3d_CDrvD3d9TexObjBase *Tex = 0; if(iTex < m_ProgCtx->m_MaxSampCnt) Tex = SampTexArray[iTex]; if(Tex) { Vec4[0] = 1 / s3d_SysFloatOfInt(Tex->m_Width); Vec4[1] = 1 / s3d_SysFloatOfInt(Tex->m_Height); Vec4[2] = 1 / s3d_SysFloatOfInt(Tex->m_Depth); Vec4[3] = 0; } TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); } } s3d_CDrvUtilVarFetch VarFetch( m_ProgCtx->m_MsgHandler, GfxParam.m_Blk); s3d_CDrvD3d9ProgAsmParamEntry *ParamArray = TrackBlk.m_ParamArray.GetPtrRaw(); s3d_CSysIntps nParam = TrackBlk.m_ParamArray.GetCnt(); s3d_CSysIntps iParam; for(iParam = 0; iParam < nParam; iParam++) { s3d_CDrvD3d9ProgAsmParamEntry *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_CDrvD3d9ProgAsmParam *ParamEntry = &Param->m_Val; int Addr = ParamEntry->m_Addr; if(Addr < 0) 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 *ConstVal = reinterpret_cast(&DrvVar->m_Val); TrackBlk.SetShaderConstF(m_ProgCtx, Addr, ConstVal, 1); } 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(Addr, Trans, &Mat, 1, TrackBlk); } break; } default: S3D_SYS_ASSERT(0); break; } } } void s3d_CDrvD3d9ProgAsm::TrackNoLighting( const s3d_CDrvD3d9ParamBlk &ParamBlk, const s3d_CDrvD3d9ParamBlkState &ParamBlkState, s3d_CDrvD3d9ProgAsmTrackBlk &TrackBlk) { LPDIRECT3DDEVICE9 D3dDev = m_ProgCtx->m_D3dDev; int Addr = TrackBlk.m_Mtl.m_EmissiveAddr; if(Addr >= 0) { const float *Vec4 = reinterpret_cast(&ParamBlk.m_ColorAlphaVal); TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); } Addr = TrackBlk.m_ActiveLightCntAddr; if(Addr >= 0) { int Vec4[4]; Vec4[0] = 0; Vec4[1] = 0; Vec4[2] = 0; Vec4[3] = 0; TrackBlk.SetShaderConstI(m_ProgCtx, Addr, Vec4, 1); } s3d_CSysIntps FromLight = 0; TrackLightingBlack(ParamBlk, ParamBlkState, TrackBlk, FromLight); } void s3d_CDrvD3d9ProgAsm::TrackLighting( const s3d_CDrvD3d9ParamBlk &ParamBlk, const s3d_CDrvD3d9ParamBlkState &ParamBlkState, s3d_CDrvD3d9ProgAsmTrackBlk &TrackBlk) { LPDIRECT3DDEVICE9 D3dDev = m_ProgCtx->m_D3dDev; if(ParamBlkState.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_Mtl) { int Addr = TrackBlk.m_Mtl.m_EmissiveAddr; if(Addr >= 0) { const float *Vec4 = reinterpret_cast( &ParamBlk.m_Mtl.Emissive); TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); } Addr = TrackBlk.m_Mtl.m_PowerAddr; if(Addr >= 0) { float Vec4[4]; Vec4[0] = ParamBlk.m_Mtl.Power; Vec4[1] = ParamBlk.m_Mtl.Power; Vec4[2] = ParamBlk.m_Mtl.Power; Vec4[3] = ParamBlk.m_Mtl.Power; TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); } } if(ParamBlkState.m_DirtyMask & s3d_CDrvD3d9ParamBlkState::Dirty_Light) { const s3d_CDrvD3d9ProgAsmLightArray *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_CDrvD3d9ProgAsmLight *ProgLight = LightTrackArray->GetPtrRaw(); s3d_CSysIntps iLight; for(iLight = 0; iLight < nLightCnt; iLight++) { int Addr = ProgLight->m_AmbientAddr; if(Addr >= 0) { const float *Vec4 = reinterpret_cast(&Light->Ambient); TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); } Addr = ProgLight->m_DiffuseAddr; if(Addr >= 0) { const float *Vec4 = reinterpret_cast(&Light->Diffuse); TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); } Addr = ProgLight->m_SpecularAddr; if(Addr >= 0) { const float *Vec4 = reinterpret_cast(&Light->Specular); TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); } Addr = ProgLight->m_PosAddr; if(Addr >= 0) { const float *Vec4 = reinterpret_cast(&Light->Position); TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); } Addr = ProgLight->m_DirAddr; if(Addr >= 0) { const float *Vec4 = reinterpret_cast(&Light->Direction); TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); } Addr = ProgLight->m_AttenAddr; if(Addr >= 0) { float Atten[4]; Atten[0] = Light->Attenuation0; Atten[1] = Light->Attenuation1; Atten[2] = Light->Attenuation2; Atten[3] = Light->Range; TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Atten, 1); } Light++; ProgLight++; } int Addr = TrackBlk.m_ActiveLightCntAddr; if(Addr >= 0) { int Vec4[4]; Vec4[0] = int(nLightCnt); Vec4[1] = int(nLightCnt); Vec4[2] = int(nLightCnt); Vec4[3] = int(nLightCnt); TrackBlk.SetShaderConstI(m_ProgCtx, Addr, Vec4, 1); } if(nLightCnt < MaxProgLightCnt) { TrackLightingBlack( ParamBlk, ParamBlkState, TrackBlk, nLightCnt); } } } void s3d_CDrvD3d9ProgAsm::TrackLightingBlack( const s3d_CDrvD3d9ParamBlk &ParamBlk, const s3d_CDrvD3d9ParamBlkState &ParamBlkState, s3d_CDrvD3d9ProgAsmTrackBlk &TrackBlk, s3d_CSysIntps FromLight) { LPDIRECT3DDEVICE9 D3dDev = m_ProgCtx->m_D3dDev; const s3d_CDrvD3d9ProgAsmLightArray *LightArray = &TrackBlk.m_LightTrackArray; s3d_CSysIntps nLightCnt = LightArray->GetCnt(); s3d_CSysIntps iLight; for(iLight = FromLight; iLight < nLightCnt; iLight++) { const s3d_CDrvD3d9ProgAsmLight *ProgLight = &LightArray->RefAtRaw(iLight); const float Vec4[4] = {0, 0, 0, 0}; int Addr = ProgLight->m_AmbientAddr; if(Addr >= 0) TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); Addr = ProgLight->m_DiffuseAddr; if(Addr >= 0) TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); Addr = ProgLight->m_SpecularAddr; if(Addr >= 0) TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); Addr = ProgLight->m_PosAddr; if(Addr >= 0) TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); Addr = ProgLight->m_DirAddr; if(Addr >= 0) TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); Addr = ProgLight->m_AttenAddr; if(Addr >= 0) TrackBlk.SetShaderConstF(m_ProgCtx, Addr, Vec4, 1); } } void s3d_CDrvD3d9ProgAsm::TrackTransfBone( s3d_CSysIntps BoneIdxCnt, const s3d_CSysInt32u *BoneIdxData, s3d_CSysIntps MatBoneCnt, const D3DXMATRIXA16 *MatBoneArray, s3d_CDrvD3d9ProgAsmTrackBlk &TrackBlk) { if(!BoneIdxData) return; if(!MatBoneArray) return; LPDIRECT3DDEVICE9 D3dDev = m_ProgCtx->m_D3dDev; const s3d_CSysChar *Info = TrackBlk.m_CodeInfo.GetChars(); 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) continue; BoneMatData[iBoneIdx] = MatBoneArray[MatBoneIdx]; } const s3d_CDrvD3d9ProgAsmTrackMatArray *TrackMatArray = &TrackBlk.m_BoneTrackArray; s3d_CSysIntps nTrackMat = TrackMatArray->GetCnt(); s3d_CSysIntps iTrackMat; for(iTrackMat = 0; iTrackMat < nTrackMat; iTrackMat++) { const s3d_CDrvD3d9ProgAsmTrackMat *TrackMat = &TrackMatArray->RefAtRaw(iTrackMat); int Addr = TrackMat->m_Addr; if(Addr < 0) continue; int Trans = TrackMat->m_Trans; switch(TrackMat->m_Chan) { case s3d_CDrvUtilGfxProg::TrackChan_Bone: { TrackMatTrans( Addr, Trans, BoneMatData, BoneIdxCnt, TrackBlk); break; } default: { S3D_SYS_ASSERT(0); } } } } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9ProgAsmUtil::CreateShader( s3d_CUtilNotifGather *NotifGather, s3d_CUtilSnkChunk *Param, s3d_CDrvD3d9ProgCtx *ProgCtx, bool VertShader, s3d_CDrvD3d9Prog *Prog, s3d_CDrvD3d9ProgAsmTrackBlk &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_CDrvD3d9ProgAsmUtil::ExtractPredefine( ProgCtx, PreproState, SnkExtract); /*@{ @declare{shaderprog.param} {.code_variant_array}{$ [chunk]...[chunk]} Each chunk specifies a D3D assembly 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.req_ver}{$ [str]} Shader version required to run this shader implementation. @}*/ s3d_CUtilStr ReqVer = CodeSnkExtract.ExtractStr("req_ver", false); /* if(!s3d_CDrvD3d9ProgUtil::IsVersAllowed(MaxMajor, MaxMinor, ReqVer)) continue; */ /*@{ @declare{shaderprog.param} {.code_variant_array.code} {$ [str]} Specifies the D3D assembly 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); CodeSnkExtract.CheckForUnknown(); s3d_CDrvD3d9Buf CodeBuf; if(ProgCtx->m_D3dParam->m_ShaderDebug && !DbgCodeName.IsEmpty()) { s3d_CDrvD3d9ProgAsmUtil::AssembleFromFile( NotifGather, ProgCtx, CodeInfo, DbgCodeName, PreproState, CodeBuf); } else { s3d_CDrvD3d9ProgAsmUtil::AssembleFromRes( NotifGather, ProgCtx, CodeInfo, CodeName, PreproState, CodeBuf); } 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_progasm.vsvers"; m.m_StdTempl = "D3D: " "Asm 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_progasm.psvers"; m.m_StdTempl = "D3D: " "Asm 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)) continue; if(VertShader) { s3d_CDrvD3d9ProgUtil::GetProgDecl( ProgCtx, Prog->m_VertProgDecl, CodeBuf->GetBufferSize(), Function); s3d_CDrvD3d9ProgUtil::ExtractComprFmt( ProgCtx, CodeInfo, CodeName, Prog, SnkExtract); } s3d_CDrvD3d9ProgAsmUtil::InitTrackBlk( ProgCtx, CodeInfo, CodeName, TrackBlk, SnkExtract); SnkExtract.CheckForUnknown(); break; } } void s3d_CDrvD3d9ProgAsmUtil::ExtractPredefine( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CLibStreamPreproState *PreproState, s3d_CUtilSnkExtract &SnkExtract) { /*@{ @declare{shaderprog.param}{.predefine_array} {$ [chunk]...[chunk]} See @ident{shaderprog}{.predefine_array}. @}*/ 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.name}{$ [str]} See @ident{shaderprog}{.predefine_array.name}. @}*/ s3d_CUtilStr Name, NameInfo; SnkExtract.ExtractStr(NameInfo, Name, "name", true); /*@{ @declare{shaderprog.param} {.predefine.val}{$ [str]} See @ident{shaderprog}{.predefine_array.val}. @}*/ s3d_CUtilStr Def = SnkExtract.ExtractStr("val", false); PreproState->DefineSimple(ProgCtx->m_MsgHandler, NameInfo, Name, Def); SnkExtract.CheckForUnknown(); } } void s3d_CDrvD3d9ProgAsmUtil::ExtractParamArray( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, s3d_CDrvD3d9ProgAsmParamArray &ParamArray, s3d_CUtilSnkExtract &SnkExtract) { ParamArray.Reset(); /*@{ @declare{shaderprog.param} {.param_array}{$ [chunk]...[chunk]} Each entry maps @ident{comp}{.dest_progvar} to shader code const address. See also @ident{comp}{}. @listing { @sident{shaderprog}{.param_array} { @sident{shaderprog}{.param_array@$ .src_progvar} "prog_cenrange" @sident{shaderprog}{.param_array@$ .dest_codeaddr} 42 @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]); /*@{ @declare{shaderprog.param} {.param_array.src_progvar}{$ [str]} Shader source variable. See @ident{comp}{.dest_progvar}. @}*/ s3d_CUtilStr ParamInfo; s3d_CUtilAtomPtr ParamAtom; s3d_CUtilSnkExtractUtil::ExtractAtom( ParamInfo, ParamAtom, ProgCtx->m_AtomMgr, SnkExtract, "src_progvar", true); /*@{ @declare{shaderprog.param} {.param_array.dest_codeaddr}{$ [int]} Shader code destination address. @}*/ int ParamDestAddr = SnkExtract.ExtractInt("dest_codeaddr", true, -1); /*@{ @declare{shaderprog.param} {.param_array.type}{$ [str]} See @ident{shaderprog}{.param_array.type}. @}*/ 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_CDrvD3d9ProgAsmParam Param; Param.m_Info = ParamInfo; Param.m_Addr = ParamDestAddr; Param.m_Type = Type; ParamArray.InsertBack(s3d_CDrvD3d9ProgAsmParamEntry(ParamAtom, Param)); } s3d_UtilArraySortDefault(ParamArray); ParamArray.Compactify(); } void s3d_CDrvD3d9ProgAsmUtil::ExtractTexSize( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, s3d_CDrvD3d9ProgAsmAddrArray &TexSizeAddrArray, s3d_CDrvD3d9ProgAsmAddrArray &TexRcpSizeAddrArray, s3d_CUtilSnkExtract &SnkExtract) { TexSizeAddrArray.Reset(); TexRcpSizeAddrArray.Reset(); /*@{ @declare{shaderprog.param} {.tex_size_codeaddr_array}{$ [int]...[int]} Array of shader code const addresses to upload texture dimensions to. @table { { @code{texsize_codeaddr.x} } { Width } } { { @code{texsize_codeaddr.y} } { Height } } { { @code{texsize_codeaddr.z} } { Depth } } { { @code{texsize_codeaddr.w} } { } } For example: @listing { @sident{shaderprog}{@$ .tex_size_codeaddr_array} 20 -1 40 } Uploads size of texture currently bound to sampler 0 and 2, @it{-1} disables upload of texture bound to sampler 1. @}*/ s3d_CUtilStr TexSizeAddrArrayInfo; SnkExtract.ExtractIntArray( TexSizeAddrArrayInfo, TexSizeAddrArray, "tex_size_codeaddr_array", false); /*@{ @declare{shaderprog.param} {.tex_rcpsize_codeaddr_array}{$ [int]...[int]} Array of shader code const addresses to upload reciprocal texture dimensions to. See also @ident{shaderprog}{.tex_size_codeaddr_array}. @}*/ s3d_CUtilStr TexRcpSizeAddrArrayInfo; SnkExtract.ExtractIntArray( TexRcpSizeAddrArrayInfo, TexRcpSizeAddrArray, "tex_rcpsize_codeaddr_array", false); s3d_CSysIntps nTexSize = TexSizeAddrArray.GetCnt(); if(nTexSize >= ProgCtx->m_MaxSampCnt) { s3d_CDrvDxError e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_progasm.invalid_tex_size_cnt."; e.m_StdTempl = "Too many ASM tex_size_codeaddr_array entries '[1]'." " Must be less than or equal to [2]."; e.AddInfo(TexSizeAddrArrayInfo); e.AddInfo(s3d_CUtilStrUtil::StrOfInt(nTexSize)); e.AddInfo(s3d_CUtilStrUtil::StrOfInt(ProgCtx->m_MaxSampCnt)); s3d_UtilMsgReportError(ProgCtx->m_MsgHandler, e); } s3d_CSysIntps nRcpTexSize = TexRcpSizeAddrArray.GetCnt(); if(nRcpTexSize >= ProgCtx->m_MaxSampCnt) { s3d_CDrvDxError e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_progasm" ".invalid_rcptex_size_cnt."; e.m_StdTempl = "Too many ASM tex_rcpsize_codeaddr_array entries '[1]'." " Must be less than or equal to [2]."; e.AddInfo(TexRcpSizeAddrArrayInfo); e.AddInfo(s3d_CUtilStrUtil::StrOfInt(nRcpTexSize)); e.AddInfo(s3d_CUtilStrUtil::StrOfInt(ProgCtx->m_MaxSampCnt)); s3d_UtilMsgReportError(ProgCtx->m_MsgHandler, e); } TexSizeAddrArray.Compactify(); TexRcpSizeAddrArray.Compactify(); } void s3d_CDrvD3d9ProgAsmUtil::ExtractTrackArray( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, s3d_CDrvD3d9ProgAsmTrackMatArray &MatTrackArray, s3d_CDrvD3d9ProgAsmTrackMatArray &BoneTrackArray, s3d_CUtilSnkExtract &SnkExtract) { /*@{ @declare{shaderprog.param} {.tracking}{$ [chunk]...[chunk]} Track matrices to shader code const addresses. @listing { @sident{shaderprog}{.tracking} { @sident{shaderprog}{.tracking@$ .codeaddr} 0 @sident{shaderprog}{.tracking@$ .cnt} 1 @sident{shaderprog}{.tracking@$ .slot} 0 @sident{shaderprog}{.tracking@$ .chan} "proj" @sident{shaderprog}{.tracking@$ .trans} "identity" } } One matrix needs 4 constants. @}*/ 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_CDrvD3d9ProgAsmTrackMat Track; /*@{ @declare{shaderprog.param} {.tracking.chan}{$ [str]} See @ident{shaderprog}{.tracking.chan}. @}*/ 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]} See @ident{shaderprog}{.tracking.slot}. @}*/ s3d_CUtilStr TrackSlotInfo; SnkExtract.ExtractInt(TrackSlotInfo, Track.m_Slot, "slot", true, 0); if(Track.m_Slot < 0 || Track.m_Slot >= ProgCtx->m_MaxAttrCnt) { s3d_CDrvDxError e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_progasm.invalid_slot."; e.m_StdTempl = "Invalid ASM 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.cnt}{$ [int]} @}*/ Track.m_Cnt = SnkExtract.ExtractInt("cnt", true, 1); if(Track.m_Cnt < 0) Track.m_Cnt = 0; /*@{ @declare{shaderprog.param} {.tracking.trans}{$ [str]} See @ident{shaderprog}{.tracking.trans}. @}*/ 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.codeaddr}{$ [int]} Shader constant register address where matrix is uploaded to. @}*/ Track.m_Addr = SnkExtract.ExtractInt("codeaddr", true, -1); if(Track.m_Addr >= 0) { if(Track.m_Chan == s3d_CDrvUtilGfxProg::TrackChan_Bone) BoneTrackArray.InsertBack(Track); else MatTrackArray.InsertBack(Track); } SnkExtract.CheckForUnknown(); } MatTrackArray.Compactify(); BoneTrackArray.Compactify(); } void s3d_CDrvD3d9ProgAsmUtil::ExtractLightArray( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, int &ActiveLightCntAddr, s3d_CDrvD3d9ProgAsmLightArray &LightTrackArray, s3d_CUtilSnkExtract &SnkExtract) { /*@{ @declare{shaderprog.param} {.light_array}{$ [chunk]...[chunk]} Specifies how many lights a shader can handle and the shader code const address where to upload light values. @listing { @sident{shaderprog}{.light_array} { @sident{shaderprog}{.light_array@$ .cnt} 2 @sident{shaderprog}{.light_array@$ .stride} 5 @sident{shaderprog}{.light_array@$ .pos_codeaddr} 20 @sident{shaderprog}{.light_array@$ .dir_codeaddr} -1 @sident{shaderprog}{.light_array@$ .ambient_codeaddr} 21 @sident{shaderprog}{.light_array@$ .diffuse_codeaddr} 22 @sident{shaderprog}{.light_array@$ .specular_codeaddr} 23 @sident{shaderprog}{.light_array@$ .atten_codeaddr} 24 } } In this example first light position will be uploaded to address @it{20}, direction will be skipped, ambient color to address @it{21} and so on. Second light position will be uploaded to address @it{25} ( pos_codeaddr + stride * index ), etc. @}*/ s3d_CUtilSnkChunkPtr LightChunk; s3d_CUtilStr LightInfo; SnkExtract.ExtractChunk( LightInfo, LightChunk, "light_array", false); /*@{ @declare{shaderprog.param} {.light_activecnt_codeaddr}{$ [int]} In D3D shader version >= 2.0. this address is used for uploading the active light cnt. @}*/ ActiveLightCntAddr = SnkExtract.ExtractInt("light_activecnt_codeaddr", false, -1); 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("cnt", true); if(LightCnt > ProgCtx->m_MaxLightCnt) { s3d_CDrvDxError e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_progasm.invalid_lightcnt."; e.m_StdTempl = "Invalid ASM 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.stride}{$ [int]} Stride of each light component. @listing { light[n].comp_codeaddr = comp_codeaddr + stride * n n := [0..cnt] } @}*/ int Stride = SnkLightExtract.ExtractInt("stride", true); /*@{ @declare{shaderprog.param} {.light_array.pos_codeaddr}{$ [int]} Light position (in viewspace) shader code const address. @}*/ int PosAddr = SnkLightExtract.ExtractInt("pos_codeaddr", true, -1); /*@{ @declare{shaderprog.param} {.light_array.dir_codeaddr}{$ [int]} Light direction (in viewspace) shader code const address. @}*/ int DirAddr = SnkLightExtract.ExtractInt("dir_codeaddr", true, -1); /*@{ @declare{shaderprog.param} {.light_array.ambient_codeaddr}{$ [int]} Light ambient color shader code const address. @}*/ int AmbientAddr = SnkLightExtract.ExtractInt("ambient_codeaddr", true, -1); /*@{ @declare{shaderprog.param} {.light_array.diffuse_codeaddr}{$ [int]} Light diffuse color shader code const address. @}*/ int DiffuseAddr = SnkLightExtract.ExtractInt("diffuse_codeaddr", true, -1); /*@{ @declare{shaderprog.param} {.light_array.specular_codeaddr}{$ [int]} Light specular color shader code const address. @}*/ int SpecularAddr = SnkLightExtract.ExtractInt( "specular_codeaddr", true, -1); /*@{ @declare{shaderprog.param} {.light_array.atten_codeaddr}{$ [int]} Light attenuation shader code const address. @table { { @code{atten_codeaddr.x} } { AttenConst } } { { @code{atten_codeaddr.y} } { AttenLinear } } { { @code{atten_codeaddr.z} } { AttenQuadr } } { { @code{atten_codeaddr.w} } { Range } } @}*/ int AttenAddr = SnkLightExtract.ExtractInt("atten_codeaddr", true, -1); SnkLightExtract.CheckForUnknown(); int iLightParam; for(iLightParam = 0; iLightParam < LightCnt; iLightParam++) { s3d_CDrvD3d9ProgAsmLight Light; int LightOffs = Stride * iLightParam; if(PosAddr >= 0) Light.m_PosAddr = PosAddr + LightOffs; if(DirAddr >= 0) Light.m_DirAddr = DirAddr + LightOffs; if(AmbientAddr >= 0) Light.m_AmbientAddr = AmbientAddr + LightOffs; if(DiffuseAddr >= 0) Light.m_DiffuseAddr = DiffuseAddr + LightOffs; if(SpecularAddr >= 0) Light.m_SpecularAddr = SpecularAddr + LightOffs; if(AttenAddr >= 0) Light.m_AttenAddr = AttenAddr + LightOffs; LightTrackArray.InsertBack(Light); } LightTrackArray.Compactify(); } void s3d_CDrvD3d9ProgAsmUtil::ExtractMtl( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, s3d_CDrvD3d9ProgAsmTrackMtrl &Mtl, 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_codeaddr}{$ [int]} Mtl power shader const address. @table { { @code{power_codeaddr.x} } { MtlPower } } { { @code{power_codeaddr.y} } { MtlPower } } { { @code{power_codeaddr.z} } { MtlPower } } { { @code{power_codeaddr.w} } { MtlPower } } @}*/ Mtl.m_PowerAddr = MtrlSnkExtract.ExtractInt("power_codeaddr", false, -1); /*@{ @declare{shaderprog.param} {.mtl.emissive_codeaddr}{$ [int]} Mtl emissive shader const address. @table { { @code{emissive_codeaddr.x} } { MtlEmissive.r } } { { @code{emissive_codeaddr.y} } { MtlEmissive.g } } { { @code{emissive_codeaddr.z} } { MtlEmissive.b } } { { @code{emissive_codeaddr.w} } { MtlEmissive.a } } @}*/ Mtl.m_EmissiveAddr = MtrlSnkExtract.ExtractInt("emissive_codeaddr", false, -1); MtrlSnkExtract.CheckForUnknown(); } void s3d_CDrvD3d9ProgAsmUtil::ExtractFog( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, int &FogAddr, s3d_CUtilSnkExtract &SnkExtract) { /*@{ @declare{shaderprog.param} {.fog_codeaddr}{$ [int]} Fog color and denisity shader const address. @table { { @code{fog_codeaddr.x} } { FogColor.r } } { { @code{fog_codeaddr.y} } { FogColor.g } } { { @code{fog_codeaddr.z} } { FogColor.b } } { { @code{fog_codeaddr.w} } { FogDensity } } @}*/ FogAddr = SnkExtract.ExtractInt("fog_codeaddr", false, -1); } void s3d_CDrvD3d9ProgAsmUtil::InitTrackBlk( const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, s3d_CDrvD3d9ProgAsmTrackBlk &TrackBlk, s3d_CUtilSnkExtract &SnkExtract) { TrackBlk.m_CodeInfo = CodeInfo; TrackBlk.m_CodeName = CodeName; s3d_CDrvD3d9ProgAsmUtil::ExtractParamArray( ProgCtx, CodeInfo, CodeName, TrackBlk.m_ParamArray, SnkExtract); s3d_CDrvD3d9ProgAsmUtil::ExtractTexSize( ProgCtx, CodeInfo, CodeName, TrackBlk.m_TexSizeArray, TrackBlk.m_TexRcpSizeArray, SnkExtract); s3d_CDrvD3d9ProgAsmUtil::ExtractTrackArray( ProgCtx, CodeInfo, CodeName, TrackBlk.m_MatTrackArray, TrackBlk.m_BoneTrackArray, SnkExtract); s3d_CDrvD3d9ProgAsmUtil::ExtractLightArray( ProgCtx, CodeInfo, CodeName, TrackBlk.m_ActiveLightCntAddr, TrackBlk.m_LightTrackArray, SnkExtract); s3d_CDrvD3d9ProgAsmUtil::ExtractMtl( ProgCtx, CodeInfo, CodeName, TrackBlk.m_Mtl, SnkExtract); s3d_CDrvD3d9ProgAsmUtil::ExtractFog( ProgCtx, CodeInfo, CodeName, TrackBlk.m_FogAddr, SnkExtract); } bool s3d_CDrvD3d9ProgAsmUtil::AssembleFromRes( s3d_CUtilNotifGather *NotifGather, const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, s3d_CLibStreamPreproState *PreproState, s3d_CDrvD3d9Buf &CodeBuf) { 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 = D3DXAssembleShader( D3dStream, D3dStreamLen, D3dMacroArray.Get(), &ProgIncMgr, Flags, &CodeBuf.EmptyRef(), &ErrBuf.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_CDrvD3d9ProgAsmUtil::AssembleFromFile( s3d_CUtilNotifGather *NotifGather, const s3d_CDrvD3d9ProgCtx *ProgCtx, s3d_CUtilStr_cr CodeInfo, s3d_CUtilStr_cr CodeName, s3d_CLibStreamPreproState *PreproState, s3d_CDrvD3d9Buf &CodeBuf) { if(!ProgCtx) return false; s3d_CUtilMsgHandler *MsgHandler = ProgCtx->m_MsgHandler; s3d_CCompResMgr *ResMgr = ProgCtx->m_ResMgr; s3d_CUtilMemPool *MemPool = ProgCtx->m_MemPool; s3d_CUtilMap StreamNameMap; // Errors contain no filename for the main file: StreamNameMap.SetAt("", CodeName); s3d_CDrvD3d9Buf ErrBuf; int DxResult = 0; // Own scope for MemPoolFrm, used by ProgIncMgr { s3d_CUtilMemPoolFrm MemPoolFrm(MemPool); s3d_CDrvD3d9ProgIncMgr ProgIncMgr( MsgHandler, CodeInfo, MemPool, ResMgr, NotifGather, &StreamNameMap); s3d_CUtilOwnArray D3dMacroArray; s3d_CDrvD3d9ProgUtil::D3dMarcoArrayOfPreprocArray( D3dMacroArray, PreproState); DWORD Flags = D3DXSHADER_DEBUG; DxResult = D3DXAssembleShaderFromFile( CodeName.GetChars(), D3dMacroArray.Get(), &ProgIncMgr, Flags, &CodeBuf.EmptyRef(), &ErrBuf.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; } ///////////////////////////////////////////////////////////////////////////////