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"; } }