void USoundWave::FreeResources() { check(IsInAudioThread()); // Housekeeping of stats DEC_FLOAT_STAT_BY( STAT_AudioBufferTime, Duration ); DEC_FLOAT_STAT_BY( STAT_AudioBufferTimeChannels, NumChannels * Duration ); // GEngine is NULL during script compilation and GEngine->Client and its audio device might be // destroyed first during the exit purge. if( GEngine && !GExitPurge ) { // Notify the audio device to free the bulk data associated with this wave. FAudioDeviceManager* AudioDeviceManager = GEngine->GetAudioDeviceManager(); if (AudioDeviceManager) { AudioDeviceManager->StopSoundsUsingResource(this); AudioDeviceManager->FreeResource(this); } } if (CachedRealtimeFirstBuffer) { FMemory::Free(CachedRealtimeFirstBuffer); CachedRealtimeFirstBuffer = nullptr; } // Just in case the data was created but never uploaded if (RawPCMData) { FMemory::Free(RawPCMData); RawPCMData = nullptr; } // Remove the compressed copy of the data RemoveAudioResource(); // Stat housekeeping DEC_DWORD_STAT_BY(STAT_AudioMemorySize, TrackedMemoryUsage); DEC_DWORD_STAT_BY(STAT_AudioMemory, TrackedMemoryUsage); TrackedMemoryUsage = 0; ResourceID = 0; bDynamicResource = false; DecompressionType = DTYPE_Setup; bDecompressedFromOgg = 0; USoundWave* SoundWave = this; FAudioThread::RunCommandOnGameThread([SoundWave]() { SoundWave->ResourceState = ESoundWaveResourceState::Freed; }, TStatId()); }
FShaderResource::~FShaderResource() { check(Canary == FShader::ShaderMagic_Uninitialized || Canary == FShader::ShaderMagic_CleaningUp || Canary == FShader::ShaderMagic_Initialized); check(NumRefs == 0); Canary = 0; DEC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), Code.Num()); DEC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, GetSizeBytes()); DEC_DWORD_STAT_BY(STAT_Shaders_NumShaderResourcesLoaded, 1); }
void FShader::Release() { check(NumRefs != 0); if(--NumRefs == 0) { DEC_DWORD_STAT_BY(STAT_Shaders_ShaderMemory, GetSizeBytes()); DEC_DWORD_STAT_BY(STAT_Shaders_NumShadersLoaded,1); // Deregister the shader now to eliminate references to it by the type's ShaderIdMap Deregister(); BeginCleanup(this); } }
int32 FAsyncIOSystemBase::CancelRequests( uint64* RequestIndices, int32 NumIndices ) { FScopeLock ScopeLock( CriticalSection ); // Iterate over all outstanding requests and cancel matching ones. int32 RequestsCanceled = 0; for( int32 OutstandingIndex=OutstandingRequests.Num()-1; OutstandingIndex>=0 && RequestsCanceled<NumIndices; OutstandingIndex-- ) { // Iterate over all indices of requests to cancel for( int32 TheRequestIndex=0; TheRequestIndex<NumIndices; TheRequestIndex++ ) { // Look for matching request index in queue. const FAsyncIORequest IORequest = OutstandingRequests[OutstandingIndex]; if( IORequest.RequestIndex == RequestIndices[TheRequestIndex] ) { INC_DWORD_STAT( STAT_AsyncIO_CanceledReadCount ); INC_DWORD_STAT_BY( STAT_AsyncIO_CanceledReadSize, IORequest.Size ); DEC_DWORD_STAT( STAT_AsyncIO_OutstandingReadCount ); DEC_DWORD_STAT_BY( STAT_AsyncIO_OutstandingReadSize, IORequest.Size ); // Decrement thread-safe counter to indicate that request has been "completed". IORequest.Counter->Decrement(); // IORequest variable no longer valid after removal. OutstandingRequests.RemoveAt( OutstandingIndex ); RequestsCanceled++; // Break out of loop as we've modified OutstandingRequests AND it no longer is valid. break; } } } return RequestsCanceled; }
void FStreamingWaveData::FreeLoadedChunk(FLoadedAudioChunk& LoadedChunk) { if (LoadedChunk.Data != NULL) { FMemory::Free(LoadedChunk.Data); // Stat housekeeping DEC_DWORD_STAT_BY(STAT_AudioMemorySize, LoadedChunk.MemorySize); DEC_DWORD_STAT_BY(STAT_AudioMemory, LoadedChunk.MemorySize); LoadedChunk.Data = NULL; LoadedChunk.DataSize = 0; LoadedChunk.MemorySize = 0; LoadedChunk.Index = 0; } }
virtual void ReleaseRHI() override { DEC_DWORD_STAT_BY( STAT_TextureMemory, TextureSize ); DEC_DWORD_STAT_FNAME_BY( LODGroupStatName, TextureSize ); RHIUpdateTextureReference(Owner->TextureReference.TextureReferenceRHI,FTextureRHIParamRef()); TextureCubeRHI.SafeRelease(); FTextureResource::ReleaseRHI(); }
void FStaticShadowDepthMap::Empty() { DEC_DWORD_STAT_BY(STAT_PrecomputedShadowDepthMapMemory, DepthSamples.GetAllocatedSize()); ShadowMapSizeX = 0; ShadowMapSizeY = 0; DepthSamples.Empty(); }
FPrecomputedLightVolume::~FPrecomputedLightVolume() { if (bInitialized) { const SIZE_T VolumeBytes = GetAllocatedBytes(); DEC_DWORD_STAT_BY(STAT_PrecomputedLightVolumeMemory, VolumeBytes); } }
void FShader::Release() { // Lock the shader id map. Note that we don't necessarily have to deregister at this point but // the shader id map has to be locked while we remove references to this shader so that nothing // can find the shader in the map after we remove the final reference but before we deregister the shader LockShaderIdMap(); if(--NumRefs == 0) { DEC_DWORD_STAT_BY(STAT_Shaders_ShaderMemory, GetSizeBytes()); DEC_DWORD_STAT_BY(STAT_Shaders_NumShadersLoaded,1); // Deregister the shader now to eliminate references to it by the type's ShaderIdMap Deregister(); Canary = ShaderMagic_CleaningUp; BeginCleanup(this); } UnlockShaderIdMap(); }
void USoundWave::FreeResources() { // Housekeeping of stats DEC_FLOAT_STAT_BY( STAT_AudioBufferTime, Duration ); DEC_FLOAT_STAT_BY( STAT_AudioBufferTimeChannels, NumChannels * Duration ); // GEngine is NULL during script compilation and GEngine->Client and its audio device might be // destroyed first during the exit purge. if( GEngine && !GExitPurge ) { // Notify the audio device to free the bulk data associated with this wave. FAudioDevice* AudioDevice = GEngine->GetAudioDevice(); if (AudioDevice != NULL) { TArray<UAudioComponent*> StoppedComponents; AudioDevice->StopSoundsUsingResource(this, StoppedComponents); AudioDevice->FreeResource( this ); } } // Just in case the data was created but never uploaded if (RawPCMData != NULL) { FMemory::Free(RawPCMData); RawPCMData = NULL; } // Remove the compressed copy of the data RemoveAudioResource(); // Stat housekeeping DEC_DWORD_STAT_BY(STAT_AudioMemorySize, TrackedMemoryUsage); DEC_DWORD_STAT_BY(STAT_AudioMemory, TrackedMemoryUsage); TrackedMemoryUsage = 0; SampleRate = 0; Duration = 0.0f; ResourceID = 0; bDynamicResource = false; DecompressionType = DTYPE_Setup; bDecompressedFromOgg = 0; RawPCMDataSize = 0; }
void FShaderResource::ReleaseRHI() { DEC_DWORD_STAT_BY(STAT_Shaders_NumShadersUsedForRendering, 1); VertexShader.SafeRelease(); PixelShader.SafeRelease(); HullShader.SafeRelease(); DomainShader.SafeRelease(); GeometryShader.SafeRelease(); ComputeShader.SafeRelease(); }
void UFontBulkData::Unlock() const { bool bWasLoaded = BulkData.IsBulkDataLoaded(); int32 BulkDataSize = BulkData.GetBulkDataSize(); BulkData.Unlock(); #if STATS if( bWasLoaded && !BulkData.IsBulkDataLoaded() ) { DEC_DWORD_STAT_BY( STAT_SlateBulkFontDataMemory, BulkDataSize ); } #endif CriticalSection.Unlock(); }
void FShaderResource::InitRHI() { checkf(Code.Num() > 0, TEXT("FShaderResource::InitRHI was called with empty bytecode, which can happen if the resource is initialized multiple times on platforms with no editor data.")); // we can't have this called on the wrong platform's shaders if (!ArePlatformsCompatible(GMaxRHIShaderPlatform, (EShaderPlatform)Target.Platform)) { if (FPlatformProperties::RequiresCookedData()) { UE_LOG(LogShaders, Fatal, TEXT("FShaderResource::InitRHI got platform %s but it is not compatible with %s"), *LegacyShaderPlatformToShaderFormat((EShaderPlatform)Target.Platform).ToString(), *LegacyShaderPlatformToShaderFormat(GMaxRHIShaderPlatform).ToString()); } return; } INC_DWORD_STAT_BY(STAT_Shaders_NumShadersUsedForRendering, 1); SCOPE_CYCLE_COUNTER(STAT_Shaders_RTShaderLoadTime); if(Target.Frequency == SF_Vertex) { VertexShader = RHICreateVertexShader(Code); } else if(Target.Frequency == SF_Pixel) { PixelShader = RHICreatePixelShader(Code); } else if(Target.Frequency == SF_Hull) { HullShader = RHICreateHullShader(Code); } else if(Target.Frequency == SF_Domain) { DomainShader = RHICreateDomainShader(Code); } else if(Target.Frequency == SF_Geometry) { GeometryShader = RHICreateGeometryShader(Code); } else if(Target.Frequency == SF_Compute) { ComputeShader = RHICreateComputeShader(Code); } if (!FPlatformProperties::HasEditorOnlyData()) { DEC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), Code.Num()); DEC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, Code.GetAllocatedSize()); Code.Empty(); } }
void FShaderResource::InitRHI() { checkf(Code.Num() > 0, TEXT("FShaderResource::InitRHI was called with empty bytecode, which can happen if the resource is initialized multiple times on platforms with no editor data.")); // we can't have this called on the wrong platform's shaders if (!ArePlatformsCompatible(GMaxRHIShaderPlatform, (EShaderPlatform)Target.Platform)) { if (FPlatformProperties::RequiresCookedData()) { UE_LOG(LogShaders, Fatal, TEXT("FShaderResource::InitRHI got platform %s but it is not compatible with %s"), *LegacyShaderPlatformToShaderFormat((EShaderPlatform)Target.Platform).ToString(), *LegacyShaderPlatformToShaderFormat(GMaxRHIShaderPlatform).ToString()); } return; } INC_DWORD_STAT_BY(STAT_Shaders_NumShadersUsedForRendering, 1); SCOPE_CYCLE_COUNTER(STAT_Shaders_RTShaderLoadTime); FShaderCache* ShaderCache = FShaderCache::GetShaderCache(); if(Target.Frequency == SF_Vertex) { VertexShader = ShaderCache ? ShaderCache->GetVertexShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateVertexShader(Code); } else if(Target.Frequency == SF_Pixel) { PixelShader = ShaderCache ? ShaderCache->GetPixelShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreatePixelShader(Code); } else if(Target.Frequency == SF_Hull) { HullShader = ShaderCache ? ShaderCache->GetHullShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateHullShader(Code); } else if(Target.Frequency == SF_Domain) { DomainShader = ShaderCache ? ShaderCache->GetDomainShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateDomainShader(Code); } else if(Target.Frequency == SF_Geometry) { if (SpecificType) { FStreamOutElementList ElementList; TArray<uint32> StreamStrides; int32 RasterizedStream = -1; SpecificType->GetStreamOutElements(ElementList, StreamStrides, RasterizedStream); checkf(ElementList.Num(), *FString::Printf(TEXT("Shader type %s was given GetStreamOutElements implementation that had no elements!"), SpecificType->GetName())); //@todo - not using the cache GeometryShader = RHICreateGeometryShaderWithStreamOutput(Code, ElementList, StreamStrides.Num(), StreamStrides.GetData(), RasterizedStream); } else { GeometryShader = ShaderCache ? ShaderCache->GetGeometryShader((EShaderPlatform)Target.Platform, OutputHash, Code) : RHICreateGeometryShader(Code); } } else if(Target.Frequency == SF_Compute) { ComputeShader = ShaderCache ? ShaderCache->GetComputeShader((EShaderPlatform)Target.Platform, Code) : RHICreateComputeShader(Code); } if (Target.Frequency != SF_Geometry) { checkf(!SpecificType, *FString::Printf(TEXT("Only geometry shaders can use GetStreamOutElements, shader type %s"), SpecificType->GetName())); } if (!FPlatformProperties::HasEditorOnlyData()) { DEC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), Code.Num()); DEC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, Code.GetAllocatedSize()); Code.Empty(); } }
void FEnvQueryInstance::ExecuteOneStep(double InTimeLimit) { if (!Owner.IsValid()) { Status = EEnvQueryStatus::OwnerLost; return; } FEnvQueryOptionInstance& OptionItem = Options[OptionIndex]; CONDITIONAL_SCOPE_CYCLE_COUNTER(STAT_AI_EnvQuery_GeneratorTime, CurrentTest < 0); CONDITIONAL_SCOPE_CYCLE_COUNTER(STAT_AI_EnvQuery_TestTime, CurrentTest >= 0); bool bStepDone = true; TimeLimit = InTimeLimit; if (CurrentTest < 0) { DEC_DWORD_STAT_BY(STAT_AI_EnvQuery_NumItems, Items.Num()); RawData.Reset(); Items.Reset(); ItemType = OptionItem.ItemType; ValueSize = ((UEnvQueryItemType*)ItemType->GetDefaultObject())->GetValueSize(); OptionItem.GenerateDelegate.Execute(*this); FinalizeGeneration(); } else { const int32 ItemsAlreadyProcessed = CurrentTestStartingItem; OptionItem.TestDelegates[CurrentTest].Execute(*this); bStepDone = CurrentTestStartingItem >= Items.Num() || bFoundSingleResult // or no items processed ==> this means error || (ItemsAlreadyProcessed == CurrentTestStartingItem); if (bStepDone) { FinalizeTest(); } } if (bStepDone) { #if WITH_EDITOR if (bStoreDebugInfo) { DebugData.Store(this); } #endif // WITH_EDITOR CurrentTest++; CurrentTestStartingItem = 0; } // sort results or switch to next option when all tests are performed if (Status == EEnvQueryStatus::Processing && (OptionItem.TestDelegates.Num() == CurrentTest || NumValidItems <= 0)) { if (NumValidItems > 0) { // found items, sort and finish FinalizeQuery(); } else { // no items here, go to next option or finish if (OptionIndex + 1 >= Options.Num()) { // out of options, finish processing without errors FinalizeQuery(); } else { // not doing it always for debugging purposes OptionIndex++; CurrentTest = -1; } } } }
void FAsyncIOSystemBase::Tick() { // Create file handles. { TArray<FString> FileNamesToCacheHandles; // Only enter critical section for copying existing array over. We don't operate on the // real array as creating file handles might take a while and we don't want to have other // threads stalling on submission of requests. { FScopeLock ScopeLock( CriticalSection ); for( int32 RequestIdx=0; RequestIdx<OutstandingRequests.Num(); RequestIdx++ ) { // Early outs avoid unnecessary work and string copies with implicit allocator churn. FAsyncIORequest& OutstandingRequest = OutstandingRequests[RequestIdx]; if( OutstandingRequest.bHasAlreadyRequestedHandleToBeCached == false && OutstandingRequest.bIsDestroyHandleRequest == false && FindCachedFileHandle( OutstandingRequest.FileNameHash ) == NULL ) { new(FileNamesToCacheHandles)FString(*OutstandingRequest.FileName); OutstandingRequest.bHasAlreadyRequestedHandleToBeCached = true; } } } // Create file handles for requests down the pipe. This is done here so we can later on // use the handles to figure out the sort keys. for( int32 FileNameIndex=0; FileNameIndex<FileNamesToCacheHandles.Num(); FileNameIndex++ ) { GetCachedFileHandle( FileNamesToCacheHandles[FileNameIndex] ); } } // Copy of request. FAsyncIORequest IORequest; bool bIsRequestPending = false; { FScopeLock ScopeLock( CriticalSection ); if( OutstandingRequests.Num() ) { // Gets next request index based on platform specific criteria like layout on disc. int32 TheRequestIndex = PlatformGetNextRequestIndex(); if( TheRequestIndex != INDEX_NONE ) { // We need to copy as we're going to remove it... IORequest = OutstandingRequests[ TheRequestIndex ]; // ...right here. // NOTE: this needs to be a Remove, not a RemoveSwap because the base implementation // of PlatformGetNextRequestIndex is a FIFO taking priority into account OutstandingRequests.RemoveAt( TheRequestIndex ); // We're busy. Updated inside scoped lock to ensure BlockTillAllRequestsFinished works correctly. BusyWithRequest.Increment(); bIsRequestPending = true; } } } // We only have work to do if there's a request pending. if( bIsRequestPending ) { // handle a destroy handle request from the queue if( IORequest.bIsDestroyHandleRequest ) { IFileHandle* FileHandle = FindCachedFileHandle( IORequest.FileNameHash ); if( FileHandle ) { // destroy and remove the handle delete FileHandle; NameHashToHandleMap.Remove(IORequest.FileNameHash); } } else { // Retrieve cached handle or create it if it wasn't cached. We purposefully don't look at currently // set value as it might be stale by now. IFileHandle* FileHandle = GetCachedFileHandle( IORequest.FileName ); if( FileHandle ) { if( IORequest.UncompressedSize ) { // Data is compressed on disc so we need to also decompress. FulfillCompressedRead( IORequest, FileHandle ); } else { // Read data after seeking. InternalRead( FileHandle, IORequest.Offset, IORequest.Size, IORequest.Dest ); } INC_DWORD_STAT( STAT_AsyncIO_FulfilledReadCount ); INC_DWORD_STAT_BY( STAT_AsyncIO_FulfilledReadSize, IORequest.Size ); } else { //@todo streaming: add warning once we have thread safe logging. } DEC_DWORD_STAT( STAT_AsyncIO_OutstandingReadCount ); DEC_DWORD_STAT_BY( STAT_AsyncIO_OutstandingReadSize, IORequest.Size ); } // Request fulfilled. if( IORequest.Counter ) { IORequest.Counter->Decrement(); } // We're done reading for now. BusyWithRequest.Decrement(); } else { if( !OutstandingRequests.Num() && FPlatformProcess::SupportsMultithreading() ) { // We're really out of requests now, wait till the calling thread signals further work OutstandingRequestsEvent->Wait(); } } }
FShaderResource::~FShaderResource() { DEC_DWORD_STAT_BY_FName(GetMemoryStatType((EShaderFrequency)Target.Frequency).GetName(), Code.Num()); DEC_DWORD_STAT_BY(STAT_Shaders_ShaderResourceMemory, GetSizeBytes()); DEC_DWORD_STAT_BY(STAT_Shaders_NumShaderResourcesLoaded, 1); }
FNavigationOctree::~FNavigationOctree() { DEC_DWORD_STAT_BY( STAT_NavigationMemory, sizeof(*this) ); DEC_MEMORY_STAT_BY(STAT_Navigation_CollisionTreeMemory, NodesMemory); }