void FSlateRHIResourceManager::CreateTextures( const TArray< const FSlateBrush* >& Resources ) { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Loading Slate Textures"), STAT_Slate, STATGROUP_LoadTime); TMap<FName,FNewTextureInfo> TextureInfoMap; const uint32 Stride = GPixelFormats[PF_R8G8B8A8].BlockBytes; for( int32 ResourceIndex = 0; ResourceIndex < Resources.Num(); ++ResourceIndex ) { const FSlateBrush& Brush = *Resources[ResourceIndex]; const FName TextureName = Brush.GetResourceName(); if( TextureName != NAME_None && !Brush.HasUObject() && !Brush.IsDynamicallyLoaded() && !ResourceMap.Contains(TextureName) ) { // Find the texture or add it if it doesnt exist (only load the texture once) FNewTextureInfo& Info = TextureInfoMap.FindOrAdd( TextureName ); Info.bSrgb = (Brush.ImageType != ESlateBrushImageType::Linear); // Only atlas the texture if none of the brushes that use it tile it and the image is srgb Info.bShouldAtlas &= ( Brush.Tiling == ESlateBrushTileType::NoTile && Info.bSrgb && AtlasSize > 0 ); // Texture has been loaded if the texture data is valid if( !Info.TextureData.IsValid() ) { uint32 Width = 0; uint32 Height = 0; TArray<uint8> RawData; bool bSucceeded = LoadTexture( Brush, Width, Height, RawData ); Info.TextureData = MakeShareable( new FSlateTextureData( Width, Height, Stride, RawData ) ); const bool bTooLargeForAtlas = (Width >= 256 || Height >= 256 || Width >= AtlasSize || Height >= AtlasSize ); Info.bShouldAtlas &= !bTooLargeForAtlas; if( !bSucceeded || !ensureMsgf( Info.TextureData->GetRawBytes().Num() > 0, TEXT("Slate resource: (%s) contains no data"), *TextureName.ToString() ) ) { TextureInfoMap.Remove( TextureName ); } } } } // Sort textures by size. The largest textures are atlased first which creates a more compact atlas TextureInfoMap.ValueSort( FCompareFNewTextureInfoByTextureSize() ); for( TMap<FName,FNewTextureInfo>::TConstIterator It(TextureInfoMap); It; ++It ) { const FNewTextureInfo& Info = It.Value(); FName TextureName = It.Key(); FString NameStr = TextureName.ToString(); checkSlow( TextureName != NAME_None ); FSlateShaderResourceProxy* NewTexture = GenerateTextureResource( Info ); ResourceMap.Add( TextureName, NewTexture ); } }
/** Retrieves the derived chunk from the derived data cache. */ void FAsyncStreamDerivedChunkWorker::DoWork() { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("FAsyncStreamDerivedChunkWorker::DoWork"), STAT_AsyncStreamDerivedChunkWorker_DoWork, STATGROUP_StreamingDetails); UE_LOG(LogAudio, Verbose, TEXT("Start of ASync DDC Chunk read for key: %s"), *DerivedDataKey); TArray<uint8> DerivedChunkData; if (GetDerivedDataCacheRef().GetSynchronous(*DerivedDataKey, DerivedChunkData)) { FMemoryReader Ar(DerivedChunkData, true); int32 ChunkSize = 0; Ar << ChunkSize; checkf(ChunkSize == ExpectedChunkSize, TEXT("ChunkSize(%d) != ExpectedSize(%d)"), ChunkSize, ExpectedChunkSize); Ar.Serialize(DestChunkData, ChunkSize); } else { bRequestFailed = true; } FPlatformMisc::MemoryBarrier(); ThreadSafeCounter->Decrement(); UE_LOG(LogAudio, Verbose, TEXT("End of ASync DDC Chunk read for key: %s"), *DerivedDataKey); }
/** * The real thread entry point. It waits for work events to be queued. Once * an event is queued, it executes it and goes back to waiting. */ virtual uint32 Run() override { while (!TimeToDie) { // This will force sending the stats packet from the previous frame. SET_DWORD_STAT( STAT_ThreadPoolDummyCounter, 0 ); // We need to wait for shorter amount of time bool bContinueWaiting = true; while( bContinueWaiting ) { DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "FQueuedThread::Run.WaitForWork" ), STAT_FQueuedThread_Run_WaitForWork, STATGROUP_ThreadPoolAsyncTasks ); // Wait for some work to do bContinueWaiting = !DoWorkEvent->Wait( 10 ); } IQueuedWork* LocalQueuedWork = QueuedWork; QueuedWork = nullptr; FPlatformMisc::MemoryBarrier(); check(LocalQueuedWork || TimeToDie); // well you woke me up, where is the job or termination request? while (LocalQueuedWork) { // Tell the object to do the work LocalQueuedWork->DoThreadedWork(); // Let the object cleanup before we remove our ref to it LocalQueuedWork = OwningThreadPool->ReturnToPoolOrGetNextJob(this); } } return 0; }
bool FStartupPackages::LoadAll() { bool bReturn = true; DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Loading Startup Packages"), STAT_StartupPackages, STATGROUP_LoadTime); // should startup packages load from memory? bool bSerializeStartupPackagesFromMemory = false; GConfig->GetBool(TEXT("Engine.StartupPackages"), TEXT("bSerializeStartupPackagesFromMemory"), bSerializeStartupPackagesFromMemory, GEngineIni); // Get list of startup packages. TArray<FString> StartupPackages; // if the user wants to skip loading these, then don't (can be helpful for deleting objects in startup packages in the editor, etc) if (!FParse::Param(FCommandLine::Get(), TEXT("NoLoadStartupPackages"))) { FStartupPackages::GetStartupPackageNames(StartupPackages); } if( bSerializeStartupPackagesFromMemory ) { if( GUseSeekFreeLoading ) { // kick them off to be preloaded AsyncPreloadPackageList(StartupPackages); } } return bReturn; }
static bool AvoidsNavEdges(const FVector& OrgLocation, const FVector& TestVelocity, const TArray<FNavEdgeSegment>& NavEdges, float MaxZDiff) { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Avoidance: avoid nav edges"), STAT_AIAvoidanceEdgeAvoid, STATGROUP_AI); for (int32 Idx = 0; Idx < NavEdges.Num(); Idx++) { const FVector2D Seg1ToSeg0(NavEdges[Idx].P1 - NavEdges[Idx].P0); const FVector2D NewPosToOrg(TestVelocity); const FVector2D OrgToSeg0(NavEdges[Idx].P0 - OrgLocation); const float CrossD = FVector2D::CrossProduct(Seg1ToSeg0, NewPosToOrg); if (FMath::Abs(CrossD) < KINDA_SMALL_NUMBER) { continue; } const float CrossS = FVector2D::CrossProduct(NewPosToOrg, OrgToSeg0) / CrossD; const float CrossT = FVector2D::CrossProduct(Seg1ToSeg0, OrgToSeg0) / CrossD; if (CrossS < 0.0f || CrossS > 1.0f || CrossT < 0.0f || CrossT > 1.0f) { continue; } const FVector CrossPt = FMath::Lerp(NavEdges[Idx].P0, NavEdges[Idx].P1, CrossT); const float ZDiff = FMath::Abs(OrgLocation.Z - CrossPt.Z); if (ZDiff > MaxZDiff) { continue; } return false; } return true; }
void FAsyncIOSystemBase::BlockTillAllRequestsFinished() { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("FAsyncIOSystemBase::BlockTillAllRequestsFinished"), STAT_FAsyncIOSystemBase_BlockTillAllRequestsFinished, STATGROUP_AsyncIO_Verbose); // Block till all requests are fulfilled. while( true ) { bool bHasFinishedRequests = false; { FScopeLock ScopeLock( CriticalSection ); bHasFinishedRequests = (OutstandingRequests.Num() == 0) && (BusyWithRequest.GetValue() == 0); } if( bHasFinishedRequests ) { break; } else { SHUTDOWN_IF_EXIT_REQUESTED; //@todo streaming: this should be replaced by waiting for an event. FPlatformProcess::SleepNoStats( 0.001f ); } } }
void DoWork() { DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "FAllocPool::DoWork" ), Stat_FAllocPool_DoWork, STATGROUP_Quick ); int8* IntAlloc = new int8[223311]; int8* LeakTask = new int8[100000]; delete[] IntAlloc; }
static void Alloc() { DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "FAllocTask::Alloc" ), Stat_FAllocTask_Alloc, STATGROUP_Quick ); int8* IntAlloc = new int8[112233]; int8* LeakTask = new int8[100000]; delete[] IntAlloc; }
FString FSandboxPlatformFile::ConvertToSandboxPath( const TCHAR* Filename ) const { // Mostly for the malloc profiler to flush the data. DECLARE_SCOPE_CYCLE_COUNTER(TEXT("FSandboxPlatformFile::ConvertToSandboxPath"), STAT_SandboxPlatformFile_ConvertToSandboxPath, STATGROUP_LoadTimeVerbose); // convert to a standardized path (relative) FString SandboxPath = Filename; FPaths::MakeStandardFilename(SandboxPath); if ((bSandboxEnabled == true) && (SandboxDirectory.Len() > 0)) { // See whether Filename is relative to root directory. // if it's not inside the root, then just use it FString FullSandboxPath = FPaths::ConvertRelativePathToFull(SandboxPath); FString FullGameDir; #if IS_PROGRAM if (FPaths::IsProjectFilePathSet()) { FullGameDir = FPaths::ConvertRelativePathToFull(FPaths::GetPath(FPaths::GetProjectFilePath()) + TEXT("/")); } else #endif { FullGameDir = FPaths::ConvertRelativePathToFull(FPaths::GameDir()); } if(FullSandboxPath.StartsWith(FullGameDir)) { #if IS_PROGRAM SandboxPath = FPaths::Combine(*SandboxDirectory, *FPaths::GetBaseFilename(FPaths::GetProjectFilePath()), *FullSandboxPath + FullGameDir.Len()); #else SandboxPath = FPaths::Combine(*SandboxDirectory, FApp::GetGameName(), *FullSandboxPath + FullGameDir.Len()); #endif } else if (FullSandboxPath.StartsWith(*AbsoluteRootDirectory)) { SandboxPath = FPaths::Combine(*SandboxDirectory, *FullSandboxPath + AbsoluteRootDirectory.Len()); } else { int32 SeparatorIndex = SandboxPath.Find(TEXT("/"), ESearchCase::CaseSensitive); int32 SeparatorIndex2 = SandboxPath.Find(TEXT("\\"), ESearchCase::CaseSensitive); if (SeparatorIndex < 0 || (SeparatorIndex2 >= 0 && SeparatorIndex2 < SeparatorIndex)) { SeparatorIndex = SeparatorIndex2; } if( FPaths::IsDrive( SandboxPath.Mid( 0, SeparatorIndex ) ) == false ) { FString Dir = FPlatformProcess::BaseDir(); FPaths::MakeStandardFilename(Dir); SandboxPath = Dir / SandboxPath; SandboxPath = SandboxPath.Replace( *RelativeRootDirectory, *SandboxDirectory, ESearchCase::IgnoreCase ); } } } return SandboxPath; }
bool FProjectManager::LoadModulesForProject( const ELoadingPhase::Type LoadingPhase ) { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Loading Game Modules"), STAT_GameModule, STATGROUP_LoadTime); bool bSuccess = true; if ( CurrentProject.IsValid() ) { TMap<FName, EModuleLoadResult> ModuleLoadFailures; FModuleDescriptor::LoadModulesForPhase(LoadingPhase, CurrentProject->Modules, ModuleLoadFailures); if ( ModuleLoadFailures.Num() > 0 ) { FText FailureMessage; for ( auto FailureIt = ModuleLoadFailures.CreateConstIterator(); FailureIt; ++FailureIt ) { const EModuleLoadResult FailureReason = FailureIt.Value(); if( FailureReason != EModuleLoadResult::Success ) { const FText TextModuleName = FText::FromName(FailureIt.Key()); if ( FailureReason == EModuleLoadResult::FileNotFound ) { FailureMessage = FText::Format( LOCTEXT("PrimaryGameModuleNotFound", "The game module '{0}' could not be found. Please ensure that this module exists and that it is compiled."), TextModuleName ); } else if ( FailureReason == EModuleLoadResult::FileIncompatible ) { FailureMessage = FText::Format( LOCTEXT("PrimaryGameModuleIncompatible", "The game module '{0}' does not appear to be up to date. This may happen after updating the engine. Please recompile this module and try again."), TextModuleName ); } else if ( FailureReason == EModuleLoadResult::FailedToInitialize ) { FailureMessage = FText::Format( LOCTEXT("PrimaryGameModuleFailedToInitialize", "The game module '{0}' could not be successfully initialized after it was loaded."), TextModuleName ); } else if ( FailureReason == EModuleLoadResult::CouldNotBeLoadedByOS ) { FailureMessage = FText::Format( LOCTEXT("PrimaryGameModuleCouldntBeLoaded", "The game module '{0}' could not be loaded. There may be an operating system error or the module may not be properly set up."), TextModuleName ); } else { ensure(0); // If this goes off, the error handling code should be updated for the new enum values! FailureMessage = FText::Format( LOCTEXT("PrimaryGameModuleGenericLoadFailure", "The game module '{0}' failed to load for an unspecified reason. Please report this error."), TextModuleName ); } // Just report the first error break; } } FMessageDialog::Open(EAppMsgType::Ok, FailureMessage); bSuccess = false; } } return bSuccess; }
/** * Tells the thread there is work to be done. Upon completion, the thread * is responsible for adding itself back into the available pool. * * @param InQueuedWork The queued work to perform */ void DoWork(IQueuedWork* InQueuedWork) { DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "FQueuedThread::DoWork" ), STAT_FQueuedThread_DoWork, STATGROUP_ThreadPoolAsyncTasks ); check(QueuedWork == nullptr && "Can't do more than one task at a time"); // Tell the thread the work to be done QueuedWork = InQueuedWork; FPlatformMisc::MemoryBarrier(); // Tell the thread to wake up and do its job DoWorkEvent->Trigger(); }
/** * Thread-safe abstract compression routine. Compresses memory from uncompressed buffer and writes it to compressed * buffer. Updates CompressedSize with size of compressed data. * * @param CompressedBuffer Buffer compressed data is going to be written to * @param CompressedSize [in/out] Size of CompressedBuffer, at exit will be size of compressed data * @param UncompressedBuffer Buffer containing uncompressed data * @param UncompressedSize Size of uncompressed data in bytes * @return true if compression succeeds, false if it fails because CompressedBuffer was too small or other reasons */ static bool appCompressMemoryZLIB( void* CompressedBuffer, int32& CompressedSize, const void* UncompressedBuffer, int32 UncompressedSize ) { DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "Compress Memory ZLIB" ), STAT_appCompressMemoryZLIB, STATGROUP_Compression ); // Zlib wants to use unsigned long. unsigned long ZCompressedSize = CompressedSize; unsigned long ZUncompressedSize = UncompressedSize; // Compress data bool bOperationSucceeded = compress( (uint8*) CompressedBuffer, &ZCompressedSize, (const uint8*) UncompressedBuffer, ZUncompressedSize ) == Z_OK ? true : false; // Propagate compressed size from intermediate variable back into out variable. CompressedSize = ZCompressedSize; return bOperationSucceeded; }
void UGameplayCueManager::InitObjectLibraries(TArray<FString> Paths, UObjectLibrary* ActorObjectLibrary, UObjectLibrary* StaticObjectLibrary, FOnGameplayCueNotifySetLoaded OnLoadDelegate, FShouldLoadGCNotifyDelegate ShouldLoadDelegate) { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Loading Library"), STAT_ObjectLibrary, STATGROUP_LoadTime); #if WITH_EDITOR bAccelerationMapOutdated = false; FFormatNamedArguments Args; FScopedSlowTask SlowTask(0, FText::Format(NSLOCTEXT("AbilitySystemEditor", "BeginLoadingGameplayCueNotify", "Loading GameplayCue Library"), Args)); SlowTask.MakeDialog(); #endif FScopeCycleCounterUObject PreloadScopeActor(ActorObjectLibrary); ActorObjectLibrary->LoadBlueprintAssetDataFromPaths(Paths); StaticObjectLibrary->LoadBlueprintAssetDataFromPaths(Paths); // --------------------------------------------------------- // Determine loading scheme. // Sync at startup in commandlets like cook. // Async at startup in all other cases // --------------------------------------------------------- const bool bSyncFullyLoad = IsRunningCommandlet(); const bool bAsyncLoadAtStartup = !bSyncFullyLoad && ShouldAsyncLoadAtStartup(); if (bSyncFullyLoad) { #if STATS FString PerfMessage = FString::Printf(TEXT("Fully Loaded GameplayCueNotify object library")); SCOPE_LOG_TIME_IN_SECONDS(*PerfMessage, nullptr) #endif ActorObjectLibrary->LoadAssetsFromAssetData(); StaticObjectLibrary->LoadAssetsFromAssetData(); } // --------------------------------------------------------- // Look for GameplayCueNotifies that handle events // --------------------------------------------------------- TArray<FAssetData> ActorAssetDatas; ActorObjectLibrary->GetAssetDataList(ActorAssetDatas); TArray<FAssetData> StaticAssetDatas; StaticObjectLibrary->GetAssetDataList(StaticAssetDatas); TArray<FGameplayCueReferencePair> CuesToAdd; BuildCuesToAddToGlobalSet(ActorAssetDatas, GET_MEMBER_NAME_CHECKED(AGameplayCueNotify_Actor, GameplayCueName), bAsyncLoadAtStartup, CuesToAdd, OnLoadDelegate, ShouldLoadDelegate); BuildCuesToAddToGlobalSet(StaticAssetDatas, GET_MEMBER_NAME_CHECKED(UGameplayCueNotify_Static, GameplayCueName), bAsyncLoadAtStartup, CuesToAdd, OnLoadDelegate, ShouldLoadDelegate); check(GlobalCueSet); GlobalCueSet->AddCues(CuesToAdd); }
void FStreamedAudioChunk::Serialize(FArchive& Ar, UObject* Owner, int32 ChunkIndex) { DECLARE_SCOPE_CYCLE_COUNTER( TEXT("FStreamedAudioChunk::Serialize"), STAT_StreamedAudioChunk_Serialize, STATGROUP_LoadTime ); bool bCooked = Ar.IsCooking(); Ar << bCooked; BulkData.Serialize(Ar, Owner, ChunkIndex); Ar << DataSize; #if WITH_EDITORONLY_DATA if (!bCooked) { Ar << DerivedDataKey; } #endif // #if WITH_EDITORONLY_DATA }
void FAsyncIOSystemBase::InternalRead( IFileHandle* FileHandle, int64 Offset, int64 Size, void* Dest ) { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("FAsyncIOSystemBase::InternalRead"), STAT_AsyncIOSystemBase_InternalRead, STATGROUP_AsyncIO_Verbose); FScopeLock ScopeLock( ExclusiveReadCriticalSection ); STAT(double ReadTime = 0); { SCOPE_SECONDS_COUNTER(ReadTime); PlatformReadDoNotCallDirectly( FileHandle, Offset, Size, Dest ); } INC_FLOAT_STAT_BY(STAT_AsyncIO_PlatformReadTime,(float)ReadTime); // The platform might actually read more than Size due to aligning and internal min read sizes // though we only really care about throttling requested bandwidth as it's not very accurate // to begin with. STAT(ConstrainBandwidth(Size, ReadTime)); }
void USoundWave::SerializeCookedPlatformData(FArchive& Ar) { if (IsTemplate()) { return; } DECLARE_SCOPE_CYCLE_COUNTER( TEXT("USoundWave::SerializeCookedPlatformData"), STAT_SoundWave_SerializeCookedPlatformData, STATGROUP_LoadTime ); #if WITH_EDITORONLY_DATA if (Ar.IsCooking() && Ar.IsPersistent()) { check(!Ar.CookingTarget()->IsServerOnly()); FName PlatformFormat = Ar.CookingTarget()->GetWaveFormat(this); FString DerivedDataKey; GetStreamedAudioDerivedDataKey(*this, PlatformFormat, DerivedDataKey); FStreamedAudioPlatformData *PlatformDataToSave = CookedPlatformData.FindRef(DerivedDataKey); if (PlatformDataToSave == NULL) { PlatformDataToSave = new FStreamedAudioPlatformData(); PlatformDataToSave->Cache(*this, PlatformFormat, EStreamedAudioCacheFlags::InlineChunks | EStreamedAudioCacheFlags::Async); CookedPlatformData.Add(DerivedDataKey, PlatformDataToSave); } PlatformDataToSave->FinishCache(); PlatformDataToSave->Serialize(Ar, this); } else #endif // #if WITH_EDITORONLY_DATA { check(!FPlatformProperties::IsServerOnly()); CleanupCachedRunningPlatformData(); check(RunningPlatformData == NULL); // Don't serialize streaming data on servers, even if this platform supports streaming in theory RunningPlatformData = new FStreamedAudioPlatformData(); RunningPlatformData->Serialize(Ar, this); } }
static bool appCompressMemoryGZIP(void* CompressedBuffer, int32& CompressedSize, const void* UncompressedBuffer, int32 UncompressedSize) { DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "Compress Memory GZIP" ), STAT_appCompressMemoryGZIP, STATGROUP_Compression ); z_stream gzipstream; gzipstream.zalloc = Z_NULL; gzipstream.zfree = Z_NULL; gzipstream.opaque = Z_NULL; // Setup input buffer gzipstream.next_in = (uint8*)UncompressedBuffer; gzipstream.avail_in = UncompressedSize; // Init deflate settings to use GZIP int windowsBits = 15; int GZIP_ENCODING = 16; deflateInit2( &gzipstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, windowsBits | GZIP_ENCODING, MAX_MEM_LEVEL, Z_DEFAULT_STRATEGY); // Setup output buffer const unsigned long GzipHeaderLength = 12; // This is how much memory we may need, however the consumer is allocating memory for us without knowing the required length. //unsigned long CompressedMaxSize = deflateBound(&gzipstream, gzipstream.avail_in) + GzipHeaderLength; gzipstream.next_out = (uint8*)CompressedBuffer; gzipstream.avail_out = UncompressedSize; int status = 0; bool bOperationSucceeded = false; while ((status = deflate(&gzipstream, Z_FINISH)) == Z_OK); if (status == Z_STREAM_END) { bOperationSucceeded = true; deflateEnd(&gzipstream); } // Propagate compressed size from intermediate variable back into out variable. CompressedSize = gzipstream.total_out; return bOperationSucceeded; }
/** * Thread-safe abstract compression routine. Compresses memory from uncompressed buffer and writes it to compressed * buffer. Updates CompressedSize with size of compressed data. * * @param UncompressedBuffer Buffer containing uncompressed data * @param UncompressedSize Size of uncompressed data in bytes * @param CompressedBuffer Buffer compressed data is going to be read from * @param CompressedSize Size of CompressedBuffer data in bytes * @return true if compression succeeds, false if it fails because CompressedBuffer was too small or other reasons */ bool appUncompressMemoryZLIB( void* UncompressedBuffer, int32 UncompressedSize, const void* CompressedBuffer, int32 CompressedSize ) { DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "Uncompress Memory ZLIB" ), STAT_appUncompressMemoryZLIB, STATGROUP_Compression ); // Zlib wants to use unsigned long. unsigned long ZCompressedSize = CompressedSize; unsigned long ZUncompressedSize = UncompressedSize; z_stream stream; stream.zalloc = &zalloc; stream.zfree = &zfree; stream.opaque = Z_NULL; stream.next_in = (uint8*)CompressedBuffer; stream.avail_in = ZCompressedSize; stream.next_out = (uint8*)UncompressedBuffer; stream.avail_out = ZUncompressedSize; int32 Result = inflateInit(&stream); if(Result != Z_OK) return false; // Uncompress data. Result = inflate(&stream, Z_FINISH); if(Result == Z_STREAM_END) { ZUncompressedSize = stream.total_out; } Result = inflateEnd(&stream); // These warnings will be compiled out in shipping. UE_CLOG(Result == Z_MEM_ERROR, LogCompression, Warning, TEXT("appUncompressMemoryZLIB failed: Error: Z_MEM_ERROR, not enough memory!")); UE_CLOG(Result == Z_BUF_ERROR, LogCompression, Warning, TEXT("appUncompressMemoryZLIB failed: Error: Z_BUF_ERROR, not enough room in the output buffer!")); UE_CLOG(Result == Z_DATA_ERROR, LogCompression, Warning, TEXT("appUncompressMemoryZLIB failed: Error: Z_DATA_ERROR, input data was corrupted or incomplete!")); const bool bOperationSucceeded = (Result == Z_OK); // Sanity check to make sure we uncompressed as much data as we expected to. check( UncompressedSize == ZUncompressedSize ); return bOperationSucceeded; }
/** * Thread-safe abstract compression routine. Compresses memory from uncompressed buffer and writes it to compressed * buffer. Updates CompressedSize with size of compressed data. * * @param UncompressedBuffer Buffer containing uncompressed data * @param UncompressedSize Size of uncompressed data in bytes * @param CompressedBuffer Buffer compressed data is going to be read from * @param CompressedSize Size of CompressedBuffer data in bytes * @return true if compression succeeds, false if it fails because CompressedBuffer was too small or other reasons */ bool appUncompressMemoryZLIB( void* UncompressedBuffer, int32 UncompressedSize, const void* CompressedBuffer, int32 CompressedSize ) { DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "Uncompress Memory ZLIB" ), STAT_appUncompressMemoryZLIB, STATGROUP_Compression ); // Zlib wants to use unsigned long. unsigned long ZCompressedSize = CompressedSize; unsigned long ZUncompressedSize = UncompressedSize; // Uncompress data. const int32 Result = uncompress((uint8*)UncompressedBuffer, &ZUncompressedSize, (const uint8*)CompressedBuffer, ZCompressedSize); // These warnings will be compiled out in shipping. UE_CLOG(Result == Z_MEM_ERROR, LogCompression, Warning, TEXT("appUncompressMemoryZLIB failed: Error: Z_MEM_ERROR, not enough memory!")); UE_CLOG(Result == Z_BUF_ERROR, LogCompression, Warning, TEXT("appUncompressMemoryZLIB failed: Error: Z_BUF_ERROR, not enough room in the output buffer!")); UE_CLOG(Result == Z_DATA_ERROR, LogCompression, Warning, TEXT("appUncompressMemoryZLIB failed: Error: Z_DATA_ERROR, input data was corrupted or incomplete!")); const bool bOperationSucceeded = (Result == Z_OK); // Sanity check to make sure we uncompressed as much data as we expected to. check( UncompressedSize == ZUncompressedSize ); return bOperationSucceeded; }
void UTextureCube::Serialize(FArchive& Ar) { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("UTextureCube::Serialize"), STAT_TextureCube_Serialize, STATGROUP_LoadTime); Super::Serialize(Ar); FStripDataFlags StripFlags(Ar); bool bCooked = Ar.IsCooking(); Ar << bCooked; if (bCooked || Ar.IsCooking()) { SerializeCookedPlatformData(Ar); } #if WITH_EDITOR if (Ar.IsLoading() && !Ar.IsTransacting() && !bCooked) { BeginCachePlatformData(); } #endif // #if WITH_EDITOR }
/** * Renders the stats data * * @param Viewport The viewport to render to * @param Canvas Canvas object to use for rendering * @param X the X location to start rendering at * @param Y the Y location to start rendering at */ void RenderStats(FViewport* Viewport, class FCanvas* Canvas, int32 X, int32 Y) { DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "RenderStats" ), STAT_RenderStats, STATGROUP_StatSystem ); FGameThreadHudData* ViewData = FHUDGroupGameThreadRenderer::Get().Latest; if (!ViewData) { return; } GetStatRenderGlobals().Initialize( Viewport->GetSizeXY() ); if( !ViewData->bDrawOnlyRawStats ) { RenderGroupedWithHierarchy(*ViewData, Viewport, Canvas, X, Y); } else { // Render all counters. for( int32 RowIndex = 0; RowIndex < ViewData->GroupDescriptions.Num(); ++RowIndex ) { Canvas->DrawShadowedString(X, Y, *ViewData->GroupDescriptions[RowIndex], GetStatRenderGlobals().StatFont, GetStatRenderGlobals().StatColor); Y += GetStatRenderGlobals().GetFontHeight(); } } }
void UGameEngine::Init(IEngineLoop* InEngineLoop) { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("UGameEngine Init"), STAT_GameEngineStartup, STATGROUP_LoadTime); // Call base. UEngine::Init(InEngineLoop); #if USE_NETWORK_PROFILER FString NetworkProfilerTag; if( FParse::Value(FCommandLine::Get(), TEXT("NETWORKPROFILER="), NetworkProfilerTag ) ) { GNetworkProfiler.EnableTracking(true); } #endif // Load all of the engine modules that we need at startup that are not editor-related UGameEngine::LoadRuntimeEngineStartupModules(); // Load and apply user game settings GetGameUserSettings()->LoadSettings(); GetGameUserSettings()->ApplyNonResolutionSettings(); // Create game instance. For GameEngine, this should be the only GameInstance that ever gets created. { FStringClassReference GameInstanceClassName = GetDefault<UGameMapsSettings>()->GameInstanceClass; UClass* GameInstanceClass = (GameInstanceClassName.IsValid() ? LoadObject<UClass>(NULL, *GameInstanceClassName.ToString()) : UGameInstance::StaticClass()); GameInstance = NewObject<UGameInstance>(this, GameInstanceClass); GameInstance->InitializeStandalone(); } // // Creates the initial world context. For GameEngine, this should be the only WorldContext that ever gets created. // FWorldContext& InitialWorldContext = CreateNewWorldContext(EWorldType::Game); // Initialize the viewport client. UGameViewportClient* ViewportClient = NULL; if(GIsClient) { ViewportClient = NewObject<UGameViewportClient>(this, GameViewportClientClass); ViewportClient->Init(*GameInstance->GetWorldContext(), GameInstance); GameViewport = ViewportClient; GameInstance->GetWorldContext()->GameViewport = ViewportClient; } bCheckForMovieCapture = true; // Attach the viewport client to a new viewport. if(ViewportClient) { // This must be created before any gameplay code adds widgets bool bWindowAlreadyExists = GameViewportWindow.IsValid(); if (!bWindowAlreadyExists) { GameViewportWindow = CreateGameWindow(); } CreateGameViewport( ViewportClient ); if( !bWindowAlreadyExists ) { SwitchGameWindowToUseGameViewport(); } FString Error; if(ViewportClient->SetupInitialLocalPlayer(Error) == NULL) { UE_LOG(LogEngine, Fatal,TEXT("%s"),*Error); } UGameViewportClient::OnViewportCreated().Broadcast(); } GameInstance->StartGameInstance(); UE_LOG(LogInit, Display, TEXT("Game Engine Initialized.") ); // for IsInitialized() bIsInitialized = true; }
int32 EditorInit( IEngineLoop& EngineLoop ) { // Create debug exec. GDebugToolExec = new FDebugToolExec; DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Editor Initialized"), STAT_EditorStartup, STATGROUP_LoadTime); FScopedSlowTask SlowTask(100, NSLOCTEXT("EngineLoop", "EngineLoop_Loading", "Loading...")); SlowTask.EnterProgressFrame(50); int32 ErrorLevel = EngineLoop.Init(); if( ErrorLevel != 0 ) { FPlatformSplash::Hide(); return 0; } // Let the analytics know that the editor has started if ( FEngineAnalytics::IsAvailable() ) { TArray<FAnalyticsEventAttribute> EventAttributes; EventAttributes.Add(FAnalyticsEventAttribute(TEXT("MachineID"), FPlatformMisc::GetMachineId().ToString(EGuidFormats::Digits).ToLower())); EventAttributes.Add(FAnalyticsEventAttribute(TEXT("AccountID"), FPlatformMisc::GetEpicAccountId())); EventAttributes.Add(FAnalyticsEventAttribute(TEXT("GameName"), FApp::GetGameName())); EventAttributes.Add(FAnalyticsEventAttribute(TEXT("CommandLine"), FCommandLine::Get())); FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.ProgramStarted"), EventAttributes); } SlowTask.EnterProgressFrame(40); // Initialize the misc editor FUnrealEdMisc::Get().OnInit(); SlowTask.EnterProgressFrame(10); // Prime our array of default directories for loading and saving content files to FEditorDirectories::Get().LoadLastDirectories(); // Set up the actor folders singleton FActorFolders::Init(); // =================== CORE EDITOR INIT FINISHED =================== // Hide the splash screen now that everything is ready to go FPlatformSplash::Hide(); // Are we in immersive mode? const bool bIsImmersive = FPaths::IsProjectFilePathSet() && FParse::Param( FCommandLine::Get(), TEXT( "immersive" ) ); // Do final set up on the editor frame and show it { // Tear down rendering thread once instead of doing it for every window being resized. SCOPED_SUSPEND_RENDERING_THREAD(true); // Startup Slate main frame and other editor windows { const bool bStartImmersive = bIsImmersive; const bool bStartPIE = bIsImmersive; IMainFrameModule& MainFrameModule = FModuleManager::LoadModuleChecked<IMainFrameModule>(TEXT("MainFrame")); MainFrameModule.CreateDefaultMainFrame( bStartImmersive, bStartPIE ); } } // Go straight to VR mode if we were asked to { if( !bIsImmersive && FParse::Param( FCommandLine::Get(), TEXT( "VREditor" ) ) ) { IVREditorModule& VREditorModule = IVREditorModule::Get(); VREditorModule.EnableVREditor( true ); } else if( FParse::Param( FCommandLine::Get(), TEXT( "ForceVREditor" ) ) ) { GEngine->DeferredCommands.Add( TEXT( "VREd.ForceVRMode" ) ); } } // Check for automated build/submit option const bool bDoAutomatedMapBuild = FParse::Param( FCommandLine::Get(), TEXT("AutomatedMapBuild") ); // Prompt to update the game project file to the current version, if necessary if ( FPaths::IsProjectFilePathSet() ) { FGameProjectGenerationModule::Get().CheckForOutOfDateGameProjectFile(); FGameProjectGenerationModule::Get().CheckAndWarnProjectFilenameValid(); } // =================== EDITOR STARTUP FINISHED =================== // Stat tracking { const float StartupTime = (float)( FPlatformTime::Seconds() - GStartTime ); if( FEngineAnalytics::IsAvailable() ) { FEngineAnalytics::GetProvider().RecordEvent( TEXT( "Editor.Performance.Startup" ), TEXT( "Duration" ), FString::Printf( TEXT( "%.3f" ), StartupTime ) ); } } FModuleManager::LoadModuleChecked<IModuleInterface>(TEXT("HierarchicalLODOutliner")); // this will be ultimately returned from main(), so no error should be 0. return 0; }
void FAsyncIOSystemBase::FulfillCompressedRead( const FAsyncIORequest& IORequest, IFileHandle* FileHandle ) { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("FAsyncIOSystemBase::FulfillCompressedRead"), STAT_AsyncIOSystemBase_FulfillCompressedRead, STATGROUP_AsyncIO_Verbose); if (GbLogAsyncLoading == true) { LogIORequest(TEXT("FulfillCompressedRead"), IORequest); } // Initialize variables. FAsyncUncompress* Uncompressor = NULL; uint8* UncompressedBuffer = (uint8*) IORequest.Dest; // First compression chunk contains information about total size so we skip that one. int32 CurrentChunkIndex = 1; int32 CurrentBufferIndex = 0; bool bHasProcessedAllData = false; // read the first two ints, which will contain the magic bytes (to detect byteswapping) // and the original size the chunks were compressed from int64 HeaderData[2]; int32 HeaderSize = sizeof(HeaderData); InternalRead(FileHandle, IORequest.Offset, HeaderSize, HeaderData); RETURN_IF_EXIT_REQUESTED; // if the magic bytes don't match, then we are byteswapped (or corrupted) bool bIsByteswapped = HeaderData[0] != PACKAGE_FILE_TAG; // if its potentially byteswapped, make sure it's not just corrupted if (bIsByteswapped) { // if it doesn't equal the swapped version, then data is corrupted if (HeaderData[0] != PACKAGE_FILE_TAG_SWAPPED) { UE_LOG(LogStreaming, Warning, TEXT("Detected data corruption [header] trying to read %lld bytes at offset %lld from '%s'. Please delete file and recook."), IORequest.UncompressedSize, IORequest.Offset , *IORequest.FileName ); check(0); FPlatformMisc::HandleIOFailure(*IORequest.FileName); } // otherwise, we have a valid byteswapped file, so swap the chunk size else { HeaderData[1] = BYTESWAP_ORDER64(HeaderData[1]); } } int32 CompressionChunkSize = HeaderData[1]; // handle old packages that don't have the chunk size in the header, in which case // we can use the old hardcoded size if (CompressionChunkSize == PACKAGE_FILE_TAG) { CompressionChunkSize = LOADING_COMPRESSION_CHUNK_SIZE; } // calculate the number of chunks based on the size they were compressed from int32 TotalChunkCount = (IORequest.UncompressedSize + CompressionChunkSize - 1) / CompressionChunkSize + 1; // allocate chunk info data based on number of chunks FCompressedChunkInfo* CompressionChunks = (FCompressedChunkInfo*)FMemory::Malloc(sizeof(FCompressedChunkInfo) * TotalChunkCount); int32 ChunkInfoSize = (TotalChunkCount) * sizeof(FCompressedChunkInfo); void* CompressedBuffer[2] = { 0, 0 }; // Read table of compression chunks after seeking to offset (after the initial header data) InternalRead( FileHandle, IORequest.Offset + HeaderSize, ChunkInfoSize, CompressionChunks ); RETURN_IF_EXIT_REQUESTED; // Handle byte swapping. This is required for opening a cooked file on the PC. int64 CalculatedUncompressedSize = 0; if (bIsByteswapped) { for( int32 ChunkIndex=0; ChunkIndex<TotalChunkCount; ChunkIndex++ ) { CompressionChunks[ChunkIndex].CompressedSize = BYTESWAP_ORDER64(CompressionChunks[ChunkIndex].CompressedSize); CompressionChunks[ChunkIndex].UncompressedSize = BYTESWAP_ORDER64(CompressionChunks[ChunkIndex].UncompressedSize); if (ChunkIndex > 0) { CalculatedUncompressedSize += CompressionChunks[ChunkIndex].UncompressedSize; } } } else { for( int32 ChunkIndex=1; ChunkIndex<TotalChunkCount; ChunkIndex++ ) { CalculatedUncompressedSize += CompressionChunks[ChunkIndex].UncompressedSize; } } if (CompressionChunks[0].UncompressedSize != CalculatedUncompressedSize) { UE_LOG(LogStreaming, Warning, TEXT("Detected data corruption [incorrect uncompressed size] calculated %i bytes, requested %i bytes at offset %i from '%s'. Please delete file and recook."), CalculatedUncompressedSize, IORequest.UncompressedSize, IORequest.Offset , *IORequest.FileName ); check(0); FPlatformMisc::HandleIOFailure(*IORequest.FileName); } if (ChunkInfoSize + HeaderSize + CompressionChunks[0].CompressedSize > IORequest.Size ) { UE_LOG(LogStreaming, Warning, TEXT("Detected data corruption [undershoot] trying to read %lld bytes at offset %lld from '%s'. Please delete file and recook."), IORequest.UncompressedSize, IORequest.Offset , *IORequest.FileName ); check(0); FPlatformMisc::HandleIOFailure(*IORequest.FileName); } if (IORequest.UncompressedSize != CalculatedUncompressedSize) { UE_LOG(LogStreaming, Warning, TEXT("Detected data corruption [incorrect uncompressed size] calculated %lld bytes, requested %lld bytes at offset %lld from '%s'. Please delete file and recook."), CalculatedUncompressedSize, IORequest.UncompressedSize, IORequest.Offset , *IORequest.FileName ); check(0); FPlatformMisc::HandleIOFailure(*IORequest.FileName); } // Figure out maximum size of compressed data chunk. int64 MaxCompressedSize = 0; for (int32 ChunkIndex = 1; ChunkIndex < TotalChunkCount; ChunkIndex++) { MaxCompressedSize = FMath::Max(MaxCompressedSize, CompressionChunks[ChunkIndex].CompressedSize); // Verify the all chunks are 'full size' until the last one... if (CompressionChunks[ChunkIndex].UncompressedSize < CompressionChunkSize) { if (ChunkIndex != (TotalChunkCount - 1)) { checkf(0, TEXT("Calculated too many chunks: %d should be last, there are %d from '%s'"), ChunkIndex, TotalChunkCount, *IORequest.FileName); } } check( CompressionChunks[ChunkIndex].UncompressedSize <= CompressionChunkSize ); } int32 Padding = 0; // Allocate memory for compressed data. CompressedBuffer[0] = FMemory::Malloc( MaxCompressedSize + Padding ); CompressedBuffer[1] = FMemory::Malloc( MaxCompressedSize + Padding ); // Initial read request. InternalRead( FileHandle, FileHandle->Tell(), CompressionChunks[CurrentChunkIndex].CompressedSize, CompressedBuffer[CurrentBufferIndex] ); RETURN_IF_EXIT_REQUESTED; // Loop till we're done decompressing all data. while( !bHasProcessedAllData ) { FAsyncTask<FAsyncUncompress> UncompressTask( IORequest.CompressionFlags, UncompressedBuffer, CompressionChunks[CurrentChunkIndex].UncompressedSize, CompressedBuffer[CurrentBufferIndex], CompressionChunks[CurrentChunkIndex].CompressedSize, (Padding > 0) ); #if BLOCK_ON_DECOMPRESSION UncompressTask.StartSynchronousTask(); #else UncompressTask.StartBackgroundTask(); #endif // Advance destination pointer. UncompressedBuffer += CompressionChunks[CurrentChunkIndex].UncompressedSize; // Check whether we are already done reading. if( CurrentChunkIndex < TotalChunkCount-1 ) { // Can't postincrement in if statement as we need it to remain at valid value for one more loop iteration to finish // the decompression. CurrentChunkIndex++; // Swap compression buffers to read into. CurrentBufferIndex = 1 - CurrentBufferIndex; // Read more data. InternalRead( FileHandle, FileHandle->Tell(), CompressionChunks[CurrentChunkIndex].CompressedSize, CompressedBuffer[CurrentBufferIndex] ); RETURN_IF_EXIT_REQUESTED; } // We were already done reading the last time around so we are done processing now. else { bHasProcessedAllData = true; } //@todo async loading: should use event for this STAT(double UncompressorWaitTime = 0); { SCOPE_SECONDS_COUNTER(UncompressorWaitTime); UncompressTask.EnsureCompletion(); // just decompress on this thread if it isn't started yet } INC_FLOAT_STAT_BY(STAT_AsyncIO_UncompressorWaitTime,(float)UncompressorWaitTime); } FMemory::Free(CompressionChunks); FMemory::Free(CompressedBuffer[0]); FMemory::Free(CompressedBuffer[1] ); }
bool UNavigationComponent::GeneratePathTo(const FVector& GoalLocation, TSharedPtr<const FNavigationQueryFilter> QueryFilter) { if (GetWorld() == NULL || GetWorld()->GetNavigationSystem() == NULL || GetOuter() == NULL) { return false; } // Make sure we're trying to path to the closest valid location TO that location rather than the absolute location. // After talking with Steve P., if we need to ever allow pathing WITHOUT projecting to nav-mesh, it will probably be // best to do so using a flag while keeping this as the default behavior. NOTE:` If any changes to this behavior // are made, you should search for other places in UNavigationComponent using NavMeshGoalLocation and make sure the // behavior remains consistent. // make sure that nav data is updated GetNavData(); const FNavAgentProperties* NavAgentProps = MyNavAgent ? MyNavAgent->GetNavAgentProperties() : NULL; if (NavAgentProps != NULL) { FVector NavMeshGoalLocation; #if ENABLE_VISUAL_LOG UE_VLOG_LOCATION(GetOwner(), GoalLocation, 34, FColor(0,127,14), TEXT("GoalLocation")); const FVector ProjectionExtent = MyNavData ? MyNavData->GetDefaultQueryExtent() : FVector(DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL, DEFAULT_NAV_QUERY_EXTENT_HORIZONTAL, DEFAULT_NAV_QUERY_EXTENT_VERTICAL); UE_VLOG_BOX(GetOwner(), FBox(GoalLocation - ProjectionExtent, GoalLocation + ProjectionExtent), FColor::Green, TEXT_EMPTY); #endif if (ProjectPointToNavigation(GoalLocation, NavMeshGoalLocation) == QuerySuccess) { UE_VLOG_SEGMENT(GetOwner(), GoalLocation, NavMeshGoalLocation, FColor::Blue, TEXT_EMPTY); UE_VLOG_LOCATION(GetOwner(), NavMeshGoalLocation, 34, FColor::Blue, TEXT_EMPTY); UNavigationSystem* NavSys = GetWorld()->GetNavigationSystem(); FPathFindingQuery Query(MyNavData, MyNavAgent->GetNavAgentLocation(), NavMeshGoalLocation, QueryFilter); const EPathFindingMode::Type Mode = bDoHierarchicalPathfinding ? EPathFindingMode::Hierarchical : EPathFindingMode::Regular; FPathFindingResult Result = NavSys->FindPathSync(*MyNavAgent->GetNavAgentProperties(), Query, Mode); // try reversing direction if (bSearchFromGoalWhenOutOfNodes && !bDoHierarchicalPathfinding && Result.Path.IsValid() && Result.Path->DidSearchReachedLimit()) { // quick check if path exists bool bPathExists = false; { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Pathfinding: HPA* test time"), STAT_Navigation_PathVerifyTime, STATGROUP_Navigation); bPathExists = NavSys->TestPathSync(Query, EPathFindingMode::Hierarchical); } UE_VLOG(GetOwner(), LogNavigation, Log, TEXT("GeneratePathTo: out of nodes, HPA* path: %s"), bPathExists ? TEXT("exists, trying reversed search") : TEXT("doesn't exist")); // reverse search if (bPathExists) { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Pathfinding: reversed test time"), STAT_Navigation_PathReverseTime, STATGROUP_Navigation); TSharedPtr<FNavigationQueryFilter> Filter = QueryFilter.IsValid() ? QueryFilter->GetCopy() : MyNavData->GetDefaultQueryFilter()->GetCopy(); Filter->SetBacktrackingEnabled(true); FPathFindingQuery ReversedQuery(MyNavData, Query.EndLocation, Query.StartLocation, Filter); Result = NavSys->FindPathSync(*MyNavAgent->GetNavAgentProperties(), Query, Mode); } } if (Result.IsSuccessful() || Result.IsPartial()) { CurrentGoal = NavMeshGoalLocation; SetPath(Result.Path); if (IsFollowing() == true) { // make sure ticking is enabled (and it shouldn't be enabled before _first_ async path finding) SetComponentTickEnabledAsync(true); } NotifyPathUpdate(); return true; } else { UE_VLOG(GetOwner(), LogNavigation, Display, TEXT("Failed to generate path to destination")); } } else { UE_VLOG(GetOwner(), LogNavigation, Display, TEXT("Destination not on navmesh (and nowhere near!)")); } } else { UE_VLOG(GetOwner(), LogNavigation, Display, TEXT("UNavigationComponent::GeneratePathTo: NavAgentProps == NULL (Probably Pawn died)")); } return false; }
void EndInitTextLocalization() { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("EndInitTextLocalization"), STAT_EndInitTextLocalization, STATGROUP_LoadTime); const bool ShouldLoadEditor = WITH_EDITOR; const bool ShouldLoadGame = FApp::IsGame(); FInternationalization& I18N = FInternationalization::Get(); // Set culture according to configuration now that configs are available. #if ENABLE_LOC_TESTING if( FCommandLine::IsInitialized() && FParse::Param(FCommandLine::Get(), TEXT("LEET")) ) { I18N.SetCurrentCulture(TEXT("LEET")); } else #endif { FString RequestedCultureName; if (FParse::Value(FCommandLine::Get(), TEXT("CULTUREFORCOOKING="), RequestedCultureName)) { // Write the culture passed in if first install... if (FParse::Param(FCommandLine::Get(), TEXT("firstinstall"))) { GConfig->SetString(TEXT("Internationalization"), TEXT("Culture"), *RequestedCultureName, GEngineIni); } } else #if !UE_BUILD_SHIPPING // Use culture override specified on commandline. if (FParse::Value(FCommandLine::Get(), TEXT("CULTURE="), RequestedCultureName)) { //UE_LOG(LogInit, Log, TEXT("Overriding culture %s w/ command-line option".), *CultureName); } else #endif // !UE_BUILD_SHIPPING #if WITH_EDITOR // See if we've been provided a culture override in the editor if(GConfig->GetString( TEXT("Internationalization"), TEXT("Culture"), RequestedCultureName, GEditorGameAgnosticIni )) { //UE_LOG(LogInit, Log, TEXT("Overriding culture %s w/ editor configuration."), *CultureName); } else #endif // WITH_EDITOR // Use culture specified in engine configuration. if(GConfig->GetString( TEXT("Internationalization"), TEXT("Culture"), RequestedCultureName, GEngineIni )) { //UE_LOG(LogInit, Log, TEXT("Overriding culture %s w/ engine configuration."), *CultureName); } else { RequestedCultureName = I18N.GetDefaultCulture()->GetName(); } FString TargetCultureName = RequestedCultureName; { TArray<FString> LocalizationPaths; if(ShouldLoadEditor) { LocalizationPaths += FPaths::GetEditorLocalizationPaths(); } if(ShouldLoadGame) { LocalizationPaths += FPaths::GetGameLocalizationPaths(); } LocalizationPaths += FPaths::GetEngineLocalizationPaths(); // Validate the locale has data or fallback to one that does. TArray< FCultureRef > AvailableCultures; I18N.GetCulturesWithAvailableLocalization(LocalizationPaths, AvailableCultures, false); TArray<FString> PrioritizedParentCultureNames = I18N.GetCurrentCulture()->GetPrioritizedParentCultureNames(); FString ValidCultureName; for (const FString& CultureName : PrioritizedParentCultureNames) { FCulturePtr ValidCulture = I18N.GetCulture(CultureName); if (ValidCulture.IsValid() && AvailableCultures.Contains(ValidCulture.ToSharedRef())) { ValidCultureName = CultureName; break; } } if(!ValidCultureName.IsEmpty()) { if(RequestedCultureName != ValidCultureName) { // Make the user aware that the localization data belongs to a parent culture. UE_LOG(LogTextLocalizationManager, Log, TEXT("The requested culture ('%s') has no localization data; parent culture's ('%s') localization data will be used."), *RequestedCultureName, *ValidCultureName); } } else { // Fallback to English. UE_LOG(LogTextLocalizationManager, Log, TEXT("The requested culture ('%s') has no localization data; falling back to 'en' for localization and internationalization data."), *RequestedCultureName); TargetCultureName = "en"; } } I18N.SetCurrentCulture(TargetCultureName); } FTextLocalizationManager::Get().LoadResources(ShouldLoadEditor, ShouldLoadGame); FTextLocalizationManager::Get().bIsInitialized = true; }
//RickH - We could probably significantly improve speed if we put separate Z checks in place and did everything else in 2D. FVector UAvoidanceManager::GetAvoidanceVelocity_Internal(const FNavAvoidanceData& inAvoidanceData, float DeltaTime, int32* inIgnoreThisUID) { #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) if (!bSystemActive) { return inAvoidanceData.Velocity; } #endif if (DeltaTime <= 0.0f) { return inAvoidanceData.Velocity; } FVector ReturnVelocity = inAvoidanceData.Velocity * DeltaTime; float MaxSpeed = ReturnVelocity.Size2D(); float CurrentTime; UWorld* MyWorld = Cast<UWorld>(GetOuter()); if (MyWorld) { CurrentTime = MyWorld->TimeSeconds; } else { //No world? OK, just quietly back out and don't alter anything. return inAvoidanceData.Velocity; } bool Unobstructed = true; #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) bool DebugMode = IsDebugOnForAll() || (inIgnoreThisUID ? IsDebugOnForUID(*inIgnoreThisUID) : false); #endif //If we're moving very slowly, just push forward. Not sure it's worth avoiding at this speed, though I could be wrong. if (MaxSpeed < 0.01f) { return inAvoidanceData.Velocity; } AllCones.Empty(AllCones.Max()); //DrawDebugDirectionalArrow(GetWorld(), inAvoidanceData.Center, inAvoidanceData.Center + inAvoidanceData.Velocity, 2.5f, FColor(0,255,255), true, 0.05f, SDPG_MAX); for (auto& AvoidanceObj : AvoidanceObjects) { if ((inIgnoreThisUID) && (*inIgnoreThisUID == AvoidanceObj.Key)) { continue; } FNavAvoidanceData& OtherObject = AvoidanceObj.Value; // //Start with a few fast-rejects // //If the object has expired, ignore it if (OtherObject.ShouldBeIgnored()) { continue; } //If other object is not in avoided group, ignore it if (inAvoidanceData.ShouldIgnoreGroup(OtherObject.GroupMask)) { continue; } //RickH - We should have a max-radius parameter/option here, so I'm just going to hardcode one for now. //if ((OtherObject.Radius + _AvoidanceData.Radius + MaxSpeed + OtherObject.Velocity.Size2D()) < FVector::Dist(OtherObject.Center, _AvoidanceData.Center)) if (FVector2D(OtherObject.Center - inAvoidanceData.Center).SizeSquared() > FMath::Square(inAvoidanceData.TestRadius2D)) { continue; } if (FMath::Abs(OtherObject.Center.Z - inAvoidanceData.Center.Z) > OtherObject.HalfHeight + inAvoidanceData.HalfHeight + HeightCheckMargin) { continue; } //If we are moving away from the obstacle, ignore it. Even if we're the slower one, let the other obstacle path around us. if ((ReturnVelocity | (OtherObject.Center - inAvoidanceData.Center)) <= 0.0f) { continue; } //Create data for the avoidance routine { FVector PointAWorld = inAvoidanceData.Center; FVector PointBRelative = OtherObject.Center - PointAWorld; FVector TowardB, SidewaysFromB; FVector VelAdjustment; FVector VelAfterAdjustment; float RadiusB = OtherObject.Radius + inAvoidanceData.Radius; PointBRelative.Z = 0.0f; TowardB = PointBRelative.GetSafeNormal2D(); //Don't care about height for this game. Rough height-checking will come in later, but even then it will be acceptable to do this. if (TowardB.IsZero()) { //Already intersecting, or aligned vertically, scrap this whole object. continue; } SidewaysFromB.Set(-TowardB.Y, TowardB.X, 0.0f); //Build collision cone (two planes) and store for later use. We might consider some fast rejection here to see if we can skip the cone entirely. //RickH - If we built these cones in 2D, we could avoid all the cross-product matrix stuff and just use (y, -x) 90-degree rotation. { FVector PointPlane[2]; FVector EffectiveVelocityB; FVelocityAvoidanceCone NewCone; //Use RVO (as opposed to VO) only for objects that are not overridden to max weight AND that are currently moving toward us. if ((OtherObject.OverrideWeightTime <= CurrentTime) && ((OtherObject.Velocity|PointBRelative) < 0.0f)) { float OtherWeight = (OtherObject.Weight + (1.0f - inAvoidanceData.Weight)) * 0.5f; //Use the average of what the other wants to be and what we want it to be. EffectiveVelocityB = ((inAvoidanceData.Velocity * (1.0f - OtherWeight)) + (OtherObject.Velocity * OtherWeight)) * DeltaTime; } else { EffectiveVelocityB = OtherObject.Velocity * DeltaTime; //This is equivalent to VO (not RVO) because the other object is not going to reciprocate our avoidance. } checkSlow(EffectiveVelocityB.Z == 0.0f); //Make the left plane PointPlane[0] = EffectiveVelocityB + (PointBRelative + (SidewaysFromB * RadiusB)); PointPlane[1].Set(PointPlane[0].X, PointPlane[0].Y, PointPlane[0].Z + 100.0f); NewCone.ConePlane[0] = FPlane(EffectiveVelocityB, PointPlane[0], PointPlane[1]); //First point is relative to A, which is ZeroVector in this implementation checkSlow((((PointBRelative+EffectiveVelocityB)|NewCone.ConePlane[0]) - NewCone.ConePlane[0].W) > 0.0f); #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) if (DebugMode) { // DrawDebugDirectionalArrow(MyWorld, EffectiveVelocityB + PointAWorld, PointPlane[0] + PointAWorld, 50.0f, FColor(64,64,64), true, 0.05f, SDPG_MAX); // DrawDebugLine(MyWorld, PointAWorld, EffectiveVelocityB + PointAWorld, FColor(64,64,64), true, 0.05f, SDPG_MAX, 5.0f); } #endif //Make the right plane PointPlane[0] = EffectiveVelocityB + (PointBRelative - (SidewaysFromB * RadiusB)); PointPlane[1].Set(PointPlane[0].X, PointPlane[0].Y, PointPlane[0].Z - 100.0f); NewCone.ConePlane[1] = FPlane(EffectiveVelocityB, PointPlane[0], PointPlane[1]); //First point is relative to A, which is ZeroVector in this implementation checkSlow((((PointBRelative+EffectiveVelocityB)|NewCone.ConePlane[1]) - NewCone.ConePlane[1].W) > 0.0f); #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) if (DebugMode) { // DrawDebugDirectionalArrow(MyWorld, EffectiveVelocityB + PointAWorld, PointPlane[0] + PointAWorld, 50.0f, FColor(64,64,64), true, 0.05f, SDPG_MAX); } #endif if ((((ReturnVelocity|NewCone.ConePlane[0]) - NewCone.ConePlane[0].W) > 0.0f) && (((ReturnVelocity|NewCone.ConePlane[1]) - NewCone.ConePlane[1].W) > 0.0f)) { Unobstructed = false; } AllCones.Add(NewCone); } } } if (Unobstructed) { //Trivial case, our ideal velocity is available. return inAvoidanceData.Velocity; } TArray<FNavEdgeSegment> NavEdges; if (EdgeProviderOb.IsValid()) { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("Avoidance: collect nav edges"), STAT_AIAvoidanceEdgeCollect, STATGROUP_AI); EdgeProviderInterface->GetEdges(inAvoidanceData.Center, inAvoidanceData.TestRadius2D, NavEdges); } //Find a good velocity that isn't inside a cone. if (AllCones.Num()) { float AngleCurrent; float AngleF = ReturnVelocity.HeadingAngle(); float BestScore = 0.0f; float BestScorePotential; FVector BestVelocity = FVector::ZeroVector; //Worst case is we just stand completely still. Should we also allow backing up? Should we test standing still? const int AngleCount = 4; //Every angle will be tested both right and left. float AngleOffset[AngleCount] = {FMath::DegreesToRadians<float>(23.0f), FMath::DegreesToRadians<float>(40.0f), FMath::DegreesToRadians<float>(55.0f), FMath::DegreesToRadians<float>(85.0f)}; FVector AngleVector[AngleCount<<1]; //Determine check angles for (int i = 0; i < AngleCount; ++i) { AngleCurrent = AngleF - AngleOffset[i]; AngleVector[(i<<1)].Set(FMath::Cos(AngleCurrent), FMath::Sin(AngleCurrent), 0.0f); AngleCurrent = AngleF + AngleOffset[i]; AngleVector[(i<<1) + 1].Set(FMath::Cos(AngleCurrent), FMath::Sin(AngleCurrent), 0.0f); } //Sample velocity-space destination points and drag them back to form lines for (int AngleToCheck = 0; AngleToCheck < (AngleCount<<1); ++AngleToCheck) { FVector VelSpacePoint = AngleVector[AngleToCheck] * MaxSpeed; //Skip testing if we know we can't possibly get a better score than what we have already. //Note: This assumes the furthest point is the highest-scoring value (i.e. VelSpacePoint is not moving backward relative to ReturnVelocity) BestScorePotential = (VelSpacePoint|ReturnVelocity) * (VelSpacePoint|VelSpacePoint); if (BestScorePotential > BestScore) { const bool bAvoidsNavEdges = NavEdges.Num() > 0 ? AvoidsNavEdges(inAvoidanceData.Center, VelSpacePoint, NavEdges, inAvoidanceData.HalfHeight) : true; if (bAvoidsNavEdges) { FVector CandidateVelocity = AvoidCones(AllCones, FVector::ZeroVector, VelSpacePoint, AllCones.Num()); float CandidateScore = (CandidateVelocity|ReturnVelocity) * (CandidateVelocity|CandidateVelocity); //Vectors are rated by their length and their overall forward movement. if (CandidateScore > BestScore) { BestScore = CandidateScore; BestVelocity = CandidateVelocity; } } } } ReturnVelocity = BestVelocity; #if !(UE_BUILD_SHIPPING || UE_BUILD_TEST) if (DebugMode) { DrawDebugDirectionalArrow(MyWorld, inAvoidanceData.Center + inAvoidanceData.Velocity, inAvoidanceData.Center + (ReturnVelocity / DeltaTime), 75.0f, FColor(64,255,64), true, 2.0f, SDPG_MAX); } #endif } return ReturnVelocity / DeltaTime; //Remove prediction-time scaling }
void USoundWave::Serialize( FArchive& Ar ) { DECLARE_SCOPE_CYCLE_COUNTER( TEXT("USoundWave::Serialize"), STAT_SoundWave_Serialize, STATGROUP_LoadTime ); Super::Serialize( Ar ); bool bCooked = Ar.IsCooking(); Ar << bCooked; if (FPlatformProperties::RequiresCookedData() && !bCooked && Ar.IsLoading()) { UE_LOG(LogAudio, Fatal, TEXT("This platform requires cooked packages, and audio data was not cooked into %s."), *GetFullName()); } Ar.UsingCustomVersion(FFrameworkObjectVersion::GUID); if (Ar.IsLoading() && (Ar.UE4Ver() >= VER_UE4_SOUND_COMPRESSION_TYPE_ADDED) && (Ar.CustomVer(FFrameworkObjectVersion::GUID) < FFrameworkObjectVersion::RemoveSoundWaveCompressionName)) { FName DummyCompressionName; Ar << DummyCompressionName; } bool bSupportsStreaming = false; if (Ar.IsLoading() && FPlatformProperties::SupportsAudioStreaming()) { bSupportsStreaming = true; } else if (Ar.IsCooking() && Ar.CookingTarget()->SupportsFeature(ETargetPlatformFeatures::AudioStreaming)) { bSupportsStreaming = true; } if (bCooked) { // Only want to cook/load full data if we don't support streaming if (!IsStreaming() || !bSupportsStreaming) { if (Ar.IsCooking()) { #if WITH_ENGINE TArray<FName> ActualFormatsToSave; if (!Ar.CookingTarget()->IsServerOnly()) { // for now we only support one format per wav FName Format = Ar.CookingTarget()->GetWaveFormat(this); GetCompressedData(Format); // Get the data from the DDC or build it ActualFormatsToSave.Add(Format); } CompressedFormatData.Serialize(Ar, this, &ActualFormatsToSave); #endif } else { CompressedFormatData.Serialize(Ar, this); } } } else { // only save the raw data for non-cooked packages RawData.Serialize( Ar, this ); } Ar << CompressedDataGuid; if (IsStreaming()) { if (bCooked) { // only cook/load streaming data if it's supported if (bSupportsStreaming) { SerializeCookedPlatformData(Ar); } } #if WITH_EDITORONLY_DATA if (Ar.IsLoading() && !Ar.IsTransacting() && !bCooked && !GetOutermost()->HasAnyPackageFlags(PKG_ReloadingForCooker)) { BeginCachePlatformData(); } #endif // #if WITH_EDITORONLY_DATA } }
bool FPackageName::SearchForPackageOnDisk(const FString& PackageName, FString* OutLongPackageName, FString* OutFilename, bool bUseLocalizedNames) { DECLARE_SCOPE_CYCLE_COUNTER(TEXT("FPackageName::SearchForPackageOnDisk"), STAT_PackageName_SearchForPackageOnDisk, STATGROUP_LoadTime); bool bResult = false; double StartTime = FPlatformTime::Seconds(); if (FPackageName::IsShortPackageName(PackageName) == false) { // If this is long package name, revert to using DoesPackageExist because it's a lot faster. FString Filename; if (DoesPackageExist(PackageName, NULL, &Filename)) { if (OutLongPackageName) { *OutLongPackageName = PackageName; } if (OutFilename) { *OutFilename = Filename; } bResult = true; } } else { // Attempt to find package by its short name by searching in the known content paths. TArray<FString> Paths; { TArray<FString> RootContentPaths; FPackageName::QueryRootContentPaths( RootContentPaths ); for( TArray<FString>::TConstIterator RootPathIt( RootContentPaths ); RootPathIt; ++RootPathIt ) { const FString& RootPath = *RootPathIt; const FString& ContentFolder = FPackageName::LongPackageNameToFilename( RootPath ); Paths.Add( ContentFolder ); } } const FString PackageWildcard = (PackageName.Find(TEXT("."), ESearchCase::CaseSensitive) != INDEX_NONE ? PackageName : PackageName + TEXT(".*")); TArray<FString> Results; for (int32 PathIndex = 0; PathIndex < Paths.Num() && !bResult; ++PathIndex) { // Search directly on disk. Very slow! IFileManager::Get().FindFilesRecursive(Results, *Paths[PathIndex], *PackageWildcard, true, false); for (int32 FileIndex = 0; FileIndex < Results.Num(); ++FileIndex) { FString Filename(Results[FileIndex]); if (IsPackageFilename(Results[FileIndex])) { // Convert to long package name. FString LongPackageName; if (TryConvertFilenameToLongPackageName(Filename, LongPackageName)) { if (OutLongPackageName) { if (bResult) { UE_LOG(LogPackageName, Warning, TEXT("Found ambiguous long package name for '%s'. Returning '%s', but could also be '%s'."), *PackageName, **OutLongPackageName, *LongPackageName ); } else { *OutLongPackageName = LongPackageName; } } if (OutFilename) { FPaths::MakeStandardFilename(Filename); if (bResult) { UE_LOG(LogPackageName, Warning, TEXT("Found ambiguous file name for '%s'. Returning '%s', but could also be '%s'."), *PackageName, **OutFilename, *Filename); } else { *OutFilename = Filename; } } bResult = true; } } } } } float ThisTime = FPlatformTime::Seconds() - StartTime; if ( bResult ) { UE_LOG(LogPackageName, Log, TEXT("SearchForPackageOnDisk took %7.3fs to resolve %s."), ThisTime, *PackageName); } else { UE_LOG(LogPackageName, Log, TEXT("SearchForPackageOnDisk took %7.3fs, but failed to resolve %s."), ThisTime, *PackageName); } return bResult; }
void DebugLeakTest() { if (CVarEnableLeakTest.GetValueOnGameThread() == 1) { if (GFrameCounter == 60) { DirectStatsCommand( TEXT( "stat namedmarker Frame-060" ), true ); } if (GFrameCounter == 120) { DirectStatsCommand( TEXT( "stat namedmarker Frame-120" ), true ); } if (GFrameCounter == 240) { DirectStatsCommand( TEXT( "stat namedmarker Frame-240" ), true ); } if (GFrameCounter == 300) { GIsRequestingExit = true; } // Realloc. static TArray<uint8> Array; static int32 Initial = 1; { DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "LeakTest::Realloc" ), Stat_LeakTest_Realloc, STATGROUP_Quick ); Array.AddZeroed( Initial ); Initial += 100; } if (GFrameCounter == 300) { UE_LOG( LogTemp, Warning, TEXT( "Stat_ReallocTest: %i / %i" ), Array.GetAllocatedSize(), Initial ); } // General memory leak. { DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "LeakTest::NewInt8" ), Stat_LeakTest_NewInt8, STATGROUP_Quick ); int8* Leak = new int8[1000 * 1000]; } if (GFrameCounter < 250) { // Background threads memory test. struct FAllocTask { static void Alloc() { DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "FAllocTask::Alloc" ), Stat_FAllocTask_Alloc, STATGROUP_Quick ); int8* IntAlloc = new int8[112233]; int8* LeakTask = new int8[100000]; delete[] IntAlloc; } }; for (int32 Index = 0; Index < 40; ++Index) { FSimpleDelegateGraphTask::CreateAndDispatchWhenReady( FSimpleDelegateGraphTask::FDelegate::CreateStatic( FAllocTask::Alloc ), TStatId() ); } class FAllocPool : public FNonAbandonableTask { public: void DoWork() { DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "FAllocPool::DoWork" ), Stat_FAllocPool_DoWork, STATGROUP_Quick ); int8* IntAlloc = new int8[223311]; int8* LeakTask = new int8[100000]; delete[] IntAlloc; } TStatId GetStatId() const { return TStatId(); } }; for (int32 Index = 0; Index < 40; ++Index) { (new FAutoDeleteAsyncTask<FAllocPool>())->StartBackgroundTask(); } } for (int32 Index = 0; Index < 40; ++Index) { DECLARE_SCOPE_CYCLE_COUNTER( TEXT( "DebugLeakTest::Alloc" ), Stat_LeakTest_Alloc, STATGROUP_Quick ); int8* IntAlloc = new int8[331122]; int8* LeakTask = new int8[100000]; delete[] IntAlloc; } if (GIsRequestingExit) { // If we are writing stats data, stop it now. DirectStatsCommand( TEXT( "stat stopfile" ), true ); } } }