You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
==========================
MAJOR FEATURES + CHANGES
==========================
#lockdown Nick.Penwarden
Change 2879705 on 2016/02/24 by Nick.Darnell
Editor - Tweaking some comments.
#tests n/a
#rb n/a
Change 2879674 on 2016/02/24 by Nick.Darnell
Editor - The editor now supports many new methods of opening new asset editors. You can choose where tabs open with a great deal more options in Editor Preferences > Appearance > Asset Editor Open Location. This will reset the 'always open asset editors in new windows' option, it completely replaces and enchances that option.
#tests Ran the editor, tried each option and they all seem to do what I want.
#rb matt.kuhlenschmidt
Change 2879661 on 2016/02/24 by Jamie.Dale
More general fixes for dialogue waves
- The localization key now uses a hash of the speaker and target voice GUIDs to help keep them short.
- The localization key can now be user customized, and contains a placeholder format specifier for the context hash.
- The "Variations" meta-data is now called "Context".
#rb James.Hopkin
#tests Built for Windows, Linux, and PS4. Tested a loc gather and export had the correct info in it. Tested the new UI worked as expected.
Change 2879436 on 2016/02/24 by Nicholas.Davies
A few bug fixes for blocking PS4 > PC chat
#jira OR-15467 Disable Paragon chat on PS4 for users outside of the game
#RB Antony.Carter
#codereview Sam.Zamani
#TESTS PS4 whispers to and from none Paragon PC users is blocked.
Change 2878929 on 2016/02/23 by Jason.Bestimt
#ORION_DEV - Merge Main to reconcile 0.20 branch creation
#RB:none
#Tests:none
Change 2878600 on 2016/02/23 by Dmitry.Rekman
Linux: added code to identify CPU for FPSCharts (OR-14949).
#rb none
#tests Ran dedicated server on local VM and a few physical boxes.
Change 2878443 on 2016/02/23 by Marcus.Wassmer
Fix game not ticking when PS button is pressed.
#rb andrew.grant
#test golden path ps4
Change 2878361 on 2016/02/23 by Josh.Markiewicz
#UE4 - fixed bad comment
#rb none
#tests none
Change 2878205 on 2016/02/23 by Jason.Bestimt
#ORION_DEV - Merge main (0.19) at CL# 2878162
#Tests:none
#RB:none
Change 2878095 on 2016/02/23 by Josh.Markiewicz
#UE4 - added warnings to json mcp read/write failures
- removed HostAddressOverride parameter (use -uselocalips and -multihome together instead)
#rb none
#tests matchmaking golden path
Change 2878002 on 2016/02/23 by Josh.Markiewicz
#UE4 - made two party framework functions virtual
#rb none
#tests none
Change 2877998 on 2016/02/23 by Josh.Markiewicz
#Ue4 - Party interface can optionally enable/disable creating a chat room alongside the party (defaults to enabled)
#rb rob.cannaday
#tests social/team parties golden path
#codereview rob.cannaday
Change 2877822 on 2016/02/23 by Olaf.Piesche
speculative fix for OR-15710
#rb david.hill
#tests PC game
Change 2877804 on 2016/02/23 by Uriel.Doyon
Fixed ULevel::AddReferencedObjects clearing all references to static texture streaming data
#codereview robert.manuszewski
#rb marcus.wassmer
#tests played several games on PC, also doing rejoin
#jira OR-15658
Change 2877692 on 2016/02/23 by Jamie.Dale
Added commandlet to replace sound wave players in sound cues with dialogue wave players where appropriate
#rb Saul.Abreu
#tests Built for Windows, Linux, and PS4. Tested the commandlet.
Change 2877691 on 2016/02/23 by Jamie.Dale
Added commandlet to extract out the information from our character sheets and put it into the correct dialogue waves
#rb Saul.Abreu
#tests Built for Windows, Linux, and PS4. Tested the commandlet.
Change 2877690 on 2016/02/23 by Jamie.Dale
General dialogue wave fixes
[CL 2881965 by Andrew Grant in Main branch]
272 lines
8.8 KiB
C++
272 lines
8.8 KiB
C++
// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
#include "DerivedDataCacheUsageStats.h"
|
|
|
|
/**
|
|
* Thread safe set helper
|
|
**/
|
|
struct FThreadSet
|
|
{
|
|
FCriticalSection SynchronizationObject;
|
|
TSet<FString> FilesInFlight;
|
|
|
|
void Add(const FString& Key)
|
|
{
|
|
FScopeLock ScopeLock(&SynchronizationObject);
|
|
check(Key.Len());
|
|
FilesInFlight.Add(Key);
|
|
}
|
|
void Remove(const FString& Key)
|
|
{
|
|
FScopeLock ScopeLock(&SynchronizationObject);
|
|
FilesInFlight.Remove(Key);
|
|
}
|
|
bool Exists(const FString& Key)
|
|
{
|
|
FScopeLock ScopeLock(&SynchronizationObject);
|
|
return FilesInFlight.Contains(Key);
|
|
}
|
|
bool AddIfNotExists(const FString& Key)
|
|
{
|
|
FScopeLock ScopeLock(&SynchronizationObject);
|
|
check(Key.Len());
|
|
if (!FilesInFlight.Contains(Key))
|
|
{
|
|
FilesInFlight.Add(Key);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
};
|
|
/**
|
|
* Async task to handle the fire and forget async put
|
|
**/
|
|
class FCachePutAsyncWorker
|
|
{
|
|
public:
|
|
/** Cache Key for the put to InnerBackend **/
|
|
FString CacheKey;
|
|
/** Data for the put to InnerBackend **/
|
|
TArray<uint8> Data;
|
|
/** Backend to use for storage, my responsibilities are about async puts **/
|
|
FDerivedDataBackendInterface* InnerBackend;
|
|
/** Memory based cache to clear once the put is finished **/
|
|
FDerivedDataBackendInterface* InflightCache;
|
|
/** We remember outstanding puts so that we don't do them redundantly **/
|
|
FThreadSet* FilesInFlight;
|
|
/**If true, then do not attempt skip the put even if CachedDataProbablyExists returns true **/
|
|
bool bPutEvenIfExists;
|
|
/** Usage stats to track thread times. */
|
|
FDerivedDataCacheUsageStats& UsageStats;
|
|
|
|
/** Constructor
|
|
*/
|
|
FCachePutAsyncWorker(const TCHAR* InCacheKey, const TArray<uint8>* InData, FDerivedDataBackendInterface* InInnerBackend, bool InbPutEvenIfExists, FDerivedDataBackendInterface* InInflightCache, FThreadSet* InInFilesInFlight, FDerivedDataCacheUsageStats& InUsageStats)
|
|
: CacheKey(InCacheKey)
|
|
, Data(*InData)
|
|
, InnerBackend(InInnerBackend)
|
|
, InflightCache(InInflightCache)
|
|
, FilesInFlight(InInFilesInFlight)
|
|
, bPutEvenIfExists(InbPutEvenIfExists)
|
|
, UsageStats(InUsageStats)
|
|
{
|
|
check(InnerBackend);
|
|
}
|
|
|
|
/** Call the inner backend and when that completes, remove the memory cache */
|
|
void DoWork()
|
|
{
|
|
COOK_STAT(auto Timer = UsageStats.TimePut());
|
|
bool bOk = true;
|
|
const bool bAlreadyExists = InnerBackend->CachedDataProbablyExists(*CacheKey);
|
|
if (!bAlreadyExists || bPutEvenIfExists)
|
|
{
|
|
InnerBackend->PutCachedData(*CacheKey, Data, bPutEvenIfExists);
|
|
COOK_STAT(Timer.AddHit(Data.Num()));
|
|
}
|
|
// if it already existed, don't bother checking if we need to retry. We don't.
|
|
if (InflightCache && !bAlreadyExists && !InnerBackend->CachedDataProbablyExists(*CacheKey))
|
|
{
|
|
// retry
|
|
InnerBackend->PutCachedData(*CacheKey, Data, false);
|
|
if (!InnerBackend->CachedDataProbablyExists(*CacheKey))
|
|
{
|
|
UE_LOG(LogDerivedDataCache, Warning, TEXT("FDerivedDataBackendAsyncPutWrapper: Put failed, keeping in memory copy %s."),*CacheKey);
|
|
bOk = false;
|
|
}
|
|
}
|
|
if (bOk && InflightCache)
|
|
{
|
|
InflightCache->RemoveCachedData(*CacheKey, /*bTransient=*/ false); // we can remove this from the temp cache, since the real cache will hit now
|
|
}
|
|
FilesInFlight->Remove(CacheKey);
|
|
FDerivedDataBackend::Get().AddToAsyncCompletionCounter(-1);
|
|
}
|
|
|
|
FORCEINLINE TStatId GetStatId() const
|
|
{
|
|
RETURN_QUICK_DECLARE_CYCLE_STAT(FCachePutAsyncWorker, STATGROUP_ThreadPoolAsyncTasks);
|
|
}
|
|
|
|
/** Indicates to the thread pool that this task is abandonable */
|
|
bool CanAbandon()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
/** Abandon routine, we need to remove the item from the in flight cache because something might be waiting for that */
|
|
void Abandon()
|
|
{
|
|
if (InflightCache)
|
|
{
|
|
InflightCache->RemoveCachedData(*CacheKey, /*bTransient=*/ false); // we can remove this from the temp cache, since the real cache will hit now
|
|
}
|
|
FilesInFlight->Remove(CacheKey);
|
|
FDerivedDataBackend::Get().AddToAsyncCompletionCounter(-1);
|
|
}
|
|
};
|
|
|
|
|
|
/**
|
|
* A backend wrapper that coordinates async puts. This means that a Get will hit an in-memory cache while the async put is still in flight.
|
|
**/
|
|
class FDerivedDataBackendAsyncPutWrapper : public FDerivedDataBackendInterface
|
|
{
|
|
public:
|
|
|
|
/**
|
|
* Constructor
|
|
*
|
|
* @param InInnerBackend Backend to use for storage, my responsibilities are about async puts
|
|
* @param bCacheInFlightPuts if true, cache in-flight puts in a memory cache so that they hit immediately
|
|
*/
|
|
FDerivedDataBackendAsyncPutWrapper(FDerivedDataBackendInterface* InInnerBackend, bool bCacheInFlightPuts)
|
|
: InnerBackend(InInnerBackend)
|
|
, InflightCache(bCacheInFlightPuts ? (new FMemoryDerivedDataBackend) : NULL)
|
|
{
|
|
check(InnerBackend);
|
|
}
|
|
|
|
/** return true if this cache is writable **/
|
|
virtual bool IsWritable() override
|
|
{
|
|
return InnerBackend->IsWritable();
|
|
}
|
|
|
|
/**
|
|
* Synchronous test for the existence of a cache item
|
|
*
|
|
* @param CacheKey Alphanumeric+underscore key of this cache item
|
|
* @return true if the data probably will be found, this can't be guaranteed because of concurrency in the backends, corruption, etc
|
|
*/
|
|
virtual bool CachedDataProbablyExists(const TCHAR* CacheKey) override
|
|
{
|
|
COOK_STAT(auto Timer = UsageStats.TimeProbablyExists());
|
|
bool Result = (InflightCache && InflightCache->CachedDataProbablyExists(CacheKey)) || InnerBackend->CachedDataProbablyExists(CacheKey);
|
|
COOK_STAT(if (Result) { Timer.AddHit(0); });
|
|
return Result;
|
|
}
|
|
/**
|
|
* Synchronous retrieve of a cache item
|
|
*
|
|
* @param CacheKey Alphanumeric+underscore key of this cache item
|
|
* @param OutData Buffer to receive the results, if any were found
|
|
* @return true if any data was found, and in this case OutData is non-empty
|
|
*/
|
|
virtual bool GetCachedData(const TCHAR* CacheKey, TArray<uint8>& OutData) override
|
|
{
|
|
COOK_STAT(auto Timer = UsageStats.TimeGet());
|
|
if (InflightCache && InflightCache->GetCachedData(CacheKey, OutData))
|
|
{
|
|
COOK_STAT(Timer.AddHit(OutData.Num()));
|
|
return true;
|
|
}
|
|
bool bSuccess = InnerBackend->GetCachedData(CacheKey, OutData);
|
|
if (bSuccess)
|
|
{
|
|
COOK_STAT(Timer.AddHit(OutData.Num()));
|
|
}
|
|
return bSuccess;
|
|
}
|
|
/**
|
|
* Asynchronous, fire-and-forget placement of a cache item
|
|
*
|
|
* @param CacheKey Alphanumeric+underscore key of this cache item
|
|
* @param InData Buffer containing the data to cache, can be destroyed after the call returns, immediately
|
|
* @param bPutEvenIfExists If true, then do not attempt skip the put even if CachedDataProbablyExists returns true
|
|
*/
|
|
virtual void PutCachedData(const TCHAR* CacheKey, TArray<uint8>& InData, bool bPutEvenIfExists) override
|
|
{
|
|
COOK_STAT(auto Timer = PutSyncUsageStats.TimePut());
|
|
if (!InnerBackend->IsWritable())
|
|
{
|
|
return; // no point in continuing down the chain
|
|
}
|
|
const bool bAdded = FilesInFlight.AddIfNotExists(CacheKey);
|
|
if (!bAdded)
|
|
{
|
|
return; // if it is already on its way, we don't need to send it again
|
|
}
|
|
if (InflightCache)
|
|
{
|
|
if (InflightCache->CachedDataProbablyExists(CacheKey))
|
|
{
|
|
return; // if it is already on its way, we don't need to send it again
|
|
}
|
|
InflightCache->PutCachedData(CacheKey, InData, true); // temp copy stored in memory while the async task waits to complete
|
|
COOK_STAT(Timer.AddHit(InData.Num()));
|
|
}
|
|
FDerivedDataBackend::Get().AddToAsyncCompletionCounter(1);
|
|
(new FAutoDeleteAsyncTask<FCachePutAsyncWorker>(CacheKey, &InData, InnerBackend, bPutEvenIfExists, InflightCache.GetOwnedPointer(), &FilesInFlight, UsageStats))->StartBackgroundTask();
|
|
}
|
|
|
|
virtual void RemoveCachedData(const TCHAR* CacheKey, bool bTransient) override
|
|
{
|
|
if (!InnerBackend->IsWritable())
|
|
{
|
|
return; // no point in continuing down the chain
|
|
}
|
|
while (FilesInFlight.Exists(CacheKey))
|
|
{
|
|
FPlatformProcess::Sleep(0.0f); // this is an exception condition (corruption), spin and wait for it to clear
|
|
}
|
|
if (InflightCache)
|
|
{
|
|
InflightCache->RemoveCachedData(CacheKey, bTransient);
|
|
}
|
|
InnerBackend->RemoveCachedData(CacheKey, bTransient);
|
|
}
|
|
|
|
virtual void GatherUsageStats(TMap<FString, FDerivedDataCacheUsageStats>& UsageStatsMap, FString&& GraphPath) override
|
|
{
|
|
COOK_STAT(
|
|
{
|
|
UsageStatsMap.Add(GraphPath + TEXT(": AsyncPut"), UsageStats);
|
|
UsageStatsMap.Add(GraphPath + TEXT(": AsyncPutSync"), PutSyncUsageStats);
|
|
if (InnerBackend)
|
|
{
|
|
InnerBackend->GatherUsageStats(UsageStatsMap, GraphPath + TEXT(". 0"));
|
|
}
|
|
if (InflightCache)
|
|
{
|
|
InflightCache->GatherUsageStats(UsageStatsMap, GraphPath + TEXT(". 1"));
|
|
}
|
|
});
|
|
}
|
|
|
|
private:
|
|
FDerivedDataCacheUsageStats UsageStats;
|
|
FDerivedDataCacheUsageStats PutSyncUsageStats;
|
|
|
|
/** Backend to use for storage, my responsibilities are about async puts **/
|
|
FDerivedDataBackendInterface* InnerBackend;
|
|
/** Memory based cache to deal with gets that happen while an async put is still in flight **/
|
|
TScopedPointer<FDerivedDataBackendInterface> InflightCache;
|
|
/** We remember outstanding puts so that we don't do them redundantly **/
|
|
FThreadSet FilesInFlight;
|
|
};
|
|
|
|
|
|
|