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/Cry3DEngine/GeomCacheManager.h

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