Merge remote-tracking branch 'origin/1.11' into sdl_platform_1.11
# Conflicts: # Source/Engine/Platform/Windows/WindowsPlatform.cpp # Source/Tools/Flax.Build/Build/ProjectTarget.cs # Source/Tools/Flax.Build/Configuration.cs
This commit is contained in:
@@ -748,6 +748,11 @@ void AndroidPlatform::Sleep(int32 milliseconds)
|
||||
usleep(milliseconds * 1000);
|
||||
}
|
||||
|
||||
void AndroidPlatform::Yield()
|
||||
{
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
double AndroidPlatform::GetTimeSeconds()
|
||||
{
|
||||
struct timespec ts;
|
||||
|
||||
@@ -30,6 +30,10 @@ public:
|
||||
{
|
||||
__sync_synchronize();
|
||||
}
|
||||
FORCE_INLINE static void MemoryPrefetch(void const* ptr)
|
||||
{
|
||||
__builtin_prefetch(static_cast<char const*>(ptr));
|
||||
}
|
||||
FORCE_INLINE static int64 InterlockedExchange(int64 volatile* dst, int64 exchange)
|
||||
{
|
||||
return __sync_lock_test_and_set(dst, exchange);
|
||||
@@ -74,10 +78,6 @@ public:
|
||||
{
|
||||
__atomic_store(dst, &value, __ATOMIC_RELAXED);
|
||||
}
|
||||
FORCE_INLINE static void Prefetch(void const* ptr)
|
||||
{
|
||||
__builtin_prefetch(static_cast<char const*>(ptr));
|
||||
}
|
||||
static bool Is64BitPlatform();
|
||||
static String GetSystemName();
|
||||
static Version GetSystemVersion();
|
||||
@@ -91,6 +91,7 @@ public:
|
||||
static void SetThreadPriority(ThreadPriority priority);
|
||||
static void SetThreadAffinityMask(uint64 affinityMask);
|
||||
static void Sleep(int32 milliseconds);
|
||||
static void Yield();
|
||||
static double GetTimeSeconds();
|
||||
static uint64 GetTimeCycles();
|
||||
FORCE_INLINE static uint64 GetClockFrequency()
|
||||
|
||||
@@ -2,6 +2,13 @@
|
||||
|
||||
#if PLATFORM_MAC || PLATFORM_IOS
|
||||
|
||||
#if PLATFORM_MAC
|
||||
#define PLATFORM_MAC_CACHED 1
|
||||
#endif
|
||||
#if PLATFORM_IOS
|
||||
#define PLATFORM_IOS_CACHED 1
|
||||
#endif
|
||||
|
||||
#include "ApplePlatform.h"
|
||||
#include "AppleUtils.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
@@ -50,6 +57,25 @@
|
||||
#include <cxxabi.h>
|
||||
#endif
|
||||
|
||||
// System includes break those defines
|
||||
#undef PLATFORM_MAC
|
||||
#if PLATFORM_MAC_CACHED
|
||||
#define PLATFORM_MAC 1
|
||||
#else
|
||||
#define PLATFORM_MAC 0
|
||||
#endif
|
||||
#undef PLATFORM_IOS
|
||||
#if PLATFORM_IOS_CACHED
|
||||
#define PLATFORM_IOS 1
|
||||
#else
|
||||
#define PLATFORM_IOS 0
|
||||
#endif
|
||||
|
||||
#if PLATFORM_IOS
|
||||
#include <sys/resource.h>
|
||||
extern "C" int proc_pid_rusage(int pid, int flavor, rusage_info_t *buffer) __OSX_AVAILABLE_STARTING(__MAC_10_9, __IPHONE_7_0);
|
||||
#endif
|
||||
|
||||
CPUInfo Cpu;
|
||||
String UserLocale;
|
||||
double SecondsPerCycle;
|
||||
@@ -224,8 +250,17 @@ MemoryStats ApplePlatform::GetMemoryStats()
|
||||
ProcessMemoryStats ApplePlatform::GetProcessMemoryStats()
|
||||
{
|
||||
ProcessMemoryStats result;
|
||||
result.UsedPhysicalMemory = 1024;
|
||||
result.UsedVirtualMemory = 1024;
|
||||
#if PLATFORM_IOS
|
||||
rusage_info_current rusage_payload;
|
||||
proc_pid_rusage(getpid(), RUSAGE_INFO_CURRENT, (rusage_info_t*)&rusage_payload);
|
||||
result.UsedPhysicalMemory = rusage_payload.ri_phys_footprint;
|
||||
#else
|
||||
mach_task_basic_info_data_t taskInfo;
|
||||
mach_msg_type_number_t count = MACH_TASK_BASIC_INFO_COUNT;
|
||||
task_info(mach_task_self(), MACH_TASK_BASIC_INFO, (task_info_t)&taskInfo, &count);
|
||||
result.UsedPhysicalMemory = taskInfo.resident_size;
|
||||
#endif
|
||||
result.UsedVirtualMemory = result.UsedPhysicalMemory;
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -258,6 +293,15 @@ void ApplePlatform::Sleep(int32 milliseconds)
|
||||
usleep(milliseconds * 1000);
|
||||
}
|
||||
|
||||
void ApplePlatform::Yield()
|
||||
{
|
||||
#if PLATFORM_ARCH_ARM64
|
||||
__builtin_arm_yield();
|
||||
#else
|
||||
_mm_pause();
|
||||
#endif
|
||||
}
|
||||
|
||||
double ApplePlatform::GetTimeSeconds()
|
||||
{
|
||||
return SecondsPerCycle * mach_absolute_time();
|
||||
|
||||
@@ -21,6 +21,10 @@ public:
|
||||
{
|
||||
__sync_synchronize();
|
||||
}
|
||||
FORCE_INLINE static void MemoryPrefetch(void const* ptr)
|
||||
{
|
||||
__builtin_prefetch(static_cast<char const*>(ptr));
|
||||
}
|
||||
FORCE_INLINE static int64 InterlockedExchange(int64 volatile* dst, int64 exchange)
|
||||
{
|
||||
return __sync_lock_test_and_set(dst, exchange);
|
||||
@@ -61,10 +65,6 @@ public:
|
||||
{
|
||||
__atomic_store_n((volatile int64*)dst, value, __ATOMIC_RELAXED);
|
||||
}
|
||||
FORCE_INLINE static void Prefetch(void const* ptr)
|
||||
{
|
||||
__builtin_prefetch(static_cast<char const*>(ptr));
|
||||
}
|
||||
static bool Is64BitPlatform();
|
||||
static String GetSystemName();
|
||||
static Version GetSystemVersion();
|
||||
@@ -75,6 +75,7 @@ public:
|
||||
static void SetThreadPriority(ThreadPriority priority);
|
||||
static void SetThreadAffinityMask(uint64 affinityMask);
|
||||
static void Sleep(int32 milliseconds);
|
||||
static void Yield();
|
||||
static double GetTimeSeconds();
|
||||
static uint64 GetTimeCycles();
|
||||
static uint64 GetClockFrequency();
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "Engine/Core/Utilities.h"
|
||||
#if COMPILE_WITH_PROFILER
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Profiler/ProfilerMemory.h"
|
||||
#endif
|
||||
#include "Engine/Threading/Threading.h"
|
||||
#include "Engine/Engine/CommandLine.h"
|
||||
@@ -206,6 +207,16 @@ void PlatformBase::Exit()
|
||||
|
||||
#if COMPILE_WITH_PROFILER
|
||||
|
||||
#define TEST_MALLOC 0
|
||||
#if TEST_MALLOC
|
||||
#include "Engine/Utilities/MallocTester.h"
|
||||
MallocTester& GetMallocTester()
|
||||
{
|
||||
static MallocTester MallocTest;
|
||||
return MallocTest;
|
||||
}
|
||||
#endif
|
||||
|
||||
#define TRACY_ENABLE_MEMORY (TRACY_ENABLE)
|
||||
|
||||
void PlatformBase::OnMemoryAlloc(void* ptr, uint64 size)
|
||||
@@ -213,12 +224,21 @@ void PlatformBase::OnMemoryAlloc(void* ptr, uint64 size)
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
#if TEST_MALLOC
|
||||
if (GetMallocTester().OnMalloc(ptr, size))
|
||||
LOG(Fatal, "Invalid mallloc detected for pointer 0x{0:x} ({1} bytes)!\n{2}", (uintptr)ptr, size, Platform::GetStackTrace(3));
|
||||
#endif
|
||||
|
||||
#if TRACY_ENABLE_MEMORY
|
||||
// Track memory allocation in Tracy
|
||||
//tracy::Profiler::MemAlloc(ptr, (size_t)size, false);
|
||||
tracy::Profiler::MemAllocCallstack(ptr, (size_t)size, 12, false);
|
||||
#endif
|
||||
|
||||
// Register in memory profiler
|
||||
if (ProfilerMemory::Enabled)
|
||||
ProfilerMemory::OnMemoryAlloc(ptr, size);
|
||||
|
||||
// Register allocation during the current CPU event
|
||||
auto thread = ProfilerCPU::GetCurrentThread();
|
||||
if (thread != nullptr && thread->Buffer.GetCount() != 0)
|
||||
@@ -236,10 +256,19 @@ void PlatformBase::OnMemoryFree(void* ptr)
|
||||
if (!ptr)
|
||||
return;
|
||||
|
||||
// Register in memory profiler
|
||||
if (ProfilerMemory::Enabled)
|
||||
ProfilerMemory::OnMemoryFree(ptr);
|
||||
|
||||
#if TRACY_ENABLE_MEMORY
|
||||
// Track memory allocation in Tracy
|
||||
tracy::Profiler::MemFree(ptr, false);
|
||||
#endif
|
||||
|
||||
#if TEST_MALLOC
|
||||
if (GetMallocTester().OnFree(ptr))
|
||||
LOG(Fatal, "Invalid free detected for pointer 0x{0:x}!\n{1}", (uintptr)ptr, Platform::GetStackTrace(3));
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -325,10 +354,11 @@ void PlatformBase::Fatal(const StringView& msg, void* context, FatalErrorType er
|
||||
Engine::RequestingExit();
|
||||
|
||||
// Collect crash info (platform-dependant implementation that might collect stack trace and/or create memory dump)
|
||||
#if LOG_ENABLE
|
||||
{
|
||||
// Log separation for crash info
|
||||
LOG_FLUSH();
|
||||
Log::Logger::WriteFloor();
|
||||
LOG_FLOOR();
|
||||
LOG(Error, "");
|
||||
LOG(Error, "Critical error! Reason: {0}", msg);
|
||||
LOG(Error, "");
|
||||
@@ -396,6 +426,12 @@ void PlatformBase::Fatal(const StringView& msg, void* context, FatalErrorType er
|
||||
LOG(Error, "External Used Physical Memory: {0} ({1}%)", Utilities::BytesToText(externalUsedPhysical), (int32)(100 * externalUsedPhysical / memoryStats.TotalPhysicalMemory));
|
||||
LOG(Error, "External Used Virtual Memory: {0} ({1}%)", Utilities::BytesToText(externalUsedVirtual), (int32)(100 * externalUsedVirtual / memoryStats.TotalVirtualMemory));
|
||||
}
|
||||
#if COMPILE_WITH_PROFILER
|
||||
if (error == FatalErrorType::OutOfMemory || error == FatalErrorType::GPUOutOfMemory)
|
||||
{
|
||||
ProfilerMemory::Dump();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
if (Log::Logger::LogFilePath.HasChars())
|
||||
{
|
||||
@@ -408,13 +444,14 @@ void PlatformBase::Fatal(const StringView& msg, void* context, FatalErrorType er
|
||||
|
||||
// Capture the original log file
|
||||
LOG(Error, "");
|
||||
Log::Logger::WriteFloor();
|
||||
LOG_FLOOR();
|
||||
LOG_FLUSH();
|
||||
FileSystem::CopyFile(crashDataFolder / TEXT("Log.txt"), Log::Logger::LogFilePath);
|
||||
|
||||
LOG(Error, "Crash info collected.");
|
||||
Log::Logger::WriteFloor();
|
||||
LOG_FLOOR();
|
||||
}
|
||||
#endif
|
||||
|
||||
// Show error message
|
||||
if (Engine::ReportCrash.IsBinded())
|
||||
|
||||
@@ -186,7 +186,7 @@ DECLARE_SCRIPTING_TYPE_MINIMAL(PlatformBase);
|
||||
static void BeforeExit();
|
||||
|
||||
/// <summary>
|
||||
/// Called after engine exit to shutdown platform service.
|
||||
/// Called after engine exit to shut down platform service.
|
||||
/// </summary>
|
||||
static void Exit();
|
||||
|
||||
@@ -246,6 +246,12 @@ public:
|
||||
/// </summary>
|
||||
static void MemoryBarrier() = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates to the processor that a cache line will be needed in the near future.
|
||||
/// </summary>
|
||||
/// <param name="ptr">The address of the cache line to be loaded. This address is not required to be on a cache line boundary.</param>
|
||||
static void MemoryPrefetch(void const* ptr) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Sets a 64-bit variable to the specified value as an atomic operation. The function prevents more than one thread from using the same variable simultaneously.
|
||||
/// </summary>
|
||||
@@ -257,7 +263,7 @@ public:
|
||||
/// <summary>
|
||||
/// Performs an atomic compare-and-exchange operation on the specified values. The function compares two specified 32-bit values and exchanges with another 32-bit value based on the outcome of the comparison.
|
||||
/// </summary>
|
||||
/// <remarks>The function compares the dst value with the comperand value. If the dst value is equal to the comperand value, the value value is stored in the address specified by dst. Otherwise, no operation is performed.</remarks>
|
||||
/// <remarks>The function compares the dst value with the comperand value. If the dst value is equal to the comperand value, the value is stored in the address specified by dst. Otherwise, no operation is performed.</remarks>
|
||||
/// <param name="dst">A pointer to the first operand. This value will be replaced with the result of the operation.</param>
|
||||
/// <param name="exchange">The value to exchange.</param>
|
||||
/// <param name="comperand">The value to compare to destination.</param>
|
||||
@@ -267,7 +273,7 @@ public:
|
||||
/// <summary>
|
||||
/// Performs an atomic compare-and-exchange operation on the specified values. The function compares two specified 64-bit values and exchanges with another 64-bit value based on the outcome of the comparison.
|
||||
/// </summary>
|
||||
/// <remarks>The function compares the dst value with the comperand value. If the dst value is equal to the comperand value, the value value is stored in the address specified by dst. Otherwise, no operation is performed.</remarks>
|
||||
/// <remarks>The function compares the dst value with the comperand value. If the dst value is equal to the comperand value, the value is stored in the address specified by dst. Otherwise, no operation is performed.</remarks>
|
||||
/// <param name="dst">A pointer to the first operand. This value will be replaced with the result of the operation.</param>
|
||||
/// <param name="exchange">The value to exchange.</param>
|
||||
/// <param name="comperand">The value to compare to destination.</param>
|
||||
@@ -293,7 +299,7 @@ public:
|
||||
/// </summary>
|
||||
/// <param name="dst">A pointer to the first operand. This value will be replaced with the result of the operation.</param>
|
||||
/// <param name="value">The second operand.</param>
|
||||
/// <returns>The result value of the operation.</returns>
|
||||
/// <returns>The original value of the dst parameter.</returns>
|
||||
static int64 InterlockedAdd(int64 volatile* dst, int64 value) = delete;
|
||||
|
||||
/// <summary>
|
||||
@@ -324,12 +330,6 @@ public:
|
||||
/// <param name="value">The value to be set.</param>
|
||||
static void AtomicStore(int64 volatile* dst, int64 value) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates to the processor that a cache line will be needed in the near future.
|
||||
/// </summary>
|
||||
/// <param name="ptr">The address of the cache line to be loaded. This address is not required to be on a cache line boundary.</param>
|
||||
static void Prefetch(void const* ptr) = delete;
|
||||
|
||||
#if COMPILE_WITH_PROFILER
|
||||
static void OnMemoryAlloc(void* ptr, uint64 size);
|
||||
static void OnMemoryFree(void* ptr);
|
||||
@@ -458,11 +458,16 @@ public:
|
||||
static void SetThreadAffinityMask(uint64 affinityMask) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Suspends the execution of the current thread until the time-out interval elapses
|
||||
/// Suspends the execution of the current thread until the time-out interval elapses.
|
||||
/// </summary>
|
||||
/// <param name="milliseconds">The time interval for which execution is to be suspended, in milliseconds.</param>
|
||||
static void Sleep(int32 milliseconds) = delete;
|
||||
|
||||
/// <summary>
|
||||
/// Yields the execution of the current thread to another thread that is ready to run on the current processor.
|
||||
/// </summary>
|
||||
static void Yield() = delete;
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Gets the current time in seconds.
|
||||
|
||||
@@ -16,6 +16,30 @@ constexpr char DirectorySeparatorChar = '\\';
|
||||
constexpr char AltDirectorySeparatorChar = '/';
|
||||
constexpr char VolumeSeparatorChar = ':';
|
||||
|
||||
int32 StringUtils::Copy(char* dst, const Char* src, int32 count)
|
||||
{
|
||||
int32 i = 0;
|
||||
while (i < count && src[i])
|
||||
{
|
||||
dst[i] = (char)src[i];
|
||||
i++;
|
||||
}
|
||||
dst[i] = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
int32 StringUtils::Copy(Char* dst, const char* src, int32 count)
|
||||
{
|
||||
int32 i = 0;
|
||||
while (i < count && src[i])
|
||||
{
|
||||
dst[i] = (Char)src[i];
|
||||
i++;
|
||||
}
|
||||
dst[i] = 0;
|
||||
return i;
|
||||
}
|
||||
|
||||
const Char* StringUtils::FindIgnoreCase(const Char* str, const Char* toFind)
|
||||
{
|
||||
if (toFind == nullptr || str == nullptr)
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Engine/Platform/IGuiData.h"
|
||||
#include "Engine/Scripting/ScriptingType.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Profiler/ProfilerMemory.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MException.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MUtils.h"
|
||||
#include "Engine/Scripting/ManagedCLR/MMethod.h"
|
||||
@@ -213,6 +214,7 @@ void WindowBase::SetRenderingEnabled(bool value)
|
||||
void WindowBase::OnCharInput(Char c)
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnCharInput");
|
||||
PROFILE_MEM(UI);
|
||||
CharInput(c);
|
||||
INVOKE_EVENT_PARAMS_1(OnCharInput, &c);
|
||||
}
|
||||
@@ -220,6 +222,7 @@ void WindowBase::OnCharInput(Char c)
|
||||
void WindowBase::OnKeyDown(KeyboardKeys key)
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnKeyDown");
|
||||
PROFILE_MEM(UI);
|
||||
KeyDown(key);
|
||||
INVOKE_EVENT_PARAMS_1(OnKeyDown, &key);
|
||||
}
|
||||
@@ -227,6 +230,7 @@ void WindowBase::OnKeyDown(KeyboardKeys key)
|
||||
void WindowBase::OnKeyUp(KeyboardKeys key)
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnKeyUp");
|
||||
PROFILE_MEM(UI);
|
||||
KeyUp(key);
|
||||
INVOKE_EVENT_PARAMS_1(OnKeyUp, &key);
|
||||
}
|
||||
@@ -234,6 +238,7 @@ void WindowBase::OnKeyUp(KeyboardKeys key)
|
||||
void WindowBase::OnMouseDown(const Float2& mousePosition, MouseButton button)
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnMouseDown");
|
||||
PROFILE_MEM(UI);
|
||||
MouseDown(mousePosition, button);
|
||||
INVOKE_EVENT_PARAMS_2(OnMouseDown, (void*)&mousePosition, &button);
|
||||
}
|
||||
@@ -241,6 +246,7 @@ void WindowBase::OnMouseDown(const Float2& mousePosition, MouseButton button)
|
||||
void WindowBase::OnMouseUp(const Float2& mousePosition, MouseButton button)
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnMouseUp");
|
||||
PROFILE_MEM(UI);
|
||||
MouseUp(mousePosition, button);
|
||||
INVOKE_EVENT_PARAMS_2(OnMouseUp, (void*)&mousePosition, &button);
|
||||
}
|
||||
@@ -248,6 +254,7 @@ void WindowBase::OnMouseUp(const Float2& mousePosition, MouseButton button)
|
||||
void WindowBase::OnMouseDoubleClick(const Float2& mousePosition, MouseButton button)
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnMouseDoubleClick");
|
||||
PROFILE_MEM(UI);
|
||||
MouseDoubleClick(mousePosition, button);
|
||||
INVOKE_EVENT_PARAMS_2(OnMouseDoubleClick, (void*)&mousePosition, &button);
|
||||
}
|
||||
@@ -255,6 +262,7 @@ void WindowBase::OnMouseDoubleClick(const Float2& mousePosition, MouseButton but
|
||||
void WindowBase::OnMouseWheel(const Float2& mousePosition, float delta)
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnMouseWheel");
|
||||
PROFILE_MEM(UI);
|
||||
MouseWheel(mousePosition, delta);
|
||||
INVOKE_EVENT_PARAMS_2(OnMouseWheel, (void*)&mousePosition, &delta);
|
||||
}
|
||||
@@ -262,6 +270,7 @@ void WindowBase::OnMouseWheel(const Float2& mousePosition, float delta)
|
||||
void WindowBase::OnMouseMove(const Float2& mousePosition)
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnMouseMove");
|
||||
PROFILE_MEM(UI);
|
||||
MouseMove(mousePosition);
|
||||
INVOKE_EVENT_PARAMS_1(OnMouseMove, (void*)&mousePosition);
|
||||
}
|
||||
@@ -276,6 +285,7 @@ void WindowBase::OnMouseMoveRelative(const Float2& mousePositionRelative)
|
||||
void WindowBase::OnMouseLeave()
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnMouseLeave");
|
||||
PROFILE_MEM(UI);
|
||||
MouseLeave();
|
||||
INVOKE_EVENT_PARAMS_0(OnMouseLeave);
|
||||
}
|
||||
@@ -283,6 +293,7 @@ void WindowBase::OnMouseLeave()
|
||||
void WindowBase::OnTouchDown(const Float2& pointerPosition, int32 pointerId)
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnTouchDown");
|
||||
PROFILE_MEM(UI);
|
||||
TouchDown(pointerPosition, pointerId);
|
||||
INVOKE_EVENT_PARAMS_2(OnTouchDown, (void*)&pointerPosition, &pointerId);
|
||||
}
|
||||
@@ -290,6 +301,7 @@ void WindowBase::OnTouchDown(const Float2& pointerPosition, int32 pointerId)
|
||||
void WindowBase::OnTouchMove(const Float2& pointerPosition, int32 pointerId)
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnTouchMove");
|
||||
PROFILE_MEM(UI);
|
||||
TouchMove(pointerPosition, pointerId);
|
||||
INVOKE_EVENT_PARAMS_2(OnTouchMove, (void*)&pointerPosition, &pointerId);
|
||||
}
|
||||
@@ -297,6 +309,7 @@ void WindowBase::OnTouchMove(const Float2& pointerPosition, int32 pointerId)
|
||||
void WindowBase::OnTouchUp(const Float2& pointerPosition, int32 pointerId)
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnTouchUp");
|
||||
PROFILE_MEM(UI);
|
||||
TouchUp(pointerPosition, pointerId);
|
||||
INVOKE_EVENT_PARAMS_2(OnTouchUp, (void*)&pointerPosition, &pointerId);
|
||||
}
|
||||
@@ -407,6 +420,7 @@ bool WindowBase::GetMouseButtonUp(MouseButton button) const
|
||||
void WindowBase::OnShow()
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnShow");
|
||||
PROFILE_MEM(UI);
|
||||
INVOKE_EVENT_PARAMS_0(OnShow);
|
||||
Shown();
|
||||
}
|
||||
@@ -414,10 +428,13 @@ void WindowBase::OnShow()
|
||||
void WindowBase::OnResize(int32 width, int32 height)
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnResize");
|
||||
PROFILE_MEM_BEGIN(Graphics);
|
||||
if (_swapChain)
|
||||
_swapChain->Resize(width, height);
|
||||
if (RenderTask)
|
||||
RenderTask->Resize(width, height);
|
||||
PROFILE_MEM_END();
|
||||
PROFILE_MEM(UI);
|
||||
Resized({ static_cast<float>(width), static_cast<float>(height) });
|
||||
INVOKE_EVENT_PARAMS_2(OnResize, &width, &height);
|
||||
}
|
||||
@@ -469,6 +486,7 @@ void WindowBase::OnLostFocus()
|
||||
void WindowBase::OnUpdate(float dt)
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnUpdate");
|
||||
PROFILE_MEM(UI);
|
||||
Update(dt);
|
||||
INVOKE_EVENT_PARAMS_1(OnUpdate, &dt);
|
||||
}
|
||||
@@ -476,6 +494,7 @@ void WindowBase::OnUpdate(float dt)
|
||||
void WindowBase::OnDraw()
|
||||
{
|
||||
PROFILE_CPU_NAMED("GUI.OnDraw");
|
||||
PROFILE_MEM(UI);
|
||||
INVOKE_EVENT_PARAMS_0(OnDraw);
|
||||
Draw();
|
||||
}
|
||||
@@ -483,6 +502,7 @@ void WindowBase::OnDraw()
|
||||
bool WindowBase::InitSwapChain()
|
||||
{
|
||||
// Setup swapchain
|
||||
PROFILE_MEM(Graphics);
|
||||
if (_swapChain == nullptr)
|
||||
{
|
||||
_swapChain = GPUDevice::Instance->CreateSwapChain((Window*)this);
|
||||
|
||||
@@ -177,6 +177,9 @@ API_ENUM() enum class ArchitectureType
|
||||
#ifndef PLATFORM_DESKTOP
|
||||
#define PLATFORM_DESKTOP 0
|
||||
#endif
|
||||
#ifndef PLATFORM_CONSOLE
|
||||
#define PLATFORM_CONSOLE 0
|
||||
#endif
|
||||
#ifndef PLATFORM_ARCH_X64
|
||||
#define PLATFORM_ARCH_X64 0
|
||||
#endif
|
||||
@@ -201,6 +204,9 @@ API_ENUM() enum class ArchitectureType
|
||||
#ifndef PLATFORM_THREADS_LIMIT
|
||||
#define PLATFORM_THREADS_LIMIT 64
|
||||
#endif
|
||||
#ifndef PLATFORM_MEMORY_ALIGNMENT
|
||||
#define PLATFORM_MEMORY_ALIGNMENT 16
|
||||
#endif
|
||||
#define PLATFORM_32BITS (!PLATFORM_64BITS)
|
||||
|
||||
// Platform family defines
|
||||
@@ -210,28 +216,22 @@ API_ENUM() enum class ArchitectureType
|
||||
#define PLATFORM_UNIX_FAMILY (PLATFORM_LINUX || PLATFORM_ANDROID || PLATFORM_PS4 || PLATFORM_PS5 || PLATFORM_APPLE_FAMILY)
|
||||
|
||||
// SIMD defines
|
||||
#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) || defined(__SSE2__)
|
||||
#if !defined(PLATFORM_SIMD_SSE2) && (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_X64) || defined(__SSE2__))
|
||||
#define PLATFORM_SIMD_SSE2 1
|
||||
#if defined(__SSE3__)
|
||||
#if !defined(PLATFORM_SIMD_SSE3) && (defined(__SSE3__))
|
||||
#define PLATFORM_SIMD_SSE3 1
|
||||
#endif
|
||||
#if defined(__SSE4__)
|
||||
#define PLATFORM_SIMD_SSE4 1
|
||||
#endif
|
||||
#if defined(__SSE4_1__)
|
||||
#if !defined(PLATFORM_SIMD_SSE4_1) && (defined(__SSE4_1__))
|
||||
#define PLATFORM_SIMD_SSE4_1 1
|
||||
#endif
|
||||
#if defined(__SSE4_2__)
|
||||
#if !defined(PLATFORM_SIMD_SSE4_2) && (defined(__SSE4_2__))
|
||||
#define PLATFORM_SIMD_SSE4_2 1
|
||||
#endif
|
||||
#endif
|
||||
#if defined(_M_ARM) || defined(__ARM_NEON__) || defined(__ARM_NEON)
|
||||
#if !defined(PLATFORM_SIMD_NEON) && (defined(_M_ARM) || defined(__ARM_NEON__) || defined(__ARM_NEON))
|
||||
#define PLATFORM_SIMD_NEON 1
|
||||
#endif
|
||||
#if defined(_M_PPC) || defined(__CELLOS_LV2__)
|
||||
#define PLATFORM_SIMD_VMX 1
|
||||
#endif
|
||||
#define PLATFORM_SIMD (PLATFORM_SIMD_SSE2 || PLATFORM_SIMD_SSE3 || PLATFORM_SIMD_SSE4 || PLATFORM_SIMD_NEON || PLATFORM_SIMD_VMX)
|
||||
#define PLATFORM_SIMD (PLATFORM_SIMD_SSE2 || PLATFORM_SIMD_SSE3 || PLATFORM_SIMD_SSE4_1 || PLATFORM_SIMD_SSE4_2 || PLATFORM_SIMD_NEON)
|
||||
|
||||
// Unicode text macro
|
||||
#if !defined(TEXT)
|
||||
|
||||
@@ -1854,6 +1854,11 @@ void LinuxPlatform::Sleep(int32 milliseconds)
|
||||
usleep(milliseconds * 1000);
|
||||
}
|
||||
|
||||
void LinuxPlatform::Yield()
|
||||
{
|
||||
sched_yield();
|
||||
}
|
||||
|
||||
double LinuxPlatform::GetTimeSeconds()
|
||||
{
|
||||
struct timespec ts;
|
||||
@@ -3061,8 +3066,10 @@ int32 LinuxPlatform::CreateProcess(CreateProcessSettings& settings)
|
||||
String line(lineBuffer);
|
||||
if (settings.SaveOutput)
|
||||
settings.Output.Add(line.Get(), line.Length());
|
||||
#if LOG_ENABLE
|
||||
if (settings.LogOutput)
|
||||
Log::Logger::Write(LogType::Info, line);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
int stat_loc;
|
||||
|
||||
@@ -45,6 +45,10 @@ public:
|
||||
{
|
||||
__sync_synchronize();
|
||||
}
|
||||
FORCE_INLINE static void MemoryPrefetch(void const* ptr)
|
||||
{
|
||||
__builtin_prefetch(static_cast<char const*>(ptr));
|
||||
}
|
||||
FORCE_INLINE static int64 InterlockedExchange(int64 volatile* dst, int64 exchange)
|
||||
{
|
||||
return __sync_lock_test_and_set(dst, exchange);
|
||||
@@ -89,10 +93,6 @@ public:
|
||||
{
|
||||
__atomic_store(dst, &value, __ATOMIC_SEQ_CST);
|
||||
}
|
||||
FORCE_INLINE static void Prefetch(void const* ptr)
|
||||
{
|
||||
__builtin_prefetch(static_cast<char const*>(ptr));
|
||||
}
|
||||
static bool Is64BitPlatform();
|
||||
static String GetSystemName();
|
||||
static Version GetSystemVersion();
|
||||
@@ -106,6 +106,7 @@ public:
|
||||
static void SetThreadPriority(ThreadPriority priority);
|
||||
static void SetThreadAffinityMask(uint64 affinityMask);
|
||||
static void Sleep(int32 milliseconds);
|
||||
static void Yield();
|
||||
static double GetTimeSeconds();
|
||||
static uint64 GetTimeCycles();
|
||||
FORCE_INLINE static uint64 GetClockFrequency()
|
||||
|
||||
@@ -491,6 +491,7 @@ int32 MacPlatform::CreateProcess(CreateProcessSettings& settings)
|
||||
String line((const char*)data.bytes, data.length);
|
||||
if (settings.SaveOutput)
|
||||
settings.Output.Add(line.Get(), line.Length());
|
||||
#if LOG_ENABLE
|
||||
if (settings.LogOutput)
|
||||
{
|
||||
StringView lineView(line);
|
||||
@@ -498,6 +499,7 @@ int32 MacPlatform::CreateProcess(CreateProcessSettings& settings)
|
||||
lineView = StringView(line.Get(), line.Length() - 1);
|
||||
Log::Logger::Write(LogType::Info, lineView);
|
||||
}
|
||||
#endif
|
||||
[[stdoutPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
|
||||
}
|
||||
}
|
||||
@@ -518,6 +520,7 @@ int32 MacPlatform::CreateProcess(CreateProcessSettings& settings)
|
||||
String line((const char*)data.bytes, data.length);
|
||||
if (settings.SaveOutput)
|
||||
settings.Output.Add(line.Get(), line.Length());
|
||||
#if LOG_ENABLE
|
||||
if (settings.LogOutput)
|
||||
{
|
||||
StringView lineView(line);
|
||||
@@ -525,6 +528,7 @@ int32 MacPlatform::CreateProcess(CreateProcessSettings& settings)
|
||||
lineView = StringView(line.Get(), line.Length() - 1);
|
||||
Log::Logger::Write(LogType::Error, lineView);
|
||||
}
|
||||
#endif
|
||||
[[stderrPipe fileHandleForReading] waitForDataInBackgroundAndNotify];
|
||||
}
|
||||
}
|
||||
|
||||
@@ -715,6 +715,11 @@ MacWindow::MacWindow(const CreateWindowSettings& settings)
|
||||
styleMask |= NSWindowStyleMaskTitled;
|
||||
styleMask &= ~NSWindowStyleMaskFullSizeContentView;
|
||||
}
|
||||
else
|
||||
{
|
||||
styleMask |= NSWindowStyleMaskBorderless;
|
||||
styleMask &= ~NSWindowStyleMaskTitled;
|
||||
}
|
||||
|
||||
const float screenScale = MacPlatform::ScreenScale;
|
||||
frame.origin.x /= screenScale;
|
||||
|
||||
15
Source/Engine/Platform/ReadWriteLock.h
Normal file
15
Source/Engine/Platform/ReadWriteLock.h
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if PLATFORM_WINDOWS || PLATFORM_UWP || PLATFORM_XBOX_ONE || PLATFORM_XBOX_SCARLETT
|
||||
#include "Win32/Win32ReadWriteLock.h"
|
||||
#elif PLATFORM_LINUX || PLATFORM_ANDROID || PLATFORM_PS4 || PLATFORM_PS5 || PLATFORM_MAC || PLATFORM_IOS
|
||||
#include "Unix/UnixReadWriteLock.h"
|
||||
#elif PLATFORM_SWITCH
|
||||
#include "Platforms/Switch/Engine/Platform/SwitchReadWriteLock.h"
|
||||
#else
|
||||
#error Missing Read Write Lock implementation!
|
||||
#endif
|
||||
|
||||
#include "Types.h"
|
||||
@@ -125,6 +125,12 @@ public:
|
||||
// Copies the string (count is maximum amount of characters to copy).
|
||||
static Char* Copy(Char* dst, const Char* src, int32 count);
|
||||
|
||||
// Copies the string (count is maximum amount of characters to copy). Returns amount of copied elements (excluding null terminator character).
|
||||
static int32 Copy(char* dst, const Char* src, int32 count);
|
||||
|
||||
// Copies the string (count is maximum amount of characters to copy). Returns amount of copied elements (excluding null terminator character).
|
||||
static int32 Copy(Char* dst, const char* src, int32 count);
|
||||
|
||||
// Finds specific sub-string in the input string. Returns the first found position in the input string or nulll if failed.
|
||||
static const Char* Find(const Char* str, const Char* toFind);
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@
|
||||
|
||||
class Win32CriticalSection;
|
||||
typedef Win32CriticalSection CriticalSection;
|
||||
class Win32ReadWriteLock;
|
||||
typedef Win32ReadWriteLock ReadWriteLock;
|
||||
class Win32ConditionVariable;
|
||||
typedef Win32ConditionVariable ConditionVariable;
|
||||
class WindowsFileSystem;
|
||||
@@ -35,6 +37,8 @@ typedef WindowsScreenUtilities ScreenUtilities;
|
||||
|
||||
class Win32CriticalSection;
|
||||
typedef Win32CriticalSection CriticalSection;
|
||||
class Win32ReadWriteLock;
|
||||
typedef Win32ReadWriteLock ReadWriteLock;
|
||||
class Win32ConditionVariable;
|
||||
typedef Win32ConditionVariable ConditionVariable;
|
||||
class UWPFileSystem;
|
||||
@@ -62,6 +66,8 @@ typedef ScreenUtilitiesBase ScreenUtilities;
|
||||
|
||||
class UnixCriticalSection;
|
||||
typedef UnixCriticalSection CriticalSection;
|
||||
class UnixReadWriteLock;
|
||||
typedef UnixReadWriteLock ReadWriteLock;
|
||||
class UnixConditionVariable;
|
||||
typedef UnixConditionVariable ConditionVariable;
|
||||
class LinuxFileSystem;
|
||||
@@ -91,6 +97,8 @@ typedef LinuxScreenUtilities ScreenUtilities;
|
||||
|
||||
class UnixCriticalSection;
|
||||
typedef UnixCriticalSection CriticalSection;
|
||||
class UnixReadWriteLock;
|
||||
typedef UnixReadWriteLock ReadWriteLock;
|
||||
class UnixConditionVariable;
|
||||
typedef UnixConditionVariable ConditionVariable;
|
||||
class PS4FileSystem;
|
||||
@@ -118,6 +126,8 @@ typedef ScreenUtilitiesBase ScreenUtilities;
|
||||
|
||||
class UnixCriticalSection;
|
||||
typedef UnixCriticalSection CriticalSection;
|
||||
class UnixReadWriteLock;
|
||||
typedef UnixReadWriteLock ReadWriteLock;
|
||||
class UnixConditionVariable;
|
||||
typedef UnixConditionVariable ConditionVariable;
|
||||
class PS5FileSystem;
|
||||
@@ -145,6 +155,8 @@ typedef ScreenUtilitiesBase ScreenUtilities;
|
||||
|
||||
class Win32CriticalSection;
|
||||
typedef Win32CriticalSection CriticalSection;
|
||||
class Win32ReadWriteLock;
|
||||
typedef Win32ReadWriteLock ReadWriteLock;
|
||||
class Win32ConditionVariable;
|
||||
typedef Win32ConditionVariable ConditionVariable;
|
||||
class XboxOneFileSystem;
|
||||
@@ -172,6 +184,8 @@ typedef ScreenUtilitiesBase ScreenUtilities;
|
||||
|
||||
class Win32CriticalSection;
|
||||
typedef Win32CriticalSection CriticalSection;
|
||||
class Win32ReadWriteLock;
|
||||
typedef Win32ReadWriteLock ReadWriteLock;
|
||||
class Win32ConditionVariable;
|
||||
typedef Win32ConditionVariable ConditionVariable;
|
||||
class XboxScarlettFileSystem;
|
||||
@@ -199,6 +213,8 @@ typedef ScreenUtilitiesBase ScreenUtilities;
|
||||
|
||||
class UnixCriticalSection;
|
||||
typedef UnixCriticalSection CriticalSection;
|
||||
class UnixReadWriteLock;
|
||||
typedef UnixReadWriteLock ReadWriteLock;
|
||||
class UnixConditionVariable;
|
||||
typedef UnixConditionVariable ConditionVariable;
|
||||
class AndroidFileSystem;
|
||||
@@ -226,6 +242,8 @@ typedef ScreenUtilitiesBase ScreenUtilities;
|
||||
|
||||
class SwitchCriticalSection;
|
||||
typedef SwitchCriticalSection CriticalSection;
|
||||
class SwitchReadWriteLock;
|
||||
typedef SwitchReadWriteLock ReadWriteLock;
|
||||
class SwitchConditionVariable;
|
||||
typedef SwitchConditionVariable ConditionVariable;
|
||||
class SwitchFileSystem;
|
||||
@@ -253,6 +271,8 @@ typedef ScreenUtilitiesBase ScreenUtilities;
|
||||
|
||||
class UnixCriticalSection;
|
||||
typedef UnixCriticalSection CriticalSection;
|
||||
class UnixReadWriteLock;
|
||||
typedef UnixReadWriteLock ReadWriteLock;
|
||||
class UnixConditionVariable;
|
||||
typedef UnixConditionVariable ConditionVariable;
|
||||
class MacFileSystem;
|
||||
@@ -282,6 +302,8 @@ typedef MacScreenUtilities ScreenUtilities;
|
||||
|
||||
class UnixCriticalSection;
|
||||
typedef UnixCriticalSection CriticalSection;
|
||||
class UnixReadWriteLock;
|
||||
typedef UnixReadWriteLock ReadWriteLock;
|
||||
class UnixConditionVariable;
|
||||
typedef UnixConditionVariable ConditionVariable;
|
||||
class iOSFileSystem;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
// Platform description
|
||||
#define PLATFORM_TYPE PlatformType::UWP
|
||||
#define PLATFORM_DESKTOP 1
|
||||
|
||||
// Use AOT for Mono
|
||||
#define USE_MONO_AOT 1
|
||||
|
||||
71
Source/Engine/Platform/Unix/UnixReadWriteLock.h
Normal file
71
Source/Engine/Platform/Unix/UnixReadWriteLock.h
Normal file
@@ -0,0 +1,71 @@
|
||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if PLATFORM_UNIX
|
||||
|
||||
#include "Engine/Platform/Platform.h"
|
||||
#include <pthread.h>
|
||||
|
||||
/// <summary>
|
||||
/// Unix implementation of a read/write lock that allows for shared reading by multiple threads and exclusive writing by a single thread.
|
||||
/// </summary>
|
||||
class FLAXENGINE_API UnixReadWriteLock
|
||||
{
|
||||
private:
|
||||
mutable pthread_rwlock_t _lock;
|
||||
|
||||
private:
|
||||
NON_COPYABLE(UnixReadWriteLock);
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UnixReadWriteLock"/> class.
|
||||
/// </summary>
|
||||
UnixReadWriteLock()
|
||||
{
|
||||
pthread_rwlock_init(&_lock, nullptr);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="UnixReadWriteLock"/> class.
|
||||
/// </summary>
|
||||
~UnixReadWriteLock()
|
||||
{
|
||||
pthread_rwlock_destroy(&_lock);
|
||||
}
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Locks for shared reading.
|
||||
/// </summary>
|
||||
void ReadLock() const
|
||||
{
|
||||
pthread_rwlock_rdlock(&_lock);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the lock after shared reading.
|
||||
/// </summary>
|
||||
void ReadUnlock() const
|
||||
{
|
||||
pthread_rwlock_unlock(&_lock);
|
||||
}
|
||||
/// <summary>
|
||||
/// Locks for exclusive writing.
|
||||
/// </summary>
|
||||
void WriteLock() const
|
||||
{
|
||||
pthread_rwlock_wrlock(&_lock);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the lock after exclusive writing.
|
||||
/// </summary>
|
||||
void WriteUnlock() const
|
||||
{
|
||||
pthread_rwlock_unlock(&_lock);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -4,6 +4,9 @@
|
||||
|
||||
#include "UnixThread.h"
|
||||
#include "Engine/Core/Log.h"
|
||||
#if PLATFORM_APPLE_FAMILY
|
||||
#include "Engine/Utilities/StringConverter.h"
|
||||
#endif
|
||||
#include "Engine/Threading/IRunnable.h"
|
||||
#include "Engine/Threading/ThreadRegistry.h"
|
||||
|
||||
@@ -29,7 +32,8 @@ void* UnixThread::ThreadProc(void* pThis)
|
||||
#if PLATFORM_APPLE_FAMILY
|
||||
// Apple doesn't support creating named thread so assign name here
|
||||
{
|
||||
pthread_setname_np(StringAnsi(thread->GetName()).Get());
|
||||
const String& name = thread->GetName();
|
||||
pthread_setname_np(StringAsANSI<>(name.Get(), name.Length()).Get());
|
||||
}
|
||||
#endif
|
||||
const int32 exitCode = thread->Run();
|
||||
|
||||
@@ -68,6 +68,7 @@
|
||||
#undef CreateMutex
|
||||
#undef DrawState
|
||||
#undef LoadLibrary
|
||||
#undef Yield
|
||||
#undef GetEnvironmentVariable
|
||||
#undef SetEnvironmentVariable
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Win32ConditionVariable"/> class.
|
||||
/// </summary>
|
||||
Win32ConditionVariable()
|
||||
__forceinline Win32ConditionVariable()
|
||||
{
|
||||
Windows::InitializeConditionVariable(&_cond);
|
||||
}
|
||||
@@ -44,7 +44,7 @@ public:
|
||||
/// Blocks the current thread execution until the condition variable is woken up.
|
||||
/// </summary>
|
||||
/// <param name="lock">The critical section locked by the current thread.</param>
|
||||
void Wait(const Win32CriticalSection& lock)
|
||||
__forceinline void Wait(const Win32CriticalSection& lock)
|
||||
{
|
||||
Windows::SleepConditionVariableCS(&_cond, &lock._criticalSection, 0xFFFFFFFF);
|
||||
}
|
||||
@@ -55,7 +55,7 @@ public:
|
||||
/// <param name="lock">The critical section locked by the current thread.</param>
|
||||
/// <param name="timeout">The time-out interval, in milliseconds. If the time-out interval elapses, the function re-acquires the critical section and returns zero. If timeout is zero, the function tests the states of the specified objects and returns immediately. If timeout is INFINITE, the function's time-out interval never elapses.</param>
|
||||
/// <returns>If the function succeeds, the return value is true, otherwise, if the function fails or the time-out interval elapses, the return value is false.</returns>
|
||||
bool Wait(const Win32CriticalSection& lock, const int32 timeout)
|
||||
__forceinline bool Wait(const Win32CriticalSection& lock, const int32 timeout)
|
||||
{
|
||||
return !!Windows::SleepConditionVariableCS(&_cond, &lock._criticalSection, timeout);
|
||||
}
|
||||
@@ -63,7 +63,7 @@ public:
|
||||
/// <summary>
|
||||
/// Notifies one waiting thread.
|
||||
/// </summary>
|
||||
void NotifyOne()
|
||||
__forceinline void NotifyOne()
|
||||
{
|
||||
Windows::WakeConditionVariable(&_cond);
|
||||
}
|
||||
@@ -71,7 +71,7 @@ public:
|
||||
/// <summary>
|
||||
/// Notifies all waiting threads.
|
||||
/// </summary>
|
||||
void NotifyAll()
|
||||
__forceinline void NotifyAll()
|
||||
{
|
||||
Windows::WakeAllConditionVariable(&_cond);
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Win32CriticalSection"/> class.
|
||||
/// </summary>
|
||||
Win32CriticalSection()
|
||||
__forceinline Win32CriticalSection()
|
||||
{
|
||||
Windows::InitializeCriticalSectionEx(&_criticalSection, 4000, 0x01000000);
|
||||
}
|
||||
@@ -34,7 +34,7 @@ public:
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="Win32CriticalSection"/> class.
|
||||
/// </summary>
|
||||
~Win32CriticalSection()
|
||||
__forceinline ~Win32CriticalSection()
|
||||
{
|
||||
Windows::DeleteCriticalSection(&_criticalSection);
|
||||
}
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
/// <summary>
|
||||
/// Locks the critical section.
|
||||
/// </summary>
|
||||
void Lock() const
|
||||
__forceinline void Lock() const
|
||||
{
|
||||
Windows::EnterCriticalSection(&_criticalSection);
|
||||
}
|
||||
@@ -52,7 +52,7 @@ public:
|
||||
/// Attempts to enter a critical section without blocking. If the call is successful, the calling thread takes ownership of the critical section.
|
||||
/// </summary>
|
||||
/// <returns>True if calling thread took ownership of the critical section.</returns>
|
||||
bool TryLock() const
|
||||
__forceinline bool TryLock() const
|
||||
{
|
||||
return Windows::TryEnterCriticalSection(&_criticalSection) != 0;
|
||||
}
|
||||
@@ -60,7 +60,7 @@ public:
|
||||
/// <summary>
|
||||
/// Releases the lock on the critical section.
|
||||
/// </summary>
|
||||
void Unlock() const
|
||||
__forceinline void Unlock() const
|
||||
{
|
||||
Windows::LeaveCriticalSection(&_criticalSection);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#if PLATFORM_WIN32
|
||||
|
||||
// Platform description
|
||||
#define PLATFORM_DESKTOP 1
|
||||
#if defined(WIN64) && defined(_M_X64)
|
||||
#define PLATFORM_64BITS 1
|
||||
#define PLATFORM_ARCH_X64 1
|
||||
|
||||
@@ -251,7 +251,7 @@ void Win32Platform::MemoryBarrier()
|
||||
#endif
|
||||
}
|
||||
|
||||
void Win32Platform::Prefetch(void const* ptr)
|
||||
void Win32Platform::MemoryPrefetch(void const* ptr)
|
||||
{
|
||||
#if _M_ARM64
|
||||
__prefetch((char const*)ptr);
|
||||
@@ -283,14 +283,23 @@ void* Win32Platform::AllocatePages(uint64 numPages, uint64 pageSize)
|
||||
{
|
||||
const uint64 numBytes = numPages * pageSize;
|
||||
#if PLATFORM_UWP
|
||||
return VirtualAllocFromApp(nullptr, (SIZE_T)numBytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
void* ptr = VirtualAllocFromApp(nullptr, (SIZE_T)numBytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
#else
|
||||
return VirtualAlloc(nullptr, (SIZE_T)numBytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
void* ptr = VirtualAlloc(nullptr, (SIZE_T)numBytes, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
|
||||
#endif
|
||||
if (!ptr)
|
||||
OutOfMemory();
|
||||
#if COMPILE_WITH_PROFILER
|
||||
OnMemoryAlloc(ptr, numBytes);
|
||||
#endif
|
||||
return ptr;
|
||||
}
|
||||
|
||||
void Win32Platform::FreePages(void* ptr)
|
||||
{
|
||||
#if COMPILE_WITH_PROFILER
|
||||
OnMemoryFree(ptr);
|
||||
#endif
|
||||
VirtualFree(ptr, 0, MEM_RELEASE);
|
||||
}
|
||||
|
||||
@@ -391,6 +400,11 @@ void Win32Platform::Sleep(int32 milliseconds)
|
||||
WaitForSingleObject(timer, INFINITE);
|
||||
}
|
||||
|
||||
void Win32Platform::Yield()
|
||||
{
|
||||
SwitchToThread();
|
||||
}
|
||||
|
||||
double Win32Platform::GetTimeSeconds()
|
||||
{
|
||||
LARGE_INTEGER counter;
|
||||
|
||||
@@ -23,6 +23,7 @@ public:
|
||||
static bool Init();
|
||||
static void Exit();
|
||||
static void MemoryBarrier();
|
||||
static void MemoryPrefetch(void const* ptr);
|
||||
static int64 InterlockedExchange(int64 volatile* dst, int64 exchange)
|
||||
{
|
||||
#if WIN64
|
||||
@@ -83,7 +84,6 @@ public:
|
||||
_interlockedexchange64(dst, value);
|
||||
#endif
|
||||
}
|
||||
static void Prefetch(void const* ptr);
|
||||
static void* Allocate(uint64 size, uint64 alignment);
|
||||
static void Free(void* ptr);
|
||||
static void* AllocatePages(uint64 numPages, uint64 pageSize);
|
||||
@@ -100,6 +100,7 @@ public:
|
||||
static void SetThreadPriority(ThreadPriority priority);
|
||||
static void SetThreadAffinityMask(uint64 affinityMask);
|
||||
static void Sleep(int32 milliseconds);
|
||||
static void Yield();
|
||||
static double GetTimeSeconds();
|
||||
static uint64 GetTimeCycles();
|
||||
static uint64 GetClockFrequency();
|
||||
|
||||
69
Source/Engine/Platform/Win32/Win32ReadWriteLock.h
Normal file
69
Source/Engine/Platform/Win32/Win32ReadWriteLock.h
Normal file
@@ -0,0 +1,69 @@
|
||||
// Copyright (c) Wojciech Figat. All rights reserved.
|
||||
|
||||
#pragma once
|
||||
|
||||
#if PLATFORM_WIN32
|
||||
|
||||
#include "WindowsMinimal.h"
|
||||
|
||||
/// <summary>
|
||||
/// Win32 implementation of a read/write lock that allows for shared reading by multiple threads and exclusive writing by a single thread.
|
||||
/// </summary>
|
||||
class FLAXENGINE_API Win32ReadWriteLock
|
||||
{
|
||||
private:
|
||||
mutable Windows::SRWLOCK _lock;
|
||||
|
||||
private:
|
||||
NON_COPYABLE(Win32ReadWriteLock);
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Win32ReadWriteLock"/> class.
|
||||
/// </summary>
|
||||
Win32ReadWriteLock()
|
||||
{
|
||||
Windows::InitializeSRWLock(&_lock);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Finalizes an instance of the <see cref="Win32ReadWriteLock"/> class.
|
||||
/// </summary>
|
||||
~Win32ReadWriteLock()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
/// <summary>
|
||||
/// Locks for shared reading.
|
||||
/// </summary>
|
||||
__forceinline void ReadLock() const
|
||||
{
|
||||
Windows::AcquireSRWLockShared(&_lock);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the lock after shared reading.
|
||||
/// </summary>
|
||||
__forceinline void ReadUnlock() const
|
||||
{
|
||||
Windows::ReleaseSRWLockShared(&_lock);
|
||||
}
|
||||
/// <summary>
|
||||
/// Locks for exclusive writing.
|
||||
/// </summary>
|
||||
__forceinline void WriteLock() const
|
||||
{
|
||||
Windows::AcquireSRWLockExclusive(&_lock);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases the lock after exclusive writing.
|
||||
/// </summary>
|
||||
__forceinline void WriteUnlock() const
|
||||
{
|
||||
Windows::ReleaseSRWLockExclusive(&_lock);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -65,6 +65,11 @@ namespace Windows
|
||||
void* Ptr;
|
||||
};
|
||||
|
||||
struct SRWLOCK
|
||||
{
|
||||
void* Ptr;
|
||||
};
|
||||
|
||||
struct OVERLAPPED
|
||||
{
|
||||
void* Data1[3];
|
||||
@@ -96,6 +101,12 @@ namespace Windows
|
||||
WIN_API void WIN_API_CALLCONV WakeConditionVariable(CONDITION_VARIABLE* ConditionVariable);
|
||||
WIN_API void WIN_API_CALLCONV WakeAllConditionVariable(CONDITION_VARIABLE* ConditionVariable);
|
||||
|
||||
WIN_API void WIN_API_CALLCONV InitializeSRWLock(SRWLOCK* SRWLock);
|
||||
WIN_API void WIN_API_CALLCONV AcquireSRWLockShared(SRWLOCK* SRWLock);
|
||||
WIN_API void WIN_API_CALLCONV ReleaseSRWLockShared(SRWLOCK* SRWLock);
|
||||
WIN_API void WIN_API_CALLCONV AcquireSRWLockExclusive(SRWLOCK* SRWLock);
|
||||
WIN_API void WIN_API_CALLCONV ReleaseSRWLockExclusive(SRWLOCK* SRWLock);
|
||||
|
||||
class IDataObject;
|
||||
typedef GUID IID;
|
||||
|
||||
|
||||
@@ -9,5 +9,6 @@
|
||||
// Platform description
|
||||
#define PLATFORM_TYPE PlatformType::Windows
|
||||
#define PLATFORM_HAS_HEADLESS_MODE 1
|
||||
#define PLATFORM_DESKTOP 1
|
||||
|
||||
#endif
|
||||
|
||||
@@ -258,6 +258,37 @@ void GetWindowsVersion(String& windowsName, int32& versionMajor, int32& versionM
|
||||
RegCloseKey(hKey);
|
||||
}
|
||||
|
||||
#if PLATFORM_ARCH_X86 || PLATFORM_ARCH_X64
|
||||
|
||||
struct CPUBrand
|
||||
{
|
||||
char Buffer[0x40];
|
||||
|
||||
CPUBrand()
|
||||
{
|
||||
Buffer[0] = 0;
|
||||
int32 cpuInfo[4];
|
||||
__cpuid(cpuInfo, 0x80000000);
|
||||
if (cpuInfo[0] >= 0x80000004)
|
||||
{
|
||||
// Get name
|
||||
for (uint32 i = 0; i < 3; i++)
|
||||
{
|
||||
__cpuid(cpuInfo, 0x80000002 + i);
|
||||
memcpy(Buffer + i * sizeof(cpuInfo), cpuInfo, sizeof(cpuInfo));
|
||||
}
|
||||
|
||||
// Trim ending whitespaces
|
||||
int32 size = StringUtils::Length(Buffer);
|
||||
while (size > 1 && Buffer[size - 1] == ' ')
|
||||
size--;
|
||||
Buffer[size] = 0;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#if !PLATFORM_SDL
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
||||
@@ -523,6 +554,60 @@ void WindowsPlatform::PreInit(void* hInstance)
|
||||
ASSERT(hInstance);
|
||||
Instance = hInstance;
|
||||
|
||||
#if PLATFORM_ARCH_X86 || PLATFORM_ARCH_X64
|
||||
// Check the minimum vector instruction set support
|
||||
int32 cpuInfo[4] = { -1 };
|
||||
__cpuid(cpuInfo, 0);
|
||||
int32 cpuInfoSize = cpuInfo[0];
|
||||
__cpuid(cpuInfo, 1);
|
||||
bool SSE2 = cpuInfo[3] & (1u << 26);
|
||||
bool SSE3 = cpuInfo[2] & (1u << 0);
|
||||
bool SSE41 = cpuInfo[2] & (1u << 19);
|
||||
bool SSE42 = cpuInfo[2] & (1u << 20);
|
||||
bool AVX = cpuInfo[2] & (1u << 28);
|
||||
bool POPCNT = cpuInfo[2] & (1u << 23);
|
||||
bool AVX2 = false;
|
||||
if (cpuInfoSize >= 7)
|
||||
{
|
||||
__cpuid(cpuInfo, 7);
|
||||
AVX2 = cpuInfo[1] & (1u << 5) && (_xgetbv(0) & 6) == 6;
|
||||
}
|
||||
const Char* missingFeature = nullptr;
|
||||
#if defined(__AVX__)
|
||||
if (!AVX)
|
||||
missingFeature = TEXT("AVX");
|
||||
#endif
|
||||
#if defined(__AVX2__)
|
||||
if (!AVX2)
|
||||
missingFeature = TEXT("AVX2");
|
||||
#endif
|
||||
#if PLATFORM_SIMD_SSE2
|
||||
if (!SSE2)
|
||||
missingFeature = TEXT("SSE2");
|
||||
#endif
|
||||
#if PLATFORM_SIMD_SSE3
|
||||
if (!SSE3)
|
||||
missingFeature = TEXT("SSE3");
|
||||
#endif
|
||||
#if PLATFORM_SIMD_SSE4_1
|
||||
if (!SSE41)
|
||||
missingFeature = TEXT("SSE4.1");
|
||||
#endif
|
||||
#if PLATFORM_SIMD_SSE4_2
|
||||
if (!SSE42)
|
||||
missingFeature = TEXT("SSE4.2");
|
||||
if (!POPCNT)
|
||||
missingFeature = TEXT("POPCNT");
|
||||
#endif
|
||||
if (missingFeature)
|
||||
{
|
||||
// Not supported CPU
|
||||
CPUBrand cpu;
|
||||
Error(String::Format(TEXT("Cannot start program due to lack of CPU feature {}.\n\n{}"), missingFeature, String(cpu.Buffer)));
|
||||
exit(-1);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Disable the process from being showing "ghosted" while not responding messages during slow tasks
|
||||
DisableProcessWindowsGhosting();
|
||||
|
||||
@@ -564,14 +649,8 @@ void WindowsPlatform::PreInit(void* hInstance)
|
||||
FlaxDbgHelpUnlock();
|
||||
#endif
|
||||
|
||||
// Get system version
|
||||
GetWindowsVersion(WindowsName, VersionMajor, VersionMinor, VersionBuild);
|
||||
|
||||
// Validate platform
|
||||
if (VersionMajor < 6)
|
||||
{
|
||||
Error(TEXT("Not supported operating system version."));
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
bool WindowsPlatform::IsWindows10()
|
||||
@@ -648,25 +727,25 @@ bool WindowsPlatform::Init()
|
||||
|
||||
// Check if can run Engine on current platform
|
||||
#if WINVER >= 0x0A00
|
||||
if (!IsWindows10OrGreater() && !IsWindowsServer())
|
||||
if (VersionMajor < 10 && !IsWindowsServer())
|
||||
{
|
||||
Platform::Fatal(TEXT("Flax Engine requires Windows 10 or higher."));
|
||||
return true;
|
||||
}
|
||||
#elif WINVER >= 0x0603
|
||||
if (!IsWindows8Point1OrGreater() && !IsWindowsServer())
|
||||
if ((VersionMajor < 8 || (VersionMajor == 8 && VersionMinor == 0)) && !IsWindowsServer())
|
||||
{
|
||||
Platform::Fatal(TEXT("Flax Engine requires Windows 8.1 or higher."));
|
||||
return true;
|
||||
}
|
||||
#elif WINVER >= 0x0602
|
||||
if (!IsWindows8OrGreater() && !IsWindowsServer())
|
||||
if (VersionMajor < 8 && !IsWindowsServer())
|
||||
{
|
||||
Platform::Fatal(TEXT("Flax Engine requires Windows 8 or higher."));
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
if (!IsWindows7OrGreater() && !IsWindowsServer())
|
||||
if (VersionMajor < 7 && !IsWindowsServer())
|
||||
{
|
||||
Platform::Fatal(TEXT("Flax Engine requires Windows 7 or higher."));
|
||||
return true;
|
||||
@@ -725,20 +804,8 @@ void WindowsPlatform::LogInfo()
|
||||
|
||||
#if PLATFORM_ARCH_X86 || PLATFORM_ARCH_X64
|
||||
// Log CPU brand
|
||||
{
|
||||
char brandBuffer[0x40] = {};
|
||||
int32 cpuInfo[4] = { -1 };
|
||||
__cpuid(cpuInfo, 0x80000000);
|
||||
if (cpuInfo[0] >= 0x80000004)
|
||||
{
|
||||
for (uint32 i = 0; i < 3; i++)
|
||||
{
|
||||
__cpuid(cpuInfo, 0x80000002 + i);
|
||||
memcpy(brandBuffer + i * sizeof(cpuInfo), cpuInfo, sizeof(cpuInfo));
|
||||
}
|
||||
}
|
||||
LOG(Info, "CPU: {0}", String(brandBuffer));
|
||||
}
|
||||
CPUBrand cpu;
|
||||
LOG(Info, "CPU: {0}", String(cpu.Buffer));
|
||||
#endif
|
||||
|
||||
LOG(Info, "Microsoft {0} {1}-bit ({2}.{3}.{4})", WindowsName, Platform::Is64BitPlatform() ? TEXT("64") : TEXT("32"), VersionMajor, VersionMinor, VersionBuild);
|
||||
@@ -1072,8 +1139,10 @@ void ReadPipe(HANDLE pipe, Array<char>& rawData, Array<Char>& logData, LogType l
|
||||
int32 tmp;
|
||||
StringUtils::ConvertANSI2UTF16(rawData.Get(), logData.Get(), rawData.Count(), tmp);
|
||||
logData.Last() = '\0';
|
||||
#if LOG_ENABLE
|
||||
if (settings.LogOutput)
|
||||
Log::Logger::Write(logType, StringView(logData.Get(), rawData.Count()));
|
||||
#endif
|
||||
if (settings.SaveOutput)
|
||||
settings.Output.Add(logData.Get(), rawData.Count());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user