You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Code/CryEngine/RenderDll/XRenderD3D9/D3DRenderAuxGeom.h

484 lines
14 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
// Original file Copyright Crytek GMBH or its affiliates, used under license.
#ifndef CRYINCLUDE_CRYENGINE_RENDERDLL_XRENDERD3D9_D3DRENDERAUXGEOM_H
#define CRYINCLUDE_CRYENGINE_RENDERDLL_XRENDERD3D9_D3DRENDERAUXGEOM_H
#pragma once
#include <RenderDll/Common/RenderAuxGeom.h>
#if defined(ENABLE_RENDER_AUX_GEOM)
class CD3D9Renderer;
class ICrySizer;
class CRenderAuxGeomD3D
: public IRenderAuxGeomImpl
{
public:
virtual void Flush(SAuxGeomCBRawDataPackaged& data, size_t begin, size_t end, bool reset = false);
virtual void RT_Flush(SAuxGeomCBRawDataPackaged& data, size_t begin, size_t end, bool reset = false);
virtual void FlushTextMessages(CTextMessages& tMessages, bool reset);
void Process();
public:
static CRenderAuxGeomD3D* Create(CD3D9Renderer& renderer)
{
return(new CRenderAuxGeomD3D(renderer));
}
public:
~CRenderAuxGeomD3D();
void FreeMemory();
CAuxGeomCB* GetRenderAuxGeom(void* jobID = 0);
int GetDeviceDataSize();
void ReleaseDeviceObjects();
HRESULT RestoreDeviceObjects();
void SetOrthoMode(bool enable, Matrix44A* pMatrix = 0);
void GetMemoryUsage(ICrySizer* pSizer) const;
void ReleaseShader() { SAFE_RELEASE_FORCE(m_pAuxGeomShader); }
void* operator new(size_t s)
{
uint8* p = (uint8*) CryModuleMalloc(s + 16 + 8);
memset(p, 0, s + 16 + 8);
uint8* pRet = (uint8*) ((size_t) (p + 16 + 8) & ~0xF);
((uint8**) pRet)[-1] = p;
return pRet;
}
void operator delete(void* p)
{
CryModuleFree(((uint8**)p)[-1]);
}
private:
struct SStreamBufferManager
{
public:
SStreamBufferManager();
void Reset();
void DiscardVB();
void DiscardIB();
public:
bool m_discardVB;
uint32 m_curVBIndex;
bool m_discardIB;
uint32 m_curIBIndex;
};
struct SDrawObjMesh
{
SDrawObjMesh()
: m_numVertices(0)
, m_numFaces(0)
, m_pVB(0)
, m_pIB(0)
{
}
~SDrawObjMesh()
{
Release();
}
void Release();
int GetDeviceDataSize()
{
int nSize = 0;
nSize += _VertBufferSize(m_pVB);
nSize += _IndexBufferSize(m_pIB);
return nSize;
}
uint32 m_numVertices;
uint32 m_numFaces;
D3DBuffer* m_pVB;
D3DBuffer* m_pIB;
};
enum EAuxObjNumLOD
{
e_auxObjNumLOD = 5
};
struct SMatrices
{
SMatrices()
: m_pCurTransMat(0)
{
m_matView.SetIdentity();
m_matViewInv.SetIdentity();
m_matProj.SetIdentity();
m_matTrans3D.SetIdentity();
m_matTrans2D = Matrix44A(2, 0, 0, 0,
0, -2, 0, 0,
0, 0, 1, 0,
-1, 1, 0, 1);
}
void UpdateMatrices(CD3D9Renderer& renderer);
Matrix44A m_matView;
Matrix44A m_matViewInv;
Matrix44A m_matProj;
Matrix44A m_matTrans3D;
Matrix44A m_matTrans2D;
const Matrix44A* m_pCurTransMat;
};
class CAuxGeomCBCollector
{
class SThread;
typedef std::map<threadID, SThread*> AUXThreadMap;
typedef std::vector<SThread*> AUXThreads;
typedef std::vector<CAuxGeomCB*> AUXJobs;
class SThread
{
typedef std::map<void*, CAuxGeomCB*> AUXJobMap;
CAuxGeomCB* m_cbCurrent;
AUXJobMap m_auxJobMap;
mutable CryRWLock m_rwlLocal;
public:
SThread()
: m_cbCurrent() {}
CAuxGeomCB* Get(IRenderAuxGeomImpl* pRenderAuxGeomImpl, void* jobID, threadID tid)
{
if (jobID == 0 && m_cbCurrent)
{
return m_cbCurrent;
}
m_rwlLocal.RLock();
AUXJobMap::const_iterator it = m_auxJobMap.find(jobID);
CAuxGeomCB* pAuxGeomCB = m_auxJobMap.end() != it ? it->second : 0;
m_rwlLocal.RUnlock();
if (!pAuxGeomCB)
{
threadID mainThreadID, renderThreadID;
gRenDev->GetThreadIDs(mainThreadID, renderThreadID);
if (tid == renderThreadID)
{
pAuxGeomCB = new CAuxGeomCB(pRenderAuxGeomImpl);
}
else if (tid == mainThreadID)
{
pAuxGeomCB = new CAuxGeomCBMainThread(pRenderAuxGeomImpl);
}
else
{
pAuxGeomCB = new CAuxGeomCBWorkerThread(pRenderAuxGeomImpl);
}
m_rwlLocal.WLock();
m_auxJobMap.insert(AUXJobMap::value_type(jobID, pAuxGeomCB));
m_rwlLocal.WUnlock();
}
return pAuxGeomCB;
}
~SThread()
{
for (AUXJobMap::iterator cbit = m_auxJobMap.begin(); cbit != m_auxJobMap.end(); ++cbit)
{
delete cbit->second;
}
}
void Process(AUXJobs& auxJobs)
{
m_rwlLocal.RLock();
for (SThread::AUXJobMap::const_iterator job = m_auxJobMap.begin(); job != m_auxJobMap.end(); ++job)
{
auxJobs.push_back(job->second);
}
m_rwlLocal.RUnlock();
}
void FreeMemory()
{
m_rwlLocal.WLock();
for (AUXJobMap::const_iterator job = m_auxJobMap.begin(); job != m_auxJobMap.end(); ++job)
{
// MUST BE called after final CAuxGeomCB::Commit()
// adding data (issuing render commands) is not thread safe !!!
job->second->FreeMemory();
}
m_rwlLocal.WUnlock();
}
void GetMemoryUsage(ICrySizer* pSizer) const
{
m_rwlLocal.RLock();
for (AUXJobMap::const_iterator job = m_auxJobMap.begin(); job != m_auxJobMap.end(); ++job)
{
// MUST BE called after final CAuxGeomCB::Commit()
// adding data (issuing render commands) is not thread safe !!!
job->second->GetMemoryUsage(pSizer);
}
m_rwlLocal.RUnlock();
}
};
AUXThreadMap m_auxThreadMap;
AUXThreads m_tmpThreads;
AUXJobs m_tmpJobs;
mutable CryRWLock m_rwGlobal;
public:
~CAuxGeomCBCollector()
{
for (AUXThreadMap::iterator cbit = m_auxThreadMap.begin(); cbit != m_auxThreadMap.end(); ++cbit)
{
delete cbit->second;
}
}
CAuxGeomCB* Get(IRenderAuxGeomImpl* pRenderAuxGeomImpl, void* jobID)
{
threadID tid = CryGetCurrentThreadId();
m_rwGlobal.RLock();
AUXThreadMap::const_iterator it = m_auxThreadMap.find(tid);
SThread* auxThread = m_auxThreadMap.end() != it ? it->second : 0;
m_rwGlobal.RUnlock();
if (!auxThread)
{
auxThread = new SThread;
m_rwGlobal.WLock();
m_auxThreadMap.insert(AUXThreadMap::value_type(tid, auxThread));
m_rwGlobal.WUnlock();
}
return auxThread->Get(pRenderAuxGeomImpl, jobID, tid);
}
void FreeMemory()
{
m_rwGlobal.WLock();
for (AUXThreadMap::const_iterator cbit = m_auxThreadMap.begin(); cbit != m_auxThreadMap.end(); ++cbit)
{
cbit->second->FreeMemory();
}
m_rwGlobal.WUnlock();
}
void Process()
{
m_rwGlobal.RLock();
for (AUXThreadMap::const_iterator it = m_auxThreadMap.begin(); it != m_auxThreadMap.end(); ++it)
{
m_tmpThreads.push_back(it->second);
}
m_rwGlobal.RUnlock();
for (AUXThreads::iterator it = m_tmpThreads.begin(); it != m_tmpThreads.end(); ++it)
{
(*it)->Process(m_tmpJobs);
}
for (AUXJobs::iterator job = m_tmpJobs.begin(); job != m_tmpJobs.end(); ++job)
{
(*job)->Process();
}
m_tmpThreads.clear();
m_tmpJobs.clear();
}
void GetMemoryUsage(ICrySizer* pSizer) const
{
m_rwGlobal.RLock();
for (AUXThreadMap::const_iterator it = m_auxThreadMap.begin(); it != m_auxThreadMap.end(); ++it)
{
it->second->GetMemoryUsage(pSizer);
}
m_rwGlobal.RUnlock();
}
};
private:
CRenderAuxGeomD3D(CD3D9Renderer& renderer);
void DetermineAuxPrimitveFlags(uint32& d3dNumPrimDivider, eRenderPrimitiveType& d3dPrim, CAuxGeomCB::EPrimType primType) const;
void DrawAuxPrimitives(CAuxGeomCB::AuxSortedPushBuffer::const_iterator itBegin, CAuxGeomCB::AuxSortedPushBuffer::const_iterator itEnd, const CAuxGeomCB::EPrimType& primType);
void DrawAuxIndexedPrimitives(CAuxGeomCB::AuxSortedPushBuffer::const_iterator itBegin, CAuxGeomCB::AuxSortedPushBuffer::const_iterator itEnd, const CAuxGeomCB::EPrimType& primType);
void DrawAuxObjects(CAuxGeomCB::AuxSortedPushBuffer::const_iterator itBegin, CAuxGeomCB::AuxSortedPushBuffer::const_iterator itEnd);
void PrepareThickLines2D(CAuxGeomCB::AuxSortedPushBuffer::const_iterator itBegin, CAuxGeomCB::AuxSortedPushBuffer::const_iterator itEnd);
void PrepareThickLines3D(CAuxGeomCB::AuxSortedPushBuffer::const_iterator itBegin, CAuxGeomCB::AuxSortedPushBuffer::const_iterator itEnd);
void PrepareRendering();
void SetShader(const SAuxGeomRenderFlags& renderFlags);
void AdjustRenderStates(const SAuxGeomRenderFlags& renderFlags);
bool BindStreams(const AZ::Vertex::Format& newVertexFormat, ID3D11Buffer* pNewVB, ID3D11Buffer* pNewIB);
template< typename TMeshFunc >
HRESULT CreateMesh(SDrawObjMesh& mesh, TMeshFunc meshFunc);
const Matrix44A& GetCurrentView() const;
const Matrix44A& GetCurrentViewInv() const;
const Matrix44A& GetCurrentProj() const;
const Matrix44A& GetCurrentTrans3D() const;
const Matrix44A& GetCurrentTrans2D() const;
bool IsOrthoMode() const;
const CAuxGeomCB::AuxVertexBuffer& GetAuxVertexBuffer() const;
const CAuxGeomCB::AuxIndexBuffer& GetAuxIndexBuffer() const;
const CAuxGeomCB::AuxDrawObjParamBuffer& GetAuxDrawObjParamBuffer() const;
const Matrix44A& GetAuxOrthoMatrix(int idx) const;
private:
CD3D9Renderer& m_renderer;
D3DBuffer* m_pAuxGeomVB;
D3DBuffer* m_pAuxGeomIB;
D3DBuffer* m_pCurVB;
D3DBuffer* m_pCurIB;
SStreamBufferManager m_auxGeomSBM;
uint32 m_wndXRes;
uint32 m_wndYRes;
float m_aspect;
float m_aspectInv;
SMatrices m_matrices;
CAuxGeomCB::EPrimType m_curPrimType;
uint8 m_curPointSize;
int m_curTransMatrixIdx;
CShader* m_pAuxGeomShader;
EAuxGeomPublicRenderflags_DrawInFrontMode m_curDrawInFrontMode;
CAuxGeomCB::AuxSortedPushBuffer m_auxSortedPushBuffer;
const CAuxGeomCB::SAuxGeomCBRawData* m_pCurCBRawData;
CAuxGeomCBCollector m_auxGeomCBCol;
int CV_r_auxGeom;
SDrawObjMesh m_sphereObj[ e_auxObjNumLOD ];
SDrawObjMesh m_diskObj[ e_auxObjNumLOD ];
SDrawObjMesh m_quadObj[ e_auxObjNumLOD ];
SDrawObjMesh m_coneObj[ e_auxObjNumLOD ];
SDrawObjMesh m_cylinderObj[ e_auxObjNumLOD ];
AZ::Vertex::Format m_auxGeomPrimitiveVertexFormat = eVF_P3F_C4B_T2F;
AZ::Vertex::Format m_auxGeomObjectVertexFormat = eVF_P3F_T3F;
};
inline
CRenderAuxGeomD3D::SStreamBufferManager::SStreamBufferManager()
: m_discardVB(true)
, m_curVBIndex(0)
, m_discardIB(true)
, m_curIBIndex(0)
{
}
inline void
CRenderAuxGeomD3D::SStreamBufferManager::Reset()
{
m_discardVB = true;
m_curVBIndex = 0;
m_discardIB = true;
m_curIBIndex = 0;
}
inline void
CRenderAuxGeomD3D::SStreamBufferManager::DiscardVB()
{
m_discardVB = true;
m_curVBIndex = 0;
}
inline void
CRenderAuxGeomD3D::SStreamBufferManager::DiscardIB()
{
m_discardIB = true;
m_curIBIndex = 0;
}
inline void CRenderAuxGeomD3D::DetermineAuxPrimitveFlags(uint32& d3dNumPrimDivider, eRenderPrimitiveType& ePrimType, CAuxGeomCB::EPrimType primType) const
{
switch (primType)
{
case CAuxGeomCB::e_PtList:
{
d3dNumPrimDivider = 1;
ePrimType = eptPointList;
break;
}
case CAuxGeomCB::e_LineList:
case CAuxGeomCB::e_LineListInd:
{
d3dNumPrimDivider = 2;
ePrimType = eptLineList;
break;
}
case CAuxGeomCB::e_TriList:
case CAuxGeomCB::e_TriListInd:
default:
{
d3dNumPrimDivider = 3;
ePrimType = eptTriangleList;
break;
}
}
}
#endif // #if defined(ENABLE_RENDER_AUX_GEOM)
#endif // D3D_RENDER_AUX_GEOM_H