/////////////////////////////////////////////////////////////////////////////// // // ## ###### // ###### ### // ## ############### Shark 3D Engine (www.shark3d.com) // ########## # # # // ######## Copyright (c) 1996-2006 Spinor GmbH. // ######### # # # All rights reserved. // ## ########## // ## // /////////////////////////////////////////////////////////////////////////////// #include "drv_d3d9_buf.h" #include "drv_d3d9_mmx.h" #include "drv_d3d9_util.h" #include "drv/interf/drv_gfx.h" #include "drv/util/drv_util_gfxutil.h" #include "sys/core/sys_util.h" #include "sys/core/sys_cmem.h" #include /////////////////////////////////////////////////////////////////////////////// #define S3D_DRV_D3D9_CACHEALIGN(A)\ (((A) & ~(S3D_DRV_D3D9_CACHELINE - 1)) + S3D_DRV_D3D9_CACHELINE) /////////////////////////////////////////////////////////////////////////////// static const D3DPRIMITIVETYPE drv_d3d9_PrimTable[6] = { D3DPT_POINTLIST, D3DPT_LINELIST, D3DPT_LINESTRIP, D3DPT_TRIANGLELIST, D3DPT_TRIANGLESTRIP, D3DPT_TRIANGLEFAN, }; /////////////////////////////////////////////////////////////////////////////// s3d_CDrvD3d9VertBufObj::~s3d_CDrvD3d9VertBufObj() { if(m_ReportMsgHandler) { s3d_CUtilMsg m; m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_buf.report_vertbuf_destroy"; m.m_StdTempl = "D3D: " "Destroying vertex buffer object addr=0x[1]."; m.AddInfo(""); m.AddInfo(s3d_CUtilStrUtil::StrOfPtr(this)); s3d_UtilMsgReportNote(m_ReportMsgHandler, m); } } void s3d_CDrvD3d9VertBufObj::Reset() { m_VertBuf.Reset(); m_BufSize = 0; m_VertSize = 0; m_VertDecl.Reset(); m_VertBufFmtDecl = 0; m_Usage = 0; m_Pool = D3DPOOL_FORCE_DWORD; } /////////////////////////////////////////////////////////////////////////////// s3d_CDrvD3d9IdxBufObj::~s3d_CDrvD3d9IdxBufObj() { if(m_ReportMsgHandler) { s3d_CUtilMsg m; m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_buf.report_idxbuf_destroy"; m.m_StdTempl = "D3D: " "Destroying index buffer object addr=0x[1]."; m.AddInfo(""); m.AddInfo(s3d_CUtilStrUtil::StrOfPtr(this)); s3d_UtilMsgReportNote(m_ReportMsgHandler, m); } } void s3d_CDrvD3d9IdxBufObj::Reset() { m_IdxBuf.Reset(); m_IdxCnt = 0; m_BufSize = 0; D3DFORMAT m_Fmt = D3DFMT_UNKNOWN; m_D3dPrim = D3DPT_FORCE_DWORD; m_Usage = 0; m_Pool = D3DPOOL_FORCE_DWORD; } /////////////////////////////////////////////////////////////////////////////// s3d_CDrvD3d9VertBufObjBatch::s3d_CDrvD3d9VertBufObjBatch() { Reset(); m_Complete = true; m_AttrCnt = 0; m_TopolSig = 0; m_Node.m_Data = this; } s3d_CDrvD3d9VertBufObjBatch::~s3d_CDrvD3d9VertBufObjBatch() { } /////////////////////////////////////////////////////////////////////////////// int s3d_CDrvD3d9VertBufObjBatchRef::Compare( const s3d_CDrvD3d9VertBufObjBatch *VertBufObj, const s3d_CDrvD3d9VertBufObjBatchRef &Ref) { if(VertBufObj->m_TopolSig < Ref.m_TopolSig) return -1; if(VertBufObj->m_TopolSig > Ref.m_TopolSig) return 1; if(VertBufObj->m_AttrCnt < Ref.m_AttrCnt) return -1; if(VertBufObj->m_AttrCnt > Ref.m_AttrCnt) return 1; S3D_SYS_ASSERT(VertBufObj->m_AttrCnt == Ref.m_AttrCnt); const s3d_CDrvD3d9VertBufAttr *Attr = VertBufObj->m_AttrArray; const s3d_CDrvGfxAttr *RefAttr = Ref.m_AttrArray; int iAttr; for(iAttr = 0; iAttr < Ref.m_AttrCnt; iAttr++) { if(Attr->m_BankDyn < RefAttr->m_BankDyn) return -1; if(Attr->m_BankDyn > RefAttr->m_BankDyn) return 1; if(Attr->m_BankSig < RefAttr->m_BankSig) return -1; if(Attr->m_BankSig > RefAttr->m_BankSig) return 1; if(Attr->m_Chan < RefAttr->m_Chan) return -1; if(Attr->m_Chan > RefAttr->m_Chan) return 1; if(Attr->m_Slot < RefAttr->m_Slot) return -1; if(Attr->m_Slot > RefAttr->m_Slot) return 1; Attr++; RefAttr++; } return 0; } /////////////////////////////////////////////////////////////////////////////// bool operator==( const s3d_CDrvD3d9VertBufObjBatch *VertBufObj, const s3d_CDrvD3d9VertBufObjBatchRef &Ref) { return s3d_CDrvD3d9VertBufObjBatchRef::Compare(VertBufObj, Ref) == 0; } bool operator<( const s3d_CDrvD3d9VertBufObjBatch *VertBufObj, const s3d_CDrvD3d9VertBufObjBatchRef &Ref) { return s3d_CDrvD3d9VertBufObjBatchRef::Compare(VertBufObj, Ref) < 0; } /////////////////////////////////////////////////////////////////////////////// s3d_CDrvD3d9IdxBufObjBatch::s3d_CDrvD3d9IdxBufObjBatch() { Reset(); m_Node.m_Data = this; } s3d_CDrvD3d9IdxBufObjBatch::~s3d_CDrvD3d9IdxBufObjBatch() { } /////////////////////////////////////////////////////////////////////////////// int s3d_CDrvD3d9IdxBufObjBatchRef::Compare( const s3d_CDrvD3d9IdxBufObjBatch *IdxBufObj, const s3d_CDrvD3d9IdxBufObjBatchRef &Ref) { if(IdxBufObj->m_TopolSig < Ref.m_TopolSig) return -1; if(IdxBufObj->m_TopolSig > Ref.m_TopolSig) return 1; return 0; } /////////////////////////////////////////////////////////////////////////////// bool operator==( const s3d_CDrvD3d9IdxBufObjBatch *IdxBufObj, const s3d_CDrvD3d9IdxBufObjBatchRef &Ref) { return s3d_CDrvD3d9IdxBufObjBatchRef::Compare(IdxBufObj, Ref) == 0; } bool operator<( const s3d_CDrvD3d9IdxBufObjBatch *IdxBufObj, const s3d_CDrvD3d9IdxBufObjBatchRef &Ref) { return s3d_CDrvD3d9IdxBufObjBatchRef::Compare(IdxBufObj, Ref) < 0; } /////////////////////////////////////////////////////////////////////////////// s3d_CDrvD3d9BufMgr::s3d_CDrvD3d9BufMgr( s3d_CUtilMsgHandler *MsgHandler, s3d_CDrvD3d9ProgMgr *ProgMgr, s3d_CDrvD3d9Env &Env, s3d_CDrvD3d9Param *D3dParam, s3d_CSysIntps VertIdxLimit, LPDIRECT3DDEVICE9 D3dDev) { m_MsgHandler = MsgHandler; m_ProgMgr = ProgMgr; m_D3dDev = D3dDev; m_Env = &Env; m_D3dParam = D3dParam; m_VertIdxLimit = VertIdxLimit; m_PreferIdxBuf32 = D3dParam->m_PreferIndexBuf32; } s3d_CDrvD3d9BufMgr::~s3d_CDrvD3d9BufMgr() { } void s3d_CDrvD3d9BufMgr::Park() { FreeDynBuffers(); } void s3d_CDrvD3d9BufMgr::Unpark() { } /////////////////////////////////////////////////////////////////////////////// s3d_CDrvD3d9VertBufObjBatchPtr s3d_CDrvD3d9BufMgr::CreateVertBufObjStatic( const s3d_CDrvGfxCharge *Charge, s3d_CDrvD3d9ProgMgr *ProgMgr, bool SWVertProc) { if(!Charge) return 0; // Search for exisiting vertexbuffer: s3d_CDrvD3d9VertBufObjBatchRef Ref; Ref.m_TopolSig = Charge->m_Topol.m_TopolSig; Ref.m_AttrCnt = Charge->m_AttrCnt; Ref.m_AttrArray = Charge->m_AttrArray; s3d_CDrvD3d9VertBufObjBatchPtr VertBufObj; s3d_CDrvD3d9VertBufObjBatchTree::CNode *Pos; Pos = s3d_UtilTreeSortedGetStart(m_VertBufTree, Ref); if(s3d_UtilTreeIsEqualAt(Pos, Ref)) VertBufObj = Pos->m_Data; s3d_CDrvD3d9VertBufDesc VertBufDesc; const s3d_CDrvD3d9Prog *ProgImpl = 0; if(Charge->m_Prog) ProgImpl = s3d_UtilRecogCastSilent( Charge->m_Prog); if(ProgImpl) ProgImpl->CalcVertBufDesc(Charge, VertBufDesc); else CalcVertBufDesc(Charge, VertBufDesc); s3d_CDrvD3d9VertDecl VertDecl; FindVertDecl(VertBufDesc, VertDecl); if(!VertDecl) return 0; if(VertBufObj) { if(VertBufObj->m_VertBufFmtDecl != VertBufDesc.m_VertBufFmtDecl) { s3d_CUtilStr ExistingVertBufDeclStr = s3d_CDrvD3d9Util::StrOfVertDecl( m_Env, VertBufObj->m_VertDecl); s3d_CUtilStr VertBufDeclStr = s3d_CDrvD3d9Util::StrOfVertDecl(m_Env, VertDecl); s3d_CDrvD3d9Error e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_buf" ".vertdecl_mismatch"; e.m_StdTempl = "The vertex program of this shader " "requires the vertex buffer format '[2]', " "whereas the vertex program of shader '[1]' " "requires the vertex buffer of format '[3]'. " "They must not use different vertex data for skinning. "; e.AddInfo(Charge->m_MainInfo); e.AddInfo(VertBufObj->m_MainInfo); e.AddInfo(VertBufDeclStr); e.AddInfo(ExistingVertBufDeclStr); s3d_UtilMsgReportError(m_MsgHandler, e); e.Reset(); e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_buf" ".sic_vertdecl_mismatch"; e.m_StdTempl = "Sic: " "The vertex program of this shader " "requires the vertex buffer format '[3]', " "whereas the vertex program of shader '[1]' " "requires the vertex buffer format '[2]'. " "They must not use different vertex data for skinning. "; e.AddInfo(VertBufObj->m_MainInfo); e.AddInfo(Charge->m_MainInfo); e.AddInfo(VertBufDeclStr); e.AddInfo(ExistingVertBufDeclStr); s3d_UtilMsgReportError(m_MsgHandler, e); } return VertBufObj; } if(Charge->m_Prog && ProgMgr) { ProgMgr->CheckVertBufIsCompatible( Charge->m_Prog, Charge->m_ObjInfo, Charge->m_ObjDesc, VertDecl); } VertBufObj = AllocVertBufObj(Charge, VertBufDesc, VertDecl, SWVertProc); if(VertBufObj) { if(Ref.m_TopolSig) m_VertBufTree.InsertBefore(Pos, &VertBufObj->m_Node); VertBufObj->m_TopolSig = Charge->m_Topol.m_TopolSig; VertBufObj->m_AttrCnt = Charge->m_AttrCnt; VertBufObj->m_AttrArray.Alloc(Charge->m_AttrCnt); s3d_CDrvD3d9VertBufAttr *AttrArray = VertBufObj->m_AttrArray; s3d_CSysIntps nAttrCnt = Charge->m_AttrCnt; int iAttr; for(iAttr = 0; iAttr < nAttrCnt; iAttr++) { s3d_CDrvGfxAttr *Attr = &Charge->m_AttrArray[iAttr]; AttrArray[iAttr].m_BankDyn = Attr->m_BankDyn; AttrArray[iAttr].m_BankSig = Attr->m_BankSig; AttrArray[iAttr].m_Chan = Attr->m_Chan; AttrArray[iAttr].m_Slot = Attr->m_Slot; } } return VertBufObj; } s3d_CDrvD3d9VertBufObjPtr s3d_CDrvD3d9BufMgr::FetchVertBufObjDyn( s3d_CUtilMemPool *MemPool, const s3d_CDrvGfxCharge *Charge, s3d_CDrvD3d9ProgMgr *ProgMgr, bool SWVertProc) { if(!Charge) return 0; s3d_CDrvD3d9VertBufDesc VertBufDesc; const s3d_CDrvD3d9Prog *ProgImpl = 0; if(Charge->m_Prog) ProgImpl = s3d_UtilRecogCastSilent(Charge->m_Prog); if(ProgImpl) ProgImpl->CalcVertBufDesc(Charge, VertBufDesc); else CalcVertBufDesc(Charge, VertBufDesc); s3d_CDrvD3d9VertDecl VertDecl; FindVertDecl(VertBufDesc, VertDecl); if(!VertDecl) return 0; if(Charge->m_Prog && ProgMgr) { ProgMgr->CheckVertBufIsCompatible( Charge->m_Prog, Charge->m_ObjInfo, Charge->m_ObjDesc, VertDecl); } s3d_CSysIntps VertCnt = Charge->m_VertSubCnt; s3d_CSysIntps VertBufSize = VertBufDesc.m_VertSize * VertCnt; DWORD Usage = D3DUSAGE_WRITEONLY | D3DUSAGE_DYNAMIC; if(SWVertProc) Usage |= D3DUSAGE_SOFTWAREPROCESSING; bool AllocNew = false; if(!m_VertBufDyn) AllocNew = true; else if(m_VertBufDyn->m_BufSize < VertBufSize) AllocNew = true; else if(m_VertBufDyn->m_Usage != Usage) AllocNew = true; if(AllocNew) { D3DPOOL Pool = D3DPOOL_SYSTEMMEM; DWORD FVF = 0; s3d_CDrvD3d9VertBuf VertBuf; S3D_DRV_D3D9_CHECK( m_Env, m_D3dDev->CreateVertexBuffer( UINT(VertBufSize), Usage, FVF, Pool, &VertBuf.EmptyRef(), 0)); if(!VertBuf) return 0; if(!m_VertBufDyn) m_VertBufDyn = S3D_SYS_NEW s3d_CDrvD3d9VertBufObj; m_VertBufDyn->m_VertBuf = VertBuf; m_VertBufDyn->m_Usage = Usage; m_VertBufDyn->m_Pool = Pool; m_VertBufDyn->m_BufSize = VertBufSize; if(m_D3dParam->m_ReportBuf) { m_VertBufDyn->m_ReportMsgHandler = m_MsgHandler; s3d_CUtilMsg m; m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_buf." "report_vertbufdyn_create"; m.m_StdTempl = "D3D: " "Creating new dynamic vertex buffer object " "addr=0x[1] size=[2]: '[3]'"; m.AddInfo(""); m.AddInfo(s3d_CUtilStrUtil::StrOfPtr(m_VertBufDyn)); m.AddInfo(s3d_CUtilStrUtil::StrOfIntps(VertBufSize)); m.AddInfo(Charge->m_MainInfo); s3d_UtilMsgReportNote(m_MsgHandler, m); } } m_VertBufDyn->m_VertSize = VertBufDesc.m_VertSize; m_VertBufDyn->m_VertDecl = VertDecl; m_VertBufDyn->m_VertBufFmtDecl = VertBufDesc.m_VertBufFmtDecl; s3d_CSysIntps DestVertBase = 0; s3d_CSysIntps VertBase = Charge->m_VertSubBase; bool DynOnly = false; bool Discard = true; LoadVertBuf( Charge, m_VertBufDyn, VertBufDesc, 0, DestVertBase, VertBase, VertCnt, DynOnly, Discard); if(!m_D3dParam->m_NoDummyBoneVertexBuf) { int VertBufFmtDecl = VertBufDesc.m_VertBufFmtDecl; CheckAllocDummyBuffers(Charge, VertBufFmtDecl, SWVertProc); } return m_VertBufDyn; } const s3d_CSysIntm *s3d_CDrvD3d9BufMgr::CheckVertBufDirectPointFloat3( const s3d_CDrvGfxCharge *Charge, s3d_CDrvD3d9VertBufDesc_cr VertBufDesc) { if(VertBufDesc.m_VertElemCnt != 2) return 0; const D3DVERTEXELEMENT9 *VertElem = &VertBufDesc.m_VertElemArray[0]; if(VertElem->Usage != D3DDECLUSAGE_POSITION) return 0; if(Charge->m_AttrCnt != 1) return 0; s3d_CDrvGfxAttr *Attr = &Charge->m_AttrArray[0]; if(Attr->m_Chan != s3d_CDrvGfxEng::AttrChan_Point) return 0; s3d_CDrvBankContent BankContent; s3d_DrvBankFetchExisting( m_MsgHandler, Charge->m_ObjInfo, "point", Attr->m_Bank, BankContent); if(BankContent.m_TypeDesc != s3d_DrvDataGetTypeDesc()) return 0; if(BankContent.m_Stride != 3 * sizeof(float)) return 0; return BankContent.m_Data; } void s3d_CDrvD3d9BufMgr::FetchVertBufMemDyn( s3d_CUtilMemPool *MemPool, const s3d_CDrvGfxCharge *Charge, s3d_CDrvD3d9ProgMgr *ProgMgr, s3d_CDrvD3d9VertBufMem &VertBuf) { VertBuf.m_Data = 0; VertBuf.m_VertSize = 0; VertBuf.m_VertBufFmtDecl = 0; if(!Charge) return; s3d_CDrvD3d9VertBufDesc VertBufDesc; const s3d_CDrvD3d9Prog *ProgImpl = 0; if(Charge->m_Prog) ProgImpl = s3d_UtilRecogCastSilent(Charge->m_Prog); if(ProgImpl) ProgImpl->CalcVertBufDesc(Charge, VertBufDesc); else CalcVertBufDesc(Charge, VertBufDesc); FindVertDecl(VertBufDesc, VertBuf.m_VertDecl); if(!VertBuf.m_VertDecl) return; if(Charge->m_Prog && ProgMgr) { ProgMgr->CheckVertBufIsCompatible( Charge->m_Prog, Charge->m_ObjInfo, Charge->m_ObjDesc, VertBuf.m_VertDecl); } VertBuf.m_VertSize = VertBufDesc.m_VertSize; VertBuf.m_VertBufFmtDecl = VertBufDesc.m_VertBufFmtDecl; const s3d_CSysIntm *DirectData = CheckVertBufDirectPointFloat3( Charge, VertBufDesc); if(DirectData) { VertBuf.m_Data = DirectData; return; } s3d_CSysIntps VertBufSize = Charge->m_VertSubCnt * VertBufDesc.m_VertSize; s3d_CSysIntm *VertBufData = new(MemPool) s3d_CSysIntm[VertBufSize]; s3d_CSysIntps DestVertBase = 0; s3d_CSysIntps VertCnt = Charge->m_VertSubCnt; s3d_CSysIntps VertBase = Charge->m_VertSubBase; bool DynOnly = false; LoadVertBufData( Charge, VertBufDesc, VertBufData, VertBase, VertCnt, DynOnly); VertBuf.m_Data = VertBufData; } s3d_CDrvD3d9IdxBufObjBatchPtr s3d_CDrvD3d9BufMgr::CreateIdxBufObjStatic( const s3d_CDrvGfxCharge *Charge, DWORD Usage, D3DPOOL Pool) { if(!Charge) return 0; // Search for indexbuf w/ same batch->topol->atom s3d_CDrvD3d9IdxBufObjBatchRef Ref; Ref.m_TopolSig = Charge->m_Topol.m_TopolSig; s3d_CDrvD3d9IdxBufObjBatchPtr IdxBufObj; s3d_CDrvD3d9IdxBufObjBatchTree::CNode *Pos = s3d_UtilTreeSortedGetStart(m_IdxBufTree, Ref); if(s3d_UtilTreeIsEqualAt(Pos, Ref)) IdxBufObj = Pos->m_Data; if(IdxBufObj) return IdxBufObj; s3d_CSysIntps MaxIdx = Charge->m_VertSubBase + Charge->m_Topol.m_VertCnt; D3DFORMAT IdxBufFmt = CalcIdxBufFmtOfCnt( Charge->m_MainInfo, MaxIdx, m_PreferIdxBuf32); const s3d_CDrvInt32u *BoneIdxData = s3d_DrvBankFetchArray( m_MsgHandler, Charge->m_MainInfo, "bone_idx", Charge->m_Topol.m_BoneIdxBank, Charge->m_Topol.m_BoneIdxCnt); s3d_CSysIntps BoneIdxCnt = 0; s3d_CUtilOwnArray BoneIdxArray; if(BoneIdxData) { BoneIdxCnt = Charge->m_Topol.m_BoneIdxCnt; BoneIdxArray.Alloc(BoneIdxCnt); s3d_CSysIntps iBoneIdx; for(iBoneIdx = 0; iBoneIdx < BoneIdxCnt; iBoneIdx++) { s3d_CSysInt32u BoneIdx = *BoneIdxData++; BoneIdxArray[iBoneIdx] = BoneIdx; } } s3d_CSysIntps PacketCnt = Charge->m_Topol.m_PacketCnt; s3d_CUtilOwnArray PacketArray; PacketArray.Alloc(PacketCnt); s3d_CSysIntps PacketSubBase = 0; LoadBatchPacketData(Charge, PacketCnt, PacketArray, PacketSubBase); IdxBufObj = AllocIdxBufObj(Charge, IdxBufFmt, Usage, Pool); if(IdxBufObj) { IdxBufObj->m_BoneIdxCnt = BoneIdxCnt; IdxBufObj->m_BoneIdxArray.Assign(BoneIdxArray); IdxBufObj->m_PacketCnt = PacketCnt; IdxBufObj->m_PacketArray.Assign(PacketArray); if(Ref.m_TopolSig) m_IdxBufTree.InsertBefore(Pos, &IdxBufObj->m_Node); } return IdxBufObj; } s3d_CDrvD3d9IdxBufObjPtr s3d_CDrvD3d9BufMgr::FetchIdxBufObjDyn( s3d_CUtilMemPool *MemPool, const s3d_CDrvGfxCharge *Charge, s3d_CUtilMemPoolArray &BoneIdxArray, DWORD Usage, D3DPOOL Pool) { if(!Charge) return 0; s3d_CSysIntps MaxIdx = Charge->m_VertSubBase + Charge->m_VertSubCnt; D3DFORMAT IdxBufFmt = CalcIdxBufFmtOfCnt( Charge->m_MainInfo, MaxIdx, m_PreferIdxBuf32); s3d_CSysIntps IdxCnt = Charge->m_IdxSubCnt; s3d_CSysIntps IdxBufSize = CalcSizeOfFmtCnt(IdxBufFmt, IdxCnt); const s3d_CDrvInt32u *BoneIdxData = s3d_DrvBankFetchArray( m_MsgHandler, Charge->m_MainInfo, "bone_idx", Charge->m_Topol.m_BoneIdxBank, Charge->m_Topol.m_BoneIdxCnt); if(BoneIdxData) { BoneIdxData += Charge->m_BoneIdxSubBase; s3d_CSysIntps BoneIdxCnt = Charge->m_BoneIdxSubCnt; BoneIdxArray.SetCnt(MemPool, BoneIdxCnt); s3d_CSysIntps iBoneIdx; for(iBoneIdx = 0; iBoneIdx < BoneIdxCnt; iBoneIdx++) { s3d_CSysInt32u BoneIdx = *BoneIdxData++; BoneIdxArray.SetAtRaw(iBoneIdx, BoneIdx); } } bool AllocNew = false; if(!m_IdxBufDyn) AllocNew = true; else if(m_IdxBufDyn->m_BufSize < IdxBufSize) AllocNew = true; else if(m_IdxBufDyn->m_Fmt < IdxBufFmt) AllocNew = true; else if(m_IdxBufDyn->m_Usage != Usage) AllocNew = true; if(AllocNew) { s3d_CDrvD3d9IdxBuf IdxBuf; S3D_DRV_D3D9_CHECK( m_Env, m_D3dDev->CreateIndexBuffer( UINT(IdxBufSize), Usage, IdxBufFmt, Pool, &IdxBuf.EmptyRef(), 0)); if(!IdxBuf) return 0; if(!m_IdxBufDyn) m_IdxBufDyn = S3D_SYS_NEW s3d_CDrvD3d9IdxBufObj; m_IdxBufDyn->m_IdxBuf = IdxBuf; m_IdxBufDyn->m_BufSize = IdxBufSize; m_IdxBufDyn->m_Pool = Pool; m_IdxBufDyn->m_Usage = Usage; m_IdxBufDyn->m_Fmt = IdxBufFmt; if(m_D3dParam->m_ReportBuf) { m_IdxBufDyn->m_ReportMsgHandler = m_MsgHandler; s3d_CUtilMsg m; m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_buf." "report_idxbufdyn_create"; m.m_StdTempl = "D3D: " "Creating new dynamic index buffer object " "addr=0x[1] size=[2]: '[3]'"; m.AddInfo(""); m.AddInfo(s3d_CUtilStrUtil::StrOfPtr(m_IdxBufDyn)); m.AddInfo(s3d_CUtilStrUtil::StrOfIntps(IdxBufSize)); m.AddInfo(Charge->m_MainInfo); s3d_UtilMsgReportNote(m_MsgHandler, m); } } int Prim = Charge->m_Topol.m_Prim; D3DPRIMITIVETYPE D3dPrim = D3DPT_POINTLIST; if(s3d_SysIsValidArrayIdx(Prim, S3D_SYS_ARRAYCNTS(drv_d3d9_PrimTable))) D3dPrim = drv_d3d9_PrimTable[Prim]; m_IdxBufDyn->m_D3dPrim = D3dPrim; m_IdxBufDyn->m_IdxCnt = IdxCnt; s3d_CSysIntps DestIdxBase = 0; s3d_CSysIntps VertOffset = Charge->m_VertSubBase; s3d_CSysIntps SrcIdxBase = Charge->m_IdxSubBase; bool Discard = true; LoadIdxBuf( Charge, m_IdxBufDyn, DestIdxBase, VertOffset, SrcIdxBase, Discard); return m_IdxBufDyn; } void s3d_CDrvD3d9BufMgr::FetchIdxBufMemDyn( s3d_CUtilMemPool *MemPool, const s3d_CDrvGfxCharge *Charge, s3d_CDrvD3d9IdxBufMem &IdxBuf, s3d_CUtilMemPoolArray &BoneIdxArray) { IdxBuf.m_Data = 0; IdxBuf.m_Fmt = D3DFMT_UNKNOWN; IdxBuf.m_Prim = D3DPT_POINTLIST; if(!Charge) return; const s3d_CDrvInt32u *BoneIdxData = s3d_DrvBankFetchArray( m_MsgHandler, Charge->m_MainInfo, "bone_idx", Charge->m_Topol.m_BoneIdxBank, Charge->m_Topol.m_BoneIdxCnt); if(BoneIdxData) { BoneIdxData += Charge->m_BoneIdxSubBase; s3d_CSysIntps BoneIdxCnt = Charge->m_BoneIdxSubCnt; BoneIdxArray.SetCnt(MemPool, BoneIdxCnt); s3d_CSysIntps iBoneIdx; for(iBoneIdx = 0; iBoneIdx < BoneIdxCnt; iBoneIdx++) { s3d_CSysInt32u BoneIdx = *BoneIdxData++; BoneIdxArray.SetAtRaw(iBoneIdx, BoneIdx); } } // prefer 32 bit indices for use w/ DIPUP coz engine delivers data // in int32u. so we dont need to convert 32 -> 16 bit indices bool PreferIdxBuf32 = true; s3d_CSysIntps MaxIdx = Charge->m_VertSubBase + Charge->m_VertSubCnt; IdxBuf.m_Fmt = s3d_CDrvD3d9BufMgr::CalcIdxBufFmtOfCnt( Charge->m_MainInfo, MaxIdx, PreferIdxBuf32); int Prim = Charge->m_Topol.m_Prim; if(s3d_SysIsValidArrayIdx(Prim, S3D_SYS_ARRAYCNTS(drv_d3d9_PrimTable))) IdxBuf.m_Prim = drv_d3d9_PrimTable[Prim]; s3d_CSysIntps IdxSubBase = Charge->m_IdxSubBase; if(IdxSubBase == 0) { s3d_CDrvBankContent BankContent; s3d_DrvBankFetchExisting( m_MsgHandler, Charge->m_MainInfo, "idx", Charge->m_Topol.m_IdxBank, BankContent); if(BankContent.m_TypeDesc == s3d_DrvDataGetTypeDesc() && BankContent.m_Stride == sizeof(s3d_CSysInt32u) && IdxBuf.m_Fmt == D3DFMT_INDEX32) { IdxBuf.m_Data = BankContent.m_Data; return; } } s3d_CSysIntps IdxCnt = Charge->m_IdxSubCnt; s3d_CSysIntps IdxBufSize = CalcSizeOfFmtCnt(IdxBuf.m_Fmt, IdxCnt); s3d_CSysIntm *IdxBufData = new(MemPool) s3d_CSysIntm[IdxBufSize]; s3d_CSysIntps DestIdxBase = 0; s3d_CSysIntps VertOffset = Charge->m_VertSubBase; s3d_CSysIntps IdxBase = Charge->m_IdxSubBase; LoadIdxBufData( Charge, IdxBuf.m_Fmt, IdxBufData, IdxCnt, DestIdxBase, VertOffset, IdxBase); IdxBuf.m_Data = IdxBufData; } void s3d_CDrvD3d9BufMgr::LoadBatchPacketData( const s3d_CDrvGfxCharge *Charge, s3d_CSysIntps PacketCnt, s3d_CDrvD3d9Packet *PacketArray, s3d_CSysIntps PacketSubBase) { if(!Charge) return; const s3d_CDrvMeshPacket *ChargePacketArray = s3d_DrvBankFetchExistingArray( m_MsgHandler, Charge->m_ObjInfo, "packet", Charge->m_Topol.m_PacketBank, Charge->m_Topol.m_PacketCnt); const s3d_CDrvMeshPacket *CurChargePacket = ChargePacketArray + PacketSubBase; s3d_CDrvD3d9Packet *CurPacket = PacketArray; s3d_CSysIntps iPacket; for(iPacket = 0; iPacket < PacketCnt; iPacket++) { CurPacket->m_VertCnt = CurChargePacket->m_VertCnt; CurPacket->m_IdxCnt = CurChargePacket->m_IdxCnt; CurPacket->m_PrimCnt = s3d_CDrvUtilGfxUtil::PrimCntOfIdxCnt( Charge->m_Topol.m_Prim, CurChargePacket->m_IdxCnt); CurPacket->m_BoneIdxCnt = CurChargePacket->m_BoneIdxCnt; CurChargePacket++; CurPacket++; } } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9BufMgr::FindVertDecl( s3d_CDrvD3d9VertBufDesc VertBufDesc, s3d_CDrvD3d9VertDecl &VertDecl) { D3DVERTEXELEMENT9 *VertElemArray = VertBufDesc.m_VertElemArray; s3d_CSysIntps VertElemCnt = VertBufDesc.m_VertElemCnt; // Search if we have already a VertDecl matching the VertBufDesc, // if not create a new VertDecl and store it in VertDeclMap. s3d_CDrvD3d9VertElemObjRef ElemObjRef; ElemObjRef.m_VertElemCnt = VertElemCnt; ElemObjRef.m_VertElemArray = VertElemArray; if(!s3d_UtilMapGetAtInto(m_VertDeclMap, ElemObjRef, VertDecl)) { DWORD Stream = 0; UINT VertSize; S3D_DRV_D3D9_HRESCALL( m_Env, VertSize, D3DXGetDeclVertexSize(VertElemArray, Stream)); if(VertSize != VertBufDesc.m_VertSize) { s3d_CUtilMsg e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_buf." "vertdecl_size_missmatch"; e.m_StdTempl = "Vertex declaration [1] size mismatch. " "D3D size is [2]. Calculated size is [3]. "; e.AddInfo(""); e.AddInfo(s3d_CDrvD3d9Util::StrOfVertElemArray( VertElemCnt, VertElemArray)); e.AddInfo(s3d_CUtilStrUtil::StrOfInt64s(VertSize)); e.AddInfo(s3d_CUtilStrUtil::StrOfInt64s(VertBufDesc.m_VertSize)); s3d_UtilMsgReportError(m_MsgHandler, e); S3D_SYS_ASSERT(0); return; } S3D_DRV_D3D9_CHECK( m_Env, m_D3dDev->CreateVertexDeclaration( VertElemArray, &VertDecl.EmptyRef())); if(!VertDecl) return; s3d_CDrvD3d9VertElemObjPtr VertElemObj = S3D_SYS_NEW s3d_CDrvD3d9VertElemObj; VertElemObj->m_VertElemCnt = VertElemCnt; VertElemObj->m_VertElemArray.Alloc(VertElemCnt); s3d_SysMemcpy( VertElemObj->m_VertElemArray, VertElemArray, VertElemCnt * S3D_SYS_SIZEOFS(D3DVERTEXELEMENT9)); s3d_CDrvD3d9VertElemObjKey VertElemObjKey; VertElemObjKey.m_VertElemObj = VertElemObj; m_VertDeclMap.SetAt(VertElemObjKey, VertDecl); } } s3d_CDrvD3d9VertBufObjBatchPtr s3d_CDrvD3d9BufMgr::AllocVertBufObj( const s3d_CDrvGfxCharge *Charge, const s3d_CDrvD3d9VertBufDesc &VertBufDesc, LPDIRECT3DVERTEXDECLARATION9 VertDecl, bool SWVertProc) { s3d_CSysIntps VertCnt = Charge->m_Topol.m_VertCnt; s3d_CSysIntps VertBufSize = VertBufDesc.m_VertSize * VertCnt; s3d_CSysIntps Offs = 0; s3d_CDrvD3d9VertBuf VertBuf; DWORD Usage = D3DUSAGE_WRITEONLY; if(SWVertProc) Usage |= D3DUSAGE_SOFTWAREPROCESSING; D3DPOOL Pool = D3DPOOL_MANAGED; DWORD FVF = 0; S3D_DRV_D3D9_CHECK( m_Env, m_D3dDev->CreateVertexBuffer( UINT(VertBufSize), Usage, FVF, Pool, &VertBuf.EmptyRef(), 0)); if(!VertBuf) return 0; D3DVERTEXBUFFER_DESC D3dVertBufDesc; S3D_DRV_D3D9_CHECK(m_Env, VertBuf->GetDesc(&D3dVertBufDesc)); s3d_CDrvD3d9VertBufObjBatchPtr VertBufObj = S3D_SYS_NEW s3d_CDrvD3d9VertBufObjBatch; VertBufObj->m_MainInfo = Charge->m_MainInfo; VertBufObj->m_VertBuf = VertBuf; VertBufObj->m_BufSize = VertBufSize; VertBufObj->m_VertSize = VertBufDesc.m_VertSize; VertBufObj->m_VertDecl = VertDecl; VertBufObj->m_VertBufFmtDecl = VertBufDesc.m_VertBufFmtDecl; VertBufObj->m_Pool = D3dVertBufDesc.Pool; VertBufObj->m_Usage = D3dVertBufDesc.Usage; if(m_D3dParam->m_ReportBuf) { VertBufObj->m_ReportMsgHandler = m_MsgHandler; s3d_CUtilMsg m; m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_buf.report_vertbuf_create"; m.m_StdTempl = "D3D: " "Creating new vertex buffer object addr=0x[1] size=[2]: " "'[3]'"; m.AddInfo(""); m.AddInfo(s3d_CUtilStrUtil::StrOfPtr(VertBufObj)); m.AddInfo(s3d_CUtilStrUtil::StrOfIntps(VertBufSize)); m.AddInfo(Charge->m_MainInfo); s3d_UtilMsgReportNote(m_MsgHandler, m); } s3d_CSysIntps DestVertBase = 0; s3d_CSysIntps VertBase = 0; bool DynOnly = false; bool Discard = false; LoadVertBuf( Charge, VertBufObj, VertBufDesc, Offs, DestVertBase, VertBase, VertCnt, DynOnly, Discard); #ifndef S3D_DRV_D3D9_NO_DUMMY_STREAMS if(!m_D3dParam->m_NoDummyBoneVertexBuf) { int VertBufFmtDecl = VertBufDesc.m_VertBufFmtDecl; CheckAllocDummyBuffers(Charge, VertBufFmtDecl, SWVertProc); } #endif return VertBufObj; } void s3d_CDrvD3d9BufMgr::LoadVertBuf( const s3d_CDrvGfxCharge *Charge, s3d_CDrvD3d9VertBufObj *VertBuf, const s3d_CDrvD3d9VertBufDesc &VertBufDesc, s3d_CSysIntps DestStartOffs, s3d_CSysIntps DestVertBase, s3d_CSysIntps VertBase, s3d_CSysIntps VertCnt, bool DynOnly, bool Discard) { if(!Charge) return; if(!VertBuf) return; LPDIRECT3DVERTEXBUFFER9 D3dVertBuf = VertBuf->m_VertBuf; if(!D3dVertBuf) return; s3d_CSysIntps VertSize = VertBuf->m_VertSize; UINT LockSize = UINT(VertCnt * VertSize); UINT LockOffset = UINT(DestVertBase * VertSize) + DestStartOffs; DWORD Flags = 0; if(Discard) Flags = D3DLOCK_DISCARD; void *LockTarget; S3D_DRV_D3D9_CHECK( m_Env, D3dVertBuf->Lock( LockOffset, LockSize, &LockTarget, Flags)); if(!LockTarget) return; s3d_CSysIntm *Data = reinterpret_cast(LockTarget); LoadVertBufData(Charge, VertBufDesc, Data, VertBase, VertCnt, DynOnly); S3D_DRV_D3D9_CHECK( m_Env, D3dVertBuf->Unlock()); if(m_D3dParam->m_PreloadResources && VertBuf->m_Pool == D3DPOOL_MANAGED) { S3D_DRV_D3D9_CALL(m_Env, D3dVertBuf->PreLoad()); } } void s3d_CDrvD3d9BufMgr::LoadVertBufData( const s3d_CDrvGfxCharge *Charge, const s3d_CDrvD3d9VertBufDesc &VertBufDesc, s3d_CSysIntm *Dest, s3d_CSysIntps VertBase, s3d_CSysIntps VertCnt, bool DynOnly) { const s3d_CDrvD3d9DummyWghAttr DummyWghAttr; const s3d_CDrvD3d9DummySubscrAttr DummySubscrAttr; s3d_CSysIntps VertexSize = VertBufDesc.m_VertSize; s3d_CSysIntps AttrCnt = VertBufDesc.m_VertElemCnt - 1; // DECL_END() int VertBufFmtDecl = VertBufDesc.m_VertBufFmtDecl; const s3d_CDrvGfxAttr *Attr = 0; s3d_CSysIntps iAttr; for(iAttr = 0; iAttr < AttrCnt; iAttr++) { const D3DVERTEXELEMENT9 *VertElemArray = &VertBufDesc.m_VertElemArray[iAttr]; switch(VertElemArray->Usage) { case D3DDECLUSAGE_POSITION: { Attr = VertBufDesc.m_PointAttr; break; } case D3DDECLUSAGE_BLENDWEIGHT: { Attr = VertBufDesc.m_BoneWghAttr; if((VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_DummyBoneWgh) && VertElemArray->Stream == 0) { Attr = &DummyWghAttr; } break; } case D3DDECLUSAGE_BLENDINDICES: { Attr = VertBufDesc.m_BoneSubscrAttr; if((VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_DummyBoneSubscr) && VertElemArray->Stream == 0) { Attr = &DummySubscrAttr; } break; } case D3DDECLUSAGE_NORMAL: { Attr = VertBufDesc.m_NormalAttr; break; } case D3DDECLUSAGE_COLOR: { Attr = VertBufDesc.m_ColorAlphaAttr; break; } case D3DDECLUSAGE_TEXCOORD: { int Idx = VertElemArray->UsageIndex; Attr = VertBufDesc.m_TexAttrArray[Idx]; break; } default: { S3D_SYS_ASSERT(0); continue; } } if(!Attr) continue; if(DynOnly && !Attr->m_BankDyn) continue; s3d_CDrvBankContent BankContent; s3d_DrvBankFetch( m_MsgHandler, Charge->m_MainInfo, "d3d_load_vertex_buf_data", Attr->m_Bank, BankContent); if(!BankContent.m_Data) continue; const s3d_CSysIntm *EffData = BankContent.m_Data + VertBase * BankContent.m_Stride; s3d_CSysIntm *Target = Dest + VertElemArray->Offset; DWORD DestType = VertElemArray->Type; switch(DestType) { case D3DDECLTYPE_FLOAT2: { if(BankContent.m_TypeDesc == s3d_DrvDataGetTypeDesc()) { s3d_CDrvD3d9BufInitUtil::InitFloatX2ToFloat32X2( Target, VertexSize, EffData, VertCnt, BankContent.m_Stride); } else s3d_CDrvD3d9BufInitUtil::VertFormatError( m_MsgHandler, Charge); break; } case D3DDECLTYPE_FLOAT3: { if(BankContent.m_TypeDesc == s3d_DrvDataGetTypeDesc()) { s3d_CDrvD3d9BufInitUtil::InitFloatX3ToFloat32X3( Target, VertexSize, EffData, VertCnt, BankContent.m_Stride); } else if(BankContent.m_TypeDesc == s3d_DrvDataGetTypeDesc()) { S3D_SYS_ASSERT( VertElemArray->Usage == D3DDECLUSAGE_BLENDWEIGHT); s3d_CDrvD3d9BufInitUtil::InitFloatX3ToFloat32X3( Target, VertexSize, EffData, VertCnt, BankContent.m_Stride); } else s3d_CDrvD3d9BufInitUtil::VertFormatError( m_MsgHandler, Charge); break; } case D3DDECLTYPE_FLOAT4: { if(BankContent.m_TypeDesc == s3d_DrvDataGetTypeDesc()) { s3d_CDrvD3d9BufInitUtil::InitFloatX4ToFloat32X4( Target, VertexSize, EffData, VertCnt, BankContent.m_Stride); } else s3d_CDrvD3d9BufInitUtil::VertFormatError( m_MsgHandler, Charge); break; } case D3DDECLTYPE_D3DCOLOR: { if(BankContent.m_TypeDesc == s3d_DrvDataGetTypeDesc()) { s3d_CDrvD3d9BufInitUtil::InitFloatX3ToColor( Target, VertexSize, EffData, VertCnt, BankContent.m_Stride); } else if(BankContent.m_TypeDesc == s3d_DrvDataGetTypeDesc()) { s3d_CDrvD3d9BufInitUtil::InitFloatX4ToColor( Target, VertexSize, EffData, VertCnt, BankContent.m_Stride); } else s3d_CDrvD3d9BufInitUtil::VertFormatError( m_MsgHandler, Charge); break; } case D3DDECLTYPE_UBYTE4: { if(BankContent.m_TypeDesc == s3d_DrvDataGetTypeDesc()) { s3d_CDrvD3d9BufInitUtil::InitIntX4ToInt8uX4( Target, VertexSize, EffData, VertCnt, BankContent.m_Stride); } else if(BankContent.m_TypeDesc == s3d_DrvDataGetTypeDesc()) { // Compress float[-1..1] to int[0..255] s3d_CDrvD3d9BufInitUtil::InitFloatX3ToInt8uX4( Target, VertexSize, EffData, VertCnt, BankContent.m_Stride); } else if(BankContent.m_TypeDesc == s3d_DrvDataGetTypeDesc()) { // Compress float[0..1] to int[0..255] s3d_CDrvD3d9BufInitUtil::InitFloatX4ToInt8uX4( Target, VertexSize, EffData, VertCnt, BankContent.m_Stride); } else s3d_CDrvD3d9BufInitUtil::VertFormatError( m_MsgHandler, Charge); break; } /* case D3DDECLTYPE_FLOAT1: case D3DDECLTYPE_SHORT2: case D3DDECLTYPE_SHORT4: case D3DDECLTYPE_UBYTE4N: case D3DDECLTYPE_SHORT2N: case D3DDECLTYPE_SHORT4N: case D3DDECLTYPE_USHORT2N: case D3DDECLTYPE_USHORT4N: case D3DDECLTYPE_UDEC3: case D3DDECLTYPE_DEC3N: case D3DDECLTYPE_FLOAT16_2: case D3DDECLTYPE_FLOAT16_4: */ default: s3d_CDrvD3d9BufInitUtil::VertFormatError(m_MsgHandler, Charge); break; } } } void s3d_CDrvD3d9BufMgr::CalcVertBufDesc( const s3d_CDrvGfxCharge *Charge, s3d_CDrvD3d9VertBufDesc &VertBufDesc) { VertBufDesc.Reset(); if(!Charge) return; bool Complete = true; int VertBufFmtDecl = 0; s3d_CDrvGfxAttr *PointAttr = 0; s3d_CDrvGfxAttr *ColorAlphaAttr = 0; s3d_CDrvGfxAttr *NormalAttr = 0; s3d_CDrvGfxAttr *BoneWghAttr = 0; s3d_CDrvGfxAttr *BoneSubscrAttr = 0; s3d_CDrvGfxAttr *TexAttrArray[S3D_DRV_D3D9_MAX_ATTR_CNT]; int TexSlotCnt = 0; const s3d_CDrvDataTypeDesc *TexTypeDescArray[S3D_DRV_D3D9_MAX_ATTR_CNT]; int iTex; for(iTex = 0; iTex < S3D_DRV_D3D9_MAX_ATTR_CNT; iTex++) { TexTypeDescArray[iTex] = 0; TexAttrArray[iTex] = 0; } int iAttr; for(iAttr = 0; iAttr < Charge->m_AttrCnt; iAttr++) { s3d_CDrvGfxAttr *Attr = &Charge->m_AttrArray[iAttr]; if(Attr->m_BankDyn) Complete = false; s3d_CDrvBankContent BankContent; s3d_DrvBankFetch( m_MsgHandler, Charge->m_MainInfo, "attr", Attr->m_Bank, BankContent); int Slot = Attr->m_Slot; int Chan = Attr->m_Chan; switch(Chan) { case s3d_CDrvGfxEng::AttrChan_Generic: { if(s3d_SysIsValidArrayIdx(Slot, S3D_DRV_D3D9_MAX_ATTR_CNT)) { while(TexSlotCnt <= Slot) TexTypeDescArray[TexSlotCnt++] = 0; TexTypeDescArray[Slot] = BankContent.m_TypeDesc; TexAttrArray[Slot] = Attr; VertBufFmtDecl |= s3d_CDrvD3d9VertBufDesc::Decl_Generic; } break; } case s3d_CDrvGfxEng::AttrChan_Point: { if(Slot == 0) { VertBufFmtDecl |= s3d_CDrvD3d9VertBufDesc::Decl_Point; PointAttr = Attr; } break; } case s3d_CDrvGfxEng::AttrChan_ColorAlpha: { if(Slot == 0) { VertBufFmtDecl |= s3d_CDrvD3d9VertBufDesc::Decl_ColorAlpha; ColorAlphaAttr = Attr; } break; } case s3d_CDrvGfxEng::AttrChan_Normal: { if(Slot == 0) { VertBufFmtDecl |= s3d_CDrvD3d9VertBufDesc::Decl_Normal; NormalAttr = Attr; } break; } case s3d_CDrvGfxEng::AttrChan_BoneWgh: { if(Slot == 0) { VertBufFmtDecl |= s3d_CDrvD3d9VertBufDesc::Decl_BoneWgh; BoneWghAttr = Attr; } break; } case s3d_CDrvGfxEng::AttrChan_BoneSubscr: { if(Slot == 0) { VertBufFmtDecl |= s3d_CDrvD3d9VertBufDesc::Decl_BoneSubscr; BoneSubscrAttr = Attr; } break; } } } D3DVERTEXELEMENT9 *VertElemArray = VertBufDesc.m_VertElemArray; WORD DeclOffs = 0; WORD VertElemStream = 0; if(VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_Point) { const D3DVERTEXELEMENT9 DeclPoint = { VertElemStream, DeclOffs, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }; DeclOffs = DeclOffs + S3D_SYS_SIZEOFS(float) * 3; VertBufDesc.m_PointAttr = PointAttr; *VertElemArray++ = DeclPoint; } if(VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_BoneWgh) { const D3DVERTEXELEMENT9 DeclBlendWgh = { VertElemStream, DeclOffs, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDWEIGHT, 0 }; DeclOffs = DeclOffs + S3D_SYS_SIZEOFS(float) * 3; VertBufDesc.m_BoneWghAttr = BoneWghAttr; *VertElemArray++ = DeclBlendWgh; } if(VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_BoneSubscr) { const D3DVERTEXELEMENT9 DeclBlendIdx = { VertElemStream, DeclOffs, D3DDECLTYPE_UBYTE4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_BLENDINDICES, 0 }; DeclOffs = DeclOffs + S3D_SYS_SIZEOFS(DWORD); VertBufDesc.m_BoneSubscrAttr = BoneSubscrAttr; *VertElemArray++ = DeclBlendIdx; } if(VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_ColorAlpha) { const D3DVERTEXELEMENT9 DeclColorAlpha = { VertElemStream, DeclOffs, D3DDECLTYPE_D3DCOLOR, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }; DeclOffs = DeclOffs + S3D_SYS_SIZEOFS(DWORD); VertBufDesc.m_ColorAlphaAttr = ColorAlphaAttr; *VertElemArray++ = DeclColorAlpha; } if(VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_Normal) { const D3DVERTEXELEMENT9 DeclNormal = { VertElemStream, DeclOffs, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0 }; DeclOffs = DeclOffs + S3D_SYS_SIZEOFS(float) * 3; VertBufDesc.m_NormalAttr = NormalAttr; *VertElemArray++ = DeclNormal; } for(iTex = 0; iTex < TexSlotCnt; iTex++) { WORD TexOffs = S3D_SYS_SIZEOFS(float) * 2; D3DDECLTYPE TexType = D3DDECLTYPE_FLOAT2; D3DVERTEXELEMENT9 DeclTex; const s3d_CDrvDataTypeDesc *TexTypeDesc = TexTypeDescArray[iTex]; if(TexTypeDesc == s3d_DrvDataGetTypeDesc()) { TexOffs = S3D_SYS_SIZEOFS(float) * 2; TexType = D3DDECLTYPE_FLOAT2; } else if(TexTypeDesc == s3d_DrvDataGetTypeDesc()) { TexOffs = S3D_SYS_SIZEOFS(float); TexType = D3DDECLTYPE_FLOAT1; } else if(TexTypeDesc == s3d_DrvDataGetTypeDesc()) { TexOffs = S3D_SYS_SIZEOFS(float) * 3; TexType = D3DDECLTYPE_FLOAT3; } else if(TexTypeDesc == s3d_DrvDataGetTypeDesc()) { TexOffs = S3D_SYS_SIZEOFS(float) * 4; TexType = D3DDECLTYPE_FLOAT4; } else { S3D_SYS_ASSERT(0); } DeclTex.Stream = VertElemStream; DeclTex.Offset = DeclOffs; DeclTex.Type = TexType; DeclTex.Method = D3DDECLMETHOD_DEFAULT; DeclTex.Usage = D3DDECLUSAGE_TEXCOORD; DeclTex.UsageIndex = BYTE(iTex); DeclOffs += TexOffs; VertBufDesc.m_TexAttrArray[iTex] = TexAttrArray[iTex]; *VertElemArray++ = DeclTex; } const D3DVERTEXELEMENT9 DeclEnd = D3DDECL_END(); *VertElemArray = DeclEnd; VertBufDesc.m_VertElemCnt = Charge->m_AttrCnt + 1; //D3DDECL_END() VertBufDesc.m_VertSize = DeclOffs; VertBufDesc.m_VertBufFmtDecl = VertBufFmtDecl; } /////////////////////////////////////////////////////////////////////////////// s3d_CDrvD3d9IdxBufObjBatchPtr s3d_CDrvD3d9BufMgr::AllocIdxBufObj( const s3d_CDrvGfxCharge *Charge, D3DFORMAT Fmt, DWORD Usage, D3DPOOL Pool) { s3d_CSysIntps IdxCnt = Charge->m_Topol.m_IdxCnt; s3d_CSysIntps IdxBufSize = CalcSizeOfFmtCnt(Fmt, IdxCnt); s3d_CDrvD3d9IdxBuf IdxBuf; S3D_DRV_D3D9_CHECK( m_Env, m_D3dDev->CreateIndexBuffer( UINT(IdxBufSize), Usage, Fmt, Pool, &IdxBuf.EmptyRef(), 0)); if(!IdxBuf) return 0; D3DINDEXBUFFER_DESC IdxBufDesc; S3D_DRV_D3D9_CHECK(m_Env, IdxBuf->GetDesc(&IdxBufDesc)); s3d_CDrvD3d9IdxBufObjBatchPtr IdxBufObj = S3D_SYS_NEW s3d_CDrvD3d9IdxBufObjBatch; IdxBufObj->m_IdxBuf = IdxBuf; IdxBufObj->m_BufSize = IdxBufDesc.Size; IdxBufObj->m_Pool = IdxBufDesc.Pool; IdxBufObj->m_Usage = IdxBufDesc.Usage; IdxBufObj->m_Fmt = IdxBufDesc.Format; IdxBufObj->m_TopolSig = Charge->m_Topol.m_TopolSig; if(m_D3dParam->m_ReportBuf) { IdxBufObj->m_ReportMsgHandler = m_MsgHandler; s3d_CUtilMsg m; m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_buf.report_idxbuf_create"; m.m_StdTempl = "D3D: " "Creating new index buffer object addr=0x[1] size=[2]: " "'[3]'"; m.AddInfo(""); m.AddInfo(s3d_CUtilStrUtil::StrOfPtr(IdxBufObj)); m.AddInfo(s3d_CUtilStrUtil::StrOfIntps(IdxBufSize)); m.AddInfo(Charge->m_MainInfo); s3d_UtilMsgReportNote(m_MsgHandler, m); } int Prim = Charge->m_Topol.m_Prim; D3DPRIMITIVETYPE D3dPrim = D3DPT_POINTLIST; if(s3d_SysIsValidArrayIdx(Prim, S3D_SYS_ARRAYCNTS(drv_d3d9_PrimTable))) D3dPrim = drv_d3d9_PrimTable[Prim]; IdxBufObj->m_D3dPrim = D3dPrim; IdxBufObj->m_IdxCnt = IdxCnt; LoadIdxBuf(Charge, IdxBufObj, 0, 0, 0, false); return IdxBufObj; } void s3d_CDrvD3d9BufMgr::LoadIdxBuf( const s3d_CDrvGfxCharge *Charge, s3d_CDrvD3d9IdxBufObj *IdxBuf, s3d_CSysIntps DestIdxBase, s3d_CSysIntps VertOffset, s3d_CSysIntps IdxBase, bool Discard) { if(!Charge) return; if(!IdxBuf) return; LPDIRECT3DINDEXBUFFER9 D3dIdxBuf = IdxBuf->m_IdxBuf; if(!D3dIdxBuf) return; D3DFORMAT Fmt = IdxBuf->m_Fmt; s3d_CSysIntps IdxCnt = IdxBuf->m_IdxCnt; UINT LockSize = UINT(CalcSizeOfFmtCnt(Fmt, IdxCnt)); UINT LockOffs = UINT(CalcSizeOfFmtCnt(Fmt, DestIdxBase)); DWORD Flags = 0; if(Discard) Flags = D3DLOCK_DISCARD; void *LockTarget = 0; S3D_DRV_D3D9_CHECK( m_Env, D3dIdxBuf->Lock(LockOffs, LockSize, &LockTarget, Flags)); if(!LockTarget) return; s3d_CSysIntm *Target = reinterpret_cast(LockTarget); LoadIdxBufData( Charge, Fmt, Target, IdxCnt, DestIdxBase, VertOffset, IdxBase); S3D_DRV_D3D9_CHECK( m_Env, D3dIdxBuf->Unlock()); if(m_D3dParam->m_PreloadResources && IdxBuf->m_Pool == D3DPOOL_MANAGED) { S3D_DRV_D3D9_CALL(m_Env, D3dIdxBuf->PreLoad()); } } void s3d_CDrvD3d9BufMgr::LoadIdxBufData( const s3d_CDrvGfxCharge *Charge, D3DFORMAT Fmt, s3d_CSysIntm *Dest, s3d_CSysIntps IdxCnt, s3d_CSysIntps DestIdxBase, s3d_CSysIntps VertOffset, s3d_CSysIntps IdxBase) { const s3d_CSysInt32u *Data = s3d_DrvBankFetchArray( m_MsgHandler, Charge->m_MainInfo, "idx", Charge->m_Topol.m_IdxBank, Charge->m_Topol.m_IdxCnt); if(!Data) return; const s3d_CSysInt32u *EffData = Data + IdxBase; if(Fmt == D3DFMT_INDEX16) { s3d_CSysInt16u *Target = reinterpret_cast(Dest); if(VertOffset == 0) { s3d_CSysIntps iIdx; for(iIdx = 0; iIdx < IdxCnt; iIdx++) Target[iIdx] = EffData[iIdx]; } else { s3d_CSysIntps iIdx; for(iIdx = 0; iIdx < IdxCnt; iIdx++) Target[iIdx] = EffData[iIdx] - VertOffset; } } else if(Fmt == D3DFMT_INDEX32) { if(VertOffset == 0) s3d_SysMemcpy(Dest, EffData, IdxCnt << 2); else { s3d_CSysInt32u *Target = reinterpret_cast(Dest); s3d_CSysIntps iIdx; for(iIdx = 0; iIdx < IdxCnt; iIdx++) Target[iIdx] = EffData[iIdx] - VertOffset; } } else { s3d_CDrvDxError e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_buf.unknown_index_format"; e.m_StdTempl = "D3D: " "Unknown index buffer or index data format."; e.AddInfo(Charge->m_MainInfo); s3d_UtilMsgReportFatal(m_MsgHandler, e); } } D3DFORMAT s3d_CDrvD3d9BufMgr::CalcIdxBufFmtOfCnt( const s3d_CSysChar *Info, s3d_CSysIntps Cnt, bool Prefer32) { D3DFORMAT IdxBufFmt = D3DFMT_INDEX16; if(Cnt > m_VertIdxLimit) { s3d_CDrvD3d9Error e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_buf.max_index_cnt"; e.m_StdTempl = "D3D error: " "Vertex count [1] exceeds maximum [2]."; e.AddInfo(Info); e.AddInfo(s3d_CUtilStrUtil::StrOfIntps(Cnt)); e.AddInfo(s3d_CUtilStrUtil::StrOfIntps(m_VertIdxLimit)); s3d_UtilMsgReportError(m_MsgHandler, e); Cnt = m_VertIdxLimit; } if(Cnt >= 0x10000) IdxBufFmt = D3DFMT_INDEX32; else if(Prefer32 && m_VertIdxLimit > 0x10000) IdxBufFmt = D3DFMT_INDEX32; return IdxBufFmt; } s3d_CSysIntps s3d_CDrvD3d9BufMgr::CalcSizeOfFmtCnt( D3DFORMAT IndexBufFmt, s3d_CSysIntps Cnt) { s3d_CSysIntps BufSize = 0; if(IndexBufFmt == D3DFMT_INDEX16) BufSize = Cnt << 1; else if(IndexBufFmt == D3DFMT_INDEX32) BufSize = Cnt << 2; return BufSize; } s3d_CSysIntps s3d_CDrvD3d9BufMgr::CalcCntOfFmtSize( D3DFORMAT IndexBufFmt, s3d_CSysIntps Size) { s3d_CSysIntps Cnt = 0; if(IndexBufFmt == D3DFMT_INDEX16) Cnt = Size >> 1; else if(IndexBufFmt == D3DFMT_INDEX32) Cnt = Size >> 2; return Cnt; } void s3d_CDrvD3d9BufMgr::CheckAllocDummyBuffers( const s3d_CDrvGfxCharge* Charge, int VertBufFmtDecl, bool SWVertProc) { DWORD Usage = D3DUSAGE_WRITEONLY; if(SWVertProc) Usage |= D3DUSAGE_SOFTWAREPROCESSING; D3DPOOL Pool = D3DPOOL_MANAGED; if((VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_DummyBoneWgh) || (VertBufFmtDecl & s3d_CDrvD3d9VertBufDesc::Decl_DummyBoneSubscr)) { if(!m_VertBufDummyWghIdx.m_VertBuf) { CreateDummyVertBuf(Usage, Pool); if(m_D3dParam->m_ReportBuf) { s3d_CUtilMsg m; m.m_Code = "drv/imp/directx/d3d9/drv_d3d9_buf." "report_vertbuf_dummyblendwghidx"; m.m_StdTempl = "D3D: " "Allocating dummy blend weight/ idx vertex buffer object " "size=[2]: '[3]'"; m.AddInfo(""); m.AddInfo(s3d_CUtilStrUtil::StrOfIntps( m_VertBufDummyWghIdx.m_UsedSize)); m.AddInfo(Charge->m_MainInfo); s3d_UtilMsgReportNote(m_MsgHandler, m); } } } } void s3d_CDrvD3d9BufMgr::CreateDummyVertBuf( DWORD Usage, D3DPOOL Pool) { UINT AllocSize = S3D_SYS_SIZEOFU(DWORD) * 4; // wgh+idx s3d_CDrvD3d9VertBuf VertBuf; S3D_DRV_D3D9_CHECK( m_Env, m_D3dDev->CreateVertexBuffer( AllocSize, Usage, 0, Pool, &VertBuf.EmptyRef(), 0)); LPVOID RawDest = 0; if(VertBuf) { S3D_DRV_D3D9_CHECK( m_Env, VertBuf->Lock( 0, AllocSize, &RawDest, 0)); } if(RawDest) { s3d_CDrvInt32uX4 *Dest = reinterpret_cast(RawDest); Dest->m_x = 0; Dest->m_y = 0; Dest->m_z = 0; Dest->m_w = 0x03020100; S3D_DRV_D3D9_CHECK( m_Env, VertBuf->Unlock()); m_VertBufDummyWghIdx.m_VertBuf = VertBuf; m_VertBufDummyWghIdx.m_UsedSize = AllocSize; if(m_D3dParam->m_PreloadResources && Pool == D3DPOOL_MANAGED) { S3D_DRV_D3D9_CALL(m_Env, VertBuf->PreLoad()); } } } void s3d_CDrvD3d9BufMgr::Reset() { m_VertBufTree.ExtractAll(); m_VertDeclMap.Reset(); m_IdxBufTree.ExtractAll(); m_VertBufDummyWghIdx.Reset(); FreeDynBuffers(); } void s3d_CDrvD3d9BufMgr::FreeDynBuffers() { if(m_VertBufDyn) m_VertBufDyn->Reset(); if(m_IdxBufDyn) m_IdxBufDyn->Reset(); m_VertBufDyn = 0; m_IdxBufDyn = 0; } /////////////////////////////////////////////////////////////////////////////// void s3d_CDrvD3d9BufInitUtil::InitFloatX2ToFloat32X2( s3d_CSysIntm *pDest, s3d_CSysIntps VertexSize, const s3d_CSysIntm *pSrc, s3d_CSysIntps Cnt, s3d_CSysIntps Stride) { s3d_CSysIntps Rest; for(Rest = Cnt; Rest > 0; Rest--) { const float *pDataSrc = reinterpret_cast(pSrc); s3d_CSysFloat32 *pDataDest = reinterpret_cast(pDest); pDataDest[0] = pDataSrc[0]; pDataDest[1] = pDataSrc[1]; pSrc += Stride; pDest += VertexSize; } } void s3d_CDrvD3d9BufInitUtil::InitFloatX3ToFloat32X3( s3d_CSysIntm *pDest, s3d_CSysIntps VertexSize, const s3d_CSysIntm *pSrc, s3d_CSysIntps Cnt, s3d_CSysIntps Stride) { s3d_CSysIntps Rest; for(Rest = Cnt; Rest > 0; Rest--) { const float *pDataSrc = reinterpret_cast(pSrc); s3d_CSysFloat32 *pDataDest = reinterpret_cast(pDest); pDataDest[0] = pDataSrc[0]; pDataDest[1] = pDataSrc[1]; pDataDest[2] = pDataSrc[2]; pSrc += Stride; pDest += VertexSize; } } void s3d_CDrvD3d9BufInitUtil::InitFloatX4ToFloat32X4( s3d_CSysIntm *pDest, s3d_CSysIntps VertexSize, const s3d_CSysIntm *pSrc, s3d_CSysIntps Cnt, s3d_CSysIntps Stride) { s3d_CSysIntps Rest; for(Rest = Cnt; Rest > 0; Rest--) { const float *pDataSrc = reinterpret_cast(pSrc); s3d_CSysFloat32 *pDataDest = reinterpret_cast(pDest); pDataDest[0] = pDataSrc[0]; pDataDest[1] = pDataSrc[1]; pDataDest[2] = pDataSrc[2]; pDataDest[3] = pDataSrc[3]; pSrc += Stride; pDest += VertexSize; } } void s3d_CDrvD3d9BufInitUtil::InitFloatX3ToColor( s3d_CSysIntm *pDest, s3d_CSysIntps VertexSize, const s3d_CSysIntm *pSrc, s3d_CSysIntps Cnt, s3d_CSysIntps Stride) { s3d_CSysIntps Rest; for(Rest = Cnt; Rest > 0; Rest--) { const float *pDataSrc = reinterpret_cast(pSrc); LPDWORD pDataDest = reinterpret_cast(pDest); float ColR = pDataSrc[0]; float ColG = pDataSrc[1]; float ColB = pDataSrc[2]; float Alpha = 1; *pDataDest = S3D_DRV_D3D9_UTIL_COLORVALUE(ColR, ColG, ColB, Alpha); pSrc += Stride; pDest += VertexSize; } } void s3d_CDrvD3d9BufInitUtil::InitFloatX4ToColor( s3d_CSysIntm *pDest, s3d_CSysIntps VertexSize, const s3d_CSysIntm *pSrc, s3d_CSysIntps Cnt, s3d_CSysIntps Stride) { s3d_CSysIntps Rest; for(Rest = Cnt; Rest > 0; Rest--) { const float *pDataSrc = reinterpret_cast(pSrc); LPDWORD pDataDest = reinterpret_cast(pDest); float ColR = pDataSrc[0]; float ColG = pDataSrc[1]; float ColB = pDataSrc[2]; float Alpha = pDataSrc[3]; *pDataDest = S3D_DRV_D3D9_UTIL_COLORVALUE(ColR, ColG, ColB, Alpha); pSrc += Stride; pDest += VertexSize; } } void s3d_CDrvD3d9BufInitUtil::InitIntX4ToInt8uX4( s3d_CSysIntm *pDest, s3d_CSysIntps VertexSize, const s3d_CSysIntm *pSrc, s3d_CSysIntps Cnt, s3d_CSysIntps Stride) { s3d_CSysIntps Rest; for(Rest = Cnt; Rest > 0; Rest--) { const int *pDataSrc = reinterpret_cast(pSrc); s3d_CSysInt8u *pDataDest = reinterpret_cast(pDest); pDataDest[0] = (pDataSrc[0] & 0xFF); pDataDest[1] = (pDataSrc[1] & 0xFF); pDataDest[2] = (pDataSrc[2] & 0xFF); pDataDest[3] = (pDataSrc[3] & 0xFF); pSrc += Stride; pDest += VertexSize; } } void s3d_CDrvD3d9BufInitUtil::InitFloatX3ToInt8uX4( s3d_CSysIntm *pDest, s3d_CSysIntps VertexSize, const s3d_CSysIntm *pSrc, s3d_CSysIntps Cnt, s3d_CSysIntps Stride) { s3d_CSysIntps Rest; for(Rest = Cnt; Rest > 0; Rest--) { const float *pDataSrc = reinterpret_cast(pSrc); s3d_CSysInt8u *pDataDest = reinterpret_cast(pDest); pDataDest[0] = s3d_SysIntOfFloatCoarse(pDataSrc[0] * 127.5f + 127.5f); pDataDest[1] = s3d_SysIntOfFloatCoarse(pDataSrc[1] * 127.5f + 127.5f); pDataDest[2] = s3d_SysIntOfFloatCoarse(pDataSrc[2] * 127.5f + 127.5f); pDataDest[3] = 0; pSrc += Stride; pDest += VertexSize; } } void s3d_CDrvD3d9BufInitUtil::InitFloatX4ToInt8uX4( s3d_CSysIntm *pDest, s3d_CSysIntps VertexSize, const s3d_CSysIntm *pSrc, s3d_CSysIntps Cnt, s3d_CSysIntps Stride) { s3d_CSysIntps Rest; for(Rest = Cnt; Rest > 0; Rest--) { const float *pDataSrc = reinterpret_cast(pSrc); s3d_CSysInt8u *pDataDest = reinterpret_cast(pDest); pDataDest[0] = s3d_SysIntOfFloatCoarse(pDataSrc[0] * 255.0f); pDataDest[1] = s3d_SysIntOfFloatCoarse(pDataSrc[1] * 255.0f); pDataDest[2] = s3d_SysIntOfFloatCoarse(pDataSrc[2] * 255.0f); pDataDest[3] = s3d_SysIntOfFloatCoarse(pDataSrc[3] * 255.0f); pSrc += Stride; pDest += VertexSize; } } void s3d_CDrvD3d9BufInitUtil::VertFormatError( s3d_CUtilMsgHandler *MsgHandler, const s3d_CDrvGfxCharge *Charge) { s3d_CDrvDxError e; e.m_Code = "drv/imp/directx/d3d9/drv_d3d9_buf.illegal_vertex_format"; e.m_StdTempl = "D3D driver: Illegal vertex format."; e.AddInfo(s3d_CDrvGfxCharge::GetMainInfoOf(Charge)); s3d_UtilMsgReportFatal(MsgHandler, e); } ///////////////////////////////////////////////////////////////////////////////