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.
284 lines
9.2 KiB
C++
284 lines
9.2 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.
|
|
|
|
// Description : Manages geometry cache instances and streaming
|
|
|
|
|
|
#ifndef CRYINCLUDE_CRY3DENGINE_GEOMCACHEMANAGER_H
|
|
#define CRYINCLUDE_CRY3DENGINE_GEOMCACHEMANAGER_H
|
|
#pragma once
|
|
|
|
#if defined(USE_GEOM_CACHES)
|
|
|
|
#include "GeomCacheDecoder.h"
|
|
#include "GeomCacheMeshManager.h"
|
|
#include <AzFramework/Asset/AssetCatalogBus.h>
|
|
|
|
#include <AzCore/Jobs/LegacyJobExecutor.h>
|
|
|
|
class CGeomCache;
|
|
class CGeomCacheRenderNode;
|
|
|
|
struct SGeomCacheStreamInfo;
|
|
|
|
struct SGeomCacheBufferHandle
|
|
{
|
|
SGeomCacheBufferHandle()
|
|
{
|
|
m_pNext = NULL;
|
|
m_startFrame = 0;
|
|
m_endFrame = 0;
|
|
m_bufferSize = 0;
|
|
m_pBuffer = NULL;
|
|
m_pStream = NULL;
|
|
m_numJobReferences = 0;
|
|
}
|
|
|
|
volatile int m_numJobReferences;
|
|
uint32 m_bufferSize;
|
|
uint32 m_startFrame;
|
|
uint32 m_endFrame;
|
|
char* m_pBuffer;
|
|
|
|
SGeomCacheStreamInfo* m_pStream;
|
|
CTimeValue m_frameTime;
|
|
|
|
// Next buffer handle for this stream or in the free list
|
|
SGeomCacheBufferHandle* m_pNext;
|
|
|
|
CryConditionVariable m_jobReferencesCV;
|
|
};
|
|
|
|
// This handle represents a block in the read buffer
|
|
struct SGeomCacheReadRequestHandle
|
|
: public SGeomCacheBufferHandle
|
|
, public IStreamCallback
|
|
{
|
|
// IStreamCallback
|
|
virtual void StreamOnComplete([[maybe_unused]] IReadStream* pStream, [[maybe_unused]] unsigned nError) {}
|
|
virtual void StreamAsyncOnComplete(IReadStream* pStream, unsigned nError)
|
|
{
|
|
if (nError != 0 && nError != ERROR_USER_ABORT)
|
|
{
|
|
string error = "Geom cache read request failed with error: " + string(pStream->GetErrorName());
|
|
gEnv->pLog->LogError("%s", error.c_str());
|
|
}
|
|
|
|
m_state = eRRHS_FinishedRead;
|
|
m_error = nError;
|
|
|
|
if (CryInterlockedDecrement(&m_numJobReferences) == 0)
|
|
{
|
|
m_jobReferencesCV.Notify();
|
|
}
|
|
}
|
|
|
|
enum EReadRequestHandleState
|
|
{
|
|
eRRHS_Reading = 0,
|
|
eRRHS_FinishedRead = 1,
|
|
eRRHS_Decompressing = 2,
|
|
eRRHS_Done = 3
|
|
};
|
|
|
|
volatile EReadRequestHandleState m_state;
|
|
volatile long m_error;
|
|
IReadStreamPtr m_pReadStream;
|
|
};
|
|
|
|
struct SGeomCacheStreamInfo
|
|
{
|
|
SGeomCacheStreamInfo(CGeomCacheRenderNode* pRenderNode, CGeomCache* pGeomCache, const uint numFrames)
|
|
: m_pRenderNode(pRenderNode)
|
|
, m_pGeomCache(pGeomCache)
|
|
, m_numFrames(numFrames)
|
|
, m_displayedFrameTime(-1.0f)
|
|
, m_wantedPlaybackTime(0.0f)
|
|
, m_wantedFloorFrame(0)
|
|
, m_wantedCeilFrame(0)
|
|
, m_sameFrameFillCount(0)
|
|
, m_numFramesMissed(0)
|
|
, m_pOldestReadRequestHandle(NULL)
|
|
, m_pNewestReadRequestHandle(NULL)
|
|
, m_pReadAbortListHead(NULL)
|
|
, m_pOldestDecompressHandle(NULL)
|
|
, m_pNewestDecompressHandle(NULL)
|
|
, m_pDecompressAbortListHead(NULL)
|
|
, m_bAbort(0L)
|
|
, m_bLooping(false)
|
|
{}
|
|
|
|
CGeomCacheRenderNode* m_pRenderNode;
|
|
CGeomCache* m_pGeomCache;
|
|
|
|
uint m_numFrames;
|
|
|
|
volatile float m_displayedFrameTime;
|
|
volatile float m_wantedPlaybackTime;
|
|
volatile uint m_wantedFloorFrame;
|
|
volatile uint m_wantedCeilFrame;
|
|
volatile int m_sameFrameFillCount;
|
|
|
|
uint m_numFramesMissed;
|
|
|
|
SGeomCacheReadRequestHandle* m_pOldestReadRequestHandle;
|
|
SGeomCacheReadRequestHandle* m_pNewestReadRequestHandle;
|
|
SGeomCacheReadRequestHandle* m_pReadAbortListHead;
|
|
|
|
SGeomCacheBufferHandle* m_pOldestDecompressHandle;
|
|
SGeomCacheBufferHandle* m_pNewestDecompressHandle;
|
|
SGeomCacheBufferHandle* m_pDecompressAbortListHead;
|
|
|
|
volatile bool m_bAbort;
|
|
CryCriticalSection m_abortCS;
|
|
|
|
bool m_bLooping;
|
|
|
|
AZ::LegacyJobExecutor m_fillRenderNodeJobExecutor;
|
|
|
|
struct SFrameData
|
|
{
|
|
bool m_bDecompressJobLaunched;
|
|
|
|
// For each frame we initialize a counter to the number of jobs
|
|
// that need to complete before the frame can be decoded.
|
|
//
|
|
// Each index frame has exactly one dependent job (inflate)
|
|
// The first B frame after an index frame has three dependencies (inflate + previous and last index frame)
|
|
// All other B frames have only two dependencies (inflate + previous B frame)
|
|
int m_decodeDependencyCounter;
|
|
|
|
// Pointer to decompress handle for this frame.
|
|
SGeomCacheBufferHandle* m_pDecompressHandle;
|
|
};
|
|
|
|
// Array with data for each frame
|
|
std::vector<SFrameData> m_frameData;
|
|
};
|
|
|
|
struct SDecodeFrameJobData
|
|
{
|
|
uint m_frameIndex;
|
|
const CGeomCache* m_pGeomCache;
|
|
SGeomCacheStreamInfo* m_pStreamInfo;
|
|
};
|
|
|
|
class CGeomCacheManager
|
|
: public Cry3DEngineBase
|
|
, public AzFramework::LegacyAssetEventBus::Handler
|
|
{
|
|
public:
|
|
CGeomCacheManager();
|
|
~CGeomCacheManager();
|
|
|
|
// Called during level unload to free all resource references
|
|
void Reset();
|
|
|
|
CGeomCache* LoadGeomCache(const char* szFileName);
|
|
void DeleteGeomCache(CGeomCache* pGeomCache);
|
|
|
|
void StreamingUpdate();
|
|
|
|
void RegisterForStreaming(CGeomCacheRenderNode* pRenderNode);
|
|
void UnRegisterForStreaming(CGeomCacheRenderNode* pRenderNode, bool bWaitForJobs);
|
|
|
|
float GetPrecachedTime(const IGeomCacheRenderNode* pRenderNode);
|
|
|
|
#ifndef _RELEASE
|
|
void DrawDebugInfo();
|
|
void ResetDebugInfo() { m_numMissedFrames = 0; m_numStreamAborts = 0; m_numFailedAllocs = 0; }
|
|
#endif
|
|
|
|
void DecompressFrame_JobEntry(SGeomCacheStreamInfo* pStreamInfo, const uint blockIndex,
|
|
SGeomCacheBufferHandle* pDecompressHandle, SGeomCacheReadRequestHandle* pReadRequestHandle);
|
|
|
|
void FillRenderNodeAsync_JobEntry(SGeomCacheStreamInfo* pStreamInfo);
|
|
|
|
void DecodeIFrame_JobEntry(SDecodeFrameJobData jobState);
|
|
void DecodeBFrame_JobEntry(SDecodeFrameJobData jobState);
|
|
|
|
CGeomCacheMeshManager& GetMeshManager() { return m_meshManager; }
|
|
|
|
void StopCacheStreamsAndWait(CGeomCache* pGeomCache);
|
|
|
|
CGeomCache* FindGeomCacheByFilename(const char* filename);
|
|
|
|
// For changing the buffer size on runtime. This will do a blocking wait on all active streams,
|
|
// so it should only be called when we are sure that no caches are playing (e.g. on level load)
|
|
void ChangeBufferSize(const uint newSizeInMiB);
|
|
|
|
private:
|
|
|
|
// override from LegacyAssetEventBus::Handler
|
|
void OnFileChanged(AZStd::string assetPath) override;
|
|
|
|
static void OnChangeBufferSize(ICVar* pCVar);
|
|
|
|
void ReinitializeStreamFrameData(SGeomCacheStreamInfo& streamInfo, uint startFrame, uint endFrame);
|
|
|
|
void UnloadGeomCaches();
|
|
|
|
bool IssueDiskReadRequest(SGeomCacheStreamInfo& pStreamInfo);
|
|
|
|
void LaunchStreamingJobs(const uint numStreams, const CTimeValue currentFrameTime);
|
|
void LaunchDecompressJobs(SGeomCacheStreamInfo* pStreamInfo, const CTimeValue currentFrameTime);
|
|
void LaunchDecodeJob(SDecodeFrameJobData jobState);
|
|
|
|
template<class TBufferHandleType>
|
|
TBufferHandleType* NewBufferHandle(const uint32 size, SGeomCacheStreamInfo& streamInfo);
|
|
SGeomCacheReadRequestHandle* NewReadRequestHandle(const uint32 size, SGeomCacheStreamInfo& streamInfo);
|
|
|
|
void RetireHandles(SGeomCacheStreamInfo& streamInfo);
|
|
void RetireOldestReadRequestHandle(SGeomCacheStreamInfo& streamInfo);
|
|
void RetireOldestDecompressHandle(SGeomCacheStreamInfo& streamInfo);
|
|
void RetireDecompressHandle(SGeomCacheStreamInfo& streamInfo, SGeomCacheBufferHandle* pHandle);
|
|
template<class TBufferHandleType>
|
|
void RetireBufferHandle(TBufferHandleType* pHandle);
|
|
|
|
void RetireRemovedStreams();
|
|
void ValidateStream(SGeomCacheStreamInfo& streamInfo);
|
|
void AbortStream(SGeomCacheStreamInfo& streamInfo);
|
|
void AbortStreamAndWait(SGeomCacheStreamInfo& streamInfo);
|
|
void RetireAbortedHandles(SGeomCacheStreamInfo& streamInfo);
|
|
|
|
SGeomCacheBufferHandle* GetFrameDecompressHandle(SGeomCacheStreamInfo* pStreamInfo, const uint frameIndex);
|
|
SGeomCacheFrameHeader* GetFrameDecompressHeader(SGeomCacheStreamInfo* pStreamInfo, const uint frameIndex);
|
|
char* GetFrameDecompressData(SGeomCacheStreamInfo* pStreamInfo, const uint frameIndex);
|
|
int* GetDependencyCounter(SGeomCacheStreamInfo* pStreamInfo, const uint frameIndex);
|
|
|
|
void* m_pPoolBaseAddress;
|
|
IGeneralMemoryHeap* m_pPool;
|
|
size_t m_poolSize;
|
|
|
|
uint m_lastRequestStream;
|
|
|
|
uint m_numMissedFrames;
|
|
uint m_numStreamAborts;
|
|
uint m_numErrorAborts;
|
|
uint m_numDecompressStreamAborts;
|
|
uint m_numReadStreamAborts;
|
|
uint m_numFailedAllocs;
|
|
|
|
typedef std::vector<SGeomCacheStreamInfo*>::iterator TStreamInfosIter;
|
|
std::vector<SGeomCacheStreamInfo*> m_streamInfos;
|
|
std::vector<SGeomCacheStreamInfo*> m_streamInfosAbortList;
|
|
|
|
typedef std::map<string, CGeomCache*, stl::less_stricmp<string> > TGeomCacheMap;
|
|
TGeomCacheMap m_nameToGeomCacheMap;
|
|
|
|
CGeomCacheMeshManager m_meshManager;
|
|
};
|
|
|
|
#endif
|
|
#endif // CRYINCLUDE_CRY3DENGINE_GEOMCACHEMANAGER_H
|