diff --git a/.github/ISSUE_TEMPLATE/1-bug.yaml b/.github/ISSUE_TEMPLATE/1-bug.yaml
index 2e2c65485..a75003f63 100644
--- a/.github/ISSUE_TEMPLATE/1-bug.yaml
+++ b/.github/ISSUE_TEMPLATE/1-bug.yaml
@@ -31,7 +31,7 @@ body:
- '1.10'
- '1.11'
- master branch
- default: 2
+ default: 3
validations:
required: true
- type: textarea
diff --git a/Content/Shaders/ColorGrading.flax b/Content/Shaders/ColorGrading.flax
index 15f723620..716e18593 100644
--- a/Content/Shaders/ColorGrading.flax
+++ b/Content/Shaders/ColorGrading.flax
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:ad1d9597dd930f0b63358dbe8326d131661f9cc2251181eeec0cb44ffc530d7a
-size 12311
+oid sha256:bce57f0ccf6d808985f4d79cc4e15d85cae999bee598d8e93ff5b1b126bc42b8
+size 12310
diff --git a/Flax.flaxproj b/Flax.flaxproj
index 284bc0652..6a37b7a85 100644
--- a/Flax.flaxproj
+++ b/Flax.flaxproj
@@ -4,7 +4,7 @@
"Major": 1,
"Minor": 11,
"Revision": 0,
- "Build": 6801
+ "Build": 6803
},
"Company": "Flax",
"Copyright": "Copyright (c) 2012-2025 Wojciech Figat. All rights reserved.",
diff --git a/README.md b/README.md
index 8e9de0424..f4cc82ee2 100644
--- a/README.md
+++ b/README.md
@@ -49,7 +49,7 @@ Follow the instructions below to compile and run the engine from source.
* Fedora: `sudo dnf install dotnet-sdk-8.0`
* Arch: `sudo pacman -S dotnet-sdk-8.0 dotnet-runtime-8.0 dotnet-targeting-pack-8.0 dotnet-host`
* Install Vulkan SDK ([https://vulkan.lunarg.com/](https://vulkan.lunarg.com/))
- * Ubuntu: `sudo apt install vulkan-sdk`
+ * Ubuntu: `sudo apt install vulkan-sdk` (deprecated, follow official docs)
* Fedora: `sudo dnf install vulkan-headers vulkan-tools vulkan-validation-layers`
* Arch: `sudo pacman -S vulkan-headers vulkan-tools vulkan-validation-layers`
* Install Git with LFS
@@ -60,7 +60,7 @@ Follow the instructions below to compile and run the engine from source.
* Ubuntu: `sudo apt-get install libx11-dev libxcursor-dev libxinerama-dev zlib1g-dev`
* Fedora: `sudo dnf install libX11-devel libXcursor-devel libXinerama-devel ghc-zlib-devel`
* Arch: `sudo pacman -S base-devel libx11 libxcursor libxinerama zlib`
-* Install Clang compiler (version 6 or later):
+* Install Clang compiler (version 14 or later):
* Ubuntu: `sudo apt-get install clang lldb lld`
* Fedora: `sudo dnf install clang llvm lldb lld`
* Arch: `sudo pacman -S clang lldb lld`
diff --git a/Source/Editor/Content/Proxy/AssetProxy.cs b/Source/Editor/Content/Proxy/AssetProxy.cs
index b96b90383..06de5369a 100644
--- a/Source/Editor/Content/Proxy/AssetProxy.cs
+++ b/Source/Editor/Content/Proxy/AssetProxy.cs
@@ -130,6 +130,11 @@ namespace FlaxEditor.Content
eyeAdaptation.Mode = EyeAdaptationMode.None;
eyeAdaptation.OverrideFlags |= EyeAdaptationSettingsOverride.Mode;
preview.PostFxVolume.EyeAdaptation = eyeAdaptation;
+
+ var antiAliasing = preview.PostFxVolume.AntiAliasing;
+ antiAliasing.Mode = AntialiasingMode.FastApproximateAntialiasing;
+ antiAliasing.OverrideFlags |= AntiAliasingSettingsOverride.Mode;
+ preview.PostFxVolume.AntiAliasing = antiAliasing;
}
}
}
diff --git a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
index 356ae5ee4..954599347 100644
--- a/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
+++ b/Source/Editor/CustomEditors/Dedicated/ScriptsEditor.cs
@@ -914,9 +914,11 @@ namespace FlaxEditor.CustomEditors.Dedicated
// Remove drop down arrows and containment lines if no objects in the group
if (group.Children.Count == 0)
{
+ group.Panel.Close();
group.Panel.ArrowImageOpened = null;
group.Panel.ArrowImageClosed = null;
group.Panel.EnableContainmentLines = false;
+ group.Panel.CanOpenClose = false;
}
// Scripts arrange bar
diff --git a/Source/Editor/Editor.cs b/Source/Editor/Editor.cs
index 85e579ec9..66328926d 100644
--- a/Source/Editor/Editor.cs
+++ b/Source/Editor/Editor.cs
@@ -1587,7 +1587,7 @@ namespace FlaxEditor
if (dockedTo != null && dockedTo.SelectedTab != gameWin && dockedTo.SelectedTab != null)
result = dockedTo.SelectedTab.Size;
else
- result = gameWin.Viewport.Size;
+ result = gameWin.Viewport.ContentSize;
result *= root.DpiScale;
result = Float2.Round(result);
diff --git a/Source/Editor/Windows/GameWindow.cs b/Source/Editor/Windows/GameWindow.cs
index 0088ddd71..872e78509 100644
--- a/Source/Editor/Windows/GameWindow.cs
+++ b/Source/Editor/Windows/GameWindow.cs
@@ -10,17 +10,117 @@ using FlaxEditor.Modules;
using FlaxEditor.Options;
using FlaxEngine;
using FlaxEngine.GUI;
-using FlaxEngine.Json;
namespace FlaxEditor.Windows
{
+ ///
+ /// Render output control with content scaling support.
+ ///
+ public class ScaledRenderOutputControl : RenderOutputControl
+ {
+ ///
+ /// Custom scale.
+ ///
+ public float ContentScale = 1.0f;
+
+ ///
+ /// Actual bounds size for content (incl. scale).
+ ///
+ public Float2 ContentSize => Size / ContentScale;
+
+ ///
+ public ScaledRenderOutputControl(SceneRenderTask task)
+ : base(task)
+ {
+ }
+
+ ///
+ public override void Draw()
+ {
+ DrawSelf();
+
+ // Draw children with scale
+ var scaling = new Float3(ContentScale, ContentScale, 1);
+ Matrix3x3.Scaling(ref scaling, out Matrix3x3 scale);
+ Render2D.PushTransform(scale);
+ if (ClipChildren)
+ {
+ GetDesireClientArea(out var clientArea);
+ Render2D.PushClip(ref clientArea);
+ DrawChildren();
+ Render2D.PopClip();
+ }
+ else
+ {
+ DrawChildren();
+ }
+
+ Render2D.PopTransform();
+ }
+
+ ///
+ public override void GetDesireClientArea(out Rectangle rect)
+ {
+ // Scale the area for the client controls
+ rect = new Rectangle(Float2.Zero, Size / ContentScale);
+ }
+
+ ///
+ public override bool IntersectsContent(ref Float2 locationParent, out Float2 location)
+ {
+ // Skip local PointFromParent but use base code
+ location = base.PointFromParent(ref locationParent);
+ return ContainsPoint(ref location);
+ }
+
+ ///
+ public override bool IntersectsChildContent(Control child, Float2 location, out Float2 childSpaceLocation)
+ {
+ location /= ContentScale;
+ return base.IntersectsChildContent(child, location, out childSpaceLocation);
+ }
+
+ ///
+ public override bool ContainsPoint(ref Float2 location, bool precise = false)
+ {
+ if (precise) // Ignore as utility-only element
+ return false;
+ return base.ContainsPoint(ref location, precise);
+ }
+
+ ///
+ public override bool RayCast(ref Float2 location, out Control hit)
+ {
+ var p = location / ContentScale;
+ if (RayCastChildren(ref p, out hit))
+ return true;
+ return base.RayCast(ref location, out hit);
+ }
+
+ ///
+ public override Float2 PointToParent(ref Float2 location)
+ {
+ var result = base.PointToParent(ref location);
+ result *= ContentScale;
+ return result;
+ }
+
+ ///
+ public override Float2 PointFromParent(ref Float2 location)
+ {
+ var result = base.PointFromParent(ref location);
+ result /= ContentScale;
+ return result;
+ }
+ }
+
///
/// Provides in-editor play mode simulation.
///
///
public class GameWindow : EditorWindow
{
- private readonly RenderOutputControl _viewport;
+ private readonly ScaledRenderOutputControl _viewport;
private readonly GameRoot _guiRoot;
private bool _showGUI = true, _editGUI = true;
private bool _showDebugDraw = false;
@@ -77,7 +177,7 @@ namespace FlaxEditor.Windows
///
/// Gets the viewport.
///
- public RenderOutputControl Viewport => _viewport;
+ public ScaledRenderOutputControl Viewport => _viewport;
///
/// Gets or sets a value indicating whether show game GUI in the view or keep it hidden.
@@ -295,7 +395,7 @@ namespace FlaxEditor.Windows
var task = MainRenderTask.Instance;
// Setup viewport
- _viewport = new RenderOutputControl(task)
+ _viewport = new ScaledRenderOutputControl(task)
{
AnchorPreset = AnchorPresets.StretchAll,
Offsets = Margin.Zero,
@@ -396,11 +496,8 @@ namespace FlaxEditor.Windows
{
if (v == null)
return;
-
if (v.Size.Y <= 0 || v.Size.X <= 0)
- {
return;
- }
if (string.Equals(v.Label, "Free Aspect", StringComparison.Ordinal) && v.Size == new Int2(1, 1))
{
@@ -448,15 +545,7 @@ namespace FlaxEditor.Windows
private void ResizeViewport()
{
- if (!_freeAspect)
- {
- _windowAspectRatio = Width / Height;
- }
- else
- {
- _windowAspectRatio = 1;
- }
-
+ _windowAspectRatio = _freeAspect ? 1 : Width / Height;
var scaleWidth = _viewportAspectRatio / _windowAspectRatio;
var scaleHeight = _windowAspectRatio / _viewportAspectRatio;
@@ -468,6 +557,24 @@ namespace FlaxEditor.Windows
{
_viewport.Bounds = new Rectangle(Width * (1 - scaleWidth) / 2, 0, Width * scaleWidth, Height);
}
+
+ if (_viewport.KeepAspectRatio)
+ {
+ var resolution = _viewport.CustomResolution.HasValue ? (Float2)_viewport.CustomResolution.Value : Size;
+ if (scaleHeight < 1)
+ {
+ _viewport.ContentScale = _viewport.Width / resolution.X;
+ }
+ else
+ {
+ _viewport.ContentScale = _viewport.Height / resolution.Y;
+ }
+ }
+ else
+ {
+ _viewport.ContentScale = 1;
+ }
+
_viewport.SyncBackbufferSize();
PerformLayout();
}
@@ -907,6 +1014,7 @@ namespace FlaxEditor.Windows
return child.OnNavigate(direction, Float2.Zero, this, visited);
}
}
+
return null;
}
@@ -957,7 +1065,7 @@ namespace FlaxEditor.Windows
else
_defaultScaleActiveIndex = 0;
}
-
+
if (_customScaleActiveIndex != -1)
{
var options = Editor.UI.CustomViewportScaleOptions;
diff --git a/Source/Engine/Engine/NativeInterop.cs b/Source/Engine/Engine/NativeInterop.cs
index 2d8f8db84..209eb54e2 100644
--- a/Source/Engine/Engine/NativeInterop.cs
+++ b/Source/Engine/Engine/NativeInterop.cs
@@ -425,6 +425,8 @@ namespace FlaxEngine.Interop
var fieldOffsetPtr = (IntPtr*)field.FieldHandle.Value; // Pointer to MonoClassField
fieldOffsetPtr += 3; // Skip three pointers (type, name, parent_and_flags)
return *(int*)fieldOffsetPtr - IntPtr.Size * 2; // Load the value of a pointer (4 bytes, int32), then subtracting 16 bytes from it (2 pointers for vtable and threadsync)
+#else
+ throw new NotImplementedException();
#endif
}
diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp
index 64c384447..a26584486 100644
--- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp
+++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp
@@ -491,7 +491,7 @@ void GPUContextDX12::flushUAVs()
ASSERT(uaCount <= GPU_MAX_UA_BINDED);
// Fill table with source descriptors
- DxShaderHeader& header = _currentCompute ? ((GPUShaderProgramCSDX12*)_currentCompute)->Header : _currentState->Header;
+ DxShaderHeader& header = _isCompute ? ((GPUShaderProgramCSDX12*)_currentCompute)->Header : _currentState->Header;
D3D12_CPU_DESCRIPTOR_HANDLE srcDescriptorRangeStarts[GPU_MAX_UA_BINDED];
for (uint32 i = 0; i < uaCount; i++)
{
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp
index 00af99154..c374bbeed 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp
@@ -114,7 +114,7 @@ GPUContextVulkan::GPUContextVulkan(GPUDeviceVulkan* device, QueueVulkan* queue)
#if GPU_ENABLE_TRACY
#if VK_EXT_calibrated_timestamps && VK_EXT_host_query_reset && !PLATFORM_SWITCH
// Use calibrated timestamps extension
- if (vkResetQueryPoolEXT && vkGetCalibratedTimestampsEXT)
+ if (vkResetQueryPoolEXT && vkGetCalibratedTimestampsEXT && _device->PhysicalDeviceFeatures12.hostQueryReset)
{
_tracyContext = tracy::CreateVkContext(_device->Adapter->Gpu, _device->Device, vkResetQueryPoolEXT, vkGetPhysicalDeviceCalibrateableTimeDomainsEXT, vkGetCalibratedTimestampsEXT);
}
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp
index 7c54be973..e96f7b3b3 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp
@@ -1568,7 +1568,15 @@ bool GPUDeviceVulkan::Init()
vkGetPhysicalDeviceQueueFamilyProperties(gpu, &queueCount, QueueFamilyProps.Get());
// Query device features
+ RenderToolsVulkan::ZeroStruct(PhysicalDeviceFeatures12, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_VULKAN_1_2_FEATURES);
vkGetPhysicalDeviceFeatures(gpu, &PhysicalDeviceFeatures);
+ if (vkGetPhysicalDeviceFeatures2)
+ {
+ VkPhysicalDeviceFeatures2 features2;
+ RenderToolsVulkan::ZeroStruct(features2, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2);
+ features2.pNext = &PhysicalDeviceFeatures12;
+ vkGetPhysicalDeviceFeatures2(gpu, &features2);
+ }
// Get extensions and layers
Array deviceExtensions;
@@ -1671,6 +1679,16 @@ bool GPUDeviceVulkan::Init()
VulkanPlatform::RestrictEnabledPhysicalDeviceFeatures(PhysicalDeviceFeatures, enabledFeatures);
deviceInfo.pEnabledFeatures = &enabledFeatures;
+#if GPU_ENABLE_TRACY && VK_EXT_calibrated_timestamps && VK_EXT_host_query_reset
+ VkPhysicalDeviceHostQueryResetFeatures resetFeatures;
+ if (PhysicalDeviceFeatures12.hostQueryReset)
+ {
+ RenderToolsVulkan::ZeroStruct(resetFeatures, VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_HOST_QUERY_RESET_FEATURES);
+ resetFeatures.hostQueryReset = VK_TRUE;
+ deviceInfo.pNext = &resetFeatures;
+ }
+#endif
+
// Create the device
VALIDATE_VULKAN_RESULT(vkCreateDevice(gpu, &deviceInfo, nullptr, &Device));
diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h
index ae265100c..09fa93f3e 100644
--- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h
+++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h
@@ -496,6 +496,7 @@ public:
/// The physical device enabled features.
///
VkPhysicalDeviceFeatures PhysicalDeviceFeatures;
+ VkPhysicalDeviceVulkan12Features PhysicalDeviceFeatures12;
Array TimestampQueryPools;
Array OcclusionQueryPools;
diff --git a/Source/Engine/Networking/NetworkInternal.h b/Source/Engine/Networking/NetworkInternal.h
index 7eb4f7d52..2aade3811 100644
--- a/Source/Engine/Networking/NetworkInternal.h
+++ b/Source/Engine/Networking/NetworkInternal.h
@@ -8,7 +8,7 @@
#endif
// Internal version number of networking implementation. Updated once engine changes serialization or connection rules.
-#define NETWORK_PROTOCOL_VERSION 4
+#define NETWORK_PROTOCOL_VERSION 5
// Enables encoding object ids and typenames via uint32 keys rather than full data send.
#define USE_NETWORK_KEYS 1
@@ -29,6 +29,7 @@ enum class NetworkMessageIDs : uint8
ObjectDespawn,
ObjectRole,
ObjectRpc,
+ ObjectRpcPart,
MAX,
};
@@ -48,6 +49,7 @@ public:
static void OnNetworkMessageObjectDespawn(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer);
static void OnNetworkMessageObjectRole(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer);
static void OnNetworkMessageObjectRpc(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer);
+ static void OnNetworkMessageObjectRpcPart(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer);
#if COMPILE_WITH_PROFILER
diff --git a/Source/Engine/Networking/NetworkManager.cpp b/Source/Engine/Networking/NetworkManager.cpp
index 784bbf51e..36ff94c5c 100644
--- a/Source/Engine/Networking/NetworkManager.cpp
+++ b/Source/Engine/Networking/NetworkManager.cpp
@@ -391,6 +391,7 @@ namespace
NetworkInternal::OnNetworkMessageObjectDespawn,
NetworkInternal::OnNetworkMessageObjectRole,
NetworkInternal::OnNetworkMessageObjectRpc,
+ NetworkInternal::OnNetworkMessageObjectRpcPart,
};
}
diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp
index fba916891..c584d3526 100644
--- a/Source/Engine/Networking/NetworkReplicator.cpp
+++ b/Source/Engine/Networking/NetworkReplicator.cpp
@@ -55,14 +55,14 @@ PACK_STRUCT(struct NetworkMessageObjectReplicate
uint32 OwnerFrame;
});
-PACK_STRUCT(struct NetworkMessageObjectReplicatePayload
+PACK_STRUCT(struct NetworkMessageObjectPartPayload
{
uint16 DataSize;
uint16 PartsCount;
uint16 PartSize;
});
-PACK_STRUCT(struct NetworkMessageObjectReplicatePart
+PACK_STRUCT(struct NetworkMessageObjectPart
{
NetworkMessageIDs ID = NetworkMessageIDs::ObjectReplicatePart;
uint32 OwnerFrame;
@@ -111,7 +111,7 @@ PACK_STRUCT(struct NetworkMessageObjectRole
PACK_STRUCT(struct NetworkMessageObjectRpc
{
NetworkMessageIDs ID = NetworkMessageIDs::ObjectRpc;
- uint16 ArgsSize;
+ uint32 OwnerFrame;
});
struct NetworkReplicatedObject
@@ -182,13 +182,14 @@ struct Serializer
void* Tags[2];
};
-struct ReplicateItem
+struct PartsItem
{
ScriptingObjectReference Object;
Guid ObjectId;
uint16 PartsLeft;
uint32 OwnerFrame;
uint32 OwnerClientId;
+ const void* Tag;
Array Data;
};
@@ -220,7 +221,7 @@ struct DespawnItem
DataContainer Targets;
};
-struct RpcItem
+struct RpcSendItem
{
ScriptingObjectReference Object;
NetworkRpcName Name;
@@ -233,11 +234,12 @@ namespace
{
CriticalSection ObjectsLock;
HashSet Objects;
- Array ReplicationParts;
+ Array ReplicationParts;
+ Array RpcParts;
Array SpawnParts;
Array SpawnQueue;
Array DespawnQueue;
- Array RpcQueue;
+ Array RpcQueue;
Dictionary IdsRemappingTable;
NetworkStream* CachedWriteStream = nullptr;
NetworkStream* CachedReadStream = nullptr;
@@ -251,6 +253,7 @@ namespace
#endif
Array DespawnedObjects;
uint32 SpawnId = 0;
+ uint32 RpcId = 0;
#if USE_EDITOR
void OnScriptsReloading()
@@ -505,6 +508,76 @@ void SetupObjectSpawnMessageItem(SpawnItem* e, NetworkMessage& msg)
msg.WriteStructure(msgDataItem);
}
+void SendInParts(NetworkPeer* peer, NetworkChannelType channel, const byte* data, const uint16 dataSize, NetworkMessage& msg, const NetworkRpcName& name, bool toServer, const Guid& objectId, uint32 ownerFrame, NetworkMessageIDs partId)
+{
+ NetworkMessageObjectPartPayload msgDataPayload;
+ msgDataPayload.DataSize = dataSize;
+ const uint32 networkKeyIdWorstCaseSize = sizeof(uint32) + sizeof(Guid);
+ const uint32 msgMaxData = peer->Config.MessageSize - msg.Position - sizeof(NetworkMessageObjectPartPayload);
+ const uint32 partMaxData = peer->Config.MessageSize - sizeof(NetworkMessageObjectPart) - networkKeyIdWorstCaseSize;
+ uint32 partsCount = 1;
+ uint32 dataStart = 0;
+ uint32 msgDataSize = dataSize;
+ if (dataSize > msgMaxData)
+ {
+ // Send msgMaxData within first message
+ msgDataSize = msgMaxData;
+ dataStart += msgMaxData;
+
+ // Send rest of the data in separate parts
+ partsCount += Math::DivideAndRoundUp(dataSize - dataStart, partMaxData);
+
+ // TODO: promote channel to Ordered when using parts?
+ }
+ else
+ dataStart += dataSize;
+ ASSERT(partsCount <= MAX_uint8);
+ msgDataPayload.PartsCount = partsCount;
+ msgDataPayload.PartSize = msgDataSize;
+ msg.WriteStructure(msgDataPayload);
+ msg.WriteBytes(data, msgDataSize);
+ uint32 messageSize = msg.Length;
+ if (toServer)
+ peer->EndSendMessage(channel, msg);
+ else
+ peer->EndSendMessage(channel, msg, CachedTargets);
+
+ // Send all other parts
+ for (uint32 partIndex = 1; partIndex < partsCount; partIndex++)
+ {
+ NetworkMessageObjectPart msgDataPart;
+ msgDataPart.ID = partId;
+ msgDataPart.OwnerFrame = ownerFrame;
+ msgDataPart.DataSize = msgDataPayload.DataSize;
+ msgDataPart.PartsCount = msgDataPayload.PartsCount;
+ msgDataPart.PartStart = dataStart;
+ msgDataPart.PartSize = Math::Min(dataSize - dataStart, partMaxData);
+ msg = peer->BeginSendMessage();
+ msg.WriteStructure(msgDataPart);
+ msg.WriteNetworkId(objectId);
+ msg.WriteBytes(data + msgDataPart.PartStart, msgDataPart.PartSize);
+ messageSize += msg.Length;
+ dataStart += msgDataPart.PartSize;
+ if (toServer)
+ peer->EndSendMessage(channel, msg);
+ else
+ peer->EndSendMessage(channel, msg, CachedTargets);
+ }
+ ASSERT_LOW_LAYER(dataStart == dataSize);
+
+#if COMPILE_WITH_PROFILER
+ // Network stats recording
+ if (NetworkInternal::EnableProfiling)
+ {
+ auto& profileEvent = NetworkInternal::ProfilerEvents[name];
+ profileEvent.Count++;
+ profileEvent.DataSize += dataSize;
+ profileEvent.MessageSize += messageSize;
+ profileEvent.Receivers += toServer ? 1 : CachedTargets.Count();
+ }
+#endif
+}
+
void SendObjectSpawnMessage(const SpawnGroup& group, const Array& clients)
{
PROFILE_CPU();
@@ -589,7 +662,7 @@ void SendObjectRoleMessage(const NetworkReplicatedObject& item, const NetworkCli
msg.WriteNetworkId(objectId);
if (NetworkManager::IsClient())
{
- NetworkManager::Peer->EndSendMessage(NetworkChannelType::ReliableOrdered, msg);
+ peer->EndSendMessage(NetworkChannelType::ReliableOrdered, msg);
}
else
{
@@ -598,6 +671,160 @@ void SendObjectRoleMessage(const NetworkReplicatedObject& item, const NetworkCli
}
}
+void SendDespawn(DespawnItem& e)
+{
+ NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Despawn object ID={}", e.Id.ToString());
+ NetworkMessageObjectDespawn msgData;
+ Guid objectId = e.Id;
+ {
+ // Remap local client object ids into server ids
+ IdsRemappingTable.KeyOf(objectId, &objectId);
+ }
+ auto peer = NetworkManager::Peer;
+ NetworkMessage msg = peer->BeginSendMessage();
+ msg.WriteStructure(msgData);
+ msg.WriteNetworkId(objectId);
+ BuildCachedTargets(NetworkManager::Clients, e.Targets);
+ if (NetworkManager::IsClient())
+ peer->EndSendMessage(NetworkChannelType::ReliableOrdered, msg);
+ else
+ peer->EndSendMessage(NetworkChannelType::ReliableOrdered, msg, CachedTargets);
+}
+
+void SendReplication(ScriptingObject* obj, NetworkClientsMask targetClients)
+{
+ auto it = Objects.Find(obj->GetID());
+ if (it.IsEnd())
+ return;
+ auto& item = it->Item;
+ const bool isClient = NetworkManager::IsClient();
+
+ // Skip serialization of objects that none will receive
+ if (!isClient)
+ {
+ BuildCachedTargets(item, targetClients);
+ if (CachedTargets.Count() == 0)
+ return;
+ }
+
+ if (item.AsNetworkObject)
+ item.AsNetworkObject->OnNetworkSerialize();
+
+ // Serialize object
+ NetworkStream* stream = CachedWriteStream;
+ stream->Initialize();
+ const bool failed = NetworkReplicator::InvokeSerializer(obj->GetTypeHandle(), obj, stream, true);
+ if (failed)
+ {
+ //NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Cannot serialize object {} of type {} (missing serialization logic)", item.ToString(), obj->GetType().ToString());
+ return;
+ }
+ const uint32 size = stream->GetPosition();
+ if (size > MAX_uint16)
+ {
+ LOG(Error, "Too much data for object {} replication ({} bytes provided while limit is {}).", item.ToString(), size, MAX_uint16);
+ return;
+ }
+
+#if USE_NETWORK_REPLICATOR_CACHE
+ // Process replication cache to skip sending object data if it didn't change
+ if (item.RepCache.Data.Length() == size &&
+ item.RepCache.Mask == targetClients &&
+ Platform::MemoryCompare(item.RepCache.Data.Get(), stream->GetBuffer(), size) == 0)
+ {
+ return;
+ }
+ item.RepCache.Mask = targetClients;
+ item.RepCache.Data.Copy(stream->GetBuffer(), size);
+#endif
+ // TODO: use Unreliable for dynamic objects that are replicated every frame? (eg. player state)
+ constexpr NetworkChannelType repChannel = NetworkChannelType::Reliable;
+
+ // Send object to clients
+ NetworkMessageObjectReplicate msgData;
+ msgData.OwnerFrame = NetworkManager::Frame;
+ Guid objectId = item.ObjectId, parentId = item.ParentId;
+ {
+ // Remap local client object ids into server ids
+ IdsRemappingTable.KeyOf(objectId, &objectId);
+ IdsRemappingTable.KeyOf(parentId, &parentId);
+ }
+ NetworkPeer* peer = NetworkManager::Peer;
+ NetworkMessage msg = peer->BeginSendMessage();
+ msg.WriteStructure(msgData);
+ msg.WriteNetworkId(objectId);
+ msg.WriteNetworkId(parentId);
+ msg.WriteNetworkName(obj->GetType().Fullname);
+ const NetworkRpcName name(obj->GetTypeHandle(), StringAnsiView::Empty);
+ SendInParts(peer, repChannel, stream->GetBuffer(), size, msg, name, isClient, objectId, msgData.OwnerFrame, NetworkMessageIDs::ObjectReplicatePart);
+}
+
+void SendRpc(RpcSendItem& e)
+{
+ ScriptingObject* obj = e.Object.Get();
+ if (!obj)
+ return;
+ auto it = Objects.Find(obj->GetID());
+ if (it == Objects.End())
+ {
+#if !BUILD_RELEASE
+ if (!DespawnedObjects.Contains(obj->GetID()))
+ LOG(Error, "Cannot invoke RPC method '{0}.{1}' on object '{2}' that is not registered in networking (use 'NetworkReplicator.AddObject').", e.Name.First.ToString(), e.Name.Second.ToString(), obj->GetID());
+#endif
+ return;
+ }
+ auto& item = it->Item;
+ if (e.ArgsData.Length() > MAX_uint16)
+ {
+ LOG(Error, "Too much data for object RPC method '{}.{}' on object '{}' ({} bytes provided while limit is {}).", e.Name.First.ToString(), e.Name.Second.ToString(), obj->GetID(), e.ArgsData.Length(), MAX_uint16);
+ return;
+ }
+ const NetworkManagerMode mode = NetworkManager::Mode;
+ NetworkPeer* peer = NetworkManager::Peer;
+
+ bool toServer;
+ if (e.Info.Server && mode == NetworkManagerMode::Client)
+ {
+ // Client -> Server
+#if USE_NETWORK_REPLICATOR_LOG
+ if (e.Targets.Length() != 0)
+ NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Server RPC '{}.{}' called with non-empty list of targets is not supported (only server will receive it)", e.Name.First.ToString(), e.Name.Second.ToString());
+#endif
+ toServer = true;
+ }
+ else if (e.Info.Client && (mode == NetworkManagerMode::Server || mode == NetworkManagerMode::Host))
+ {
+ // Server -> Client(s)
+ BuildCachedTargets(NetworkManager::Clients, item.TargetClientIds, e.Targets, NetworkManager::LocalClientId);
+ if (CachedTargets.IsEmpty())
+ return;
+ toServer = false;
+ }
+ else
+ return;
+
+ // Send RPC message
+ //NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Rpc {}.{} object ID={}", e.Name.First.ToString(), e.Name.Second.ToString(), item.ToString());
+ NetworkMessageObjectRpc msgData;
+ msgData.OwnerFrame = ++RpcId;
+ Guid objectId = item.ObjectId;
+ Guid parentId = item.ParentId;
+ {
+ // Remap local client object ids into server ids
+ IdsRemappingTable.KeyOf(objectId, &objectId);
+ IdsRemappingTable.KeyOf(parentId, &parentId);
+ }
+ NetworkMessage msg = peer->BeginSendMessage();
+ msg.WriteStructure(msgData);
+ msg.WriteNetworkId(objectId);
+ msg.WriteNetworkId(parentId);
+ msg.WriteNetworkName(obj->GetType().Fullname);
+ msg.WriteNetworkName(e.Name.First.GetType().Fullname);
+ msg.WriteNetworkName(e.Name.Second);
+ NetworkChannelType channel = (NetworkChannelType)e.Info.Channel;
+ SendInParts(peer, channel, e.ArgsData.Get(), e.ArgsData.Length(), msg, e.Name, toServer, objectId, msgData.OwnerFrame, NetworkMessageIDs::ObjectRpcPart);
+}
+
void DeleteNetworkObject(ScriptingObject* obj)
{
// Remove from the mapping table
@@ -708,38 +935,43 @@ FORCE_INLINE void DirtyObjectImpl(NetworkReplicatedObject& item, ScriptingObject
Hierarchy->DirtyObject(obj);
}
-ReplicateItem* AddObjectReplicateItem(NetworkEvent& event, uint32 ownerFrame, uint16 partsCount, uint16 dataSize, const Guid& objectId, uint16 partStart, uint16 partSize, uint32 senderClientId)
+PartsItem* AddPartsItem(Array& items, NetworkEvent& event, uint32 ownerFrame, uint16 partsCount, uint16 dataSize, const Guid& objectId, uint16 partStart, uint16 partSize, uint32 senderClientId)
{
// Reuse or add part item
- ReplicateItem* replicateItem = nullptr;
- for (auto& e : ReplicationParts)
+ PartsItem* item = nullptr;
+ for (auto& e : items)
{
if (e.OwnerFrame == ownerFrame && e.Data.Count() == dataSize && e.ObjectId == objectId)
{
// Reuse
- replicateItem = &e;
+ item = &e;
break;
}
}
- if (!replicateItem)
+ if (!item)
{
// Add
- replicateItem = &ReplicationParts.AddOne();
- replicateItem->ObjectId = objectId;
- replicateItem->PartsLeft = partsCount;
- replicateItem->OwnerFrame = ownerFrame;
- replicateItem->OwnerClientId = senderClientId;
- replicateItem->Data.Resize(dataSize);
+ item = &items.AddOne();
+ item->ObjectId = objectId;
+ item->PartsLeft = partsCount;
+ item->OwnerFrame = ownerFrame;
+ item->OwnerClientId = senderClientId;
+ item->Data.Resize(dataSize);
}
// Copy part data
- ASSERT(replicateItem->PartsLeft > 0);
- replicateItem->PartsLeft--;
- ASSERT(partStart + partSize <= replicateItem->Data.Count());
+ ASSERT(item->PartsLeft > 0);
+ item->PartsLeft--;
+ ASSERT(partStart + partSize <= item->Data.Count());
const void* partData = event.Message.SkipBytes(partSize);
- Platform::MemoryCopy(replicateItem->Data.Get() + partStart, partData, partSize);
+ Platform::MemoryCopy(item->Data.Get() + partStart, partData, partSize);
- return replicateItem;
+ return item;
+}
+
+FORCE_INLINE PartsItem* AddObjectReplicateItem(NetworkEvent& event, uint32 ownerFrame, uint16 partsCount, uint16 dataSize, const Guid& objectId, uint16 partStart, uint16 partSize, uint32 senderClientId)
+{
+ return AddPartsItem(ReplicationParts, event, ownerFrame, partsCount, dataSize, objectId, partStart, partSize, senderClientId);
}
void InvokeObjectReplication(NetworkReplicatedObject& item, uint32 ownerFrame, byte* data, uint32 dataSize, uint32 senderClientId)
@@ -787,6 +1019,24 @@ void InvokeObjectReplication(NetworkReplicatedObject& item, uint32 ownerFrame, b
DirtyObjectImpl(item, obj);
}
+FORCE_INLINE PartsItem* AddObjectRpcItem(NetworkEvent& event, uint32 ownerFrame, uint16 partsCount, uint16 dataSize, const Guid& objectId, uint16 partStart, uint16 partSize, uint32 senderClientId)
+{
+ return AddPartsItem(RpcParts, event, ownerFrame, partsCount, dataSize, objectId, partStart, partSize, senderClientId);
+}
+
+void InvokeObjectRpc(const NetworkRpcInfo* info, byte* data, uint32 dataSize, uint32 senderClientId, ScriptingObject* obj)
+{
+ // Setup message reading stream
+ if (CachedReadStream == nullptr)
+ CachedReadStream = New();
+ NetworkStream* stream = CachedReadStream;
+ stream->SenderId = senderClientId;
+ stream->Initialize(data, dataSize);
+
+ // Execute RPC
+ info->Execute(obj, stream, info->Tag);
+}
+
void InvokeObjectSpawn(const NetworkMessageObjectSpawn& msgData, const Guid& prefabId, const NetworkMessageObjectSpawnItem* msgDataItems)
{
ScopeLock lock(ObjectsLock);
@@ -1652,9 +1902,6 @@ void NetworkInternal::NetworkReplicatorUpdate()
if (Objects.Count() == 0)
return;
const bool isClient = NetworkManager::IsClient();
- const bool isServer = NetworkManager::IsServer();
- const bool isHost = NetworkManager::IsHost();
- NetworkPeer* peer = NetworkManager::Peer;
if (!isClient && NewClients.Count() != 0)
{
@@ -1694,22 +1941,7 @@ void NetworkInternal::NetworkReplicatorUpdate()
PROFILE_CPU_NAMED("DespawnQueue");
for (DespawnItem& e : DespawnQueue)
{
- // Send despawn message
- NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Despawn object ID={}", e.Id.ToString());
- NetworkMessageObjectDespawn msgData;
- Guid objectId = e.Id;
- {
- // Remap local client object ids into server ids
- IdsRemappingTable.KeyOf(objectId, &objectId);
- }
- NetworkMessage msg = peer->BeginSendMessage();
- msg.WriteStructure(msgData);
- msg.WriteNetworkId(objectId);
- BuildCachedTargets(NetworkManager::Clients, e.Targets);
- if (isClient)
- peer->EndSendMessage(NetworkChannelType::ReliableOrdered, msg);
- else
- peer->EndSendMessage(NetworkChannelType::ReliableOrdered, msg, CachedTargets);
+ SendDespawn(e);
}
DespawnQueue.Clear();
}
@@ -1830,6 +2062,7 @@ void NetworkInternal::NetworkReplicatorUpdate()
}
}
+ // TODO: remove items from RpcParts after some TTL to reduce memory usage
// TODO: remove items from SpawnParts after some TTL to reduce memory usage
// Replicate all owned networked objects with other clients or server
@@ -1871,136 +2104,11 @@ void NetworkInternal::NetworkReplicatorUpdate()
PROFILE_CPU_NAMED("Replication");
if (CachedWriteStream == nullptr)
CachedWriteStream = New();
- NetworkStream* stream = CachedWriteStream;
- stream->SenderId = NetworkManager::LocalClientId;
+ CachedWriteStream->SenderId = NetworkManager::LocalClientId;
// TODO: use Job System when replicated objects count is large
for (auto& e : CachedReplicationResult->_entries)
{
- ScriptingObject* obj = e.Object;
- auto it = Objects.Find(obj->GetID());
- if (it.IsEnd())
- continue;
- auto& item = it->Item;
-
- // Skip serialization of objects that none will receive
- if (!isClient)
- {
- BuildCachedTargets(item, e.TargetClients);
- if (CachedTargets.Count() == 0)
- continue;
- }
-
- if (item.AsNetworkObject)
- item.AsNetworkObject->OnNetworkSerialize();
-
- // Serialize object
- stream->Initialize();
- const bool failed = NetworkReplicator::InvokeSerializer(obj->GetTypeHandle(), obj, stream, true);
- if (failed)
- {
- //NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Cannot serialize object {} of type {} (missing serialization logic)", item.ToString(), obj->GetType().ToString());
- continue;
- }
- const uint32 size = stream->GetPosition();
- if (size > MAX_uint16)
- {
- LOG(Error, "Too much data for object {} replication ({} bytes provided while limit is {}).", item.ToString(), size, MAX_uint16);
- continue;
- }
-
-#if USE_NETWORK_REPLICATOR_CACHE
- // Process replication cache to skip sending object data if it didn't change
- if (item.RepCache.Data.Length() == size &&
- item.RepCache.Mask == e.TargetClients &&
- Platform::MemoryCompare(item.RepCache.Data.Get(), stream->GetBuffer(), size) == 0)
- {
- continue;
- }
- item.RepCache.Mask = e.TargetClients;
- item.RepCache.Data.Copy(stream->GetBuffer(), size);
-#endif
- // TODO: use Unreliable for dynamic objects that are replicated every frame? (eg. player state)
- constexpr NetworkChannelType repChannel = NetworkChannelType::Reliable;
-
- // Send object to clients
- NetworkMessageObjectReplicate msgData;
- msgData.OwnerFrame = NetworkManager::Frame;
- Guid objectId = item.ObjectId, parentId = item.ParentId;
- {
- // Remap local client object ids into server ids
- IdsRemappingTable.KeyOf(objectId, &objectId);
- IdsRemappingTable.KeyOf(parentId, &parentId);
- }
- NetworkMessage msg = peer->BeginSendMessage();
- msg.WriteStructure(msgData);
- msg.WriteNetworkId(objectId);
- msg.WriteNetworkId(parentId);
- msg.WriteNetworkName(obj->GetType().Fullname);
- NetworkMessageObjectReplicatePayload msgDataPayload;
- msgDataPayload.DataSize = size;
- const uint32 networkKeyIdWorstCaseSize = sizeof(uint32) + sizeof(Guid);
- const uint32 msgMaxData = peer->Config.MessageSize - msg.Position - sizeof(NetworkMessageObjectReplicatePayload);
- const uint32 partMaxData = peer->Config.MessageSize - sizeof(NetworkMessageObjectReplicatePart) - networkKeyIdWorstCaseSize;
- uint32 partsCount = 1;
- uint32 dataStart = 0;
- uint32 msgDataSize = size;
- if (size > msgMaxData)
- {
- // Send msgMaxData within first message
- msgDataSize = msgMaxData;
- dataStart += msgMaxData;
-
- // Send rest of the data in separate parts
- partsCount += Math::DivideAndRoundUp(size - dataStart, partMaxData);
- }
- else
- dataStart += size;
- ASSERT(partsCount <= MAX_uint8);
- msgDataPayload.PartsCount = partsCount;
- msgDataPayload.PartSize = msgDataSize;
- msg.WriteStructure(msgDataPayload);
- msg.WriteBytes(stream->GetBuffer(), msgDataSize);
- uint32 dataSize = msgDataSize, messageSize = msg.Length;
- if (isClient)
- peer->EndSendMessage(repChannel, msg);
- else
- peer->EndSendMessage(repChannel, msg, CachedTargets);
-
- // Send all other parts
- for (uint32 partIndex = 1; partIndex < partsCount; partIndex++)
- {
- NetworkMessageObjectReplicatePart msgDataPart;
- msgDataPart.OwnerFrame = msgData.OwnerFrame;
- msgDataPart.DataSize = msgDataPayload.DataSize;
- msgDataPart.PartsCount = msgDataPayload.PartsCount;
- msgDataPart.PartStart = dataStart;
- msgDataPart.PartSize = Math::Min(size - dataStart, partMaxData);
- msg = peer->BeginSendMessage();
- msg.WriteStructure(msgDataPart);
- msg.WriteNetworkId(objectId);
- msg.WriteBytes(stream->GetBuffer() + msgDataPart.PartStart, msgDataPart.PartSize);
- messageSize += msg.Length;
- dataSize += msgDataPart.PartSize;
- dataStart += msgDataPart.PartSize;
- if (isClient)
- peer->EndSendMessage(repChannel, msg);
- else
- peer->EndSendMessage(repChannel, msg, CachedTargets);
- }
- ASSERT_LOW_LAYER(dataStart == size);
-
-#if COMPILE_WITH_PROFILER
- // Network stats recording
- if (EnableProfiling)
- {
- const Pair name(obj->GetTypeHandle(), StringAnsiView::Empty);
- auto& profileEvent = ProfilerEvents[name];
- profileEvent.Count++;
- profileEvent.DataSize += dataSize;
- profileEvent.MessageSize += messageSize;
- profileEvent.Receivers += isClient ? 1 : CachedTargets.Count();
- }
-#endif
+ SendReplication(e.Object, e.TargetClients);
}
}
@@ -2009,70 +2117,7 @@ void NetworkInternal::NetworkReplicatorUpdate()
PROFILE_CPU_NAMED("Rpc");
for (auto& e : RpcQueue)
{
- ScriptingObject* obj = e.Object.Get();
- if (!obj)
- continue;
- auto it = Objects.Find(obj->GetID());
- if (it == Objects.End())
- {
-#if USE_EDITOR || !BUILD_RELEASE
- if (!DespawnedObjects.Contains(obj->GetID()))
- LOG(Error, "Cannot invoke RPC method '{0}.{1}' on object '{2}' that is not registered in networking (use 'NetworkReplicator.AddObject').", e.Name.First.ToString(), String(e.Name.Second), obj->GetID());
-#endif
- continue;
- }
- auto& item = it->Item;
-
- // Send RPC message
- //NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Rpc {}::{} object ID={}", e.Name.First.ToString(), String(e.Name.Second), item.ToString());
- NetworkMessageObjectRpc msgData;
- Guid msgObjectId = item.ObjectId;
- Guid msgParentId = item.ParentId;
- {
- // Remap local client object ids into server ids
- IdsRemappingTable.KeyOf(msgObjectId, &msgObjectId);
- IdsRemappingTable.KeyOf(msgParentId, &msgParentId);
- }
- msgData.ArgsSize = (uint16)e.ArgsData.Length();
- NetworkMessage msg = peer->BeginSendMessage();
- msg.WriteStructure(msgData);
- msg.WriteNetworkId(msgObjectId);
- msg.WriteNetworkId(msgParentId);
- msg.WriteNetworkName(obj->GetType().Fullname);
- msg.WriteNetworkName(e.Name.First.GetType().Fullname);
- msg.WriteNetworkName(e.Name.Second);
- msg.WriteBytes(e.ArgsData.Get(), e.ArgsData.Length());
- uint32 dataSize = e.ArgsData.Length(), messageSize = msg.Length, receivers = 0;
- NetworkChannelType channel = (NetworkChannelType)e.Info.Channel;
- if (e.Info.Server && isClient)
- {
- // Client -> Server
-#if USE_NETWORK_REPLICATOR_LOG
- if (e.Targets.Length() != 0)
- NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Server RPC '{}::{}' called with non-empty list of targets is not supported (only server will receive it)", e.Name.First.ToString(), e.Name.Second.ToString());
-#endif
- peer->EndSendMessage(channel, msg);
- receivers = 1;
- }
- else if (e.Info.Client && (isServer || isHost))
- {
- // Server -> Client(s)
- BuildCachedTargets(NetworkManager::Clients, item.TargetClientIds, e.Targets, NetworkManager::LocalClientId);
- peer->EndSendMessage(channel, msg, CachedTargets);
- receivers = CachedTargets.Count();
- }
-
-#if COMPILE_WITH_PROFILER
- // Network stats recording
- if (EnableProfiling && receivers)
- {
- auto& profileEvent = ProfilerEvents[e.Name];
- profileEvent.Count++;
- profileEvent.DataSize += dataSize;
- profileEvent.MessageSize += messageSize;
- profileEvent.Receivers += receivers;
- }
-#endif
+ SendRpc(e);
}
RpcQueue.Clear();
}
@@ -2085,7 +2130,7 @@ void NetworkInternal::OnNetworkMessageObjectReplicate(NetworkEvent& event, Netwo
{
PROFILE_CPU();
NetworkMessageObjectReplicate msgData;
- NetworkMessageObjectReplicatePayload msgDataPayload;
+ NetworkMessageObjectPartPayload msgDataPayload;
Guid objectId, parentId;
StringAnsiView objectTypeName;
event.Message.ReadStructure(msgData);
@@ -2095,7 +2140,7 @@ void NetworkInternal::OnNetworkMessageObjectReplicate(NetworkEvent& event, Netwo
event.Message.ReadStructure(msgDataPayload);
ScopeLock lock(ObjectsLock);
if (DespawnedObjects.Contains(objectId))
- return; // Skip replicating not-existing objects
+ return; // Skip replicating non-existing objects
NetworkReplicatedObject* e = ResolveObject(objectId, parentId, objectTypeName);
if (!e)
return;
@@ -2114,7 +2159,7 @@ void NetworkInternal::OnNetworkMessageObjectReplicate(NetworkEvent& event, Netwo
else
{
// Add to replication from multiple parts
- ReplicateItem* replicateItem = AddObjectReplicateItem(event, msgData.OwnerFrame, msgDataPayload.PartsCount, msgDataPayload.DataSize, objectId, 0, msgDataPayload.PartSize, senderClientId);
+ PartsItem* replicateItem = AddObjectReplicateItem(event, msgData.OwnerFrame, msgDataPayload.PartsCount, msgDataPayload.DataSize, objectId, 0, msgDataPayload.PartSize, senderClientId);
replicateItem->Object = e->Object;
}
}
@@ -2122,13 +2167,13 @@ void NetworkInternal::OnNetworkMessageObjectReplicate(NetworkEvent& event, Netwo
void NetworkInternal::OnNetworkMessageObjectReplicatePart(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer)
{
PROFILE_CPU();
- NetworkMessageObjectReplicatePart msgData;
+ NetworkMessageObjectPart msgData;
Guid objectId;
event.Message.ReadStructure(msgData);
event.Message.ReadNetworkId(objectId);
ScopeLock lock(ObjectsLock);
if (DespawnedObjects.Contains(objectId))
- return; // Skip replicating not-existing objects
+ return; // Skip replicating non-existing objects
const uint32 senderClientId = client ? client->ClientId : NetworkManager::ServerClientId;
AddObjectReplicateItem(event, msgData.OwnerFrame, msgData.PartsCount, msgData.DataSize, objectId, msgData.PartStart, msgData.PartSize, senderClientId);
@@ -2288,14 +2333,16 @@ void NetworkInternal::OnNetworkMessageObjectRpc(NetworkEvent& event, NetworkClie
{
PROFILE_CPU();
NetworkMessageObjectRpc msgData;
- Guid msgObjectId, msgParentId;
+ NetworkMessageObjectPartPayload msgDataPayload;
+ Guid objectId, parentId;
StringAnsiView objectTypeName, rpcTypeName, rpcName;
event.Message.ReadStructure(msgData);
- event.Message.ReadNetworkId(msgObjectId);
- event.Message.ReadNetworkId(msgParentId);
+ event.Message.ReadNetworkId(objectId);
+ event.Message.ReadNetworkId(parentId);
event.Message.ReadNetworkName(objectTypeName);
event.Message.ReadNetworkName(rpcTypeName);
event.Message.ReadNetworkName(rpcName);
+ event.Message.ReadStructure(msgDataPayload);
ScopeLock lock(ObjectsLock);
// Find RPC info
@@ -2305,11 +2352,11 @@ void NetworkInternal::OnNetworkMessageObjectRpc(NetworkEvent& event, NetworkClie
const NetworkRpcInfo* info = NetworkRpcInfo::RPCsTable.TryGet(name);
if (!info)
{
- NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Unknown RPC {}::{} for object {}", String(rpcTypeName), String(rpcName), msgObjectId);
+ NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Unknown RPC {}::{} for object {}", String(rpcTypeName), String(rpcName), objectId);
return;
}
- NetworkReplicatedObject* e = ResolveObject(msgObjectId, msgParentId, objectTypeName);
+ NetworkReplicatedObject* e = ResolveObject(objectId, parentId, objectTypeName);
if (e)
{
auto& item = *e;
@@ -2329,18 +2376,50 @@ void NetworkInternal::OnNetworkMessageObjectRpc(NetworkEvent& event, NetworkClie
return;
}
- // Setup message reading stream
- if (CachedReadStream == nullptr)
- CachedReadStream = New();
- NetworkStream* stream = CachedReadStream;
- stream->SenderId = client ? client->ClientId : NetworkManager::ServerClientId;
- stream->Initialize(event.Message.Buffer + event.Message.Position, msgData.ArgsSize);
-
- // Execute RPC
- info->Execute(obj, stream, info->Tag);
+ const uint32 senderClientId = client ? client->ClientId : NetworkManager::ServerClientId;
+ if (msgDataPayload.PartsCount == 1)
+ {
+ // Call RPC
+ InvokeObjectRpc(info, event.Message.Buffer + event.Message.Position, msgDataPayload.DataSize, senderClientId, obj);
+ }
+ else
+ {
+ // Add to RPC from multiple parts
+ PartsItem* rpcItem = AddObjectRpcItem(event, msgData.OwnerFrame, msgDataPayload.PartsCount, msgDataPayload.DataSize, objectId, 0, msgDataPayload.PartSize, senderClientId);
+ rpcItem->Object = e->Object;
+ rpcItem->Tag = info;
+ }
}
else if (info->Channel != static_cast(NetworkChannelType::Unreliable) && info->Channel != static_cast(NetworkChannelType::UnreliableOrdered))
{
- NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Unknown object {} RPC {}::{}", msgObjectId, String(rpcTypeName), String(rpcName));
+ NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Unknown object {} RPC {}::{}", objectId, String(rpcTypeName), String(rpcName));
+ }
+}
+
+void NetworkInternal::OnNetworkMessageObjectRpcPart(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer)
+{
+ PROFILE_CPU();
+ NetworkMessageObjectPart msgData;
+ Guid objectId;
+ event.Message.ReadStructure(msgData);
+ event.Message.ReadNetworkId(objectId);
+ ScopeLock lock(ObjectsLock);
+ if (DespawnedObjects.Contains(objectId))
+ return; // Skip replicating non-existing objects
+
+ const uint32 senderClientId = client ? client->ClientId : NetworkManager::ServerClientId;
+ PartsItem* rpcItem = AddObjectRpcItem(event, msgData.OwnerFrame, msgData.PartsCount, msgData.DataSize, objectId, msgData.PartStart, msgData.PartSize, senderClientId);
+ if (rpcItem && rpcItem->PartsLeft == 0)
+ {
+ // Got all parts so invoke RPC
+ ScriptingObject* obj = rpcItem->Object.Get();
+ if (obj)
+ {
+ InvokeObjectRpc((const NetworkRpcInfo*)rpcItem->Tag, rpcItem->Data.Get(), rpcItem->Data.Count(), rpcItem->OwnerClientId, obj);
+ }
+
+ // Remove item
+ int32 partIndex = (int32)((RpcParts.Get() - rpcItem) / sizeof(rpcItem));
+ RpcParts.RemoveAt(partIndex);
}
}
diff --git a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
index 8d61e9ba5..18929ab73 100644
--- a/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
+++ b/Source/Engine/Physics/PhysX/PhysicsBackendPhysX.cpp
@@ -1969,6 +1969,7 @@ void PhysicsBackend::EndSimulateScene(void* scene)
scenePhysX->EventsCallback.SendTriggerEvents();
scenePhysX->EventsCallback.SendCollisionEvents();
scenePhysX->EventsCallback.SendJointEvents();
+ scenePhysX->EventsCallback.Clear();
}
// Clear delta after simulation ended
@@ -4466,14 +4467,14 @@ void PhysicsBackend::FlushRequests(void* scene)
}
if (scenePhysX->RemoveColliders.HasItems())
{
- for (int32 i = 0; i < scenePhysX->RemoveColliders.Count(); i++)
- scenePhysX->EventsCallback.OnColliderRemoved(scenePhysX->RemoveColliders[i]);
+ for (PhysicsColliderActor* e : scenePhysX->RemoveColliders)
+ scenePhysX->EventsCallback.OnColliderRemoved(e);
scenePhysX->RemoveColliders.Clear();
}
if (scenePhysX->RemoveJoints.HasItems())
{
- for (int32 i = 0; i < scenePhysX->RemoveJoints.Count(); i++)
- scenePhysX->EventsCallback.OnJointRemoved(scenePhysX->RemoveJoints[i]);
+ for (Joint* e : scenePhysX->RemoveJoints)
+ scenePhysX->EventsCallback.OnJointRemoved(e);
scenePhysX->RemoveJoints.Clear();
}
diff --git a/Source/Engine/Platform/Windows/WindowsPlatform.cpp b/Source/Engine/Platform/Windows/WindowsPlatform.cpp
index 116cb3deb..e40ae1ca7 100644
--- a/Source/Engine/Platform/Windows/WindowsPlatform.cpp
+++ b/Source/Engine/Platform/Windows/WindowsPlatform.cpp
@@ -543,11 +543,9 @@ void WindowsPlatform::ReleaseMutex()
}
}
-void WindowsPlatform::PreInit(void* hInstance)
+PRAGMA_DISABLE_OPTIMIZATION;
+void CheckInstructionSet()
{
- ASSERT(hInstance);
- Instance = hInstance;
-
#if PLATFORM_ARCH_X86 || PLATFORM_ARCH_X64
// Check the minimum vector instruction set support
int32 cpuInfo[4] = { -1 };
@@ -597,10 +595,19 @@ void WindowsPlatform::PreInit(void* hInstance)
{
// Not supported CPU
CPUBrand cpu;
- Error(String::Format(TEXT("Cannot start program due to lack of CPU feature {}.\n\n{}"), missingFeature, String(cpu.Buffer)));
+ Platform::Error(String::Format(TEXT("Cannot start program due to lack of CPU feature {}.\n\n{}"), missingFeature, String(cpu.Buffer)));
exit(-1);
}
#endif
+}
+PRAGMA_ENABLE_OPTIMIZATION;
+
+void WindowsPlatform::PreInit(void* hInstance)
+{
+ ASSERT(hInstance);
+ Instance = hInstance;
+
+ CheckInstructionSet();
// Disable the process from being showing "ghosted" while not responding messages during slow tasks
DisableProcessWindowsGhosting();
diff --git a/Source/Engine/Renderer/ColorGradingPass.cpp b/Source/Engine/Renderer/ColorGradingPass.cpp
index bbb45ef4c..d6e164622 100644
--- a/Source/Engine/Renderer/ColorGradingPass.cpp
+++ b/Source/Engine/Renderer/ColorGradingPass.cpp
@@ -47,6 +47,9 @@ public:
Data CachedData;
ToneMappingMode Mode = ToneMappingMode::None;
Texture* LutTexture = nullptr;
+#if COMPILE_WITH_DEV_ENV
+ uint64 FrameRendered = 0;
+#endif
~ColorGradingCustomBuffer()
{
@@ -54,6 +57,17 @@ public:
}
};
+#if COMPILE_WITH_DEV_ENV
+
+void ColorGradingPass::OnShaderReloading(Asset* obj)
+{
+ _psLut.Release();
+ invalidateResources();
+ _reloadedFrame = Engine::FrameCount;
+}
+
+#endif
+
String ColorGradingPass::ToString() const
{
return TEXT("ColorGradingPass");
@@ -194,6 +208,9 @@ GPUTexture* ColorGradingPass::RenderLUT(RenderContext& renderContext)
// Check if LUT parameter hasn't been changed since the last time
if (Platform::MemoryCompare(&colorGradingBuffer.CachedData , &data, sizeof(Data)) == 0 &&
colorGradingBuffer.Mode == toneMapping.Mode &&
+#if COMPILE_WITH_DEV_ENV
+ colorGradingBuffer.FrameRendered > _reloadedFrame &&
+#endif
Engine::FrameCount > 30 && // Skip caching when engine is starting TODO: find why this hack is needed
colorGradingBuffer.LutTexture == lutTexture)
{
@@ -203,6 +220,9 @@ GPUTexture* ColorGradingPass::RenderLUT(RenderContext& renderContext)
colorGradingBuffer.CachedData = data;
colorGradingBuffer.Mode = toneMapping.Mode;
colorGradingBuffer.LutTexture = lutTexture;
+#if COMPILE_WITH_DEV_ENV
+ colorGradingBuffer.FrameRendered = Engine::FrameCount;
+#endif
// Render LUT
PROFILE_GPU("Color Grading LUT");
diff --git a/Source/Engine/Renderer/ColorGradingPass.h b/Source/Engine/Renderer/ColorGradingPass.h
index 612940e76..dd17e7786 100644
--- a/Source/Engine/Renderer/ColorGradingPass.h
+++ b/Source/Engine/Renderer/ColorGradingPass.h
@@ -25,11 +25,8 @@ public:
private:
#if COMPILE_WITH_DEV_ENV
- void OnShaderReloading(Asset* obj)
- {
- _psLut.Release();
- invalidateResources();
- }
+ uint64 _reloadedFrame = 0;
+ void OnShaderReloading(Asset* obj);
#endif
public:
diff --git a/Source/Engine/Renderer/EyeAdaptationPass.cpp b/Source/Engine/Renderer/EyeAdaptationPass.cpp
index 3cf44af1b..b539cb212 100644
--- a/Source/Engine/Renderer/EyeAdaptationPass.cpp
+++ b/Source/Engine/Renderer/EyeAdaptationPass.cpp
@@ -98,6 +98,7 @@ void EyeAdaptationPass::Render(RenderContext& renderContext, GPUTexture* colorBu
if (mode == EyeAdaptationMode::Manual)
{
// Apply fixed manual exposure
+ context->ResetSR();
context->SetRenderTarget(*colorBuffer);
context->SetViewportAndScissors((float)colorBuffer->Width(), (float)colorBuffer->Height());
context->SetState(_psManual);
diff --git a/Source/Engine/Scripting/Scripting.Build.cs b/Source/Engine/Scripting/Scripting.Build.cs
index d15b460c9..206513259 100644
--- a/Source/Engine/Scripting/Scripting.Build.cs
+++ b/Source/Engine/Scripting/Scripting.Build.cs
@@ -32,7 +32,7 @@ public class Scripting : EngineModule
options.ScriptingAPI.Defines.Add("NET");
AddFrameworkDefines("NET{0}_{1}", dotnetSdk.Version.Major, 0); // "NET7_0"
for (int i = 5; i <= dotnetSdk.Version.Major; i++)
- AddFrameworkDefines("NET{0}_{1}_OR_GREATER", dotnetSdk.Version.Major, 0); // "NET7_0_OR_GREATER"
+ AddFrameworkDefines("NET{0}_{1}_OR_GREATER", i, 0); // "NET7_0_OR_GREATER"
options.ScriptingAPI.Defines.Add("NETCOREAPP");
AddFrameworkDefines("NETCOREAPP{0}_{1}_OR_GREATER", 3, 1); // "NETCOREAPP3_1_OR_GREATER"
AddFrameworkDefines("NETCOREAPP{0}_{1}_OR_GREATER", 2, 2);
diff --git a/Source/Engine/Tools/TextureTool/TextureTool.stb.cpp b/Source/Engine/Tools/TextureTool/TextureTool.stb.cpp
index b88bc4ef3..7c74ef3f2 100644
--- a/Source/Engine/Tools/TextureTool/TextureTool.stb.cpp
+++ b/Source/Engine/Tools/TextureTool/TextureTool.stb.cpp
@@ -65,6 +65,8 @@
#endif
+#undef MessageBox
+
static void stbWrite(void* context, void* data, int size)
{
auto file = (FileWriteStream*)context;
diff --git a/Source/Engine/UI/GUI/Panels/DropPanel.cs b/Source/Engine/UI/GUI/Panels/DropPanel.cs
index 0bfa799c2..de80f9fc5 100644
--- a/Source/Engine/UI/GUI/Panels/DropPanel.cs
+++ b/Source/Engine/UI/GUI/Panels/DropPanel.cs
@@ -104,13 +104,20 @@ namespace FlaxEngine.GUI
///
/// Gets or sets a value indicating whether enable drop down icon drawing.
///
- [EditorOrder(1)]
+ [EditorOrder(2)]
public bool EnableDropDownIcon { get; set; }
+ ///
+ /// Get or sets a value indicating whether the panel can be opened or closed via the user interacting with the ui.
+ /// Changing the open/ closed state from code or the Properties panel will still work regardless.
+ ///
+ [EditorOrder(1)]
+ public bool CanOpenClose { get; set; } = true;
+
///
/// Gets or sets a value indicating whether to enable containment line drawing,
///
- [EditorOrder(2)]
+ [EditorOrder(3)]
public bool EnableContainmentLines { get; set; } = false;
///
@@ -369,7 +376,7 @@ namespace FlaxEngine.GUI
}
// Header
- var color = _mouseOverHeader ? HeaderColorMouseOver : HeaderColor;
+ var color = _mouseOverHeader && CanOpenClose ? HeaderColorMouseOver : HeaderColor;
if (color.A > 0.0f)
{
Render2D.FillRectangle(new Rectangle(0, 0, Width, HeaderHeight), color);
@@ -510,7 +517,7 @@ namespace FlaxEngine.GUI
if (button == MouseButton.Left && _mouseButtonLeftDown)
{
_mouseButtonLeftDown = false;
- if (_mouseOverHeader)
+ if (_mouseOverHeader && CanOpenClose)
Toggle();
return true;
}
@@ -540,7 +547,7 @@ namespace FlaxEngine.GUI
if (button == MouseButton.Left && _mouseButtonLeftDown)
{
_mouseButtonLeftDown = false;
- if (_mouseOverHeader)
+ if (_mouseOverHeader && CanOpenClose)
Toggle();
return true;
}
diff --git a/Source/Engine/UI/GUI/RenderOutputControl.cs b/Source/Engine/UI/GUI/RenderOutputControl.cs
index 9025cbc04..8dc6707bf 100644
--- a/Source/Engine/UI/GUI/RenderOutputControl.cs
+++ b/Source/Engine/UI/GUI/RenderOutputControl.cs
@@ -180,7 +180,7 @@ namespace FlaxEngine.GUI
}
///
- public override void Draw()
+ public override void DrawSelf()
{
var bounds = new Rectangle(Float2.Zero, Size);
@@ -205,21 +205,6 @@ namespace FlaxEngine.GUI
Render2D.DrawTexture(buffer, bounds, color);
else
Render2D.FillRectangle(bounds, Color.Black);
-
- // Push clipping mask
- if (ClipChildren)
- {
- GetDesireClientArea(out var clientArea);
- Render2D.PushClip(ref clientArea);
- }
-
- DrawChildren();
-
- // Pop clipping mask
- if (ClipChildren)
- {
- Render2D.PopClip();
- }
}
///
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libGenericCodeGen.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libGenericCodeGen.a
index 1a8237027..c5745f338 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libGenericCodeGen.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libGenericCodeGen.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:5c6add4697d7513883ea5583587a50b3b01ff0156d06e2ccc48070e23c415bf4
-size 31902
+oid sha256:794ce94a3f89c080a59889c7d49f98a5e3ce004c8c5fea533370e6dc9a388396
+size 30214
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libHLSL.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libHLSL.a
index 3ce822729..5e9764557 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libHLSL.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libHLSL.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:254756fe20ea96e73bd82a9a491c1f18c852aae33dd8bf9d6648c91d0247c7eb
+oid sha256:0fd14ac5c4b03136ad2734a3b866c6524cf817afa1e6294c8f1408cac44f5b24
size 1068
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libMachineIndependent.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libMachineIndependent.a
index 0235bd398..56ac04634 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libMachineIndependent.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libMachineIndependent.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:c9e79710c30285e0c5e4fe2ff1e9c47d06d9457428c177c6580e1ec8966dd079
-size 5287654
+oid sha256:1d3af5ec52f4d1aa80ed28e41a40bd53f3162f2c42965e162a0fca8329d479a6
+size 5370940
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libNvCloth.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libNvCloth.a
index 573dfb245..51e71d359 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libNvCloth.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libNvCloth.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:6234ee8e0cea08be467f8d13994fee8b94dfa2ed2147460a3268dbe6cfeb87a6
-size 553518
+oid sha256:62687b3036959f1b873623202dbfef3706c154ceb3fa26e87dea6702d9bab657
+size 553390
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libOGLCompiler.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libOGLCompiler.a
index 7ac2e3cc5..ca8f14082 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libOGLCompiler.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libOGLCompiler.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2b78a2a48c4c17a066164b7d151260d836e01ddb0d4087f25a6266aafc220eb5
-size 3332
+oid sha256:90b0951e9d0fcbcd63d53c60981d342bcd5d3c40f04983ee281fb45821f84ab0
+size 3308
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libOSDependent.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libOSDependent.a
index ce233ff4f..b9dad7646 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libOSDependent.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libOSDependent.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:67afb8e80b768c785905821f4ab4e4491598ab3a69f3fd514d4a9dadf6f80d36
-size 4966
+oid sha256:c5725e2cfe85e4c8a03f407562098306d3d1cc6715c4349288433cde0efcceb2
+size 4918
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXCharacterKinematic_static_64.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXCharacterKinematic_static_64.a
index 98a4a8286..7e702f665 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXCharacterKinematic_static_64.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXCharacterKinematic_static_64.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a9cf1125a7e1d0f2fb1a12b6f04537228cd37e3322cf818696a2d3446f97b953
-size 278626
+oid sha256:9929fabaa9ca418b8e48ea1081652fa61180fe0bec0518f5603966f6b4918e5c
+size 278562
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXCommon_static_64.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXCommon_static_64.a
index 242c33ca5..6b596b38b 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXCommon_static_64.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXCommon_static_64.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:19d0245e6dce80bb596ed10a154a5e18a5902df6c3e95c087e856fa6ca25f6f6
-size 4596892
+oid sha256:8b8f2a44b37ac65ea3eaee9ad090f471be3848490017d06980e6224b443a2218
+size 4595548
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXCooking_static_64.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXCooking_static_64.a
index e7d99ad1f..851680c01 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXCooking_static_64.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXCooking_static_64.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3d44653d8526acb4fd631cf007941a656ab054552b9406cf54199abf7bfab98c
+oid sha256:a1126331d2ba6933b1fa70d8d735c766e67785d58c243d960d6c0225f207bdf3
size 28284
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXExtensions_static_64.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXExtensions_static_64.a
index 150fe2099..5b547830d 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXExtensions_static_64.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXExtensions_static_64.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:0667c4d6515bb6c95c9ce5072edc56da7da45b6691eba2d3332f6b1db27c7511
-size 4081244
+oid sha256:d516b0b54861a86ed413f7a0e3358d8ea74952b5ef84871332453f758f0d8920
+size 4081602
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXFoundation_static_64.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXFoundation_static_64.a
index 94622de79..8d0a04c50 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXFoundation_static_64.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXFoundation_static_64.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:db06448b20f3d0b14780730e7e884cb18be4b546dc228b84c0ad8d33b088dcd4
-size 121148
+oid sha256:ee3df94bba27db3a77864816c460c76f82c58a98fd1b3055554fb773232b3fef
+size 121028
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXPvdSDK_static_64.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXPvdSDK_static_64.a
index e49794ebc..c22a96c31 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXPvdSDK_static_64.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXPvdSDK_static_64.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:419c688357cf3c4b781fa3cae601906be8e46d1de9d1238f8acb482166b5f837
-size 503210
+oid sha256:c22c955f6cf0d5b55033d0acdcae44b6e17e07eaaec884fa5ad80dcef8ddc15d
+size 503146
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXVehicle2_static_64.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXVehicle2_static_64.a
index 2da3cad95..5163432ac 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXVehicle2_static_64.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXVehicle2_static_64.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:a5559f869db603d979003f6d8d3d35179db5193974f39481bc2ee821af27faf3
-size 195454
+oid sha256:12d23592318c74bd3d5aed5134bf8be50fa32c78e66e59236d25620aed7316e9
+size 195302
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXVehicle_static_64.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXVehicle_static_64.a
index abcca2a9a..488e90c95 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXVehicle_static_64.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysXVehicle_static_64.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:427613612343bd0ea40d523ea0c7458a6ed927357fe4a277428d4ee0228bad95
-size 1209552
+oid sha256:bd1af110b345dc5548cf07885ea4f0e95bd8f83b4f9c041bfc962a6e72d8cc71
+size 1209456
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysX_static_64.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysX_static_64.a
index 12db8e2e6..c4e817356 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysX_static_64.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libPhysX_static_64.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:2b606e398be2f9772da1c0dd0f1b9aead20974cf03eeaa7a2df1a477eb6caff9
-size 6360866
+oid sha256:7d2e9591a28c5d0bf0aee830e340c6e9a1e978aa7f80cdbda002c5fa1fac7196
+size 6359770
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libSPIRV-Tools-opt.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libSPIRV-Tools-opt.a
index 5c0736d35..fca25c5e9 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libSPIRV-Tools-opt.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libSPIRV-Tools-opt.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:d101fdbbdb514937ef3ccdbb2a0791542fdb880b0331a59599e1cab3fdaba8d0
-size 8949560
+oid sha256:5205664eaa07b9161d5c9daa4ca7a2e224a7e8d082d13390bd3743e7cd9937cf
+size 8105308
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libSPIRV-Tools.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libSPIRV-Tools.a
index 3732827d0..7f73d4824 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libSPIRV-Tools.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libSPIRV-Tools.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:dafaa04b6d0896fdb33738ea7104fa47ad150f287d046bd752d7f343efb6bc1a
-size 2515558
+oid sha256:17699265b59441501b4837cef88d6f82d7404201f2d05cf2eb35e083b4b63c14
+size 2394830
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libSPIRV.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libSPIRV.a
index 2c9b04e3d..622011e31 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libSPIRV.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libSPIRV.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:4e8ee83a8a956e1e700aa5599107a5710d9c17f350a7d9025765b588146272c7
-size 1057884
+oid sha256:e5bdbd77d71f37080617b261aa92b589ea62a2bc0e567755367733535ddf9d60
+size 1071492
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libassimp.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libassimp.a
index 92b3c5545..dd916929d 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libassimp.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libassimp.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b3510d6c5585f08fc9fcbf2044bb0dc0238e2501c1914e3b98aef36bc8cd2711
-size 10303430
+oid sha256:d9e8469042e4734543f142f9559347bd1e36bc897b8962ae4f58fcec985e70ba
+size 10261802
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libcurl.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libcurl.a
index f722e3a16..f08214054 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libcurl.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libcurl.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:7b7f66f58d5e7dabe0a0ec7e01ae5dd3683c2ae474ac6dbc133393b2be715bbf
-size 574086
+oid sha256:ab21e8f683649d34388dbdddafb33ac4ba152e0e0fb1d631e03641e3bfc484c3
+size 767214
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libfreetype.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libfreetype.a
index 5d8a644ec..a77930866 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libfreetype.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libfreetype.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:678c906be4431bbf7b1a5e915e587f0e1f4f0c14cd2dc30a90e44e669d7f690c
-size 1123598
+oid sha256:0885cd644e330c5b622e1312395125c2f14ac78deaf9ca58b66fdcfa074d28bb
+size 1136190
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libglslang.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libglslang.a
index 0e82c48ea..9f830b8e1 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libglslang.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libglslang.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:b5f1fad7d2bc3a7768ea1e8a075315c371064cfd5cfcc64f9d4a55837e304b3a
-size 32314
+oid sha256:9a1f4379e8262064813ab001df54d5759077d5c19191ad464374a07073d7db8e
+size 34130
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libopenal.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libopenal.a
index 2a0348bcd..b88eb07e6 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libopenal.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libopenal.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:762b5fd6fe17dc4a99fd49488b32486e6744aef278a44c9843bdda05972e1287
-size 1565506
+oid sha256:3e51434c5af3558b73ced5051a239b33077bce527d25e5c71602e7b27b65c80c
+size 3506588
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libvorbis.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libvorbis.a
index 0feb18fa5..c606738e6 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libvorbis.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libvorbis.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:3257e82c3740aec7b15d065ef0b89064b971f77db4251c220fd277b3a96ac19d
-size 294326
+oid sha256:fdc79150a98f6f589d5a339dc50e4ad628f92767aa194c8ac4a202ebd78cec1d
+size 296926
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libvorbisenc.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libvorbisenc.a
index 59ef26a02..1fc00718c 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libvorbisenc.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libvorbisenc.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:50c8f8977fece27302c967c7d65b4a64b1c07f538b54edb0852169bba0bca91b
-size 778766
+oid sha256:6d8cbdad00f1a7f0a59f500d6687a64fbcdfc3db7c3acc05a65f68b7ea6566cb
+size 782150
diff --git a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libvorbisfile.a b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libvorbisfile.a
index 9e6ebdd68..41abc9b37 100644
--- a/Source/Platforms/Linux/Binaries/ThirdParty/x64/libvorbisfile.a
+++ b/Source/Platforms/Linux/Binaries/ThirdParty/x64/libvorbisfile.a
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
-oid sha256:bc394079fd2b794b637e879357494d0db3e1a8e9690949d7708766ccf360d5eb
-size 38204
+oid sha256:1b8377b841a4a871487ff0f591970ada56306087b1f4e3f09a8fb457f6811ac4
+size 38804
diff --git a/Source/Shaders/ColorGrading.shader b/Source/Shaders/ColorGrading.shader
index 9d1d71697..fe2ca4c91 100644
--- a/Source/Shaders/ColorGrading.shader
+++ b/Source/Shaders/ColorGrading.shader
@@ -164,16 +164,14 @@ float3 TonemapACES(float3 linearColor)
// The code was originally written by Stephen Hill (@self_shadow).
// sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT
- static const float3x3 ACESInputMat =
- {
+ static const float3x3 ACESInputMat = {
{0.59719, 0.35458, 0.04823},
{0.07600, 0.90834, 0.01566},
{0.02840, 0.13383, 0.83777}
};
// ODT_SAT => XYZ => D60_2_D65 => sRGB
- static const float3x3 ACESOutputMat =
- {
+ static const float3x3 ACESOutputMat = {
{ 1.60475, -0.53108, -0.07367},
{-0.10208, 1.10813, -0.00605},
{-0.00327, -0.07276, 1.07602}
@@ -188,6 +186,7 @@ float3 TonemapACES(float3 linearColor)
color = a / b;
color = mul(ACESOutputMat, color);
+
return saturate(color);
}
diff --git a/Source/Shaders/GammaCorrectionCommon.hlsl b/Source/Shaders/GammaCorrectionCommon.hlsl
index b687f9166..e410400ad 100644
--- a/Source/Shaders/GammaCorrectionCommon.hlsl
+++ b/Source/Shaders/GammaCorrectionCommon.hlsl
@@ -37,7 +37,7 @@ float4 FastTonemapInvert(float4 c)
return float4(FastTonemapInvert(c.rgb), c.a);
}
-float LinearToSrgbChannel(float linearColor)
+float LinearToSrgb(float linearColor)
{
if (linearColor < 0.00313067)
return linearColor * 12.92;
@@ -46,10 +46,7 @@ float LinearToSrgbChannel(float linearColor)
float3 LinearToSrgb(float3 linearColor)
{
- return float3(
- LinearToSrgbChannel(linearColor.r),
- LinearToSrgbChannel(linearColor.g),
- LinearToSrgbChannel(linearColor.b));
+ return float3(LinearToSrgb(linearColor.r), LinearToSrgb(linearColor.g), LinearToSrgb(linearColor.b));
}
float3 sRGBToLinear(float3 color)
diff --git a/Source/ThirdParty/detex/detex.h b/Source/ThirdParty/detex/detex.h
index adbeac512..ec61d7495 100644
--- a/Source/ThirdParty/detex/detex.h
+++ b/Source/ThirdParty/detex/detex.h
@@ -72,7 +72,11 @@ __BEGIN_DECLS
#include
#include
+#if defined(_MSC_VER)
+#define DETEX_INLINE_ONLY __forceinline
+#else
#define DETEX_INLINE_ONLY __attribute__((always_inline)) inline
+#endif
#define DETEX_RESTRICT __restrict
/* Maximum uncompressed block size in bytes. */
diff --git a/Source/ThirdParty/tracy/client/TracyAlloc.cpp b/Source/ThirdParty/tracy/client/TracyAlloc.cpp
index 545a6062b..923c92494 100644
--- a/Source/ThirdParty/tracy/client/TracyAlloc.cpp
+++ b/Source/ThirdParty/tracy/client/TracyAlloc.cpp
@@ -6,6 +6,10 @@
#include "../common/TracyYield.hpp"
+#if PLATFORM_WINDOWS
+extern void CheckInstructionSet();
+#endif
+
namespace tracy
{
@@ -18,6 +22,10 @@ tracy_no_inline static void InitRpmallocPlumbing()
const auto done = RpInitDone.load( std::memory_order_acquire );
if( !done )
{
+#if PLATFORM_WINDOWS
+ // Check instruction set before executing any code (Tracy init static vars before others)
+ CheckInstructionSet();
+#endif
int expected = 0;
while( !RpInitLock.compare_exchange_weak( expected, 1, std::memory_order_release, std::memory_order_relaxed ) ) { expected = 0; YieldThread(); }
const auto done = RpInitDone.load( std::memory_order_acquire );
diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs b/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs
index f72928bf8..bb1c4fa3c 100644
--- a/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependencies/Assimp.cs
@@ -127,11 +127,12 @@ namespace Flax.Deps.Dependencies
{ "CC", "clang-" + Configuration.LinuxClangMinVer },
{ "CC_FOR_BUILD", "clang-" + Configuration.LinuxClangMinVer },
{ "CXX", "clang++-" + Configuration.LinuxClangMinVer },
+ { "CMAKE_BUILD_PARALLEL_LEVEL", CmakeBuildParallel },
};
// Build for Linux
RunCmake(root, platform, TargetArchitecture.x64, " -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF " + globalConfig, envVars);
- Utilities.Run("make", null, null, root, Utilities.RunOptions.ThrowExceptionOnError, envVars);
+ Utilities.Run("make", null, null, root, Utilities.RunOptions.DefaultTool, envVars);
configHeaderFilePath = Path.Combine(root, "include", "assimp", "config.h");
var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.x64);
Utilities.FileCopy(Path.Combine(root, "lib", "libassimp.a"), Path.Combine(depsFolder, "libassimp.a"));
@@ -143,11 +144,11 @@ namespace Flax.Deps.Dependencies
foreach (var architecture in new[] { TargetArchitecture.x64, TargetArchitecture.ARM64 })
{
RunCmake(root, platform, architecture, " -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=OFF " + globalConfig);
- Utilities.Run("make", null, null, root, Utilities.RunOptions.ThrowExceptionOnError);
+ Utilities.Run("make", null, null, root, Utilities.RunOptions.DefaultTool);
configHeaderFilePath = Path.Combine(root, "include", "assimp", "config.h");
var depsFolder = GetThirdPartyFolder(options, platform, architecture);
Utilities.FileCopy(Path.Combine(root, "lib", "libassimp.a"), Path.Combine(depsFolder, "libassimp.a"));
- Utilities.Run("make", "clean", null, root, Utilities.RunOptions.ThrowExceptionOnError);
+ Utilities.Run("make", "clean", null, root, Utilities.RunOptions.DefaultTool);
}
break;
}
diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs b/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs
index 699e40f72..1120a94f8 100644
--- a/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependencies/NvCloth.cs
@@ -115,6 +115,7 @@ namespace Flax.Deps.Dependencies
var buildFolder = Path.Combine(nvCloth, "compiler", platform.ToString() + '_' + architecture.ToString());
var envVars = new Dictionary();
envVars["GW_DEPS_ROOT"] = root;
+ envVars["CMAKE_BUILD_PARALLEL_LEVEL"] = CmakeBuildParallel;
switch (platform)
{
case TargetPlatform.Windows:
@@ -166,6 +167,8 @@ namespace Flax.Deps.Dependencies
cmakeArgs += " -DTARGET_BUILD_PLATFORM=linux";
cmakeName = "linux";
binariesPrefix = "lib";
+ envVars.Add("CC", "clang-" + Configuration.LinuxClangMinVer);
+ envVars.Add("CXX", "clang++-" + Configuration.LinuxClangMinVer);
break;
default: throw new InvalidPlatformException(platform);
}
diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs b/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs
index 034b2a4b8..319ad70b3 100644
--- a/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependencies/OpenAL.cs
@@ -123,6 +123,7 @@ namespace Flax.Deps.Dependencies
{
{ "CC", "clang-" + Configuration.LinuxClangMinVer },
{ "CC_FOR_BUILD", "clang-" + Configuration.LinuxClangMinVer },
+ { "CXX", "clang++-" + Configuration.LinuxClangMinVer },
{ "CMAKE_BUILD_PARALLEL_LEVEL", CmakeBuildParallel },
};
var config = $"-DALSOFT_REQUIRE_ALSA=ON " +
diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/PhysX.cs b/Source/Tools/Flax.Build/Deps/Dependencies/PhysX.cs
index 32e2d2f38..39f7ad975 100644
--- a/Source/Tools/Flax.Build/Deps/Dependencies/PhysX.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependencies/PhysX.cs
@@ -238,6 +238,8 @@ namespace Flax.Deps.Dependencies
case TargetPlatform.Linux:
envVars.Add("CC", "clang-" + Configuration.LinuxClangMinVer);
envVars.Add("CC_FOR_BUILD", "clang-" + Configuration.LinuxClangMinVer);
+ envVars.Add("CXX", "clang++-" + Configuration.LinuxClangMinVer);
+ envVars.Add("CMAKE_BUILD_PARALLEL_LEVEL", CmakeBuildParallel);
break;
case TargetPlatform.Mac: break;
default: throw new InvalidPlatformException(BuildPlatform);
@@ -258,7 +260,7 @@ namespace Flax.Deps.Dependencies
Log.Info("Building PhysX version " + File.ReadAllText(Path.Combine(root, "physx", "version.txt")) + " to " + binariesSubDir);
// Generate project files
- Utilities.Run(projectGenPath, preset, null, projectGenDir, Utilities.RunOptions.ThrowExceptionOnError, envVars);
+ Utilities.Run(projectGenPath, preset, null, projectGenDir, Utilities.RunOptions.DefaultTool, envVars);
switch (targetPlatform)
{
@@ -304,10 +306,10 @@ namespace Flax.Deps.Dependencies
}
break;
case TargetPlatform.Linux:
- Utilities.Run("make", null, null, Path.Combine(projectGenDir, "compiler", "linux-" + configuration), Utilities.RunOptions.ConsoleLogOutput);
+ Utilities.Run("make", null, null, Path.Combine(projectGenDir, "compiler", "linux-" + configuration), Utilities.RunOptions.ConsoleLogOutput, envVars);
break;
case TargetPlatform.Mac:
- Utilities.Run("xcodebuild", "-project PhysXSDK.xcodeproj -alltargets -configuration " + configuration, null, Path.Combine(projectGenDir, "compiler", preset), Utilities.RunOptions.ConsoleLogOutput);
+ Utilities.Run("xcodebuild", "-project PhysXSDK.xcodeproj -alltargets -configuration " + configuration, null, Path.Combine(projectGenDir, "compiler", preset), Utilities.RunOptions.ConsoleLogOutput, envVars);
break;
default: throw new InvalidPlatformException(BuildPlatform);
}
diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/curl.cs b/Source/Tools/Flax.Build/Deps/Dependencies/curl.cs
index a474b9566..447f573a7 100644
--- a/Source/Tools/Flax.Build/Deps/Dependencies/curl.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependencies/curl.cs
@@ -107,13 +107,14 @@ namespace Flax.Deps.Dependencies
{
{ "CC", "clang-" + Configuration.LinuxClangMinVer },
{ "CC_FOR_BUILD", "clang-" + Configuration.LinuxClangMinVer },
+ { "CMAKE_BUILD_PARALLEL_LEVEL", CmakeBuildParallel },
};
var buildDir = Path.Combine(root, "build");
SetupDirectory(buildDir, true);
- Utilities.Run("chmod", "+x configure", null, root, Utilities.RunOptions.ThrowExceptionOnError);
- Utilities.Run(Path.Combine(root, "configure"), string.Join(" ", settings) + " --prefix=\"" + buildDir + "\"", null, root, Utilities.RunOptions.ThrowExceptionOnError, envVars);
- Utilities.Run("make", null, null, root, Utilities.RunOptions.ThrowExceptionOnError);
- Utilities.Run("make", "install", null, root, Utilities.RunOptions.ThrowExceptionOnError);
+ Utilities.Run("chmod", "+x configure", null, root, Utilities.RunOptions.DefaultTool);
+ Utilities.Run(Path.Combine(root, "configure"), string.Join(" ", settings) + " --prefix=\"" + buildDir + "\"", null, root, Utilities.RunOptions.DefaultTool, envVars);
+ Utilities.Run("make", null, null, root, Utilities.RunOptions.DefaultTool);
+ Utilities.Run("make", "install", null, root, Utilities.RunOptions.DefaultTool);
var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.x64);
var filename = "libcurl.a";
Utilities.FileCopy(Path.Combine(buildDir, "lib", filename), Path.Combine(depsFolder, filename));
@@ -153,11 +154,11 @@ namespace Flax.Deps.Dependencies
};
var buildDir = Path.Combine(root, "build");
SetupDirectory(buildDir, true);
- Utilities.Run("chmod", "+x configure", null, root, Utilities.RunOptions.ThrowExceptionOnError);
- Utilities.Run("chmod", "+x install-sh", null, root, Utilities.RunOptions.ThrowExceptionOnError);
- Utilities.Run(Path.Combine(root, "configure"), string.Join(" ", settings) + " --host=" + archName + " --prefix=\"" + buildDir + "\"", null, root, Utilities.RunOptions.ThrowExceptionOnError, envVars);
- Utilities.Run("make", null, null, root, Utilities.RunOptions.ThrowExceptionOnError);
- Utilities.Run("make", "install", null, root, Utilities.RunOptions.ThrowExceptionOnError);
+ Utilities.Run("chmod", "+x configure", null, root, Utilities.RunOptions.DefaultTool);
+ Utilities.Run("chmod", "+x install-sh", null, root, Utilities.RunOptions.DefaultTool);
+ Utilities.Run(Path.Combine(root, "configure"), string.Join(" ", settings) + " --host=" + archName + " --prefix=\"" + buildDir + "\"", null, root, Utilities.RunOptions.DefaultTool, envVars);
+ Utilities.Run("make", null, null, root, Utilities.RunOptions.DefaultTool);
+ Utilities.Run("make", "install", null, root, Utilities.RunOptions.DefaultTool);
var depsFolder = GetThirdPartyFolder(options, platform, architecture);
var filename = "libcurl.a";
Utilities.FileCopy(Path.Combine(buildDir, "lib", filename), Path.Combine(depsFolder, filename));
diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/freetype.cs b/Source/Tools/Flax.Build/Deps/Dependencies/freetype.cs
index ac0079401..89ed09a72 100644
--- a/Source/Tools/Flax.Build/Deps/Dependencies/freetype.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependencies/freetype.cs
@@ -114,19 +114,22 @@ namespace Flax.Deps.Dependencies
}
case TargetPlatform.Linux:
{
- var envVars = new Dictionary
+ var envVars = new Dictionary
{
{ "CC", "clang-" + Configuration.LinuxClangMinVer },
- { "CC_FOR_BUILD", "clang-" + Configuration.LinuxClangMinVer }
+ { "CC_FOR_BUILD", "clang-" + Configuration.LinuxClangMinVer },
+ { "CMAKE_BUILD_PARALLEL_LEVEL", CmakeBuildParallel },
};
// Fix scripts
- Utilities.Run("sed", "-i -e \'s/\r$//\' autogen.sh", null, root, Utilities.RunOptions.ThrowExceptionOnError, envVars);
- Utilities.Run("sed", "-i -e \'s/\r$//\' configure", null, root, Utilities.RunOptions.ThrowExceptionOnError, envVars);
+ Utilities.Run("dos2unix", "autogen.sh", null, root, Utilities.RunOptions.ThrowExceptionOnError, envVars);
+ Utilities.Run("dos2unix", "configure", null, root, Utilities.RunOptions.ThrowExceptionOnError, envVars);
+ //Utilities.Run("sed", "-i -e \'s/\r$//\' autogen.sh", null, root, Utilities.RunOptions.ThrowExceptionOnError, envVars);
+ //Utilities.Run("sed", "-i -e \'s/\r$//\' configure", null, root, Utilities.RunOptions.ThrowExceptionOnError, envVars);
Utilities.Run("chmod", "+x autogen.sh", null, root, Utilities.RunOptions.ThrowExceptionOnError);
Utilities.Run("chmod", "+x configure", null, root, Utilities.RunOptions.ThrowExceptionOnError);
- Utilities.Run(Path.Combine(root, "autogen.sh"), null, null, root, Utilities.RunOptions.Default, envVars);
+ Utilities.Run(Path.Combine(root, "autogen.sh"), null, null, root, Utilities.RunOptions.ThrowExceptionOnError, envVars);
// Disable using libpng even if it's found on the system
var cmakeFile = Path.Combine(root, "CMakeLists.txt");
@@ -140,8 +143,8 @@ namespace Flax.Deps.Dependencies
// Build for Linux
SetupDirectory(buildDir, true);
var toolchain = UnixToolchain.GetToolchainName(platform, TargetArchitecture.x64);
- Utilities.Run("cmake", string.Format("-G \"Unix Makefiles\" -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DFT_WITH_BZIP2=OFF -DFT_WITH_ZLIB=OFF -DFT_WITH_PNG=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER_TARGET={0} ..", toolchain), null, buildDir, Utilities.RunOptions.ThrowExceptionOnError, envVars);
- Utilities.Run("cmake", "--build .", null, buildDir, Utilities.RunOptions.ThrowExceptionOnError, envVars);
+ Utilities.Run("cmake", string.Format("-G \"Unix Makefiles\" -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DFT_WITH_BZIP2=OFF -DFT_WITH_ZLIB=OFF -DFT_WITH_PNG=OFF -DCMAKE_BUILD_TYPE=Release -DCMAKE_C_COMPILER_TARGET={0} ..", toolchain), null, buildDir, Utilities.RunOptions.DefaultTool, envVars);
+ Utilities.Run("cmake", "--build .", null, buildDir, Utilities.RunOptions.DefaultTool, envVars);
var depsFolder = GetThirdPartyFolder(options, platform, TargetArchitecture.x64);
Utilities.FileCopy(Path.Combine(buildDir, libraryFileName), Path.Combine(depsFolder, libraryFileName));
diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/nethost.cs b/Source/Tools/Flax.Build/Deps/Dependencies/nethost.cs
index 11ab39f8d..1991aa605 100644
--- a/Source/Tools/Flax.Build/Deps/Dependencies/nethost.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependencies/nethost.cs
@@ -303,9 +303,9 @@ namespace Flax.Deps.Dependencies
}
// Ensure to have dependencies installed
- Utilities.Run("ninja", "--version", null, null, Utilities.RunOptions.ThrowExceptionOnError);
- Utilities.Run("cmake", "--version", null, null, Utilities.RunOptions.ThrowExceptionOnError);
- Utilities.Run("python", "--version", null, null, Utilities.RunOptions.ThrowExceptionOnError);
+ Utilities.Run("ninja", "--version", null, null, Utilities.RunOptions.DefaultTool);
+ Utilities.Run("cmake", "--version", null, null, Utilities.RunOptions.DefaultTool);
+ Utilities.Run("python", "--version", null, null, Utilities.RunOptions.DefaultTool);
// Get the source
if (!Directory.Exists(Path.Combine(root, ".git")))
diff --git a/Source/Tools/Flax.Build/Deps/Dependencies/vorbis.cs b/Source/Tools/Flax.Build/Deps/Dependencies/vorbis.cs
index 45adc9188..d22f8696f 100644
--- a/Source/Tools/Flax.Build/Deps/Dependencies/vorbis.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependencies/vorbis.cs
@@ -366,15 +366,17 @@ namespace Flax.Deps.Dependencies
var envVars = new Dictionary
{
{ "CC", "clang-" + Configuration.LinuxClangMinVer },
- { "CC_FOR_BUILD", "clang-" + Configuration.LinuxClangMinVer }
+ { "CC_FOR_BUILD", "clang-" + Configuration.LinuxClangMinVer },
+ { "CXX", "clang++-" + Configuration.LinuxClangMinVer },
+ { "CMAKE_BUILD_PARALLEL_LEVEL", CmakeBuildParallel },
};
var buildDir = Path.Combine(root, "build");
- Utilities.Run(Path.Combine(root, "autogen.sh"), null, null, root, Utilities.RunOptions.Default, envVars);
+ Utilities.Run(Path.Combine(root, "autogen.sh"), null, null, root, Utilities.RunOptions.DefaultTool, envVars);
// Build for Linux
var toolchain = UnixToolchain.GetToolchainName(platform, TargetArchitecture.x64);
- Utilities.Run(Path.Combine(root, "configure"), string.Format("--host={0}", toolchain), null, root, Utilities.RunOptions.Default, envVars);
+ Utilities.Run(Path.Combine(root, "configure"), string.Format("--host={0}", toolchain), null, root, Utilities.RunOptions.ThrowExceptionOnError, envVars);
SetupDirectory(buildDir, true);
Utilities.Run("cmake", "-G \"Unix Makefiles\" -DCMAKE_POSITION_INDEPENDENT_CODE=ON -DCMAKE_BUILD_TYPE=Release ..", null, buildDir, Utilities.RunOptions.ConsoleLogOutput, envVars);
Utilities.Run("cmake", "--build .", null, buildDir, Utilities.RunOptions.ConsoleLogOutput, envVars);
diff --git a/Source/Tools/Flax.Build/Deps/Dependency.cs b/Source/Tools/Flax.Build/Deps/Dependency.cs
index a79a968a3..43cdcc146 100644
--- a/Source/Tools/Flax.Build/Deps/Dependency.cs
+++ b/Source/Tools/Flax.Build/Deps/Dependency.cs
@@ -456,7 +456,7 @@ namespace Flax.Deps
case TargetPlatform.Mac: break;
default: throw new InvalidPlatformException(BuildPlatform);
}
- Utilities.Run(path, args, null, workspace, Utilities.RunOptions.ThrowExceptionOnError, envVars);
+ Utilities.Run(path, args, null, workspace, Utilities.RunOptions.DefaultTool, envVars);
}
internal bool GetMsBuildForPlatform(TargetPlatform targetPlatform, out VisualStudioVersion vsVersion, out string msBuildPath)
diff --git a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs
index 174b2bcee..6d017806d 100644
--- a/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs
+++ b/Source/Tools/Flax.Build/Platforms/Linux/LinuxToolchain.cs
@@ -14,7 +14,7 @@ namespace Flax.Build
/// Specifies the minimum Clang compiler version to use on Linux (eg. 10).
///
[CommandLine("linuxClangMinVer", "", "Specifies the minimum Clang compiler version to use on Linux (eg. 10).")]
- public static string LinuxClangMinVer = "13";
+ public static string LinuxClangMinVer = "14";
}
}