/* * 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 #include #include #include #include #include #include #include #include #include #include #include #include #include #include "IRenderer.h"//Because IShader.h won't compile without this. #include "IShader.h" #include "IStatObj.h" #include "I3DEngine.h" #include "ITexture.h" #include "SvoBrick.h" /* These clases represent a sparse voxel octree. The SvoEnvironment contains the tree root and associated meta data. It handles the entry into the tree and provides the interface for the system module. The Voxel class represents the nodes of the sparse voxel octree. Each voxel contains a texture block structer and bricks of data to be used with cone tracing. This represents the basic brick map algorithm. */ namespace SVOGI { #define nAtlasDimMaxXY (SvoEnvironment::m_brickTexturePoolDimXY / nVoxBloMaxDim) #define nAtlasDimMaxZ (SvoEnvironment::m_brickTexturePoolDimZ/ nVoxBloMaxDim) #define nAtlasDimBriXY (SvoEnvironment::m_brickTexturePoolDimXY / brickDimension) #define nAtlasDimBriZ (SvoEnvironment::m_brickTexturePoolDimZ/ brickDimension) #define nVoxNodPoolDimXY (nVoxNodMaxDim * nAtlasDimMaxXY) #define nVoxNodPoolDimZ (nVoxNodMaxDim * nAtlasDimMaxZ) const static AZ::u32 s_bufferCount = 2; const static AZ::u32 s_numVoxelChildren = 8; class Voxel { public: AZ_CLASS_ALLOCATOR(Voxel, AZ::SystemAllocator, 0); Voxel(const AZ::Aabb& box, AZStd::shared_ptr parent, class SvoEnvironment* env, AZ::u8 childIndex); ~Voxel(); //Recursive functions. void Update(AZStd::deque>& processingQueue, AZStd::shared_ptr self, float maxSize, float minSize); void ReserveGPUMemory(AZStd::shared_ptr self, float maxSize); void UpdateGpuTree(AZStd::shared_ptr self); void Evict(AZ::u32 frameDelay, bool forceEvict, float minSize); void EvictGpuData(AZ::u32 frameDelay, bool forceEvict); //Debug drawing functionality. void DrawVoxels(); void EnqueueMeshes(const EntityMeshDataMap& insertions, const EntityMeshDataMap& removals, float maxSize); //Non-recursive functions. void UpdateBrickData(float maxSize, AZ::s32 maxLoadedNodes, DataBrick& scratchData); AZ::s32 GetOffset(); AZ::Aabb GetChildBBox(AZ::u8 childIndex); void AllocateChildren(AZStd::shared_ptr self, float maxSize, float minSize); void UpdateBrickRenderData(); void UpdateTreeRenderData(); void DrawBrickData(); float GetLodRatio(); void ReleaseBlock(); AZ::Aabb m_nodeBox; EntityMeshDataMap m_insertedAndPendingInsertionMeshes; EntityMeshDataMap m_insertions[s_bufferCount]; EntityMeshDataMap m_removals[s_bufferCount]; AZ::u32 m_queueId; AZStd::mutex m_queueMutex; AZStd::shared_ptr m_children[s_numVoxelChildren]; AZStd::weak_ptr m_parentNode; class Brick* m_brick; AZ::s32 m_blockID; struct TextureBlock3D* m_block; class SvoEnvironment* m_svoEnv; float m_boxSize; AZ::s32 m_lastVisibleFrameId; AZ::s32 m_lastUpdatedFrameId; bool m_childOffsetsDirty; //This flag will be set when a child changes its gpu mapping. AZStd::atomic_bool m_cpuEnqueued; //This flag is set to prevent double enqueuing for voxel processing (m_processingQueue). bool m_gpuEnqueued; //This flag is set to prevent double enqueuing for voxel's brick update (m_brickUpdateQueue). AZ::u8 m_childIndex; }; class SvoEnvironment { public: AZ_CLASS_ALLOCATOR(SvoEnvironment, AZ::SystemAllocator, 0); SvoEnvironment(); ~SvoEnvironment(); //These functions are called from the SVO renderer to get associated data for rendering. //Thus they will be invoked from the render thread currently. void GetSvoStaticTextures(I3DEngine::SSvoStaticTexInfo& svoInfo, PodArray* pLightsTI_S, PodArray* pLightsTI_D); void GetSvoBricksForUpdate(PodArray& arrNodeInfo, bool getDynamic); //This function can be called from any thread as it will only upload data. //Currently it should be invoked from the Main thread. void UploadVoxels(bool showVoxels); //These functions are intended to be called from the same thread //These functions can modify the svo structure. //Currently they should be invoked from the main thread. void UpdateVoxels(); void ProcessVoxels(); void EvictVoxels(); void EvictGpuData(); void ReconstructTree(); void SetCamera(const CCamera& newCam); void AllocateTexturePools(); void DeallocateTexturePools(); void CollectLights(); void UpsertMesh(AZ::EntityId entityId, AZ::Transform transform, AZ::Aabb worldAabb, AZ::Data::Asset meshAsset, _smart_ptr material); void RemoveMesh(AZ::EntityId entityId); //Camera for culling Voxels CCamera m_camera; //Class for handling data upload to GPU class TextureBlockPacker3D* m_blockPacker; PodArray m_lightsTI_S, m_lightsTI_D; AZStd::shared_ptr m_svoRoot; //Queue for voxels that need to have CPU data generated. AZStd::deque> m_processingQueue; //Queues for voxels that need to have GPU data modified. AZStd::deque> m_brickUpdateQueue; EntityMeshDataMap m_globalInsertedMeshes; EntityMeshDataMap m_globalInsertions; EntityMeshDataMap m_globalRemovals; AZ::JobContext* m_jobContext; AZ::JobCompletion m_voxelJobsCompletion; ITexture* m_globalSpecularCM; float m_globalSpecularCM_Mult; double m_prevCheckVal; float m_voxelLodCutoff; const static AZ::s32 s_uninitializedTexturePoolId; AZ::s32 m_nTexOpasPoolId = s_uninitializedTexturePoolId; AZ::s32 m_nTexNodePoolId = s_uninitializedTexturePoolId; AZ::s32 m_nTexRgb0PoolId = s_uninitializedTexturePoolId; AZ::s32 m_nTexRgb1PoolId = s_uninitializedTexturePoolId; AZ::s32 m_nTexDynlPoolId = s_uninitializedTexturePoolId; AZ::s32 m_nTexRgb2PoolId = s_uninitializedTexturePoolId; AZ::s32 m_nTexRgb3PoolId = s_uninitializedTexturePoolId; AZ::s32 m_nTexNormPoolId = s_uninitializedTexturePoolId; AZ::s32 m_nTexAldiPoolId = s_uninitializedTexturePoolId; AZ::u32 m_blockIndex; //Counter to control how many voxels are actively in flight and have data. AZStd::atomic_int m_activeVoxels; //Delay to run eviction on the tree const AZ::s32 m_delayToEvictInFrames = 120; AZ::s32 m_lastEvictionFrame = 0; // Used to track when to run eviction on the tree and prune it by removing older nodes. //When evicting, toss anything older than this number of frames const AZ::s32 m_evictionDelayInFrames = 60; const AZ::s32 m_blockUpdateDelayInFrames = 60; //Delay to warn users that the maximum number of bricks on CPU is not high enough const AZ::s32 m_delayToWarnReachingMaxBricksOnCPUInFrames = 30; AZ::s32 m_numFramesReachingMaxBricksOnCPU = 0; //Currently set to just RGBA8 but should eventually be used to control compression. ETEX_Format m_brickTextureFormat; bool m_evictGpu; static AZ::s32 m_currentPassFrameId; static AZ::s32 m_brickTexturePoolDimXY; static AZ::s32 m_brickTexturePoolDimZ; protected: void AllocateTexturePool(AZ::s32& texPoolId, AZ::s32 width, AZ::s32 height, AZ::s32 depth, ETEX_Format texFormat, AZ::s32 filter, AZ::s32 flags = 0); void DeallocateTexturePool(AZ::s32& texPoolId); }; inline AZ::s32 GetCurrPassMainFrameID() { return SvoEnvironment::m_currentPassFrameId; } }