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/Common/FencedVB.h

150 lines
5.0 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.
#pragma once
///////////////////////////////////////////////////////////////////////////////
// Vertex Data container optmized for direct VideoMemory access on Consoles
// No driver overhead, the lock function returns a direct pointer into Video Memory
// which is used by the GPU
// *NOTE: The programmer has to ensure that the Video Memory is not overwritten
// while beeing used. For this the container provides additional fence and
// wait for fence functions. Also double buffering of the container could be needed
// *NOTE: On non console platforms, this container is using the driver facilities to ensure
// no memory is overwrite. This could mean additional memory allocated by the driver
template <class VertexType>
class FencedVB
{
public:
FencedVB(uint32 nVertexCount, uint32 nVertStride);
~FencedVB();
VertexType* LockVB(uint32 nLockCount);
void UnlockVB();
HRESULT Bind(uint32 StreamNumber = 0, int nBytesOffset = 0, int nStride = 0);
uint32 GetVertexCount() const;
void SetFence();
void WaitForFence();
private:
D3DBuffer* m_pVB;
uint32 m_nVertexCount;
VertexType* m_pLockedData;
uint32 m_nVertStride;
DeviceFenceHandle m_Fence;
};
///////////////////////////////////////////////////////////////////////////////
template <class VertexType>
FencedVB<VertexType>::FencedVB(uint32 nVertexCount, uint32 nVertStride)
: m_pVB(NULL)
, m_pLockedData(NULL)
, m_nVertStride(nVertStride)
, m_nVertexCount(nVertexCount)
{
HRESULT hr = gRenDev->m_DevMan.CreateDirectAccessBuffer(m_nVertexCount, m_nVertStride, CDeviceManager::BIND_VERTEX_BUFFER, (D3DBuffer**)&m_pVB);
CHECK_HRESULT(hr);
gRenDev->m_DevMan.CreateFence(m_Fence);
}
///////////////////////////////////////////////////////////////////////////////
template <class VertexType>
FencedVB<VertexType>::~FencedVB()
{
UnlockVB();
if (m_pVB)
{
gRenDev->m_DevMan.DestroyDirectAccessBuffer((D3DBuffer*)m_pVB);
}
gRenDev->m_DevMan.ReleaseFence(m_Fence);
}
///////////////////////////////////////////////////////////////////////////////
template <class VertexType>
VertexType* FencedVB<VertexType>::LockVB([[maybe_unused]] uint32 nLockCount)
{
// Ensure there is enough space in the VB for this data
assert (nLockCount <= m_nVertexCount);
if (m_pLockedData)
{
return m_pLockedData;
}
if (m_pVB)
{
gRenDev->m_DevMan.LockDirectAccessBuffer((D3DBuffer*)m_pVB, CDeviceManager::BIND_VERTEX_BUFFER, (void**)&m_pLockedData);
}
return m_pLockedData;
}
///////////////////////////////////////////////////////////////////////////////
template <class VertexType>
void FencedVB<VertexType>::UnlockVB()
{
if (m_pLockedData && m_pVB)
{
gRenDev->m_DevMan.UnlockDirectAccessBuffer((D3DBuffer*)m_pVB, CDeviceManager::BIND_VERTEX_BUFFER);
#if defined(AZ_RESTRICTED_PLATFORM)
#include AZ_RESTRICTED_FILE(FencedVB_h)
#endif
#if defined(AZ_RESTRICTED_SECTION_IMPLEMENTED)
#undef AZ_RESTRICTED_SECTION_IMPLEMENTED
# else
CDeviceManager::InvalidateCpuCache(m_pLockedData, 0, m_nVertexCount * m_nVertStride);
CDeviceManager::InvalidateGpuCache((D3DBuffer*)m_pVB, m_pLockedData, 0, m_nVertexCount * m_nVertStride);
# endif
m_pLockedData = NULL;
}
}
///////////////////////////////////////////////////////////////////////////////
template <class VertexType>
HRESULT FencedVB<VertexType>::Bind(uint32 StreamNumber, int nBytesOffset, int nStride)
{
HRESULT h = gcpRendD3D->FX_SetVStream(StreamNumber, m_pVB, nBytesOffset, nStride == 0 ? m_nVertStride : nStride);
CHECK_HRESULT(h);
return h;
}
///////////////////////////////////////////////////////////////////////////////
template <class VertexType>
uint32 FencedVB<VertexType>::GetVertexCount() const
{
return m_nVertexCount;
}
///////////////////////////////////////////////////////////////////////////////
template <class VertexType>
void FencedVB<VertexType>::SetFence()
{
#if BUFFER_ENABLE_DIRECT_ACCESS == 1
gRenDev->m_DevMan.IssueFence(m_Fence);
#endif
}
///////////////////////////////////////////////////////////////////////////////
template <class VertexType>
void FencedVB<VertexType>::WaitForFence()
{
#if BUFFER_ENABLE_DIRECT_ACCESS == 1
gRenDev->m_DevMan.SyncFence(m_Fence, true, false);
#endif
}