From b02020f8017bb4f3f22440bc39b60857ab364179 Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Thu, 10 Nov 2022 10:51:20 +0100 Subject: [PATCH 01/83] PE: AudioSource - Stop() folowed by Play() now act like a restart. --- Source/Engine/Audio/AudioSource.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Audio/AudioSource.cpp b/Source/Engine/Audio/AudioSource.cpp index 10e2cf429..333ac2c72 100644 --- a/Source/Engine/Audio/AudioSource.cpp +++ b/Source/Engine/Audio/AudioSource.cpp @@ -132,7 +132,7 @@ void AudioSource::Play() Clip->RequestStreamingUpdate(); // If we are looping and streaming also update streaming buffers - if (_loop) + if (_loop || state == States::Stopped) RequestStreamingBuffersUpdate(); } } From 29900a3cc005f7f5ac74254d2b7a58920341d73c Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Thu, 10 Nov 2022 11:19:29 +0100 Subject: [PATCH 02/83] PE: Support importing WAV files that contain "extra format bytes" in "fmt" header. --- Source/Engine/Tools/AudioTool/WaveDecoder.cpp | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Tools/AudioTool/WaveDecoder.cpp b/Source/Engine/Tools/AudioTool/WaveDecoder.cpp index 58adfde89..0336e965d 100644 --- a/Source/Engine/Tools/AudioTool/WaveDecoder.cpp +++ b/Source/Engine/Tools/AudioTool/WaveDecoder.cpp @@ -23,11 +23,14 @@ bool WaveDecoder::ParseHeader(AudioDataInfo& info) uint32 subChunkSize = 0; mStream->ReadUint32(&subChunkSize); + uint32 totalread = 0; + // FMT chunk if (subChunkId[0] == 'f' && subChunkId[1] == 'm' && subChunkId[2] == 't' && subChunkId[3] == ' ') { uint16 format; mStream->ReadUint16(&format); + totalread += 2; if (format != WAVE_FORMAT_PCM && format != WAVE_FORMAT_IEEE_FLOAT && format != WAVE_FORMAT_EXTENDED) { @@ -37,18 +40,23 @@ bool WaveDecoder::ParseHeader(AudioDataInfo& info) uint16 numChannels = 0; mStream->ReadUint16(&numChannels); + totalread += 2; uint32 sampleRate = 0; mStream->ReadUint32(&sampleRate); + totalread += 4; uint32 byteRate = 0; mStream->ReadUint32(&byteRate); + totalread += 4; uint16 blockAlign = 0; mStream->ReadUint16(&blockAlign); + totalread += 2; uint16 bitDepth = 0; mStream->ReadUint16(&bitDepth); + totalread += 2; if (bitDepth != 8 && bitDepth != 16 && bitDepth != 24 && bitDepth != 32) { @@ -65,6 +73,7 @@ bool WaveDecoder::ParseHeader(AudioDataInfo& info) { uint16 extensionSize = 0; mStream->ReadUint16(&extensionSize); + totalread += 2; if (extensionSize != 22) { @@ -74,12 +83,15 @@ bool WaveDecoder::ParseHeader(AudioDataInfo& info) uint16 validBitDepth = 0; mStream->ReadUint16(&validBitDepth); + totalread += 2; uint32 channelMask = 0; mStream->ReadUint32(&channelMask); + totalread += 4; uint8 subFormat[16]; mStream->Read(subFormat, sizeof(subFormat)); + totalread += 16; Platform::MemoryCopy(&format, subFormat, sizeof(format)); if (format != WAVE_FORMAT_PCM) @@ -89,10 +101,18 @@ bool WaveDecoder::ParseHeader(AudioDataInfo& info) } } + // PE: Support wav with "extra format bytes", just ignore not needed. + while (totalread < subChunkSize) + { + uint8 singlebyte; + mStream->Read(&singlebyte, sizeof(singlebyte)); + totalread++; + } + mBytesPerSample = bitDepth / 8; mFormat = format; } - // DATA chunk + // DATA chunk else if (subChunkId[0] == 'd' && subChunkId[1] == 'a' && subChunkId[2] == 't' && subChunkId[3] == 'a') { info.NumSamples = subChunkSize / mBytesPerSample; @@ -100,7 +120,7 @@ bool WaveDecoder::ParseHeader(AudioDataInfo& info) foundData = true; } - // Unsupported chunk type + // Unsupported chunk type else { if (mStream->GetPosition() + subChunkSize >= mStream->GetLength()) From 54ccf9edc7ffcda8490687ac9a4dbb4a652d4f63 Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Thu, 10 Nov 2022 11:35:29 +0100 Subject: [PATCH 03/83] PE: Fixed - Custom animation import, frame index start and end was not the actual index but depended on frames per second. Made it impossible to use, now use the real frame index. --- Source/Engine/Tools/ModelTool/ModelTool.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index 53fd90de4..ae8e8fe7b 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -1275,8 +1275,16 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op // Trim the animation keyframes range if need to if (options.Duration == AnimationDuration::Custom) { - const float start = (float)(options.FramesRange.X / data.Animation.FramesPerSecond); - const float end = (float)(options.FramesRange.Y / data.Animation.FramesPerSecond); + // PE: This is wrong, FramesRange is Frame Index start end, not the frame time. + // PE: To extract Frame Index you has to enter Frame*FramesPerSecond or it will not work. + // PE: This also makes another problem as the "length" get wrong and your not able to loop animatons. + // const float start = (float)(options.FramesRange.X / data.Animation.FramesPerSecond); + // const float end = (float)(options.FramesRange.Y / data.Animation.FramesPerSecond); + // data.Animation.Duration = (end - start); // *data.Animation.FramesPerSecond; + + // PE: Custom animation import , frame index start and end, is now correct and the real index. + const float start = (float)(options.FramesRange.X); + const float end = (float)(options.FramesRange.Y); for (int32 i = 0; i < data.Animation.Channels.Count(); i++) { auto& anim = data.Animation.Channels[i]; @@ -1285,7 +1293,7 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op anim.Rotation.Trim(start, end); anim.Scale.Trim(start, end); } - data.Animation.Duration = (end - start) * data.Animation.FramesPerSecond; + data.Animation.Duration = (end - start); } // Change the sampling rate if need to From c73eb548c0e8967624d4cb85c8f80d230e583ef8 Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Thu, 10 Nov 2022 13:14:19 +0100 Subject: [PATCH 04/83] PE: FBX Import - Improved normal map detection using diffuse name, if normap map was not setup inside object. --- .../Tools/ModelTool/ModelTool.OpenFBX.cpp | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp b/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp index 05681aadc..cea29f7fb 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp @@ -229,6 +229,57 @@ struct OpenFbxImporterData ImportMaterialTexture(result, mat, ofbx::Texture::EMISSIVE, material.Emissive.TextureIndex, TextureEntry::TypeHint::ColorRGB); ImportMaterialTexture(result, mat, ofbx::Texture::NORMAL, material.Normals.TextureIndex, TextureEntry::TypeHint::Normals); + // PE: FBX dont always store normal maps inside the object. + if (material.Diffuse.TextureIndex != -1 && material.Normals.TextureIndex == -1) + { + // PE: If missing , try to locate a normal map in the same path as the diffuse. + const String srcFolder = String(StringUtils::GetDirectoryName(result.Textures[material.Diffuse.TextureIndex].FilePath)); + const String srcName = StringUtils::GetFileNameWithoutExtension(result.Textures[material.Diffuse.TextureIndex].FilePath); + String srcSearch; + + const int32 num = srcName.FindLast('_'); + String srcSmallName = srcName; + if (num != -1) + { + srcSmallName = srcName.Substring(0, num); + } + + bool bNormal = false; + for (int iext = 0; iext < 6; iext++) + { + String sext = TEXT(".dds"); + if (iext == 1) sext = TEXT(".png"); + if (iext == 2) sext = TEXT(".jpg"); + if (iext == 3) sext = TEXT(".jpeg"); + if (iext == 4) sext = TEXT(".tif"); + if (iext == 5) sext = TEXT(".tga"); + for (int i = 0; i < 5; i++) + { + String sfind = TEXT("_normal" + sext); + if (i == 1) sfind = TEXT("_n" + sext); + if (i == 2) sfind = TEXT("_nm" + sext); + if (i == 3) sfind = TEXT("_nmp" + sext); + if (i == 4) sfind = TEXT("_nor" + sext); + srcSearch = srcFolder + TEXT("/") + srcSmallName + sfind; + if (FileSystem::FileExists(srcSearch)) + { + bNormal = true; + break; + } + } + if (bNormal) + break; + } + if (bNormal) + { + auto& texture = result.Textures.AddOne(); + texture.FilePath = srcSearch; + texture.Type = TextureEntry::TypeHint::Normals; + texture.AssetID = Guid::Empty; + material.Normals.TextureIndex = result.Textures.Count() - 1; + } + } + if (material.Diffuse.TextureIndex != -1) { // Detect using alpha mask in diffuse texture From c26e0f5923bd44a0356dab8064db3e2fadecd972 Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Thu, 10 Nov 2022 13:41:40 +0100 Subject: [PATCH 05/83] PE: DDS - Improve import time if source already has mipmaps and are compressed. --- .../TextureTool/TextureTool.DirectXTex.cpp | 27 ++++++++++++++----- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp b/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp index b58dd878a..540c8e186 100644 --- a/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp +++ b/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp @@ -623,8 +623,21 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path sliceData.Mips.Resize(mipLevels); } + bool bKeepAsIs = false; + if (!options.FlipY &&options.Compress && type == ImageType::DDS && mipLevels == sourceMipLevels && DirectX::IsCompressed(sourceDxgiFormat)) + { + if (!DirectX::IsSRGB(sourceDxgiFormat)) + { + // PE: Keep image in the current compressed format (artist choice) so we dont have to run the slow mipmap generation. + // PE: Also converting a BC1 normal map to BC5 will not improve it but just use double gpu mem. + bKeepAsIs = true; + targetDxgiFormat = sourceDxgiFormat; + targetFormat = ToPixelFormat(currentImage->GetMetadata().format); + } + } + // Decompress if texture is compressed (next steps need decompressed input data, for eg. mip maps generation or format changing) - if (DirectX::IsCompressed(sourceDxgiFormat)) + if (!bKeepAsIs && DirectX::IsCompressed(sourceDxgiFormat)) { auto& tmpImg = GET_TMP_IMG(); @@ -640,7 +653,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path } // Fix sRGB problem - if (DirectX::IsSRGB(sourceDxgiFormat)) + if (!bKeepAsIs && DirectX::IsSRGB(sourceDxgiFormat)) { sourceDxgiFormat = ToDxgiFormat(PixelFormatExtensions::ToNonsRGB(ToPixelFormat(sourceDxgiFormat))); ((DirectX::TexMetadata&)currentImage->GetMetadata()).format = sourceDxgiFormat; @@ -649,7 +662,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path } // Remove alpha if source texture has it but output should not, valid for compressed output only (DirectX seams to use alpha to pre-multiply colors because BC1 format has no place for alpha) - if (DirectX::HasAlpha(sourceDxgiFormat) && options.Type == TextureFormatType::ColorRGB && options.Compress) + if (!bKeepAsIs && DirectX::HasAlpha(sourceDxgiFormat) && options.Type == TextureFormatType::ColorRGB && options.Compress) { auto& tmpImg = GET_TMP_IMG(); @@ -674,7 +687,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path } // Check flip/rotate source image - if (options.FlipY) + if (!bKeepAsIs && options.FlipY) { auto& tmpImg = GET_TMP_IMG(); @@ -691,7 +704,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path } // Generate mip maps chain - if (useMipLevels && options.GenerateMipMaps) + if (!bKeepAsIs && useMipLevels && options.GenerateMipMaps) { auto& tmpImg = GET_TMP_IMG(); @@ -714,7 +727,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path } // Preserve mipmap alpha coverage (if requested) - if (DirectX::HasAlpha(currentImage->GetMetadata().format) && options.PreserveAlphaCoverage && useMipLevels) + if (!bKeepAsIs && DirectX::HasAlpha(currentImage->GetMetadata().format) && options.PreserveAlphaCoverage && useMipLevels) { auto& tmpImg = GET_TMP_IMG(); @@ -746,7 +759,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path ASSERT((int32)currentImage->GetMetadata().mipLevels >= mipLevels); // Compress mip maps or convert image - if (targetDxgiFormat != sourceDxgiFormat) + if (!bKeepAsIs && targetDxgiFormat != sourceDxgiFormat) { auto& tmpImg = GET_TMP_IMG(); From eab45f0c4884e162dc3ba7c2a69901a4d4241587 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 11 Nov 2022 12:42:12 -0600 Subject: [PATCH 06/83] renames item when clicking off of the popup and name is changed --- Source/Editor/GUI/Popups/RenamePopup.cs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Source/Editor/GUI/Popups/RenamePopup.cs b/Source/Editor/GUI/Popups/RenamePopup.cs index 891ced9c7..0e21f331b 100644 --- a/Source/Editor/GUI/Popups/RenamePopup.cs +++ b/Source/Editor/GUI/Popups/RenamePopup.cs @@ -81,6 +81,20 @@ namespace FlaxEditor.GUI private bool IsInputValid => !string.IsNullOrWhiteSpace(_inputField.Text) && (_inputField.Text == _startValue || Validate == null || Validate(this, _inputField.Text)); + /// + public override void Update(float deltaTime) + { + var mouseLocation = Root.MousePosition; + if (!ContainsPoint(ref mouseLocation) && RootWindow.ContainsFocus && Text != _startValue) + { + // rename item before closing if left mouse button in clicked + if (FlaxEngine.Input.GetMouseButton(MouseButton.Left)) + OnEnd(); + } + + base.Update(deltaTime); + } + private void OnTextChanged() { if (Validate == null) From 6c18ca3f454cdc6bd41c42ac17283aa8535f7f4d Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 11 Nov 2022 12:45:10 -0600 Subject: [PATCH 07/83] changed to MouseButtonDown --- Source/Editor/GUI/Popups/RenamePopup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/GUI/Popups/RenamePopup.cs b/Source/Editor/GUI/Popups/RenamePopup.cs index 0e21f331b..01fbdc03f 100644 --- a/Source/Editor/GUI/Popups/RenamePopup.cs +++ b/Source/Editor/GUI/Popups/RenamePopup.cs @@ -88,7 +88,7 @@ namespace FlaxEditor.GUI if (!ContainsPoint(ref mouseLocation) && RootWindow.ContainsFocus && Text != _startValue) { // rename item before closing if left mouse button in clicked - if (FlaxEngine.Input.GetMouseButton(MouseButton.Left)) + if (FlaxEngine.Input.GetMouseButtonDown(MouseButton.Left)) OnEnd(); } From 451584421906e499dabb34466f4cd88947763fbb Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 11 Nov 2022 16:37:45 -0600 Subject: [PATCH 08/83] changed how the actor toolbox is created. Allows fo user to enter their own tabs and actors with an attribute --- Source/Editor/Windows/ToolboxWindow.cs | 106 +++++++++++++++++- .../SceneAnimations/SceneAnimationPlayer.h | 2 +- Source/Engine/Audio/AudioListener.h | 2 +- Source/Engine/Audio/AudioSource.h | 2 +- Source/Engine/Level/Actors/AnimatedModel.h | 2 +- Source/Engine/Level/Actors/BoneSocket.h | 2 +- Source/Engine/Level/Actors/BoxBrush.h | 2 +- Source/Engine/Level/Actors/Camera.h | 2 +- Source/Engine/Level/Actors/Decal.h | 2 +- Source/Engine/Level/Actors/DirectionalLight.h | 2 +- Source/Engine/Level/Actors/EmptyActor.h | 2 +- Source/Engine/Level/Actors/EnvironmentProbe.h | 2 +- .../Level/Actors/ExponentialHeightFog.h | 2 +- Source/Engine/Level/Actors/PointLight.h | 2 +- Source/Engine/Level/Actors/PostFxVolume.h | 2 +- Source/Engine/Level/Actors/Sky.h | 2 +- Source/Engine/Level/Actors/SkyLight.h | 2 +- Source/Engine/Level/Actors/Skybox.h | 2 +- Source/Engine/Level/Actors/Spline.h | 2 +- Source/Engine/Level/Actors/SpotLight.h | 2 +- Source/Engine/Navigation/NavLink.h | 2 +- .../Engine/Navigation/NavMeshBoundsVolume.h | 2 +- Source/Engine/Navigation/NavModifierVolume.h | 2 +- Source/Engine/Particles/ParticleEffect.h | 2 +- Source/Engine/Physics/Actors/RigidBody.h | 2 +- Source/Engine/Physics/Colliders/BoxCollider.h | 2 +- .../Physics/Colliders/CapsuleCollider.h | 2 +- .../Physics/Colliders/CharacterController.h | 2 +- .../Engine/Physics/Colliders/MeshCollider.h | 2 +- .../Engine/Physics/Colliders/SphereCollider.h | 2 +- Source/Engine/Physics/Joints/D6Joint.h | 2 +- Source/Engine/Physics/Joints/DistanceJoint.h | 2 +- Source/Engine/Physics/Joints/FixedJoint.h | 2 +- Source/Engine/Physics/Joints/HingeJoint.h | 2 +- Source/Engine/Physics/Joints/SliderJoint.h | 2 +- Source/Engine/Physics/Joints/SphericalJoint.h | 2 +- .../Attributes/Editor/ActorToolbox.cs | 26 +++++ Source/Engine/UI/SpriteRender.h | 2 +- Source/Engine/UI/TextRender.h | 2 +- Source/Engine/UI/UICanvas.h | 2 +- Source/Engine/UI/UIControl.h | 2 +- 41 files changed, 169 insertions(+), 41 deletions(-) create mode 100644 Source/Engine/Scripting/Attributes/Editor/ActorToolbox.cs diff --git a/Source/Editor/Windows/ToolboxWindow.cs b/Source/Editor/Windows/ToolboxWindow.cs index 2ef8b7db2..832f57468 100644 --- a/Source/Editor/Windows/ToolboxWindow.cs +++ b/Source/Editor/Windows/ToolboxWindow.cs @@ -100,6 +100,7 @@ namespace FlaxEditor.Windows private TextBox _searchBox; private ContainerControl _groupSearch; + private Tabs actorGroups; /// /// The editor instance. @@ -117,8 +118,9 @@ namespace FlaxEditor.Windows Editor = editor; Selected += tab => Editor.Windows.EditWin.Viewport.SetActiveMode(); ScriptsBuilder.ScriptsReload += OnScriptsReload; + ScriptsBuilder.ScriptsReloadEnd += OnScriptsReloadEnd; - var actorGroups = new Tabs + actorGroups = new Tabs { Orientation = Orientation.Vertical, UseScroll = true, @@ -127,7 +129,19 @@ namespace FlaxEditor.Windows TabsSize = new Float2(120, 32), Parent = this, }; + + _groupSearch = CreateGroupWithList(actorGroups, "Search", 26); + _searchBox = new TextBox + { + AnchorPreset = AnchorPresets.HorizontalStretchTop, + WatermarkText = "Search...", + Parent = _groupSearch.Parent.Parent, + Bounds = new Rectangle(4, 4, actorGroups.Width - 8, 18), + }; + _searchBox.TextChanged += OnSearchBoxTextChanged; + RefreshActorTabs(); +/* _groupSearch = CreateGroupWithList(actorGroups, "Search", 26); _searchBox = new TextBox { @@ -194,7 +208,7 @@ namespace FlaxEditor.Windows groupGui.AddChild(CreateActorItem("UI Canvas", typeof(UICanvas))); groupGui.AddChild(CreateActorItem("Text Render", typeof(TextRender))); groupGui.AddChild(CreateActorItem("Sprite Render", typeof(SpriteRender))); - +*/ actorGroups.SelectedTabIndex = 1; } @@ -206,6 +220,94 @@ namespace FlaxEditor.Windows _groupSearch.PerformLayout(); } + private void OnScriptsReloadEnd() + { + RefreshActorTabs(); + } + + private void RefreshActorTabs() + { + // Remove tabs + List tabs = new List(); + foreach (var child in actorGroups.Children) + { + if (child is Tab tab) + { + if (tab.Text != "Search") + tabs.Add(tab); + } + } + + foreach (var tab in tabs) + { + var group = actorGroups.Children.Find(T => T == tab); + group.Dispose(); + } + + var groupBasicModels = CreateGroupWithList(actorGroups, "Basic Models"); + groupBasicModels.AddChild(CreateEditorAssetItem("Cube", "Primitives/Cube.flax")); + groupBasicModels.AddChild(CreateEditorAssetItem("Sphere", "Primitives/Sphere.flax")); + groupBasicModels.AddChild(CreateEditorAssetItem("Plane", "Primitives/Plane.flax")); + groupBasicModels.AddChild(CreateEditorAssetItem("Cylinder", "Primitives/Cylinder.flax")); + groupBasicModels.AddChild(CreateEditorAssetItem("Cone", "Primitives/Cone.flax")); + groupBasicModels.AddChild(CreateEditorAssetItem("Capsule", "Primitives/Capsule.flax")); + + // Created first to order specific tabs + CreateGroupWithList(actorGroups, "Lights"); + CreateGroupWithList(actorGroups, "Visuals"); + CreateGroupWithList(actorGroups, "Physics"); + CreateGroupWithList(actorGroups, "GUI"); + CreateGroupWithList(actorGroups, "Other"); + + // Add other actor types to respective tab based on attribute + foreach (var actorType in Editor.CodeEditing.Actors.Get()) + { + if (actorType.IsAbstract) + continue; + + ActorToolboxAttribute attribute = null; + foreach (var e in actorType.GetAttributes(true)) + { + if (e is ActorToolboxAttribute actorToolboxAttribute) + { + attribute = actorToolboxAttribute; + break; + } + } + + if (attribute == null) + continue; + + var groupName = attribute.Group; + + // Check if tab already exists and add it to the tab + var actorTabExists = false; + foreach (var child in actorGroups.Children) + { + if (child is Tab tab) + { + if (tab.Text == groupName) + { + var tree = tab.GetChild().GetChild(); + if (tree != null) + { + tree.AddChild(CreateActorItem(Utilities.Utils.GetPropertyNameUI(actorType.Name), actorType)); + tree.SortChildren(); + } + actorTabExists = true; + break; + } + } + } + if (actorTabExists) + continue; + + var group = CreateGroupWithList(actorGroups, groupName); + group.AddChild(CreateActorItem(Utilities.Utils.GetPropertyNameUI(actorType.Name), actorType)); + group.SortChildren(); + } + } + private void OnSearchBoxTextChanged() { // Skip events during setup or init stuff diff --git a/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h b/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h index cdeb29fa5..35c7bd013 100644 --- a/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h +++ b/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h @@ -11,7 +11,7 @@ /// /// The scene animation playback actor. /// -API_CLASS(Attributes = "ActorContextMenu(\"New/Other/Scene Animation\")") class FLAXENGINE_API SceneAnimationPlayer : public Actor, public IPostFxSettingsProvider +API_CLASS(Attributes = "ActorContextMenu(\"New/Other/Scene Animation\"), ActorToolbox(\"Other\")") class FLAXENGINE_API SceneAnimationPlayer : public Actor, public IPostFxSettingsProvider { DECLARE_SCENE_OBJECT(SceneAnimationPlayer); diff --git a/Source/Engine/Audio/AudioListener.h b/Source/Engine/Audio/AudioListener.h index 9edcb4ff7..6090983ae 100644 --- a/Source/Engine/Audio/AudioListener.h +++ b/Source/Engine/Audio/AudioListener.h @@ -7,7 +7,7 @@ /// /// Represents a listener that hears audio sources. For spatial audio the volume and pitch of played audio is determined by the distance, orientation and velocity differences between the source and the listener. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Listener\")") class FLAXENGINE_API AudioListener : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Listener\"), ActorToolbox(\"Other\")") class FLAXENGINE_API AudioListener : public Actor { DECLARE_SCENE_OBJECT(AudioListener); private: diff --git a/Source/Engine/Audio/AudioSource.h b/Source/Engine/Audio/AudioSource.h index 4335795e9..71575d318 100644 --- a/Source/Engine/Audio/AudioSource.h +++ b/Source/Engine/Audio/AudioSource.h @@ -13,7 +13,7 @@ /// /// Whether or not an audio source is spatial is controlled by the assigned AudioClip.The volume and the pitch of a spatial audio source is controlled by its position and the AudioListener's position/direction/velocity. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Source\")") class FLAXENGINE_API AudioSource : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Source\"), ActorToolbox(\"Other\")") class FLAXENGINE_API AudioSource : public Actor { DECLARE_SCENE_OBJECT(AudioSource); friend class AudioStreamingHandler; diff --git a/Source/Engine/Level/Actors/AnimatedModel.h b/Source/Engine/Level/Actors/AnimatedModel.h index 0e9cd2fe3..8d7471ae0 100644 --- a/Source/Engine/Level/Actors/AnimatedModel.h +++ b/Source/Engine/Level/Actors/AnimatedModel.h @@ -12,7 +12,7 @@ /// /// Performs an animation and renders a skinned model. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Other/Animated Model\")") class FLAXENGINE_API AnimatedModel : public ModelInstanceActor +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Animated Model\"), ActorToolbox(\"Other\")") class FLAXENGINE_API AnimatedModel : public ModelInstanceActor { DECLARE_SCENE_OBJECT(AnimatedModel); friend class AnimationsSystem; diff --git a/Source/Engine/Level/Actors/BoneSocket.h b/Source/Engine/Level/Actors/BoneSocket.h index 4e107aac0..6d516481e 100644 --- a/Source/Engine/Level/Actors/BoneSocket.h +++ b/Source/Engine/Level/Actors/BoneSocket.h @@ -7,7 +7,7 @@ /// /// Actor that links to the animated model skeleton node transformation. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Other/Bone Socket\")") class FLAXENGINE_API BoneSocket : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Bone Socket\"), ActorToolbox(\"Other\")") class FLAXENGINE_API BoneSocket : public Actor { DECLARE_SCENE_OBJECT(BoneSocket); diff --git a/Source/Engine/Level/Actors/BoxBrush.h b/Source/Engine/Level/Actors/BoxBrush.h index 5e8fe2cb9..62621577b 100644 --- a/Source/Engine/Level/Actors/BoxBrush.h +++ b/Source/Engine/Level/Actors/BoxBrush.h @@ -65,7 +65,7 @@ public: /// /// Performs CSG box brush operation that adds or removes geometry. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Other/Box Brush\")") class FLAXENGINE_API BoxBrush : public Actor, public CSG::Brush +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Box Brush\"), ActorToolbox(\"Other\")") class FLAXENGINE_API BoxBrush : public Actor, public CSG::Brush { DECLARE_SCENE_OBJECT(BoxBrush); private: diff --git a/Source/Engine/Level/Actors/Camera.h b/Source/Engine/Level/Actors/Camera.h index e01cf11c4..0cd866003 100644 --- a/Source/Engine/Level/Actors/Camera.h +++ b/Source/Engine/Level/Actors/Camera.h @@ -18,7 +18,7 @@ /// /// Describes the camera projection and view. Provides information about how to render scene (viewport location and direction, etc.). /// -API_CLASS(Sealed, Attributes="ActorContextMenu(\"New/Camera\")") class FLAXENGINE_API Camera : public Actor +API_CLASS(Sealed, Attributes="ActorContextMenu(\"New/Camera\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API Camera : public Actor { DECLARE_SCENE_OBJECT(Camera); diff --git a/Source/Engine/Level/Actors/Decal.h b/Source/Engine/Level/Actors/Decal.h index 497186cc5..a8e015045 100644 --- a/Source/Engine/Level/Actors/Decal.h +++ b/Source/Engine/Level/Actors/Decal.h @@ -11,7 +11,7 @@ /// /// Actor that draws the can be used to draw a custom decals on top of the other objects. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Decal\")") class FLAXENGINE_API Decal : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Decal\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API Decal : public Actor { DECLARE_SCENE_OBJECT(Decal); private: diff --git a/Source/Engine/Level/Actors/DirectionalLight.h b/Source/Engine/Level/Actors/DirectionalLight.h index 196ae0d26..e20b7f0f6 100644 --- a/Source/Engine/Level/Actors/DirectionalLight.h +++ b/Source/Engine/Level/Actors/DirectionalLight.h @@ -7,7 +7,7 @@ /// /// Directional light emits light from direction in space. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Directional Light\")") class FLAXENGINE_API DirectionalLight : public LightWithShadow +API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Directional Light\"), ActorToolbox(\"Lights\")") class FLAXENGINE_API DirectionalLight : public LightWithShadow { DECLARE_SCENE_OBJECT(DirectionalLight); private: diff --git a/Source/Engine/Level/Actors/EmptyActor.h b/Source/Engine/Level/Actors/EmptyActor.h index 17742d137..bd4e2b04a 100644 --- a/Source/Engine/Level/Actors/EmptyActor.h +++ b/Source/Engine/Level/Actors/EmptyActor.h @@ -7,7 +7,7 @@ /// /// The empty actor that is useful to create hierarchy and/or hold scripts. See . /// -API_CLASS(Attributes="ActorContextMenu(\"New/Actor\")") class FLAXENGINE_API EmptyActor : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Actor\"), ActorToolbox(\"Other\")") class FLAXENGINE_API EmptyActor : public Actor { DECLARE_SCENE_OBJECT(EmptyActor); public: diff --git a/Source/Engine/Level/Actors/EnvironmentProbe.h b/Source/Engine/Level/Actors/EnvironmentProbe.h index e5a5faa84..4d317a7f7 100644 --- a/Source/Engine/Level/Actors/EnvironmentProbe.h +++ b/Source/Engine/Level/Actors/EnvironmentProbe.h @@ -10,7 +10,7 @@ /// /// Environment Probe can capture space around the objects to provide reflections. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Environment Probe\")") class FLAXENGINE_API EnvironmentProbe : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Environment Probe\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API EnvironmentProbe : public Actor { DECLARE_SCENE_OBJECT(EnvironmentProbe); public: diff --git a/Source/Engine/Level/Actors/ExponentialHeightFog.h b/Source/Engine/Level/Actors/ExponentialHeightFog.h index ac2d24d91..00bff0be0 100644 --- a/Source/Engine/Level/Actors/ExponentialHeightFog.h +++ b/Source/Engine/Level/Actors/ExponentialHeightFog.h @@ -12,7 +12,7 @@ /// /// Used to create fogging effects such as clouds but with a density that is related to the height of the fog. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Exponential Height Fog\")") class FLAXENGINE_API ExponentialHeightFog : public Actor, public IFogRenderer +API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Exponential Height Fog\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API ExponentialHeightFog : public Actor, public IFogRenderer { DECLARE_SCENE_OBJECT(ExponentialHeightFog); private: diff --git a/Source/Engine/Level/Actors/PointLight.h b/Source/Engine/Level/Actors/PointLight.h index d1d503349..29c3e5414 100644 --- a/Source/Engine/Level/Actors/PointLight.h +++ b/Source/Engine/Level/Actors/PointLight.h @@ -9,7 +9,7 @@ /// /// Point light emits light from point in all directions. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Point Light\")") class FLAXENGINE_API PointLight : public LightWithShadow +API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Point Light\"), ActorToolbox(\"Lights\")") class FLAXENGINE_API PointLight : public LightWithShadow { DECLARE_SCENE_OBJECT(PointLight); private: diff --git a/Source/Engine/Level/Actors/PostFxVolume.h b/Source/Engine/Level/Actors/PostFxVolume.h index 97d61f1f3..0ba1978ac 100644 --- a/Source/Engine/Level/Actors/PostFxVolume.h +++ b/Source/Engine/Level/Actors/PostFxVolume.h @@ -9,7 +9,7 @@ /// /// A special type of volume that blends custom set of post process settings into the rendering. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Post Fx Volume\")") class FLAXENGINE_API PostFxVolume : public BoxVolume, public IPostFxSettingsProvider +API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Post Fx Volume\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API PostFxVolume : public BoxVolume, public IPostFxSettingsProvider { DECLARE_SCENE_OBJECT(PostFxVolume); private: diff --git a/Source/Engine/Level/Actors/Sky.h b/Source/Engine/Level/Actors/Sky.h index 85c09eefd..9c3cee3ca 100644 --- a/Source/Engine/Level/Actors/Sky.h +++ b/Source/Engine/Level/Actors/Sky.h @@ -14,7 +14,7 @@ class GPUPipelineState; /// /// Sky actor renders atmosphere around the scene with fog and sky. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Sky\")") class FLAXENGINE_API Sky : public Actor, public IAtmosphericFogRenderer, public ISkyRenderer +API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Sky\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API Sky : public Actor, public IAtmosphericFogRenderer, public ISkyRenderer { DECLARE_SCENE_OBJECT(Sky); private: diff --git a/Source/Engine/Level/Actors/SkyLight.h b/Source/Engine/Level/Actors/SkyLight.h index aa42a8855..0bb1b8a33 100644 --- a/Source/Engine/Level/Actors/SkyLight.h +++ b/Source/Engine/Level/Actors/SkyLight.h @@ -9,7 +9,7 @@ /// /// Sky light captures the distant parts of the scene and applies it as a light. Allows to add ambient light. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Sky Light\")") class FLAXENGINE_API SkyLight : public Light +API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Sky Light\"), ActorToolbox(\"Lights\")") class FLAXENGINE_API SkyLight : public Light { DECLARE_SCENE_OBJECT(SkyLight); public: diff --git a/Source/Engine/Level/Actors/Skybox.h b/Source/Engine/Level/Actors/Skybox.h index 0684976bd..9d4023b4f 100644 --- a/Source/Engine/Level/Actors/Skybox.h +++ b/Source/Engine/Level/Actors/Skybox.h @@ -11,7 +11,7 @@ /// /// Skybox actor renders sky using custom cube texture or material. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Sky Box\")") class FLAXENGINE_API Skybox : public Actor, public ISkyRenderer +API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Sky Box\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API Skybox : public Actor, public ISkyRenderer { DECLARE_SCENE_OBJECT(Skybox); private: diff --git a/Source/Engine/Level/Actors/Spline.h b/Source/Engine/Level/Actors/Spline.h index a2d2fa7d2..176ed1aa9 100644 --- a/Source/Engine/Level/Actors/Spline.h +++ b/Source/Engine/Level/Actors/Spline.h @@ -8,7 +8,7 @@ /// /// Spline shape actor that defines spatial curve with utility functions for general purpose usage. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Other/Spline\")") class FLAXENGINE_API Spline : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Spline\"), ActorToolbox(\"Other\")") class FLAXENGINE_API Spline : public Actor { DECLARE_SCENE_OBJECT(Spline); typedef BezierCurveKeyframe Keyframe; diff --git a/Source/Engine/Level/Actors/SpotLight.h b/Source/Engine/Level/Actors/SpotLight.h index b85bd4f0d..10e9dd90e 100644 --- a/Source/Engine/Level/Actors/SpotLight.h +++ b/Source/Engine/Level/Actors/SpotLight.h @@ -9,7 +9,7 @@ /// /// Spot light emits light from the point in a given direction. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Spot Light\")") class FLAXENGINE_API SpotLight : public LightWithShadow +API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Spot Light\"), ActorToolbox(\"Lights\")") class FLAXENGINE_API SpotLight : public LightWithShadow { DECLARE_SCENE_OBJECT(SpotLight); private: diff --git a/Source/Engine/Navigation/NavLink.h b/Source/Engine/Navigation/NavLink.h index 7a788a2a5..edd3afa18 100644 --- a/Source/Engine/Navigation/NavLink.h +++ b/Source/Engine/Navigation/NavLink.h @@ -8,7 +8,7 @@ /// The off-mesh link objects used to define a custom point-to-point edge within the navigation graph. /// An off-mesh connection is a user defined traversable connection made up to two vertices, at least one of which resides within a navigation mesh polygon allowing movement outside the navigation mesh. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Link\")") class FLAXENGINE_API NavLink : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Link\"), ActorToolbox(\"Other\")") class FLAXENGINE_API NavLink : public Actor { DECLARE_SCENE_OBJECT(NavLink); public: diff --git a/Source/Engine/Navigation/NavMeshBoundsVolume.h b/Source/Engine/Navigation/NavMeshBoundsVolume.h index 595105048..339b72774 100644 --- a/Source/Engine/Navigation/NavMeshBoundsVolume.h +++ b/Source/Engine/Navigation/NavMeshBoundsVolume.h @@ -8,7 +8,7 @@ /// /// A special type of volume that defines the area of the scene in which navigation meshes are generated. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Mesh Bounds Volume\")") class FLAXENGINE_API NavMeshBoundsVolume : public BoxVolume +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Mesh Bounds Volume\"), ActorToolbox(\"Other\")") class FLAXENGINE_API NavMeshBoundsVolume : public BoxVolume { DECLARE_SCENE_OBJECT(NavMeshBoundsVolume); public: diff --git a/Source/Engine/Navigation/NavModifierVolume.h b/Source/Engine/Navigation/NavModifierVolume.h index c2992ccdc..0f1e9f9c6 100644 --- a/Source/Engine/Navigation/NavModifierVolume.h +++ b/Source/Engine/Navigation/NavModifierVolume.h @@ -8,7 +8,7 @@ /// /// A special type of volume that defines the area of the scene in which navigation is restricted (eg. higher traversal cost or dynamic obstacle block). /// -API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Modifier Volume\")") class FLAXENGINE_API NavModifierVolume : public BoxVolume +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Modifier Volume\"), ActorToolbox(\"Other\")") class FLAXENGINE_API NavModifierVolume : public BoxVolume { DECLARE_SCENE_OBJECT(NavModifierVolume); public: diff --git a/Source/Engine/Particles/ParticleEffect.h b/Source/Engine/Particles/ParticleEffect.h index 5f3b898ea..65a7ae292 100644 --- a/Source/Engine/Particles/ParticleEffect.h +++ b/Source/Engine/Particles/ParticleEffect.h @@ -133,7 +133,7 @@ public: /// /// The particle system instance that plays the particles simulation in the game. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Particle Effects\")") class FLAXENGINE_API ParticleEffect : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Particle Effects\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API ParticleEffect : public Actor { DECLARE_SCENE_OBJECT(ParticleEffect); public: diff --git a/Source/Engine/Physics/Actors/RigidBody.h b/Source/Engine/Physics/Actors/RigidBody.h index f93abe915..c76310e35 100644 --- a/Source/Engine/Physics/Actors/RigidBody.h +++ b/Source/Engine/Physics/Actors/RigidBody.h @@ -14,7 +14,7 @@ class Collider; /// Physics simulation driven object. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Rigid Body\")") class FLAXENGINE_API RigidBody : public Actor, public IPhysicsActor +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Rigid Body\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API RigidBody : public Actor, public IPhysicsActor { DECLARE_SCENE_OBJECT(RigidBody); protected: diff --git a/Source/Engine/Physics/Colliders/BoxCollider.h b/Source/Engine/Physics/Colliders/BoxCollider.h index a91872acd..867d29ea8 100644 --- a/Source/Engine/Physics/Colliders/BoxCollider.h +++ b/Source/Engine/Physics/Colliders/BoxCollider.h @@ -9,7 +9,7 @@ /// A box-shaped primitive collider. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Box Collider\")") class FLAXENGINE_API BoxCollider : public Collider +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Box Collider\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API BoxCollider : public Collider { DECLARE_SCENE_OBJECT(BoxCollider); private: diff --git a/Source/Engine/Physics/Colliders/CapsuleCollider.h b/Source/Engine/Physics/Colliders/CapsuleCollider.h index c4837b814..bbb80b8f6 100644 --- a/Source/Engine/Physics/Colliders/CapsuleCollider.h +++ b/Source/Engine/Physics/Colliders/CapsuleCollider.h @@ -10,7 +10,7 @@ /// /// Capsules are cylinders with a half-sphere at each end centered at the origin and extending along the X axis, and two hemispherical ends. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Capsule Collider\")") class FLAXENGINE_API CapsuleCollider : public Collider +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Capsule Collider\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API CapsuleCollider : public Collider { DECLARE_SCENE_OBJECT(CapsuleCollider); private: diff --git a/Source/Engine/Physics/Colliders/CharacterController.h b/Source/Engine/Physics/Colliders/CharacterController.h index 79a88d601..3f98e6734 100644 --- a/Source/Engine/Physics/Colliders/CharacterController.h +++ b/Source/Engine/Physics/Colliders/CharacterController.h @@ -9,7 +9,7 @@ /// Physical objects that allows to easily do player movement constrained by collisions without having to deal with a rigidbody. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Character Controller\")") class FLAXENGINE_API CharacterController : public Collider, public IPhysicsActor +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Character Controller\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API CharacterController : public Collider, public IPhysicsActor { DECLARE_SCENE_OBJECT(CharacterController); public: diff --git a/Source/Engine/Physics/Colliders/MeshCollider.h b/Source/Engine/Physics/Colliders/MeshCollider.h index 9aea57e72..8f19afd2c 100644 --- a/Source/Engine/Physics/Colliders/MeshCollider.h +++ b/Source/Engine/Physics/Colliders/MeshCollider.h @@ -10,7 +10,7 @@ /// A collider represented by an arbitrary mesh. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Mesh Collider\")") class FLAXENGINE_API MeshCollider : public Collider +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Mesh Collider\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API MeshCollider : public Collider { DECLARE_SCENE_OBJECT(MeshCollider); public: diff --git a/Source/Engine/Physics/Colliders/SphereCollider.h b/Source/Engine/Physics/Colliders/SphereCollider.h index 263ff84f2..211c74f7a 100644 --- a/Source/Engine/Physics/Colliders/SphereCollider.h +++ b/Source/Engine/Physics/Colliders/SphereCollider.h @@ -8,7 +8,7 @@ /// A sphere-shaped primitive collider. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Sphere Collider\")") class FLAXENGINE_API SphereCollider : public Collider +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Sphere Collider\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API SphereCollider : public Collider { DECLARE_SCENE_OBJECT(SphereCollider); private: diff --git a/Source/Engine/Physics/Joints/D6Joint.h b/Source/Engine/Physics/Joints/D6Joint.h index 2182f810f..aaddb4223 100644 --- a/Source/Engine/Physics/Joints/D6Joint.h +++ b/Source/Engine/Physics/Joints/D6Joint.h @@ -160,7 +160,7 @@ public: /// It also allows you to constrain limits to only specific axes or completely lock specific axes. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/D6 Joint\")") class FLAXENGINE_API D6Joint : public Joint +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/D6 Joint\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API D6Joint : public Joint { DECLARE_SCENE_OBJECT(D6Joint); private: diff --git a/Source/Engine/Physics/Joints/DistanceJoint.h b/Source/Engine/Physics/Joints/DistanceJoint.h index 1d60f8473..cd91e7eaf 100644 --- a/Source/Engine/Physics/Joints/DistanceJoint.h +++ b/Source/Engine/Physics/Joints/DistanceJoint.h @@ -37,7 +37,7 @@ DECLARE_ENUM_OPERATORS(DistanceJointFlag); /// Physics joint that maintains an upper or lower (or both) bound on the distance between two bodies. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Distance Joint\")") class FLAXENGINE_API DistanceJoint : public Joint +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Distance Joint\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API DistanceJoint : public Joint { DECLARE_SCENE_OBJECT(DistanceJoint); private: diff --git a/Source/Engine/Physics/Joints/FixedJoint.h b/Source/Engine/Physics/Joints/FixedJoint.h index cb6c9e133..288a66413 100644 --- a/Source/Engine/Physics/Joints/FixedJoint.h +++ b/Source/Engine/Physics/Joints/FixedJoint.h @@ -8,7 +8,7 @@ /// Physics joint that maintains a fixed distance and orientation between its two attached bodies. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Fixed Joint\")") class FLAXENGINE_API FixedJoint : public Joint +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Fixed Joint\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API FixedJoint : public Joint { DECLARE_SCENE_OBJECT(FixedJoint); public: diff --git a/Source/Engine/Physics/Joints/HingeJoint.h b/Source/Engine/Physics/Joints/HingeJoint.h index 27f012c85..e766a835e 100644 --- a/Source/Engine/Physics/Joints/HingeJoint.h +++ b/Source/Engine/Physics/Joints/HingeJoint.h @@ -67,7 +67,7 @@ public: /// Physics joint that removes all but a single rotation degree of freedom from its two attached bodies (for example a door hinge). /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Hinge Joint\")") class FLAXENGINE_API HingeJoint : public Joint +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Hinge Joint\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API HingeJoint : public Joint { DECLARE_SCENE_OBJECT(HingeJoint); private: diff --git a/Source/Engine/Physics/Joints/SliderJoint.h b/Source/Engine/Physics/Joints/SliderJoint.h index 3bee7d242..4753699c1 100644 --- a/Source/Engine/Physics/Joints/SliderJoint.h +++ b/Source/Engine/Physics/Joints/SliderJoint.h @@ -27,7 +27,7 @@ DECLARE_ENUM_OPERATORS(SliderJointFlag); /// Physics joint that removes all but a single translational degree of freedom. Bodies are allowed to move along a single axis. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Slider Joint\")") class FLAXENGINE_API SliderJoint : public Joint +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Slider Joint\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API SliderJoint : public Joint { DECLARE_SCENE_OBJECT(SliderJoint); private: diff --git a/Source/Engine/Physics/Joints/SphericalJoint.h b/Source/Engine/Physics/Joints/SphericalJoint.h index dbee8d7cc..949b566dc 100644 --- a/Source/Engine/Physics/Joints/SphericalJoint.h +++ b/Source/Engine/Physics/Joints/SphericalJoint.h @@ -29,7 +29,7 @@ DECLARE_ENUM_OPERATORS(SphericalJointFlag); /// rotate around the anchor points, and their rotation can be limited by an elliptical cone. /// /// -API_CLASS(Attributes = "ActorContextMenu(\"New/Physics/Spherical Joint\")") class FLAXENGINE_API SphericalJoint : public Joint +API_CLASS(Attributes = "ActorContextMenu(\"New/Physics/Spherical Joint\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API SphericalJoint : public Joint { DECLARE_SCENE_OBJECT(SphericalJoint); private: diff --git a/Source/Engine/Scripting/Attributes/Editor/ActorToolbox.cs b/Source/Engine/Scripting/Attributes/Editor/ActorToolbox.cs new file mode 100644 index 000000000..4b3fc6558 --- /dev/null +++ b/Source/Engine/Scripting/Attributes/Editor/ActorToolbox.cs @@ -0,0 +1,26 @@ +using System; + +namespace FlaxEngine +{ + /// + /// This attribute is used to show actors that can be created in the actor tab of the toolbox. + /// + [Serializable] + [AttributeUsage(AttributeTargets.Class)] + public class ActorToolboxAttribute : Attribute + { + /// + /// The path to be used in the tool box + /// + public string Group; + + /// + /// Initializes a new instance of the class. + /// + /// The group to use to create the tab + public ActorToolboxAttribute(string group) + { + Group = group; + } + } +} diff --git a/Source/Engine/UI/SpriteRender.h b/Source/Engine/UI/SpriteRender.h index 839b274f2..87e74456e 100644 --- a/Source/Engine/UI/SpriteRender.h +++ b/Source/Engine/UI/SpriteRender.h @@ -10,7 +10,7 @@ /// /// Sprite rendering object. /// -API_CLASS(Attributes="ActorContextMenu(\"New/UI/Sprite Render\")") class FLAXENGINE_API SpriteRender : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/UI/Sprite Render\"), ActorToolbox(\"GUI\")") class FLAXENGINE_API SpriteRender : public Actor { DECLARE_SCENE_OBJECT(SpriteRender); private: diff --git a/Source/Engine/UI/TextRender.h b/Source/Engine/UI/TextRender.h index 3c8be565a..0d15c7b5d 100644 --- a/Source/Engine/UI/TextRender.h +++ b/Source/Engine/UI/TextRender.h @@ -19,7 +19,7 @@ /// /// Text rendering object. /// -API_CLASS(Attributes="ActorContextMenu(\"New/UI/Text Render\")") class FLAXENGINE_API TextRender : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/UI/Text Render\"), ActorToolbox(\"GUI\")") class FLAXENGINE_API TextRender : public Actor { DECLARE_SCENE_OBJECT(TextRender); private: diff --git a/Source/Engine/UI/UICanvas.h b/Source/Engine/UI/UICanvas.h index d207739eb..28b212820 100644 --- a/Source/Engine/UI/UICanvas.h +++ b/Source/Engine/UI/UICanvas.h @@ -7,7 +7,7 @@ /// /// Root of the UI structure. Renders GUI and handles input events forwarding. /// -API_CLASS(Sealed, NoConstructor, Attributes="ActorContextMenu(\"New/UI/UI Canvas\")") class FLAXENGINE_API UICanvas : public Actor +API_CLASS(Sealed, NoConstructor, Attributes="ActorContextMenu(\"New/UI/UI Canvas\"), ActorToolbox(\"GUI\")") class FLAXENGINE_API UICanvas : public Actor { DECLARE_SCENE_OBJECT(UICanvas); public: diff --git a/Source/Engine/UI/UIControl.h b/Source/Engine/UI/UIControl.h index 381cbf98a..0aeca4c00 100644 --- a/Source/Engine/UI/UIControl.h +++ b/Source/Engine/UI/UIControl.h @@ -8,7 +8,7 @@ /// /// Contains a single GUI control (on C# side). /// -API_CLASS(Sealed, Attributes="ActorContextMenu(\"New/UI/UI Control\")") class FLAXENGINE_API UIControl : public Actor +API_CLASS(Sealed, Attributes="ActorContextMenu(\"New/UI/UI Control\"), ActorToolbox(\"GUI\")") class FLAXENGINE_API UIControl : public Actor { DECLARE_SCENE_OBJECT(UIControl); private: From 62cd59549d8bcd7c770d1dba30d7376ecb1fb163 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 11 Nov 2022 16:38:34 -0600 Subject: [PATCH 09/83] removed some old code --- Source/Editor/Windows/ToolboxWindow.cs | 69 +------------------------- 1 file changed, 1 insertion(+), 68 deletions(-) diff --git a/Source/Editor/Windows/ToolboxWindow.cs b/Source/Editor/Windows/ToolboxWindow.cs index 832f57468..aec2e6dea 100644 --- a/Source/Editor/Windows/ToolboxWindow.cs +++ b/Source/Editor/Windows/ToolboxWindow.cs @@ -141,74 +141,7 @@ namespace FlaxEditor.Windows _searchBox.TextChanged += OnSearchBoxTextChanged; RefreshActorTabs(); -/* - _groupSearch = CreateGroupWithList(actorGroups, "Search", 26); - _searchBox = new TextBox - { - AnchorPreset = AnchorPresets.HorizontalStretchTop, - WatermarkText = "Search...", - Parent = _groupSearch.Parent.Parent, - Bounds = new Rectangle(4, 4, actorGroups.Width - 8, 18), - }; - _searchBox.TextChanged += OnSearchBoxTextChanged; - - var groupBasicModels = CreateGroupWithList(actorGroups, "Basic Models"); - groupBasicModels.AddChild(CreateEditorAssetItem("Cube", "Primitives/Cube.flax")); - groupBasicModels.AddChild(CreateEditorAssetItem("Sphere", "Primitives/Sphere.flax")); - groupBasicModels.AddChild(CreateEditorAssetItem("Plane", "Primitives/Plane.flax")); - groupBasicModels.AddChild(CreateEditorAssetItem("Cylinder", "Primitives/Cylinder.flax")); - groupBasicModels.AddChild(CreateEditorAssetItem("Cone", "Primitives/Cone.flax")); - groupBasicModels.AddChild(CreateEditorAssetItem("Capsule", "Primitives/Capsule.flax")); - - var groupLights = CreateGroupWithList(actorGroups, "Lights"); - groupLights.AddChild(CreateActorItem("Directional Light", typeof(DirectionalLight))); - groupLights.AddChild(CreateActorItem("Point Light", typeof(PointLight))); - groupLights.AddChild(CreateActorItem("Spot Light", typeof(SpotLight))); - groupLights.AddChild(CreateActorItem("Sky Light", typeof(SkyLight))); - - var groupVisuals = CreateGroupWithList(actorGroups, "Visuals"); - groupVisuals.AddChild(CreateActorItem("Camera", typeof(Camera))); - groupVisuals.AddChild(CreateActorItem("Environment Probe", typeof(EnvironmentProbe))); - groupVisuals.AddChild(CreateActorItem("Skybox", typeof(Skybox))); - groupVisuals.AddChild(CreateActorItem("Sky", typeof(Sky))); - groupVisuals.AddChild(CreateActorItem("Exponential Height Fog", typeof(ExponentialHeightFog))); - groupVisuals.AddChild(CreateActorItem("PostFx Volume", typeof(PostFxVolume))); - groupVisuals.AddChild(CreateActorItem("Decal", typeof(Decal))); - groupVisuals.AddChild(CreateActorItem("Particle Effect", typeof(ParticleEffect))); - - var groupPhysics = CreateGroupWithList(actorGroups, "Physics"); - groupPhysics.AddChild(CreateActorItem("Rigid Body", typeof(RigidBody))); - groupPhysics.AddChild(CreateActorItem("Character Controller", typeof(CharacterController))); - groupPhysics.AddChild(CreateActorItem("Box Collider", typeof(BoxCollider))); - groupPhysics.AddChild(CreateActorItem("Sphere Collider", typeof(SphereCollider))); - groupPhysics.AddChild(CreateActorItem("Capsule Collider", typeof(CapsuleCollider))); - groupPhysics.AddChild(CreateActorItem("Mesh Collider", typeof(MeshCollider))); - groupPhysics.AddChild(CreateActorItem("Fixed Joint", typeof(FixedJoint))); - groupPhysics.AddChild(CreateActorItem("Distance Joint", typeof(DistanceJoint))); - groupPhysics.AddChild(CreateActorItem("Slider Joint", typeof(SliderJoint))); - groupPhysics.AddChild(CreateActorItem("Spherical Joint", typeof(SphericalJoint))); - groupPhysics.AddChild(CreateActorItem("Hinge Joint", typeof(HingeJoint))); - groupPhysics.AddChild(CreateActorItem("D6 Joint", typeof(D6Joint))); - - var groupOther = CreateGroupWithList(actorGroups, "Other"); - groupOther.AddChild(CreateActorItem("Animated Model", typeof(AnimatedModel))); - groupOther.AddChild(CreateActorItem("Bone Socket", typeof(BoneSocket))); - groupOther.AddChild(CreateActorItem("CSG Box Brush", typeof(BoxBrush))); - groupOther.AddChild(CreateActorItem("Audio Source", typeof(AudioSource))); - groupOther.AddChild(CreateActorItem("Audio Listener", typeof(AudioListener))); - groupOther.AddChild(CreateActorItem("Empty Actor", typeof(EmptyActor))); - groupOther.AddChild(CreateActorItem("Scene Animation", typeof(SceneAnimationPlayer))); - groupOther.AddChild(CreateActorItem("Nav Mesh Bounds Volume", typeof(NavMeshBoundsVolume))); - groupOther.AddChild(CreateActorItem("Nav Link", typeof(NavLink))); - groupOther.AddChild(CreateActorItem("Nav Modifier Volume", typeof(NavModifierVolume))); - groupOther.AddChild(CreateActorItem("Spline", typeof(Spline))); - - var groupGui = CreateGroupWithList(actorGroups, "GUI"); - groupGui.AddChild(CreateActorItem("UI Control", typeof(UIControl))); - groupGui.AddChild(CreateActorItem("UI Canvas", typeof(UICanvas))); - groupGui.AddChild(CreateActorItem("Text Render", typeof(TextRender))); - groupGui.AddChild(CreateActorItem("Sprite Render", typeof(SpriteRender))); -*/ + actorGroups.SelectedTabIndex = 1; } From 6b4da88ef0a9b093a8f5d8e7716e6dae31ff9b77 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 11 Nov 2022 17:03:04 -0600 Subject: [PATCH 10/83] Added the ability to specify the name of the actor in the toolbox, works in searching as well. --- Source/Editor/Windows/ToolboxWindow.cs | 20 ++++++++++++++----- .../Attributes/Editor/ActorToolbox.cs | 16 +++++++++++++++ 2 files changed, 31 insertions(+), 5 deletions(-) diff --git a/Source/Editor/Windows/ToolboxWindow.cs b/Source/Editor/Windows/ToolboxWindow.cs index aec2e6dea..b522cbb2f 100644 --- a/Source/Editor/Windows/ToolboxWindow.cs +++ b/Source/Editor/Windows/ToolboxWindow.cs @@ -219,12 +219,12 @@ namespace FlaxEditor.Windows { if (child is Tab tab) { - if (tab.Text == groupName) + if (tab.Text == groupName.Trim()) { var tree = tab.GetChild().GetChild(); if (tree != null) { - tree.AddChild(CreateActorItem(Utilities.Utils.GetPropertyNameUI(actorType.Name), actorType)); + tree.AddChild(string.IsNullOrEmpty(attribute.Name) ? CreateActorItem(Utilities.Utils.GetPropertyNameUI(actorType.Name), actorType) : CreateActorItem(attribute.Name, actorType)); tree.SortChildren(); } actorTabExists = true; @@ -235,8 +235,8 @@ namespace FlaxEditor.Windows if (actorTabExists) continue; - var group = CreateGroupWithList(actorGroups, groupName); - group.AddChild(CreateActorItem(Utilities.Utils.GetPropertyNameUI(actorType.Name), actorType)); + var group = CreateGroupWithList(actorGroups, groupName.Trim()); + group.AddChild(string.IsNullOrEmpty(attribute.Name) ? CreateActorItem(Utilities.Utils.GetPropertyNameUI(actorType.Name), actorType) : CreateActorItem(attribute.Name, actorType)); group.SortChildren(); } } @@ -253,7 +253,17 @@ namespace FlaxEditor.Windows foreach (var actorType in Editor.CodeEditing.Actors.Get()) { - var text = actorType.Name; + ActorToolboxAttribute attribute = null; + foreach (var e in actorType.GetAttributes(true)) + { + if (e is ActorToolboxAttribute actorToolboxAttribute) + { + attribute = actorToolboxAttribute; + break; + } + } + + var text = (attribute == null) ? actorType.Name : string.IsNullOrEmpty(attribute.Name) ? actorType.Name : attribute.Name; if (!QueryFilterHelper.Match(filterText, text, out QueryFilterHelper.Range[] ranges)) continue; diff --git a/Source/Engine/Scripting/Attributes/Editor/ActorToolbox.cs b/Source/Engine/Scripting/Attributes/Editor/ActorToolbox.cs index 4b3fc6558..c62b366bc 100644 --- a/Source/Engine/Scripting/Attributes/Editor/ActorToolbox.cs +++ b/Source/Engine/Scripting/Attributes/Editor/ActorToolbox.cs @@ -13,6 +13,11 @@ namespace FlaxEngine /// The path to be used in the tool box /// public string Group; + + /// + /// The name to be used for the actor in the tool box. Will default to actor name if now used. + /// + public string Name; /// /// Initializes a new instance of the class. @@ -22,5 +27,16 @@ namespace FlaxEngine { Group = group; } + + /// + /// Initializes a new instance of the class. + /// + /// The group used to creat the tab + /// The name to use rather than default + public ActorToolboxAttribute(string group, string name) + : this(group) + { + Name = name; + } } } From de6cd888709912a4956bebcbea6cb45804ae171d Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 11 Nov 2022 17:08:07 -0600 Subject: [PATCH 11/83] Changed names of a couple base types to match before change --- Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h | 2 +- Source/Engine/Level/Actors/BoxBrush.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h b/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h index 35c7bd013..185cafc79 100644 --- a/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h +++ b/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h @@ -11,7 +11,7 @@ /// /// The scene animation playback actor. /// -API_CLASS(Attributes = "ActorContextMenu(\"New/Other/Scene Animation\"), ActorToolbox(\"Other\")") class FLAXENGINE_API SceneAnimationPlayer : public Actor, public IPostFxSettingsProvider +API_CLASS(Attributes = "ActorContextMenu(\"New/Other/Scene Animation\"), ActorToolbox(\"Other\", \"Scene Animation\")") class FLAXENGINE_API SceneAnimationPlayer : public Actor, public IPostFxSettingsProvider { DECLARE_SCENE_OBJECT(SceneAnimationPlayer); diff --git a/Source/Engine/Level/Actors/BoxBrush.h b/Source/Engine/Level/Actors/BoxBrush.h index 62621577b..5dd5f7618 100644 --- a/Source/Engine/Level/Actors/BoxBrush.h +++ b/Source/Engine/Level/Actors/BoxBrush.h @@ -65,7 +65,7 @@ public: /// /// Performs CSG box brush operation that adds or removes geometry. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Other/Box Brush\"), ActorToolbox(\"Other\")") class FLAXENGINE_API BoxBrush : public Actor, public CSG::Brush +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Box Brush\"), ActorToolbox(\"Other\", \"CSG Box Brush\")") class FLAXENGINE_API BoxBrush : public Actor, public CSG::Brush { DECLARE_SCENE_OBJECT(BoxBrush); private: From 6c26cbe9ba2b314a0a44fbce9512e7affb844ea9 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Fri, 11 Nov 2022 17:11:25 -0600 Subject: [PATCH 12/83] Removed adding inherited types --- Source/Editor/Windows/ToolboxWindow.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Editor/Windows/ToolboxWindow.cs b/Source/Editor/Windows/ToolboxWindow.cs index b522cbb2f..383e40e64 100644 --- a/Source/Editor/Windows/ToolboxWindow.cs +++ b/Source/Editor/Windows/ToolboxWindow.cs @@ -199,7 +199,7 @@ namespace FlaxEditor.Windows continue; ActorToolboxAttribute attribute = null; - foreach (var e in actorType.GetAttributes(true)) + foreach (var e in actorType.GetAttributes(false)) { if (e is ActorToolboxAttribute actorToolboxAttribute) { From 76c1045444135c841d097fb69e9effa3f38c0d50 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 23 Nov 2022 19:18:30 +0100 Subject: [PATCH 13/83] Code cleanup after #823 --- Source/Editor/Windows/ToolboxWindow.cs | 56 +++++++++---------- .../SceneAnimations/SceneAnimationPlayer.h | 3 +- Source/Engine/Audio/AudioListener.h | 3 +- Source/Engine/Audio/AudioSource.h | 3 +- Source/Engine/Level/Actors/AnimatedModel.h | 3 +- Source/Engine/Level/Actors/BoneSocket.h | 8 +-- Source/Engine/Level/Actors/BoxBrush.h | 3 +- Source/Engine/Level/Actors/Camera.cpp | 1 + Source/Engine/Level/Actors/Camera.h | 4 +- Source/Engine/Level/Actors/Decal.h | 4 +- Source/Engine/Level/Actors/DirectionalLight.h | 3 +- Source/Engine/Level/Actors/EmptyActor.h | 3 +- Source/Engine/Level/Actors/EnvironmentProbe.h | 3 +- .../Level/Actors/ExponentialHeightFog.h | 3 +- Source/Engine/Level/Actors/PointLight.h | 3 +- Source/Engine/Level/Actors/PostFxVolume.h | 3 +- Source/Engine/Level/Actors/Sky.h | 3 +- Source/Engine/Level/Actors/SkyLight.h | 3 +- Source/Engine/Level/Actors/Skybox.h | 3 +- Source/Engine/Level/Actors/Spline.h | 3 +- Source/Engine/Level/Actors/SpotLight.h | 3 +- Source/Engine/Navigation/NavLink.h | 6 +- .../Engine/Navigation/NavMeshBoundsVolume.h | 3 +- Source/Engine/Particles/ParticleEffect.h | 3 +- Source/Engine/Physics/Actors/RigidBody.h | 3 +- Source/Engine/Physics/Colliders/BoxCollider.h | 3 +- .../Physics/Colliders/CapsuleCollider.h | 3 +- .../Physics/Colliders/CharacterController.h | 3 +- .../Engine/Physics/Colliders/MeshCollider.h | 3 +- .../Engine/Physics/Colliders/SphereCollider.h | 3 +- Source/Engine/Physics/Joints/D6Joint.h | 3 +- Source/Engine/Physics/Joints/DistanceJoint.h | 3 +- Source/Engine/Physics/Joints/FixedJoint.h | 3 +- Source/Engine/Physics/Joints/HingeJoint.h | 3 +- Source/Engine/Physics/Joints/SliderJoint.h | 3 +- Source/Engine/Physics/Joints/SphericalJoint.h | 3 +- ...xtMenu.cs => ActorContextMenuAttribute.cs} | 6 +- ...torToolbox.cs => ActorToolboxAttribute.cs} | 18 +++--- ...Menu.cs => ContentContextMenuAttribute.cs} | 4 +- Source/Engine/UI/SpriteRender.h | 3 +- Source/Engine/UI/TextRender.h | 7 +-- Source/Engine/UI/UICanvas.h | 3 +- Source/Engine/UI/UIControl.h | 3 +- 43 files changed, 118 insertions(+), 95 deletions(-) rename Source/Engine/Scripting/Attributes/Editor/{ActorContextMenu.cs => ActorContextMenuAttribute.cs} (94%) rename Source/Engine/Scripting/Attributes/Editor/{ActorToolbox.cs => ActorToolboxAttribute.cs} (75%) rename Source/Engine/Scripting/Attributes/Editor/{ContentContextMenu.cs => ContentContextMenuAttribute.cs} (95%) diff --git a/Source/Editor/Windows/ToolboxWindow.cs b/Source/Editor/Windows/ToolboxWindow.cs index 383e40e64..ff03d8e0d 100644 --- a/Source/Editor/Windows/ToolboxWindow.cs +++ b/Source/Editor/Windows/ToolboxWindow.cs @@ -2,7 +2,6 @@ using System; using System.Collections.Generic; -using System.Linq; using FlaxEditor.GUI.Tabs; using FlaxEditor.GUI.Tree; using FlaxEditor.Scripting; @@ -100,7 +99,7 @@ namespace FlaxEditor.Windows private TextBox _searchBox; private ContainerControl _groupSearch; - private Tabs actorGroups; + private Tabs _actorGroups; /// /// The editor instance. @@ -120,7 +119,7 @@ namespace FlaxEditor.Windows ScriptsBuilder.ScriptsReload += OnScriptsReload; ScriptsBuilder.ScriptsReloadEnd += OnScriptsReloadEnd; - actorGroups = new Tabs + _actorGroups = new Tabs { Orientation = Orientation.Vertical, UseScroll = true, @@ -129,20 +128,20 @@ namespace FlaxEditor.Windows TabsSize = new Float2(120, 32), Parent = this, }; - - _groupSearch = CreateGroupWithList(actorGroups, "Search", 26); + + _groupSearch = CreateGroupWithList(_actorGroups, "Search", 26); _searchBox = new TextBox { AnchorPreset = AnchorPresets.HorizontalStretchTop, WatermarkText = "Search...", Parent = _groupSearch.Parent.Parent, - Bounds = new Rectangle(4, 4, actorGroups.Width - 8, 18), + Bounds = new Rectangle(4, 4, _actorGroups.Width - 8, 18), }; _searchBox.TextChanged += OnSearchBoxTextChanged; RefreshActorTabs(); - - actorGroups.SelectedTabIndex = 1; + + _actorGroups.SelectedTabIndex = 1; } private void OnScriptsReload() @@ -160,9 +159,9 @@ namespace FlaxEditor.Windows private void RefreshActorTabs() { - // Remove tabs - List tabs = new List(); - foreach (var child in actorGroups.Children) + // Remove tabs + var tabs = new List(); + foreach (var child in _actorGroups.Children) { if (child is Tab tab) { @@ -170,34 +169,33 @@ namespace FlaxEditor.Windows tabs.Add(tab); } } - foreach (var tab in tabs) { - var group = actorGroups.Children.Find(T => T == tab); + var group = _actorGroups.Children.Find(T => T == tab); group.Dispose(); } - - var groupBasicModels = CreateGroupWithList(actorGroups, "Basic Models"); + + // Setup primitives tabs + var groupBasicModels = CreateGroupWithList(_actorGroups, "Basic Models"); groupBasicModels.AddChild(CreateEditorAssetItem("Cube", "Primitives/Cube.flax")); groupBasicModels.AddChild(CreateEditorAssetItem("Sphere", "Primitives/Sphere.flax")); groupBasicModels.AddChild(CreateEditorAssetItem("Plane", "Primitives/Plane.flax")); groupBasicModels.AddChild(CreateEditorAssetItem("Cylinder", "Primitives/Cylinder.flax")); groupBasicModels.AddChild(CreateEditorAssetItem("Cone", "Primitives/Cone.flax")); groupBasicModels.AddChild(CreateEditorAssetItem("Capsule", "Primitives/Capsule.flax")); - + // Created first to order specific tabs - CreateGroupWithList(actorGroups, "Lights"); - CreateGroupWithList(actorGroups, "Visuals"); - CreateGroupWithList(actorGroups, "Physics"); - CreateGroupWithList(actorGroups, "GUI"); - CreateGroupWithList(actorGroups, "Other"); - + CreateGroupWithList(_actorGroups, "Lights"); + CreateGroupWithList(_actorGroups, "Visuals"); + CreateGroupWithList(_actorGroups, "Physics"); + CreateGroupWithList(_actorGroups, "GUI"); + CreateGroupWithList(_actorGroups, "Other"); + // Add other actor types to respective tab based on attribute foreach (var actorType in Editor.CodeEditing.Actors.Get()) { if (actorType.IsAbstract) continue; - ActorToolboxAttribute attribute = null; foreach (var e in actorType.GetAttributes(false)) { @@ -207,19 +205,17 @@ namespace FlaxEditor.Windows break; } } - if (attribute == null) continue; - - var groupName = attribute.Group; + var groupName = attribute.Group.Trim(); // Check if tab already exists and add it to the tab var actorTabExists = false; - foreach (var child in actorGroups.Children) + foreach (var child in _actorGroups.Children) { if (child is Tab tab) { - if (tab.Text == groupName.Trim()) + if (string.Equals(tab.Text, groupName, StringComparison.OrdinalIgnoreCase)) { var tree = tab.GetChild().GetChild(); if (tree != null) @@ -234,8 +230,8 @@ namespace FlaxEditor.Windows } if (actorTabExists) continue; - - var group = CreateGroupWithList(actorGroups, groupName.Trim()); + + var group = CreateGroupWithList(_actorGroups, groupName); group.AddChild(string.IsNullOrEmpty(attribute.Name) ? CreateActorItem(Utilities.Utils.GetPropertyNameUI(actorType.Name), actorType) : CreateActorItem(attribute.Name, actorType)); group.SortChildren(); } diff --git a/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h b/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h index 185cafc79..d7243a09b 100644 --- a/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h +++ b/Source/Engine/Animations/SceneAnimations/SceneAnimationPlayer.h @@ -11,7 +11,8 @@ /// /// The scene animation playback actor. /// -API_CLASS(Attributes = "ActorContextMenu(\"New/Other/Scene Animation\"), ActorToolbox(\"Other\", \"Scene Animation\")") class FLAXENGINE_API SceneAnimationPlayer : public Actor, public IPostFxSettingsProvider +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Scene Animation\"), ActorToolbox(\"Other\", \"Scene Animation\")") +class FLAXENGINE_API SceneAnimationPlayer : public Actor, public IPostFxSettingsProvider { DECLARE_SCENE_OBJECT(SceneAnimationPlayer); diff --git a/Source/Engine/Audio/AudioListener.h b/Source/Engine/Audio/AudioListener.h index 6090983ae..28bca3b81 100644 --- a/Source/Engine/Audio/AudioListener.h +++ b/Source/Engine/Audio/AudioListener.h @@ -7,7 +7,8 @@ /// /// Represents a listener that hears audio sources. For spatial audio the volume and pitch of played audio is determined by the distance, orientation and velocity differences between the source and the listener. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Listener\"), ActorToolbox(\"Other\")") class FLAXENGINE_API AudioListener : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Listener\"), ActorToolbox(\"Other\")") +class FLAXENGINE_API AudioListener : public Actor { DECLARE_SCENE_OBJECT(AudioListener); private: diff --git a/Source/Engine/Audio/AudioSource.h b/Source/Engine/Audio/AudioSource.h index 71575d318..791e9465e 100644 --- a/Source/Engine/Audio/AudioSource.h +++ b/Source/Engine/Audio/AudioSource.h @@ -13,7 +13,8 @@ /// /// Whether or not an audio source is spatial is controlled by the assigned AudioClip.The volume and the pitch of a spatial audio source is controlled by its position and the AudioListener's position/direction/velocity. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Source\"), ActorToolbox(\"Other\")") class FLAXENGINE_API AudioSource : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Audio/Audio Source\"), ActorToolbox(\"Other\")") +class FLAXENGINE_API AudioSource : public Actor { DECLARE_SCENE_OBJECT(AudioSource); friend class AudioStreamingHandler; diff --git a/Source/Engine/Level/Actors/AnimatedModel.h b/Source/Engine/Level/Actors/AnimatedModel.h index 8d7471ae0..6e0c3bb6d 100644 --- a/Source/Engine/Level/Actors/AnimatedModel.h +++ b/Source/Engine/Level/Actors/AnimatedModel.h @@ -12,7 +12,8 @@ /// /// Performs an animation and renders a skinned model. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Other/Animated Model\"), ActorToolbox(\"Other\")") class FLAXENGINE_API AnimatedModel : public ModelInstanceActor +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Animated Model\"), ActorToolbox(\"Other\")") +class FLAXENGINE_API AnimatedModel : public ModelInstanceActor { DECLARE_SCENE_OBJECT(AnimatedModel); friend class AnimationsSystem; diff --git a/Source/Engine/Level/Actors/BoneSocket.h b/Source/Engine/Level/Actors/BoneSocket.h index 6d516481e..e73ec38eb 100644 --- a/Source/Engine/Level/Actors/BoneSocket.h +++ b/Source/Engine/Level/Actors/BoneSocket.h @@ -7,10 +7,10 @@ /// /// Actor that links to the animated model skeleton node transformation. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Other/Bone Socket\"), ActorToolbox(\"Other\")") class FLAXENGINE_API BoneSocket : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Bone Socket\"), ActorToolbox(\"Other\")") +class FLAXENGINE_API BoneSocket : public Actor { DECLARE_SCENE_OBJECT(BoneSocket); - private: String _node; int32 _index; @@ -20,7 +20,6 @@ public: /// /// Gets the target node name to link to it. /// - /// The target node name. API_PROPERTY(Attributes="EditorOrder(10), EditorDisplay(\"Bone Socket\"), CustomEditorAlias(\"FlaxEditor.CustomEditors.Editors.SkeletonNodeEditor\")") FORCE_INLINE const String& GetNode() const { @@ -30,14 +29,12 @@ public: /// /// Sets the target node to link to it. /// - /// The target node name. API_PROPERTY() void SetNode(const StringView& name); /// /// Gets the value indicating whenever use the target node scale. Otherwise won't override the actor scale. /// - /// If set to true the node socket will use target node scale, otherwise it will be ignored. API_PROPERTY(Attributes="EditorOrder(20), EditorDisplay(\"Bone Socket\"), DefaultValue(false)") FORCE_INLINE bool GetUseScale() const { @@ -47,7 +44,6 @@ public: /// /// Sets the value indicating whenever use the target node scale. Otherwise won't override the actor scale. /// - /// If set to true the node socket will use target node scale, otherwise it will be ignored. API_PROPERTY() void SetUseScale(bool value); diff --git a/Source/Engine/Level/Actors/BoxBrush.h b/Source/Engine/Level/Actors/BoxBrush.h index 5dd5f7618..aed66e420 100644 --- a/Source/Engine/Level/Actors/BoxBrush.h +++ b/Source/Engine/Level/Actors/BoxBrush.h @@ -65,7 +65,8 @@ public: /// /// Performs CSG box brush operation that adds or removes geometry. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Other/Box Brush\"), ActorToolbox(\"Other\", \"CSG Box Brush\")") class FLAXENGINE_API BoxBrush : public Actor, public CSG::Brush +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Box Brush\"), ActorToolbox(\"Other\", \"CSG Box Brush\")") +class FLAXENGINE_API BoxBrush : public Actor, public CSG::Brush { DECLARE_SCENE_OBJECT(BoxBrush); private: diff --git a/Source/Engine/Level/Actors/Camera.cpp b/Source/Engine/Level/Actors/Camera.cpp index 142baa745..28c8bbbe5 100644 --- a/Source/Engine/Level/Actors/Camera.cpp +++ b/Source/Engine/Level/Actors/Camera.cpp @@ -2,6 +2,7 @@ #include "Camera.h" #include "Engine/Level/SceneObjectsFactory.h" +#include "Engine/Core/Math/Matrix.h" #include "Engine/Core/Math/Viewport.h" #include "Engine/Content/Assets/Model.h" #include "Engine/Content/Content.h" diff --git a/Source/Engine/Level/Actors/Camera.h b/Source/Engine/Level/Actors/Camera.h index 0cd866003..601bb4d91 100644 --- a/Source/Engine/Level/Actors/Camera.h +++ b/Source/Engine/Level/Actors/Camera.h @@ -3,7 +3,6 @@ #pragma once #include "../Actor.h" -#include "Engine/Core/Math/Matrix.h" #include "Engine/Core/Math/BoundingFrustum.h" #include "Engine/Core/Math/Viewport.h" #include "Engine/Core/Math/Ray.h" @@ -18,7 +17,8 @@ /// /// Describes the camera projection and view. Provides information about how to render scene (viewport location and direction, etc.). /// -API_CLASS(Sealed, Attributes="ActorContextMenu(\"New/Camera\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API Camera : public Actor +API_CLASS(Sealed, Attributes="ActorContextMenu(\"New/Camera\"), ActorToolbox(\"Visuals\")") +class FLAXENGINE_API Camera : public Actor { DECLARE_SCENE_OBJECT(Camera); diff --git a/Source/Engine/Level/Actors/Decal.h b/Source/Engine/Level/Actors/Decal.h index a8e015045..6dceb223a 100644 --- a/Source/Engine/Level/Actors/Decal.h +++ b/Source/Engine/Level/Actors/Decal.h @@ -11,7 +11,8 @@ /// /// Actor that draws the can be used to draw a custom decals on top of the other objects. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Decal\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API Decal : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Decal\"), ActorToolbox(\"Visuals\")") +class FLAXENGINE_API Decal : public Actor { DECLARE_SCENE_OBJECT(Decal); private: @@ -50,7 +51,6 @@ public: /// /// Sets the decal bounds size (in local space). /// - /// The value. API_PROPERTY() void SetSize(const Vector3& value); public: diff --git a/Source/Engine/Level/Actors/DirectionalLight.h b/Source/Engine/Level/Actors/DirectionalLight.h index e20b7f0f6..180a5087a 100644 --- a/Source/Engine/Level/Actors/DirectionalLight.h +++ b/Source/Engine/Level/Actors/DirectionalLight.h @@ -7,7 +7,8 @@ /// /// Directional light emits light from direction in space. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Directional Light\"), ActorToolbox(\"Lights\")") class FLAXENGINE_API DirectionalLight : public LightWithShadow +API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Directional Light\"), ActorToolbox(\"Lights\")") +class FLAXENGINE_API DirectionalLight : public LightWithShadow { DECLARE_SCENE_OBJECT(DirectionalLight); private: diff --git a/Source/Engine/Level/Actors/EmptyActor.h b/Source/Engine/Level/Actors/EmptyActor.h index bd4e2b04a..063f96f59 100644 --- a/Source/Engine/Level/Actors/EmptyActor.h +++ b/Source/Engine/Level/Actors/EmptyActor.h @@ -7,7 +7,8 @@ /// /// The empty actor that is useful to create hierarchy and/or hold scripts. See . /// -API_CLASS(Attributes="ActorContextMenu(\"New/Actor\"), ActorToolbox(\"Other\")") class FLAXENGINE_API EmptyActor : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Actor\"), ActorToolbox(\"Other\")") +class FLAXENGINE_API EmptyActor : public Actor { DECLARE_SCENE_OBJECT(EmptyActor); public: diff --git a/Source/Engine/Level/Actors/EnvironmentProbe.h b/Source/Engine/Level/Actors/EnvironmentProbe.h index 4d317a7f7..9267c206c 100644 --- a/Source/Engine/Level/Actors/EnvironmentProbe.h +++ b/Source/Engine/Level/Actors/EnvironmentProbe.h @@ -10,7 +10,8 @@ /// /// Environment Probe can capture space around the objects to provide reflections. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Environment Probe\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API EnvironmentProbe : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Environment Probe\"), ActorToolbox(\"Visuals\")") +class FLAXENGINE_API EnvironmentProbe : public Actor { DECLARE_SCENE_OBJECT(EnvironmentProbe); public: diff --git a/Source/Engine/Level/Actors/ExponentialHeightFog.h b/Source/Engine/Level/Actors/ExponentialHeightFog.h index 00bff0be0..7c6da6a5a 100644 --- a/Source/Engine/Level/Actors/ExponentialHeightFog.h +++ b/Source/Engine/Level/Actors/ExponentialHeightFog.h @@ -12,7 +12,8 @@ /// /// Used to create fogging effects such as clouds but with a density that is related to the height of the fog. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Exponential Height Fog\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API ExponentialHeightFog : public Actor, public IFogRenderer +API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Exponential Height Fog\"), ActorToolbox(\"Visuals\")") +class FLAXENGINE_API ExponentialHeightFog : public Actor, public IFogRenderer { DECLARE_SCENE_OBJECT(ExponentialHeightFog); private: diff --git a/Source/Engine/Level/Actors/PointLight.h b/Source/Engine/Level/Actors/PointLight.h index 29c3e5414..728520a9f 100644 --- a/Source/Engine/Level/Actors/PointLight.h +++ b/Source/Engine/Level/Actors/PointLight.h @@ -9,7 +9,8 @@ /// /// Point light emits light from point in all directions. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Point Light\"), ActorToolbox(\"Lights\")") class FLAXENGINE_API PointLight : public LightWithShadow +API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Point Light\"), ActorToolbox(\"Lights\")") +class FLAXENGINE_API PointLight : public LightWithShadow { DECLARE_SCENE_OBJECT(PointLight); private: diff --git a/Source/Engine/Level/Actors/PostFxVolume.h b/Source/Engine/Level/Actors/PostFxVolume.h index 0ba1978ac..6171523f1 100644 --- a/Source/Engine/Level/Actors/PostFxVolume.h +++ b/Source/Engine/Level/Actors/PostFxVolume.h @@ -9,7 +9,8 @@ /// /// A special type of volume that blends custom set of post process settings into the rendering. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Post Fx Volume\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API PostFxVolume : public BoxVolume, public IPostFxSettingsProvider +API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Post Fx Volume\"), ActorToolbox(\"Visuals\")") +class FLAXENGINE_API PostFxVolume : public BoxVolume, public IPostFxSettingsProvider { DECLARE_SCENE_OBJECT(PostFxVolume); private: diff --git a/Source/Engine/Level/Actors/Sky.h b/Source/Engine/Level/Actors/Sky.h index 9c3cee3ca..e1fad03a3 100644 --- a/Source/Engine/Level/Actors/Sky.h +++ b/Source/Engine/Level/Actors/Sky.h @@ -14,7 +14,8 @@ class GPUPipelineState; /// /// Sky actor renders atmosphere around the scene with fog and sky. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Sky\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API Sky : public Actor, public IAtmosphericFogRenderer, public ISkyRenderer +API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Sky\"), ActorToolbox(\"Visuals\")") +class FLAXENGINE_API Sky : public Actor, public IAtmosphericFogRenderer, public ISkyRenderer { DECLARE_SCENE_OBJECT(Sky); private: diff --git a/Source/Engine/Level/Actors/SkyLight.h b/Source/Engine/Level/Actors/SkyLight.h index 0bb1b8a33..f693d7dca 100644 --- a/Source/Engine/Level/Actors/SkyLight.h +++ b/Source/Engine/Level/Actors/SkyLight.h @@ -9,7 +9,8 @@ /// /// Sky light captures the distant parts of the scene and applies it as a light. Allows to add ambient light. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Sky Light\"), ActorToolbox(\"Lights\")") class FLAXENGINE_API SkyLight : public Light +API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Sky Light\"), ActorToolbox(\"Lights\")") +class FLAXENGINE_API SkyLight : public Light { DECLARE_SCENE_OBJECT(SkyLight); public: diff --git a/Source/Engine/Level/Actors/Skybox.h b/Source/Engine/Level/Actors/Skybox.h index 9d4023b4f..088dc1ac1 100644 --- a/Source/Engine/Level/Actors/Skybox.h +++ b/Source/Engine/Level/Actors/Skybox.h @@ -11,7 +11,8 @@ /// /// Skybox actor renders sky using custom cube texture or material. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Sky Box\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API Skybox : public Actor, public ISkyRenderer +API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Sky Box\"), ActorToolbox(\"Visuals\")") +class FLAXENGINE_API Skybox : public Actor, public ISkyRenderer { DECLARE_SCENE_OBJECT(Skybox); private: diff --git a/Source/Engine/Level/Actors/Spline.h b/Source/Engine/Level/Actors/Spline.h index 176ed1aa9..a1b447a26 100644 --- a/Source/Engine/Level/Actors/Spline.h +++ b/Source/Engine/Level/Actors/Spline.h @@ -8,7 +8,8 @@ /// /// Spline shape actor that defines spatial curve with utility functions for general purpose usage. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Other/Spline\"), ActorToolbox(\"Other\")") class FLAXENGINE_API Spline : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Spline\"), ActorToolbox(\"Other\")") +class FLAXENGINE_API Spline : public Actor { DECLARE_SCENE_OBJECT(Spline); typedef BezierCurveKeyframe Keyframe; diff --git a/Source/Engine/Level/Actors/SpotLight.h b/Source/Engine/Level/Actors/SpotLight.h index 10e9dd90e..34487ad57 100644 --- a/Source/Engine/Level/Actors/SpotLight.h +++ b/Source/Engine/Level/Actors/SpotLight.h @@ -9,7 +9,8 @@ /// /// Spot light emits light from the point in a given direction. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Spot Light\"), ActorToolbox(\"Lights\")") class FLAXENGINE_API SpotLight : public LightWithShadow +API_CLASS(Attributes="ActorContextMenu(\"New/Lights/Spot Light\"), ActorToolbox(\"Lights\")") +class FLAXENGINE_API SpotLight : public LightWithShadow { DECLARE_SCENE_OBJECT(SpotLight); private: diff --git a/Source/Engine/Navigation/NavLink.h b/Source/Engine/Navigation/NavLink.h index edd3afa18..bd2aa7792 100644 --- a/Source/Engine/Navigation/NavLink.h +++ b/Source/Engine/Navigation/NavLink.h @@ -5,10 +5,10 @@ #include "Engine/Level/Actor.h" /// -/// The off-mesh link objects used to define a custom point-to-point edge within the navigation graph. -/// An off-mesh connection is a user defined traversable connection made up to two vertices, at least one of which resides within a navigation mesh polygon allowing movement outside the navigation mesh. +/// The off-mesh link objects used to define a custom point-to-point edge within the navigation graph. An off-mesh connection is a user defined traversable connection made up to two vertices, at least one of which resides within a navigation mesh polygon allowing movement outside the navigation mesh. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Link\"), ActorToolbox(\"Other\")") class FLAXENGINE_API NavLink : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Link\"), ActorToolbox(\"Other\")") +class FLAXENGINE_API NavLink : public Actor { DECLARE_SCENE_OBJECT(NavLink); public: diff --git a/Source/Engine/Navigation/NavMeshBoundsVolume.h b/Source/Engine/Navigation/NavMeshBoundsVolume.h index 339b72774..4c079c695 100644 --- a/Source/Engine/Navigation/NavMeshBoundsVolume.h +++ b/Source/Engine/Navigation/NavMeshBoundsVolume.h @@ -8,7 +8,8 @@ /// /// A special type of volume that defines the area of the scene in which navigation meshes are generated. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Mesh Bounds Volume\"), ActorToolbox(\"Other\")") class FLAXENGINE_API NavMeshBoundsVolume : public BoxVolume +API_CLASS(Attributes="ActorContextMenu(\"New/Other/Nav Mesh Bounds Volume\"), ActorToolbox(\"Other\")") +class FLAXENGINE_API NavMeshBoundsVolume : public BoxVolume { DECLARE_SCENE_OBJECT(NavMeshBoundsVolume); public: diff --git a/Source/Engine/Particles/ParticleEffect.h b/Source/Engine/Particles/ParticleEffect.h index 65a7ae292..9d735b364 100644 --- a/Source/Engine/Particles/ParticleEffect.h +++ b/Source/Engine/Particles/ParticleEffect.h @@ -133,7 +133,8 @@ public: /// /// The particle system instance that plays the particles simulation in the game. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Particle Effects\"), ActorToolbox(\"Visuals\")") class FLAXENGINE_API ParticleEffect : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/Visuals/Particle Effects\"), ActorToolbox(\"Visuals\")") +class FLAXENGINE_API ParticleEffect : public Actor { DECLARE_SCENE_OBJECT(ParticleEffect); public: diff --git a/Source/Engine/Physics/Actors/RigidBody.h b/Source/Engine/Physics/Actors/RigidBody.h index c76310e35..399e40596 100644 --- a/Source/Engine/Physics/Actors/RigidBody.h +++ b/Source/Engine/Physics/Actors/RigidBody.h @@ -14,7 +14,8 @@ class Collider; /// Physics simulation driven object. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Rigid Body\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API RigidBody : public Actor, public IPhysicsActor +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Rigid Body\"), ActorToolbox(\"Physics\")") +class FLAXENGINE_API RigidBody : public Actor, public IPhysicsActor { DECLARE_SCENE_OBJECT(RigidBody); protected: diff --git a/Source/Engine/Physics/Colliders/BoxCollider.h b/Source/Engine/Physics/Colliders/BoxCollider.h index 867d29ea8..c15d1c8b4 100644 --- a/Source/Engine/Physics/Colliders/BoxCollider.h +++ b/Source/Engine/Physics/Colliders/BoxCollider.h @@ -9,7 +9,8 @@ /// A box-shaped primitive collider. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Box Collider\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API BoxCollider : public Collider +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Box Collider\"), ActorToolbox(\"Physics\")") +class FLAXENGINE_API BoxCollider : public Collider { DECLARE_SCENE_OBJECT(BoxCollider); private: diff --git a/Source/Engine/Physics/Colliders/CapsuleCollider.h b/Source/Engine/Physics/Colliders/CapsuleCollider.h index bbb80b8f6..fa4e487ec 100644 --- a/Source/Engine/Physics/Colliders/CapsuleCollider.h +++ b/Source/Engine/Physics/Colliders/CapsuleCollider.h @@ -10,7 +10,8 @@ /// /// Capsules are cylinders with a half-sphere at each end centered at the origin and extending along the X axis, and two hemispherical ends. /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Capsule Collider\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API CapsuleCollider : public Collider +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Capsule Collider\"), ActorToolbox(\"Physics\")") +class FLAXENGINE_API CapsuleCollider : public Collider { DECLARE_SCENE_OBJECT(CapsuleCollider); private: diff --git a/Source/Engine/Physics/Colliders/CharacterController.h b/Source/Engine/Physics/Colliders/CharacterController.h index 3f98e6734..95d9e3293 100644 --- a/Source/Engine/Physics/Colliders/CharacterController.h +++ b/Source/Engine/Physics/Colliders/CharacterController.h @@ -9,7 +9,8 @@ /// Physical objects that allows to easily do player movement constrained by collisions without having to deal with a rigidbody. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Character Controller\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API CharacterController : public Collider, public IPhysicsActor +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Character Controller\"), ActorToolbox(\"Physics\")") +class FLAXENGINE_API CharacterController : public Collider, public IPhysicsActor { DECLARE_SCENE_OBJECT(CharacterController); public: diff --git a/Source/Engine/Physics/Colliders/MeshCollider.h b/Source/Engine/Physics/Colliders/MeshCollider.h index 8f19afd2c..44c3662ab 100644 --- a/Source/Engine/Physics/Colliders/MeshCollider.h +++ b/Source/Engine/Physics/Colliders/MeshCollider.h @@ -10,7 +10,8 @@ /// A collider represented by an arbitrary mesh. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Mesh Collider\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API MeshCollider : public Collider +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Mesh Collider\"), ActorToolbox(\"Physics\")") +class FLAXENGINE_API MeshCollider : public Collider { DECLARE_SCENE_OBJECT(MeshCollider); public: diff --git a/Source/Engine/Physics/Colliders/SphereCollider.h b/Source/Engine/Physics/Colliders/SphereCollider.h index 211c74f7a..6a816b5e5 100644 --- a/Source/Engine/Physics/Colliders/SphereCollider.h +++ b/Source/Engine/Physics/Colliders/SphereCollider.h @@ -8,7 +8,8 @@ /// A sphere-shaped primitive collider. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Sphere Collider\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API SphereCollider : public Collider +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Sphere Collider\"), ActorToolbox(\"Physics\")") +class FLAXENGINE_API SphereCollider : public Collider { DECLARE_SCENE_OBJECT(SphereCollider); private: diff --git a/Source/Engine/Physics/Joints/D6Joint.h b/Source/Engine/Physics/Joints/D6Joint.h index aaddb4223..a0aafd48e 100644 --- a/Source/Engine/Physics/Joints/D6Joint.h +++ b/Source/Engine/Physics/Joints/D6Joint.h @@ -160,7 +160,8 @@ public: /// It also allows you to constrain limits to only specific axes or completely lock specific axes. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/D6 Joint\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API D6Joint : public Joint +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/D6 Joint\"), ActorToolbox(\"Physics\")") +class FLAXENGINE_API D6Joint : public Joint { DECLARE_SCENE_OBJECT(D6Joint); private: diff --git a/Source/Engine/Physics/Joints/DistanceJoint.h b/Source/Engine/Physics/Joints/DistanceJoint.h index cd91e7eaf..44940b5ea 100644 --- a/Source/Engine/Physics/Joints/DistanceJoint.h +++ b/Source/Engine/Physics/Joints/DistanceJoint.h @@ -37,7 +37,8 @@ DECLARE_ENUM_OPERATORS(DistanceJointFlag); /// Physics joint that maintains an upper or lower (or both) bound on the distance between two bodies. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Distance Joint\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API DistanceJoint : public Joint +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Distance Joint\"), ActorToolbox(\"Physics\")") +class FLAXENGINE_API DistanceJoint : public Joint { DECLARE_SCENE_OBJECT(DistanceJoint); private: diff --git a/Source/Engine/Physics/Joints/FixedJoint.h b/Source/Engine/Physics/Joints/FixedJoint.h index 288a66413..0e2eee8e4 100644 --- a/Source/Engine/Physics/Joints/FixedJoint.h +++ b/Source/Engine/Physics/Joints/FixedJoint.h @@ -8,7 +8,8 @@ /// Physics joint that maintains a fixed distance and orientation between its two attached bodies. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Fixed Joint\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API FixedJoint : public Joint +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Fixed Joint\"), ActorToolbox(\"Physics\")") +class FLAXENGINE_API FixedJoint : public Joint { DECLARE_SCENE_OBJECT(FixedJoint); public: diff --git a/Source/Engine/Physics/Joints/HingeJoint.h b/Source/Engine/Physics/Joints/HingeJoint.h index e766a835e..9a3769c3c 100644 --- a/Source/Engine/Physics/Joints/HingeJoint.h +++ b/Source/Engine/Physics/Joints/HingeJoint.h @@ -67,7 +67,8 @@ public: /// Physics joint that removes all but a single rotation degree of freedom from its two attached bodies (for example a door hinge). /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Hinge Joint\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API HingeJoint : public Joint +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Hinge Joint\"), ActorToolbox(\"Physics\")") +class FLAXENGINE_API HingeJoint : public Joint { DECLARE_SCENE_OBJECT(HingeJoint); private: diff --git a/Source/Engine/Physics/Joints/SliderJoint.h b/Source/Engine/Physics/Joints/SliderJoint.h index 4753699c1..46fb2a3de 100644 --- a/Source/Engine/Physics/Joints/SliderJoint.h +++ b/Source/Engine/Physics/Joints/SliderJoint.h @@ -27,7 +27,8 @@ DECLARE_ENUM_OPERATORS(SliderJointFlag); /// Physics joint that removes all but a single translational degree of freedom. Bodies are allowed to move along a single axis. /// /// -API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Slider Joint\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API SliderJoint : public Joint +API_CLASS(Attributes="ActorContextMenu(\"New/Physics/Slider Joint\"), ActorToolbox(\"Physics\")") +class FLAXENGINE_API SliderJoint : public Joint { DECLARE_SCENE_OBJECT(SliderJoint); private: diff --git a/Source/Engine/Physics/Joints/SphericalJoint.h b/Source/Engine/Physics/Joints/SphericalJoint.h index 949b566dc..5b29a0a25 100644 --- a/Source/Engine/Physics/Joints/SphericalJoint.h +++ b/Source/Engine/Physics/Joints/SphericalJoint.h @@ -29,7 +29,8 @@ DECLARE_ENUM_OPERATORS(SphericalJointFlag); /// rotate around the anchor points, and their rotation can be limited by an elliptical cone. /// /// -API_CLASS(Attributes = "ActorContextMenu(\"New/Physics/Spherical Joint\"), ActorToolbox(\"Physics\")") class FLAXENGINE_API SphericalJoint : public Joint +API_CLASS(Attributes = "ActorContextMenu(\"New/Physics/Spherical Joint\"), ActorToolbox(\"Physics\")") +class FLAXENGINE_API SphericalJoint : public Joint { DECLARE_SCENE_OBJECT(SphericalJoint); private: diff --git a/Source/Engine/Scripting/Attributes/Editor/ActorContextMenu.cs b/Source/Engine/Scripting/Attributes/Editor/ActorContextMenuAttribute.cs similarity index 94% rename from Source/Engine/Scripting/Attributes/Editor/ActorContextMenu.cs rename to Source/Engine/Scripting/Attributes/Editor/ActorContextMenuAttribute.cs index aab4ed92d..618b88439 100644 --- a/Source/Engine/Scripting/Attributes/Editor/ActorContextMenu.cs +++ b/Source/Engine/Scripting/Attributes/Editor/ActorContextMenuAttribute.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace FlaxEngine { @@ -13,11 +13,11 @@ namespace FlaxEngine /// The path to be used in the context menu /// public string Path; - + /// /// Initializes a new instance of the class. /// - /// The path to use to create the context menu + /// The path to use to create the context menu. public ActorContextMenuAttribute(string path) { Path = path; diff --git a/Source/Engine/Scripting/Attributes/Editor/ActorToolbox.cs b/Source/Engine/Scripting/Attributes/Editor/ActorToolboxAttribute.cs similarity index 75% rename from Source/Engine/Scripting/Attributes/Editor/ActorToolbox.cs rename to Source/Engine/Scripting/Attributes/Editor/ActorToolboxAttribute.cs index c62b366bc..5d4aeb2fd 100644 --- a/Source/Engine/Scripting/Attributes/Editor/ActorToolbox.cs +++ b/Source/Engine/Scripting/Attributes/Editor/ActorToolboxAttribute.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace FlaxEngine { @@ -18,24 +18,24 @@ namespace FlaxEngine /// The name to be used for the actor in the tool box. Will default to actor name if now used. /// public string Name; - + /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The group to use to create the tab + /// The group to use to create the tab. public ActorToolboxAttribute(string group) { Group = group; } - + /// - /// Initializes a new instance of the class. + /// Initializes a new instance of the class. /// - /// The group used to creat the tab - /// The name to use rather than default + /// The group used to create the tab. + /// The name to use rather than default. public ActorToolboxAttribute(string group, string name) - : this(group) { + Group = group; Name = name; } } diff --git a/Source/Engine/Scripting/Attributes/Editor/ContentContextMenu.cs b/Source/Engine/Scripting/Attributes/Editor/ContentContextMenuAttribute.cs similarity index 95% rename from Source/Engine/Scripting/Attributes/Editor/ContentContextMenu.cs rename to Source/Engine/Scripting/Attributes/Editor/ContentContextMenuAttribute.cs index ee9956ede..24e080ed7 100644 --- a/Source/Engine/Scripting/Attributes/Editor/ContentContextMenu.cs +++ b/Source/Engine/Scripting/Attributes/Editor/ContentContextMenuAttribute.cs @@ -1,4 +1,4 @@ -using System; +using System; namespace FlaxEngine { @@ -17,7 +17,7 @@ namespace FlaxEngine /// /// Initializes a new instance of the class. /// - /// The path to use to create the context menu + /// The path to use to create the context menu. public ContentContextMenuAttribute(string path) { Path = path; diff --git a/Source/Engine/UI/SpriteRender.h b/Source/Engine/UI/SpriteRender.h index 87e74456e..c5efc018a 100644 --- a/Source/Engine/UI/SpriteRender.h +++ b/Source/Engine/UI/SpriteRender.h @@ -10,7 +10,8 @@ /// /// Sprite rendering object. /// -API_CLASS(Attributes="ActorContextMenu(\"New/UI/Sprite Render\"), ActorToolbox(\"GUI\")") class FLAXENGINE_API SpriteRender : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/UI/Sprite Render\"), ActorToolbox(\"GUI\")") +class FLAXENGINE_API SpriteRender : public Actor { DECLARE_SCENE_OBJECT(SpriteRender); private: diff --git a/Source/Engine/UI/TextRender.h b/Source/Engine/UI/TextRender.h index 0d15c7b5d..da3c73ae0 100644 --- a/Source/Engine/UI/TextRender.h +++ b/Source/Engine/UI/TextRender.h @@ -3,7 +3,6 @@ #pragma once #include "Engine/Level/Actor.h" -#include "Engine/Core/Math/Matrix.h" #include "Engine/Render2D/TextLayoutOptions.h" #include "Engine/Render2D/FontAsset.h" #include "Engine/Renderer/DrawCall.h" @@ -19,7 +18,8 @@ /// /// Text rendering object. /// -API_CLASS(Attributes="ActorContextMenu(\"New/UI/Text Render\"), ActorToolbox(\"GUI\")") class FLAXENGINE_API TextRender : public Actor +API_CLASS(Attributes="ActorContextMenu(\"New/UI/Text Render\"), ActorToolbox(\"GUI\")") +class FLAXENGINE_API TextRender : public Actor { DECLARE_SCENE_OBJECT(TextRender); private: @@ -138,16 +138,13 @@ public: API_FUNCTION() void UpdateLayout(); #if USE_PRECISE_MESH_INTERSECTS - /// /// Gets the collision proxy used by the text geometry. /// - /// The collisions proxy container object reference. FORCE_INLINE const CollisionProxy& GetCollisionProxy() const { return _collisionProxy; } - #endif private: diff --git a/Source/Engine/UI/UICanvas.h b/Source/Engine/UI/UICanvas.h index 28b212820..9a8b76794 100644 --- a/Source/Engine/UI/UICanvas.h +++ b/Source/Engine/UI/UICanvas.h @@ -7,7 +7,8 @@ /// /// Root of the UI structure. Renders GUI and handles input events forwarding. /// -API_CLASS(Sealed, NoConstructor, Attributes="ActorContextMenu(\"New/UI/UI Canvas\"), ActorToolbox(\"GUI\")") class FLAXENGINE_API UICanvas : public Actor +API_CLASS(Sealed, NoConstructor, Attributes="ActorContextMenu(\"New/UI/UI Canvas\"), ActorToolbox(\"GUI\")") +class FLAXENGINE_API UICanvas : public Actor { DECLARE_SCENE_OBJECT(UICanvas); public: diff --git a/Source/Engine/UI/UIControl.h b/Source/Engine/UI/UIControl.h index 0aeca4c00..490abcbb1 100644 --- a/Source/Engine/UI/UIControl.h +++ b/Source/Engine/UI/UIControl.h @@ -8,7 +8,8 @@ /// /// Contains a single GUI control (on C# side). /// -API_CLASS(Sealed, Attributes="ActorContextMenu(\"New/UI/UI Control\"), ActorToolbox(\"GUI\")") class FLAXENGINE_API UIControl : public Actor +API_CLASS(Sealed, Attributes="ActorContextMenu(\"New/UI/UI Control\"), ActorToolbox(\"GUI\")") +class FLAXENGINE_API UIControl : public Actor { DECLARE_SCENE_OBJECT(UIControl); private: From 18c4e34af8de7e8d0933360149339d09d81de496 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 24 Nov 2022 20:20:36 +0100 Subject: [PATCH 14/83] Fix invalid `Math::RoundUpToPowerOf2` #833 --- Source/Engine/Core/Math/Math.h | 24 ++++++++---------------- Source/Engine/Tests/TestMath.cpp | 25 +++++++++++++++++++++++++ 2 files changed, 33 insertions(+), 16 deletions(-) diff --git a/Source/Engine/Core/Math/Math.h b/Source/Engine/Core/Math/Math.h index 784afa1b2..c0bc52dcb 100644 --- a/Source/Engine/Core/Math/Math.h +++ b/Source/Engine/Core/Math/Math.h @@ -214,11 +214,8 @@ namespace Math /// The power of 2. static int32 RoundUpToPowerOf2(int32 value) { - // Source: - // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 - if (value < 0) - return 0; - value++; + // Source: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 + value--; value |= value >> 1; value |= value >> 2; value |= value >> 4; @@ -234,9 +231,8 @@ namespace Math /// The power of 2. static uint32 RoundUpToPowerOf2(uint32 value) { - // Source: - // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 - value++; + // Source: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 + value--; value |= value >> 1; value |= value >> 2; value |= value >> 4; @@ -252,11 +248,8 @@ namespace Math /// The power of 2. static int64 RoundUpToPowerOf2(int64 value) { - // Source: - // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 - if (value < 0) - return 0; - value++; + // Source: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 + value--; value |= value >> 1; value |= value >> 2; value |= value >> 4; @@ -273,9 +266,8 @@ namespace Math /// The power of 2. static uint64 RoundUpToPowerOf2(uint64 value) { - // Source: - // http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 - value++; + // Source: http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2 + value--; value |= value >> 1; value |= value >> 2; value |= value >> 4; diff --git a/Source/Engine/Tests/TestMath.cpp b/Source/Engine/Tests/TestMath.cpp index cd7e5e41d..82724064f 100644 --- a/Source/Engine/Tests/TestMath.cpp +++ b/Source/Engine/Tests/TestMath.cpp @@ -15,6 +15,31 @@ static Quaternion RotationX(float angle) return Quaternion(Math::Sin(halfAngle), 0.0f, 0.0f, Math::Cos(halfAngle)); } +TEST_CASE("Math") +{ + SECTION("Test") + { + CHECK(Math::RoundUpToPowerOf2(0) == 0); + CHECK(Math::RoundUpToPowerOf2(1) == 1); + CHECK(Math::RoundUpToPowerOf2(2) == 2); + CHECK(Math::RoundUpToPowerOf2(3) == 4); + CHECK(Math::RoundUpToPowerOf2(4) == 4); + CHECK(Math::RoundUpToPowerOf2(5) == 8); + CHECK(Math::RoundUpToPowerOf2(6) == 8); + CHECK(Math::RoundUpToPowerOf2(7) == 8); + CHECK(Math::RoundUpToPowerOf2(8) == 8); + CHECK(Math::RoundUpToPowerOf2(9) == 16); + CHECK(Math::RoundUpToPowerOf2(10) == 16); + CHECK(Math::RoundUpToPowerOf2(11) == 16); + CHECK(Math::RoundUpToPowerOf2(12) == 16); + CHECK(Math::RoundUpToPowerOf2(13) == 16); + CHECK(Math::RoundUpToPowerOf2(14) == 16); + CHECK(Math::RoundUpToPowerOf2(15) == 16); + CHECK(Math::RoundUpToPowerOf2(16) == 16); + CHECK(Math::RoundUpToPowerOf2(17) == 32); + } +} + TEST_CASE("FloatR10G10B10A2") { SECTION("Test Conversion") From e713273942c43faf8c8e25e16701a0b1ba8d8a46 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Thu, 24 Nov 2022 21:54:54 +0100 Subject: [PATCH 15/83] Fix textbox defocus on edit end #789 --- Source/Engine/UI/GUI/Common/TextBoxBase.cs | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Source/Engine/UI/GUI/Common/TextBoxBase.cs b/Source/Engine/UI/GUI/Common/TextBoxBase.cs index 340459c8f..69b4fa123 100644 --- a/Source/Engine/UI/GUI/Common/TextBoxBase.cs +++ b/Source/Engine/UI/GUI/Common/TextBoxBase.cs @@ -370,7 +370,7 @@ namespace FlaxEngine.GUI { Focus(); SetText(value); - Defocus(); + RemoveFocus(); } /// @@ -907,6 +907,14 @@ namespace FlaxEngine.GUI return HitTestText(location); } + private void RemoveFocus() + { + if (Parent != null) + Parent.Focus(); + else + Defocus(); + } + /// /// Calculates total text size. Called by to cache the text size. /// @@ -1297,7 +1305,7 @@ namespace FlaxEngine.GUI _text = _onStartEditValue; if (!IsNavFocused) - Defocus(); + RemoveFocus(); OnTextChanged(); return true; @@ -1311,7 +1319,7 @@ namespace FlaxEngine.GUI else if (!IsNavFocused) { // End editing - Defocus(); + RemoveFocus(); } return true; case KeyboardKeys.Home: From 66ce8abe0156d014c5bbf49e06e8b55cab6fd623 Mon Sep 17 00:00:00 2001 From: Ruan Lucas <79365912+RuanLucasGD@users.noreply.github.com> Date: Thu, 24 Nov 2022 23:58:24 -0400 Subject: [PATCH 16/83] Adds side mouse button shortcuts to the Content window --- Source/Editor/Windows/ContentWindow.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index 90cd77d11..3cac8c434 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -895,6 +895,16 @@ namespace FlaxEditor.Windows } } + /// + public override bool OnMouseDown(Float2 location, MouseButton button) + { + // Navigate through directories using the side mouse buttons + if (button == MouseButton.Extended1) NavigateBackward(); + else if (button == MouseButton.Extended2) NavigateForward(); + + return base.OnMouseDown(location, button); + } + /// public override bool OnMouseUp(Float2 location, MouseButton button) { From b1618a88beda1a3271bde7a2d0909c9bc0c5063a Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 25 Nov 2022 22:07:13 +0100 Subject: [PATCH 17/83] Fix invalid rounding up to power of two in allocators #833 --- Source/Engine/Core/Collections/Dictionary.h | 6 +++--- Source/Engine/Core/Collections/HashSet.h | 6 +++--- Source/Engine/Core/Memory/Allocation.h | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Engine/Core/Collections/Dictionary.h b/Source/Engine/Core/Collections/Dictionary.h index 0ee455195..4b3d35d58 100644 --- a/Source/Engine/Core/Collections/Dictionary.h +++ b/Source/Engine/Core/Collections/Dictionary.h @@ -502,14 +502,14 @@ public: _deletedCount = _elementsCount = 0; if (capacity != 0 && (capacity & (capacity - 1)) != 0) { - // Align capacity value to the next power of two (if it's not) - capacity++; + // Align capacity value to the next power of two (http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2) + capacity--; capacity |= capacity >> 1; capacity |= capacity >> 2; capacity |= capacity >> 4; capacity |= capacity >> 8; capacity |= capacity >> 16; - capacity = capacity + 1; + capacity++; } if (capacity) { diff --git a/Source/Engine/Core/Collections/HashSet.h b/Source/Engine/Core/Collections/HashSet.h index debd91cfd..855f124da 100644 --- a/Source/Engine/Core/Collections/HashSet.h +++ b/Source/Engine/Core/Collections/HashSet.h @@ -373,14 +373,14 @@ public: _deletedCount = _elementsCount = 0; if (capacity != 0 && (capacity & (capacity - 1)) != 0) { - // Align capacity value to the next power of two (if it's not) - capacity++; + // Align capacity value to the next power of two (http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2) + capacity--; capacity |= capacity >> 1; capacity |= capacity >> 2; capacity |= capacity >> 4; capacity |= capacity >> 8; capacity |= capacity >> 16; - capacity = capacity + 1; + capacity++; } if (capacity) { diff --git a/Source/Engine/Core/Memory/Allocation.h b/Source/Engine/Core/Memory/Allocation.h index 14aa41f7a..9ae127805 100644 --- a/Source/Engine/Core/Memory/Allocation.h +++ b/Source/Engine/Core/Memory/Allocation.h @@ -111,8 +111,8 @@ public: } else { - // Round up to the next power of 2 and multiply by 2 - capacity++; + // Round up to the next power of 2 and multiply by 2 (http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2) + capacity--; capacity |= capacity >> 1; capacity |= capacity >> 2; capacity |= capacity >> 4; From 8707d658f1fa929d7b129822fe4f957363771855 Mon Sep 17 00:00:00 2001 From: Tryibion Date: Fri, 25 Nov 2022 15:13:25 -0600 Subject: [PATCH 18/83] Added ability to drag maximized panels. --- Source/Editor/GUI/Docking/FloatWindowDockPanel.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs b/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs index c8e0a2b2e..f892c8237 100644 --- a/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs +++ b/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs @@ -53,8 +53,14 @@ namespace FlaxEditor.GUI.Docking // Check if window is maximized if (_window.IsMaximized) - return; - + { + // Restore window and set position to mouse. + var mousePos = _window.MousePosition; + var previousSize = _window.Size; + _window.Restore(); + _window.Window.Position = FlaxEngine.Input.MouseScreenPosition - mousePos * _window.Size / previousSize; + } + // Create docking hint window DockHintWindow.Create(this); } From c33fe04645b3aee9f575c592a08dfc8670f1a0c5 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Fri, 25 Nov 2022 23:04:17 +0100 Subject: [PATCH 19/83] Remove unused `LodProxyView` feature from `RenderContext` (shadow projections are using the same draw batch as main view now) --- Source/Engine/Graphics/RenderTask.h | 5 ----- Source/Engine/Graphics/RenderTools.cpp | 6 ++---- Source/Engine/Graphics/RenderView.cpp | 3 +-- Source/Engine/Level/Actors/Decal.cpp | 3 +-- Source/Engine/Renderer/ShadowsPass.cpp | 3 --- 5 files changed, 4 insertions(+), 16 deletions(-) diff --git a/Source/Engine/Graphics/RenderTask.h b/Source/Engine/Graphics/RenderTask.h index 92a48cf76..8efa198be 100644 --- a/Source/Engine/Graphics/RenderTask.h +++ b/Source/Engine/Graphics/RenderTask.h @@ -426,11 +426,6 @@ API_STRUCT(NoDefault) struct RenderContext /// API_FIELD() SceneRenderTask* Task = nullptr; - /// - /// The proxy render view used to synchronize objects level of detail during rendering (eg. during shadow maps rendering passes). It's optional. - /// - API_FIELD() RenderView* LodProxyView = nullptr; - /// /// The render view. /// diff --git a/Source/Engine/Graphics/RenderTools.cpp b/Source/Engine/Graphics/RenderTools.cpp index 912b0ed48..370bc71d3 100644 --- a/Source/Engine/Graphics/RenderTools.cpp +++ b/Source/Engine/Graphics/RenderTools.cpp @@ -441,8 +441,7 @@ float RenderTools::ComputeBoundsScreenRadiusSquared(const Float3& origin, float int32 RenderTools::ComputeModelLOD(const Model* model, const Float3& origin, float radius, const RenderContext& renderContext) { - const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View); - const float screenRadiusSquared = ComputeBoundsScreenRadiusSquared(origin, radius, *lodView) * renderContext.View.ModelLODDistanceFactorSqrt; + const float screenRadiusSquared = ComputeBoundsScreenRadiusSquared(origin, radius, renderContext.View) * renderContext.View.ModelLODDistanceFactorSqrt; // Check if model is being culled if (Math::Square(model->MinScreenSize * 0.5f) > screenRadiusSquared) @@ -466,8 +465,7 @@ int32 RenderTools::ComputeModelLOD(const Model* model, const Float3& origin, flo int32 RenderTools::ComputeSkinnedModelLOD(const SkinnedModel* model, const Float3& origin, float radius, const RenderContext& renderContext) { - const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View); - const float screenRadiusSquared = ComputeBoundsScreenRadiusSquared(origin, radius, *lodView) * renderContext.View.ModelLODDistanceFactorSqrt; + const float screenRadiusSquared = ComputeBoundsScreenRadiusSquared(origin, radius, renderContext.View) * renderContext.View.ModelLODDistanceFactorSqrt; // Check if model is being culled if (Math::Square(model->MinScreenSize * 0.5f) > screenRadiusSquared) diff --git a/Source/Engine/Graphics/RenderView.cpp b/Source/Engine/Graphics/RenderView.cpp index 777b7595d..efd8464b0 100644 --- a/Source/Engine/Graphics/RenderView.cpp +++ b/Source/Engine/Graphics/RenderView.cpp @@ -55,7 +55,6 @@ void RenderView::Prepare(RenderContext& renderContext) } renderContext.List->Init(renderContext); - renderContext.LodProxyView = nullptr; PrepareCache(renderContext, width, height, taaJitter); } @@ -74,7 +73,7 @@ void RenderView::PrepareCache(const RenderContext& renderContext, float width, f WorldPosition = Origin + Position; // Ortho views have issues with screen size LOD culling - const float modelLODDistanceFactor = (renderContext.LodProxyView ? renderContext.LodProxyView->IsOrthographicProjection() : IsOrthographicProjection()) ? 100.0f : ModelLODDistanceFactor; + const float modelLODDistanceFactor = IsOrthographicProjection() ? 100.0f : ModelLODDistanceFactor; ModelLODDistanceFactorSqrt = modelLODDistanceFactor * modelLODDistanceFactor; // Setup main view render info diff --git a/Source/Engine/Level/Actors/Decal.cpp b/Source/Engine/Level/Actors/Decal.cpp index 97a61c5ed..2331a943f 100644 --- a/Source/Engine/Level/Actors/Decal.cpp +++ b/Source/Engine/Level/Actors/Decal.cpp @@ -75,8 +75,7 @@ void Decal::Draw(RenderContext& renderContext) Material->IsLoaded() && Material->IsDecal()) { - const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View); - const float screenRadiusSquared = RenderTools::ComputeBoundsScreenRadiusSquared(_sphere.Center - renderContext.View.Origin, (float)_sphere.Radius, *lodView) * renderContext.View.ModelLODDistanceFactorSqrt; + const float screenRadiusSquared = RenderTools::ComputeBoundsScreenRadiusSquared(_sphere.Center - renderContext.View.Origin, (float)_sphere.Radius, renderContext.View) * renderContext.View.ModelLODDistanceFactorSqrt; // Check if decal is being culled if (Math::Square(DrawMinScreenSize * 0.5f) > screenRadiusSquared) diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp index 9449c2290..20352a2f8 100644 --- a/Source/Engine/Renderer/ShadowsPass.cpp +++ b/Source/Engine/Renderer/ShadowsPass.cpp @@ -193,9 +193,6 @@ void ShadowsPass::SetupRenderContext(RenderContext& renderContext, RenderContext { const auto& view = renderContext.View; - // Use the current render view to sync model LODs with the shadow maps rendering stage - shadowContext.LodProxyView = &renderContext.View; - // Prepare properties auto& shadowView = shadowContext.View; shadowView.Flags = view.Flags; From bdb27fef1b19c22472ccecae2032b01a43c2908d Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 26 Nov 2022 12:08:53 +0100 Subject: [PATCH 20/83] Minor optimizations --- .../Materials/MaterialShaderFeatures.cpp | 27 +++++++++---------- Source/Engine/Terrain/TerrainChunk.cpp | 3 +-- 2 files changed, 13 insertions(+), 17 deletions(-) diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp index a64fd3605..ed67a0c94 100644 --- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp +++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp @@ -13,7 +13,6 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span& cb, int32& srv) { - auto context = params.GPUContext; auto cache = params.RenderContext.List; auto& view = params.RenderContext.View; auto& drawCall = *params.FirstDrawCall; @@ -44,11 +43,11 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, SpanLastDirLight; - context->BindSR(dirLightShaderRegisterIndex, shadowPass->LastDirLightShadowMap); + params.GPUContext->BindSR(dirLightShaderRegisterIndex, shadowPass->LastDirLightShadowMap); } else { - context->UnBindSR(dirLightShaderRegisterIndex); + params.GPUContext->UnBindSR(dirLightShaderRegisterIndex); } dirLight.SetupLightData(&data.DirectionalLight, useShadow); } @@ -56,7 +55,7 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, SpanUnBindSR(dirLightShaderRegisterIndex); + params.GPUContext->UnBindSR(dirLightShaderRegisterIndex); } // Set sky light @@ -65,12 +64,12 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, SpanSkyLights.First(); skyLight.SetupLightData(&data.SkyLight, false); const auto texture = skyLight.Image ? skyLight.Image->GetTexture() : nullptr; - context->BindSR(skyLightShaderRegisterIndex, GET_TEXTURE_VIEW_SAFE(texture)); + params.GPUContext->BindSR(skyLightShaderRegisterIndex, GET_TEXTURE_VIEW_SAFE(texture)); } else { Platform::MemoryClear(&data.SkyLight, sizeof(data.SkyLight)); - context->UnBindSR(skyLightShaderRegisterIndex); + params.GPUContext->UnBindSR(skyLightShaderRegisterIndex); } // Set reflection probe data @@ -89,12 +88,12 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, SpanGetProbe()) { probe->SetupProbeData(params.RenderContext, &data.EnvironmentProbe); - context->BindSR(envProbeShaderRegisterIndex, probe->GetProbe()); + params.GPUContext->BindSR(envProbeShaderRegisterIndex, probe->GetProbe()); } else { data.EnvironmentProbe.Data1 = Float4::Zero; - context->UnBindSR(envProbeShaderRegisterIndex); + params.GPUContext->UnBindSR(envProbeShaderRegisterIndex); } // Set local lights @@ -124,13 +123,10 @@ void ForwardShadingFeature::Bind(MaterialShader::BindParameters& params, Span& cb, int32& srv) { - auto context = params.GPUContext; - auto& view = params.RenderContext.View; auto& drawCall = *params.FirstDrawCall; - auto& data = *(Data*)cb.Get(); ASSERT_LOW_LAYER(cb.Length() >= sizeof(Data)); - const bool useLightmap = view.Flags & ViewFlags::GI + const bool useLightmap = params.RenderContext.View.Flags & ViewFlags::GI #if USE_EDITOR && EnableLightmapsUsage #endif @@ -140,11 +136,12 @@ bool LightmapFeature::Bind(MaterialShader::BindParameters& params, Span& c // Bind lightmap textures GPUTexture *lightmap0, *lightmap1, *lightmap2; drawCall.Features.Lightmap->GetTextures(&lightmap0, &lightmap1, &lightmap2); - context->BindSR(srv + 0, lightmap0); - context->BindSR(srv + 1, lightmap1); - context->BindSR(srv + 2, lightmap2); + params.GPUContext->BindSR(srv + 0, lightmap0); + params.GPUContext->BindSR(srv + 1, lightmap1); + params.GPUContext->BindSR(srv + 2, lightmap2); // Set lightmap data + auto& data = *(Data*)cb.Get(); data.LightmapArea = drawCall.Features.LightmapUVsArea; } diff --git a/Source/Engine/Terrain/TerrainChunk.cpp b/Source/Engine/Terrain/TerrainChunk.cpp index bc0456e12..70551fe67 100644 --- a/Source/Engine/Terrain/TerrainChunk.cpp +++ b/Source/Engine/Terrain/TerrainChunk.cpp @@ -44,8 +44,7 @@ bool TerrainChunk::PrepareDraw(const RenderContext& renderContext) const float chunkEdgeSize = (_patch->_terrain->_chunkSize * TERRAIN_UNITS_PER_VERTEX); // Calculate chunk distance to view - const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View); - const float distance = Float3::Distance(_boundsCenter - lodView->Origin, lodView->Position); + const float distance = Float3::Distance(_boundsCenter - renderContext.View.Origin, renderContext.View.Position); lod = (int32)Math::Pow(distance / chunkEdgeSize, lodDistribution); lod += lodBias; From 39dc439cd8ac0c347ec12846132ffdf354482d88 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 26 Nov 2022 20:37:04 +0100 Subject: [PATCH 21/83] Revert "Remove unused `LodProxyView` feature from `RenderContext` (shadow projections are using the same draw batch as main view now)" This reverts commit c33fe04645b3aee9f575c592a08dfc8670f1a0c5. --- Source/Engine/Graphics/RenderTask.h | 5 +++++ Source/Engine/Graphics/RenderTools.cpp | 6 ++++-- Source/Engine/Graphics/RenderView.cpp | 3 ++- Source/Engine/Level/Actors/Decal.cpp | 3 ++- Source/Engine/Renderer/ShadowsPass.cpp | 3 +++ Source/Engine/Terrain/TerrainChunk.cpp | 3 ++- 6 files changed, 18 insertions(+), 5 deletions(-) diff --git a/Source/Engine/Graphics/RenderTask.h b/Source/Engine/Graphics/RenderTask.h index 8efa198be..92a48cf76 100644 --- a/Source/Engine/Graphics/RenderTask.h +++ b/Source/Engine/Graphics/RenderTask.h @@ -426,6 +426,11 @@ API_STRUCT(NoDefault) struct RenderContext /// API_FIELD() SceneRenderTask* Task = nullptr; + /// + /// The proxy render view used to synchronize objects level of detail during rendering (eg. during shadow maps rendering passes). It's optional. + /// + API_FIELD() RenderView* LodProxyView = nullptr; + /// /// The render view. /// diff --git a/Source/Engine/Graphics/RenderTools.cpp b/Source/Engine/Graphics/RenderTools.cpp index 370bc71d3..912b0ed48 100644 --- a/Source/Engine/Graphics/RenderTools.cpp +++ b/Source/Engine/Graphics/RenderTools.cpp @@ -441,7 +441,8 @@ float RenderTools::ComputeBoundsScreenRadiusSquared(const Float3& origin, float int32 RenderTools::ComputeModelLOD(const Model* model, const Float3& origin, float radius, const RenderContext& renderContext) { - const float screenRadiusSquared = ComputeBoundsScreenRadiusSquared(origin, radius, renderContext.View) * renderContext.View.ModelLODDistanceFactorSqrt; + const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View); + const float screenRadiusSquared = ComputeBoundsScreenRadiusSquared(origin, radius, *lodView) * renderContext.View.ModelLODDistanceFactorSqrt; // Check if model is being culled if (Math::Square(model->MinScreenSize * 0.5f) > screenRadiusSquared) @@ -465,7 +466,8 @@ int32 RenderTools::ComputeModelLOD(const Model* model, const Float3& origin, flo int32 RenderTools::ComputeSkinnedModelLOD(const SkinnedModel* model, const Float3& origin, float radius, const RenderContext& renderContext) { - const float screenRadiusSquared = ComputeBoundsScreenRadiusSquared(origin, radius, renderContext.View) * renderContext.View.ModelLODDistanceFactorSqrt; + const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View); + const float screenRadiusSquared = ComputeBoundsScreenRadiusSquared(origin, radius, *lodView) * renderContext.View.ModelLODDistanceFactorSqrt; // Check if model is being culled if (Math::Square(model->MinScreenSize * 0.5f) > screenRadiusSquared) diff --git a/Source/Engine/Graphics/RenderView.cpp b/Source/Engine/Graphics/RenderView.cpp index efd8464b0..777b7595d 100644 --- a/Source/Engine/Graphics/RenderView.cpp +++ b/Source/Engine/Graphics/RenderView.cpp @@ -55,6 +55,7 @@ void RenderView::Prepare(RenderContext& renderContext) } renderContext.List->Init(renderContext); + renderContext.LodProxyView = nullptr; PrepareCache(renderContext, width, height, taaJitter); } @@ -73,7 +74,7 @@ void RenderView::PrepareCache(const RenderContext& renderContext, float width, f WorldPosition = Origin + Position; // Ortho views have issues with screen size LOD culling - const float modelLODDistanceFactor = IsOrthographicProjection() ? 100.0f : ModelLODDistanceFactor; + const float modelLODDistanceFactor = (renderContext.LodProxyView ? renderContext.LodProxyView->IsOrthographicProjection() : IsOrthographicProjection()) ? 100.0f : ModelLODDistanceFactor; ModelLODDistanceFactorSqrt = modelLODDistanceFactor * modelLODDistanceFactor; // Setup main view render info diff --git a/Source/Engine/Level/Actors/Decal.cpp b/Source/Engine/Level/Actors/Decal.cpp index 2331a943f..97a61c5ed 100644 --- a/Source/Engine/Level/Actors/Decal.cpp +++ b/Source/Engine/Level/Actors/Decal.cpp @@ -75,7 +75,8 @@ void Decal::Draw(RenderContext& renderContext) Material->IsLoaded() && Material->IsDecal()) { - const float screenRadiusSquared = RenderTools::ComputeBoundsScreenRadiusSquared(_sphere.Center - renderContext.View.Origin, (float)_sphere.Radius, renderContext.View) * renderContext.View.ModelLODDistanceFactorSqrt; + const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View); + const float screenRadiusSquared = RenderTools::ComputeBoundsScreenRadiusSquared(_sphere.Center - renderContext.View.Origin, (float)_sphere.Radius, *lodView) * renderContext.View.ModelLODDistanceFactorSqrt; // Check if decal is being culled if (Math::Square(DrawMinScreenSize * 0.5f) > screenRadiusSquared) diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp index 20352a2f8..9449c2290 100644 --- a/Source/Engine/Renderer/ShadowsPass.cpp +++ b/Source/Engine/Renderer/ShadowsPass.cpp @@ -193,6 +193,9 @@ void ShadowsPass::SetupRenderContext(RenderContext& renderContext, RenderContext { const auto& view = renderContext.View; + // Use the current render view to sync model LODs with the shadow maps rendering stage + shadowContext.LodProxyView = &renderContext.View; + // Prepare properties auto& shadowView = shadowContext.View; shadowView.Flags = view.Flags; diff --git a/Source/Engine/Terrain/TerrainChunk.cpp b/Source/Engine/Terrain/TerrainChunk.cpp index 70551fe67..bc0456e12 100644 --- a/Source/Engine/Terrain/TerrainChunk.cpp +++ b/Source/Engine/Terrain/TerrainChunk.cpp @@ -44,7 +44,8 @@ bool TerrainChunk::PrepareDraw(const RenderContext& renderContext) const float chunkEdgeSize = (_patch->_terrain->_chunkSize * TERRAIN_UNITS_PER_VERTEX); // Calculate chunk distance to view - const float distance = Float3::Distance(_boundsCenter - renderContext.View.Origin, renderContext.View.Position); + const auto lodView = (renderContext.LodProxyView ? renderContext.LodProxyView : &renderContext.View); + const float distance = Float3::Distance(_boundsCenter - lodView->Origin, lodView->Position); lod = (int32)Math::Pow(distance / chunkEdgeSize, lodDistribution); lod += lodBias; From 189575efec41dd1944564140356a3b873549ee51 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 26 Nov 2022 21:17:05 +0100 Subject: [PATCH 22/83] Add `GPUDevice::CreateConstantBuffer` for custom constants buffers usage --- Source/Engine/Graphics/GPUDevice.h | 8 ++++++ .../Graphics/Shaders/GPUConstantBuffer.h | 1 - Source/Engine/Graphics/Shaders/GPUShader.cpp | 12 +++++++-- Source/Engine/Graphics/Shaders/GPUShader.h | 1 - .../DirectX/DX11/GPUContextDX11.cpp | 8 ++++++ .../DirectX/DX11/GPUDeviceDX11.cpp | 25 ++++++++++++++++++ .../DirectX/DX11/GPUDeviceDX11.h | 1 + .../DirectX/DX11/GPUShaderDX11.cpp | 26 ------------------- .../DirectX/DX11/GPUShaderDX11.h | 12 +-------- .../DirectX/DX12/GPUDeviceDX12.cpp | 6 ++++- .../DirectX/DX12/GPUDeviceDX12.h | 1 + .../DirectX/DX12/GPUShaderDX12.cpp | 12 --------- .../DirectX/DX12/GPUShaderDX12.h | 16 ++---------- .../GraphicsDevice/Null/GPUDeviceNull.cpp | 5 ++++ .../GraphicsDevice/Null/GPUDeviceNull.h | 1 + .../GraphicsDevice/Null/GPUShaderNull.h | 5 ---- .../GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp | 5 ++++ .../GraphicsDevice/Vulkan/GPUDeviceVulkan.h | 1 + .../GraphicsDevice/Vulkan/GPUShaderVulkan.cpp | 12 --------- .../GraphicsDevice/Vulkan/GPUShaderVulkan.h | 6 ----- 20 files changed, 73 insertions(+), 91 deletions(-) diff --git a/Source/Engine/Graphics/GPUDevice.h b/Source/Engine/Graphics/GPUDevice.h index f4b8e88ae..5f0f6175c 100644 --- a/Source/Engine/Graphics/GPUDevice.h +++ b/Source/Engine/Graphics/GPUDevice.h @@ -364,6 +364,14 @@ public: /// The native window swap chain. virtual GPUSwapChain* CreateSwapChain(Window* window) = 0; + /// + /// Creates the constant buffer. + /// + /// The resource name. + /// The buffer size (in bytes). + /// The constant buffer. + virtual GPUConstantBuffer* CreateConstantBuffer(uint32 size, const StringView& name = StringView::Empty) = 0; + /// /// Creates the GPU tasks context. /// diff --git a/Source/Engine/Graphics/Shaders/GPUConstantBuffer.h b/Source/Engine/Graphics/Shaders/GPUConstantBuffer.h index 0d6eb41f6..0c63ac6f5 100644 --- a/Source/Engine/Graphics/Shaders/GPUConstantBuffer.h +++ b/Source/Engine/Graphics/Shaders/GPUConstantBuffer.h @@ -16,7 +16,6 @@ public: /// /// Gets the buffer size (in bytes). /// - /// The buffer size (in bytes). FORCE_INLINE uint32 GetSize() const { return _size; diff --git a/Source/Engine/Graphics/Shaders/GPUShader.cpp b/Source/Engine/Graphics/Shaders/GPUShader.cpp index 805e48336..7e50b0009 100644 --- a/Source/Engine/Graphics/Shaders/GPUShader.cpp +++ b/Source/Engine/Graphics/Shaders/GPUShader.cpp @@ -4,6 +4,7 @@ #include "GPUConstantBuffer.h" #include "Engine/Core/Log.h" #include "Engine/Core/Math/Math.h" +#include "Engine/Graphics/GPUDevice.h" #include "Engine/Serialization/MemoryReadStream.h" GPUShaderProgramsContainer::GPUShaderProgramsContainer() @@ -148,7 +149,7 @@ bool GPUShader::Create(MemoryReadStream& stream) String name; #endif ASSERT(_constantBuffers[slotIndex] == nullptr); - const auto cb = CreateCB(name, size, stream); + const auto cb = GPUDevice::Instance->CreateConstantBuffer(size, name); if (cb == nullptr) { LOG(Warning, "Failed to create shader constant buffer."); @@ -196,7 +197,14 @@ GPUResource::ResourceType GPUShader::GetResourceType() const void GPUShader::OnReleaseGPU() { + for (GPUConstantBuffer*& cb : _constantBuffers) + { + if (cb) + { + SAFE_DELETE_GPU_RESOURCE(cb); + cb = nullptr; + } + } _memoryUsage = 0; _shaders.Clear(); - Platform::MemoryClear(_constantBuffers, sizeof(_constantBuffers)); } diff --git a/Source/Engine/Graphics/Shaders/GPUShader.h b/Source/Engine/Graphics/Shaders/GPUShader.h index f10da5532..bbc9c4dad 100644 --- a/Source/Engine/Graphics/Shaders/GPUShader.h +++ b/Source/Engine/Graphics/Shaders/GPUShader.h @@ -179,7 +179,6 @@ public: protected: GPUShaderProgram* GetShader(ShaderStage stage, const StringAnsiView& name, int32 permutationIndex) const; virtual GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream) = 0; - virtual GPUConstantBuffer* CreateCB(const String& name, uint32 size, MemoryReadStream& stream) = 0; public: // [GPUResource] diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp index 74ebdde32..300b1baeb 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp @@ -1,5 +1,6 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. +#include "Engine/Profiler/ProfilerCPU.h" #if GRAPHICS_API_DIRECTX11 #include "GPUContextDX11.h" @@ -348,6 +349,7 @@ void GPUContextDX11::BindUA(int32 slot, GPUResourceView* view) void GPUContextDX11::BindVB(const Span& vertexBuffers, const uint32* vertexBuffersOffsets) { + PROFILE_CPU(); ASSERT(vertexBuffers.Length() >= 0 && vertexBuffers.Length() <= GPU_MAX_VB_BINDED); bool vbEdited = false; @@ -372,6 +374,7 @@ void GPUContextDX11::BindVB(const Span& vertexBuffers, const uint32* void GPUContextDX11::BindIB(GPUBuffer* indexBuffer) { + PROFILE_CPU(); const auto ibDX11 = static_cast(indexBuffer); if (ibDX11 != _ibHandle) { @@ -452,6 +455,7 @@ void GPUContextDX11::ResolveMultisample(GPUTexture* sourceMultisampleTexture, GP void GPUContextDX11::DrawInstanced(uint32 verticesCount, uint32 instanceCount, int32 startInstance, int32 startVertex) { + PROFILE_CPU(); onDrawCall(); if (instanceCount > 1) _context->DrawInstanced(verticesCount, instanceCount, startVertex, startInstance); @@ -462,6 +466,7 @@ void GPUContextDX11::DrawInstanced(uint32 verticesCount, uint32 instanceCount, i void GPUContextDX11::DrawIndexedInstanced(uint32 indicesCount, uint32 instanceCount, int32 startInstance, int32 startVertex, int32 startIndex) { + PROFILE_CPU(); onDrawCall(); if (instanceCount > 1) _context->DrawIndexedInstanced(indicesCount, instanceCount, startIndex, startVertex, startInstance); @@ -472,6 +477,7 @@ void GPUContextDX11::DrawIndexedInstanced(uint32 indicesCount, uint32 instanceCo void GPUContextDX11::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs) { + PROFILE_CPU(); ASSERT(bufferForArgs && bufferForArgs->GetFlags() & GPUBufferFlags::Argument); const auto bufferForArgsDX11 = static_cast(bufferForArgs); @@ -483,6 +489,7 @@ void GPUContextDX11::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offs void GPUContextDX11::DrawIndexedInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs) { + PROFILE_CPU(); ASSERT(bufferForArgs && bufferForArgs->GetFlags() & GPUBufferFlags::Argument); const auto bufferForArgsDX11 = static_cast(bufferForArgs); @@ -873,6 +880,7 @@ void GPUContextDX11::flushOM() void GPUContextDX11::onDrawCall() { + PROFILE_CPU(); flushCBs(); flushSRVs(); flushUAVs(); diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp index 768cdd883..dbc5da870 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.cpp @@ -701,4 +701,29 @@ GPUSwapChain* GPUDeviceDX11::CreateSwapChain(Window* window) return New(this, window); } +GPUConstantBuffer* GPUDeviceDX11::CreateConstantBuffer(uint32 size, const StringView& name) +{ + ID3D11Buffer* buffer = nullptr; + uint32 memorySize = 0; + if (size) + { + // Create buffer + D3D11_BUFFER_DESC cbDesc; + cbDesc.ByteWidth = Math::AlignUp(size, 16); + cbDesc.Usage = D3D11_USAGE_DEFAULT; + cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; + cbDesc.CPUAccessFlags = 0; + cbDesc.MiscFlags = 0; + cbDesc.StructureByteStride = 0; + const HRESULT result = _device->CreateBuffer(&cbDesc, nullptr, &buffer); + if (FAILED(result)) + { + LOG_DIRECTX_RESULT(result); + return nullptr; + } + memorySize = cbDesc.ByteWidth; + } + return New(this, size, memorySize, buffer, name); +} + #endif diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h index 5ecd685e6..eb8a73af5 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h @@ -98,6 +98,7 @@ public: GPUBuffer* CreateBuffer(const StringView& name) override; GPUSampler* CreateSampler() override; GPUSwapChain* CreateSwapChain(Window* window) override; + GPUConstantBuffer* CreateConstantBuffer(uint32 size, const StringView& name) override; }; /// diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.cpp index 145ce948c..c523cd7d5 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.cpp @@ -159,32 +159,6 @@ GPUShaderProgram* GPUShaderDX11::CreateGPUShaderProgram(ShaderStage type, const return shader; } -GPUConstantBuffer* GPUShaderDX11::CreateCB(const String& name, uint32 size, MemoryReadStream& stream) -{ - ID3D11Buffer* buffer = nullptr; - uint32 memorySize = 0; - if (size) - { - // Create buffer - D3D11_BUFFER_DESC cbDesc; - cbDesc.ByteWidth = Math::AlignUp(size, 16); - cbDesc.Usage = D3D11_USAGE_DEFAULT; - cbDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER; - cbDesc.CPUAccessFlags = 0; - cbDesc.MiscFlags = 0; - cbDesc.StructureByteStride = 0; - const HRESULT result = _device->GetDevice()->CreateBuffer(&cbDesc, nullptr, &buffer); - if (FAILED(result)) - { - LOG_DIRECTX_RESULT(result); - return nullptr; - } - memorySize = cbDesc.ByteWidth; - } - - return new(_cbs) GPUConstantBufferDX11(_device, name, size, memorySize, buffer); -} - void GPUShaderDX11::OnReleaseGPU() { _cbs.Clear(); diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.h b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.h index 69624b12f..8f249aff9 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUShaderDX11.h @@ -18,16 +18,7 @@ private: ID3D11Buffer* _resource; public: - - /// - /// Initializes a new instance of the class. - /// - /// The graphics device. - /// The resource name. - /// The buffer size (in bytes). - /// The buffer memory size (in bytes). - /// The buffer. - GPUConstantBufferDX11(GPUDeviceDX11* device, const String& name, uint32 size, uint32 memorySize, ID3D11Buffer* buffer) noexcept + GPUConstantBufferDX11(GPUDeviceDX11* device, uint32 size, uint32 memorySize, ID3D11Buffer* buffer, const StringView& name) noexcept : GPUResourceDX11(device, name) , _resource(buffer) { @@ -97,7 +88,6 @@ protected: // [GPUShader] GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream) override; - GPUConstantBuffer* CreateCB(const String& name, uint32 size, MemoryReadStream& stream) override; void OnReleaseGPU() override; public: diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp index 260daf005..bd95b8911 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.cpp @@ -14,7 +14,6 @@ #include "Engine/Engine/Engine.h" #include "Engine/Engine/CommandLine.h" #include "Engine/Graphics/RenderTask.h" -#include "Engine/Graphics/Async/GPUTasksExecutor.h" #include "Engine/GraphicsDevice/DirectX/RenderToolsDX.h" #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Core/Log.h" @@ -795,6 +794,11 @@ GPUSwapChain* GPUDeviceDX12::CreateSwapChain(Window* window) return New(this, window); } +GPUConstantBuffer* GPUDeviceDX12::CreateConstantBuffer(uint32 size, const StringView& name) +{ + return New(this, size, name); +} + void GPUDeviceDX12::AddResourceToLateRelease(IGraphicsUnknown* resource, uint32 safeFrameCount) { if (resource == nullptr) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.h b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.h index f9f30c24b..5913724a5 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUDeviceDX12.h @@ -197,6 +197,7 @@ public: GPUBuffer* CreateBuffer(const StringView& name) override; GPUSampler* CreateSampler() override; GPUSwapChain* CreateSwapChain(Window* window) override; + GPUConstantBuffer* CreateConstantBuffer(uint32 size, const StringView& name) override; }; /// diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUShaderDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUShaderDX12.cpp index 85a22aaaa..926ea3ce4 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUShaderDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUShaderDX12.cpp @@ -127,18 +127,6 @@ GPUShaderProgram* GPUShaderDX12::CreateGPUShaderProgram(ShaderStage type, const return shader; } -GPUConstantBuffer* GPUShaderDX12::CreateCB(const String& name, uint32 size, MemoryReadStream& stream) -{ - return new(_cbs) GPUConstantBufferDX12(_device, size); -} - -void GPUShaderDX12::OnReleaseGPU() -{ - _cbs.Clear(); - - GPUShader::OnReleaseGPU(); -} - ID3D12PipelineState* GPUShaderProgramCSDX12::GetOrCreateState() { if (_state) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUShaderDX12.h b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUShaderDX12.h index 1d4cce7d2..db2cb905b 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUShaderDX12.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUShaderDX12.h @@ -14,14 +14,8 @@ class GPUConstantBufferDX12 : public GPUResourceDX12 { public: - - /// - /// Initializes a new instance of the class. - /// - /// The graphics device. - /// The buffer size (in bytes). - GPUConstantBufferDX12(GPUDeviceDX12* device, uint32 size) noexcept - : GPUResourceDX12(device, String::Empty) + GPUConstantBufferDX12(GPUDeviceDX12* device, uint32 size, const StringView& name) noexcept + : GPUResourceDX12(device, name) , GPUAddress(0) { _size = size; @@ -40,10 +34,6 @@ public: /// class GPUShaderDX12 : public GPUResourceDX12 { -private: - - Array> _cbs; - public: /// @@ -60,8 +50,6 @@ protected: // [GPUShader] GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream) override; - GPUConstantBuffer* CreateCB(const String& name, uint32 size, MemoryReadStream& stream) override; - void OnReleaseGPU() override; }; #endif diff --git a/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.cpp b/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.cpp index 53853671d..b0b980913 100644 --- a/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.cpp +++ b/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.cpp @@ -189,6 +189,11 @@ GPUSwapChain* GPUDeviceNull::CreateSwapChain(Window* window) return New(window); } +GPUConstantBuffer* GPUDeviceNull::CreateConstantBuffer(uint32 size, const StringView& name) +{ + return nullptr; +} + GPUDevice* CreateGPUDeviceNull() { return GPUDeviceNull::Create(); diff --git a/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.h b/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.h index 33dfa6687..dea05dfc1 100644 --- a/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.h +++ b/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.h @@ -48,6 +48,7 @@ public: GPUBuffer* CreateBuffer(const StringView& name) override; GPUSampler* CreateSampler() override; GPUSwapChain* CreateSwapChain(Window* window) override; + GPUConstantBuffer* CreateConstantBuffer(uint32 size, const StringView& name) override; }; extern GPUDevice* CreateGPUDeviceNull(); diff --git a/Source/Engine/GraphicsDevice/Null/GPUShaderNull.h b/Source/Engine/GraphicsDevice/Null/GPUShaderNull.h index 953dd6d9e..e73a4517a 100644 --- a/Source/Engine/GraphicsDevice/Null/GPUShaderNull.h +++ b/Source/Engine/GraphicsDevice/Null/GPUShaderNull.h @@ -19,11 +19,6 @@ protected: return nullptr; } - GPUConstantBuffer* CreateCB(const String& name, uint32 size, MemoryReadStream& stream) override - { - return nullptr; - } - public: // [GPUShader] diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp index e46786b0d..84735cbe3 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp @@ -2045,6 +2045,11 @@ GPUSwapChain* GPUDeviceVulkan::CreateSwapChain(Window* window) return New(this, window); } +GPUConstantBuffer* GPUDeviceVulkan::CreateConstantBuffer(uint32 size, const StringView& name) +{ + return New(this, size); +} + SemaphoreVulkan::SemaphoreVulkan(GPUDeviceVulkan* device) : _device(device) { diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h index f7fc6a221..b4fec211e 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h @@ -708,6 +708,7 @@ public: GPUBuffer* CreateBuffer(const StringView& name) override; GPUSampler* CreateSampler() override; GPUSwapChain* CreateSwapChain(Window* window) override; + GPUConstantBuffer* CreateConstantBuffer(uint32 size, const StringView& name) override; }; /// diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.cpp index b6b2c16d1..43205574b 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.cpp @@ -234,16 +234,4 @@ GPUShaderProgram* GPUShaderVulkan::CreateGPUShaderProgram(ShaderStage type, cons return shader; } -GPUConstantBuffer* GPUShaderVulkan::CreateCB(const String& name, uint32 size, MemoryReadStream& stream) -{ - return new(_cbs) GPUConstantBufferVulkan(_device, size); -} - -void GPUShaderVulkan::OnReleaseGPU() -{ - _cbs.Clear(); - - GPUShader::OnReleaseGPU(); -} - #endif diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.h index 4d0743fe5..06bf21bda 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.h @@ -126,10 +126,6 @@ public: /// class GPUShaderVulkan : public GPUResourceVulkan { -private: - - Array> _cbs; - public: /// @@ -146,8 +142,6 @@ protected: // [GPUShader] GPUShaderProgram* CreateGPUShaderProgram(ShaderStage type, const GPUShaderProgramInitializer& initializer, byte* cacheBytes, uint32 cacheSize, MemoryReadStream& stream) override; - GPUConstantBuffer* CreateCB(const String& name, uint32 size, MemoryReadStream& stream) override; - void OnReleaseGPU() override; }; #endif From 835a230323c99115b78a772dbac7a4bef91d7267 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 27 Nov 2022 12:06:31 +0100 Subject: [PATCH 23/83] Refactor material shaders to use separate constant buffer (slot 1) for shared per-view constants --- Content/Editor/MaterialTemplates/Decal.shader | 9 +--- .../MaterialTemplates/Deformable.shader | 10 +--- .../Editor/MaterialTemplates/Particle.shader | 9 +--- .../Editor/MaterialTemplates/Surface.shader | 13 +---- .../Editor/MaterialTemplates/Terrain.shader | 9 +--- .../MaterialTemplates/VolumeParticle.shader | 9 +--- Source/Engine/Content/Assets/Material.cpp | 2 +- .../Materials/DecalMaterialShader.cpp | 16 ------- .../Materials/DeferredMaterialShader.cpp | 25 +--------- .../Materials/DeformableMaterialShader.cpp | 18 ------- .../Materials/ForwardMaterialShader.cpp | 25 ---------- Source/Engine/Graphics/Materials/IMaterial.h | 7 +++ .../Graphics/Materials/MaterialShader.cpp | 47 +++++++++++++++++++ .../Graphics/Materials/MaterialShader.h | 2 +- .../Materials/ParticleMaterialShader.cpp | 16 ------- .../Materials/TerrainMaterialShader.cpp | 16 ------- .../VolumeParticleMaterialShader.cpp | 16 ------- .../DirectX/DX11/GPUContextDX11.cpp | 8 ---- Source/Engine/Level/Actors/Skybox.cpp | 1 + .../Renderer/Editor/MaterialComplexity.cpp | 1 + .../Renderer/Editor/QuadOverdrawPass.cpp | 1 + Source/Engine/Renderer/GBufferPass.cpp | 1 + Source/Engine/Renderer/RenderList.cpp | 1 + Source/Engine/Renderer/Renderer.cpp | 1 + Source/Engine/Renderer/VolumetricFogPass.cpp | 1 + Source/Shaders/MaterialCommon.hlsl | 22 +++++++++ 26 files changed, 92 insertions(+), 194 deletions(-) diff --git a/Content/Editor/MaterialTemplates/Decal.shader b/Content/Editor/MaterialTemplates/Decal.shader index a304b8c6e..58ef9492c 100644 --- a/Content/Editor/MaterialTemplates/Decal.shader +++ b/Content/Editor/MaterialTemplates/Decal.shader @@ -2,6 +2,7 @@ // Version: @0 #define MATERIAL 1 +#define USE_PER_VIEW_CONSTANTS 1 @3 #include "./Flax/Common.hlsl" @@ -10,17 +11,9 @@ @7 // Primary constant buffer (with additional material parameters) META_CB_BEGIN(0, Data) -float4x4 ViewProjectionMatrix; float4x4 WorldMatrix; -float4x4 ViewMatrix; float4x4 InvWorld; float4x4 SVPositionToWorld; -float3 ViewPos; -float ViewFar; -float3 ViewDir; -float TimeParam; -float4 ViewInfo; -float4 ScreenSize; @1META_CB_END // Use depth buffer for per-pixel decal layering diff --git a/Content/Editor/MaterialTemplates/Deformable.shader b/Content/Editor/MaterialTemplates/Deformable.shader index ace304e68..5be86e33b 100644 --- a/Content/Editor/MaterialTemplates/Deformable.shader +++ b/Content/Editor/MaterialTemplates/Deformable.shader @@ -2,6 +2,7 @@ // Version: @0 #define MATERIAL 1 +#define USE_PER_VIEW_CONSTANTS 1 @3 #include "./Flax/Common.hlsl" #include "./Flax/MaterialCommon.hlsl" @@ -9,23 +10,14 @@ @7 // Primary constant buffer (with additional material parameters) META_CB_BEGIN(0, Data) -float4x4 ViewProjectionMatrix; float4x4 WorldMatrix; float4x4 LocalMatrix; -float4x4 ViewMatrix; -float3 ViewPos; -float ViewFar; -float3 ViewDir; -float TimeParam; -float4 ViewInfo; -float4 ScreenSize; float3 Dummy0; float WorldDeterminantSign; float MeshMinZ; float Segment; float ChunksPerSegment; float PerInstanceRandom; -float4 TemporalAAJitter; float3 GeometrySize; float MeshMaxZ; @1META_CB_END diff --git a/Content/Editor/MaterialTemplates/Particle.shader b/Content/Editor/MaterialTemplates/Particle.shader index ec73cd072..18a270cc0 100644 --- a/Content/Editor/MaterialTemplates/Particle.shader +++ b/Content/Editor/MaterialTemplates/Particle.shader @@ -2,6 +2,7 @@ // Version: @0 #define MATERIAL 1 +#define USE_PER_VIEW_CONSTANTS 1 @3 // Ribbons don't use sorted indices so overlap the segment distances buffer on the slot #define HAS_SORTED_INDICES (!defined(_VS_Ribbon)) @@ -19,15 +20,7 @@ struct SpriteInput // Primary constant buffer (with additional material parameters) META_CB_BEGIN(0, Data) -float4x4 ViewProjectionMatrix; float4x4 WorldMatrix; -float4x4 ViewMatrix; -float3 ViewPos; -float ViewFar; -float3 ViewDir; -float TimeParam; -float4 ViewInfo; -float4 ScreenSize; uint SortedIndicesOffset; float PerInstanceRandom; int ParticleStride; diff --git a/Content/Editor/MaterialTemplates/Surface.shader b/Content/Editor/MaterialTemplates/Surface.shader index 150da0441..0e7c948a1 100644 --- a/Content/Editor/MaterialTemplates/Surface.shader +++ b/Content/Editor/MaterialTemplates/Surface.shader @@ -2,6 +2,7 @@ // Version: @0 #define MATERIAL 1 +#define USE_PER_VIEW_CONSTANTS 1 @3 #include "./Flax/Common.hlsl" #include "./Flax/MaterialCommon.hlsl" @@ -9,23 +10,11 @@ @7 // Primary constant buffer (with additional material parameters) META_CB_BEGIN(0, Data) -float4x4 ViewProjectionMatrix; float4x4 WorldMatrix; -float4x4 ViewMatrix; -float4x4 PrevViewProjectionMatrix; float4x4 PrevWorldMatrix; -float4x4 MainViewProjectionMatrix; -float4 MainScreenSize; -float3 ViewPos; -float ViewFar; -float3 ViewDir; -float TimeParam; -float4 ViewInfo; -float4 ScreenSize; float2 Dummy0; float LODDitherFactor; float PerInstanceRandom; -float4 TemporalAAJitter; float3 GeometrySize; float WorldDeterminantSign; @1META_CB_END diff --git a/Content/Editor/MaterialTemplates/Terrain.shader b/Content/Editor/MaterialTemplates/Terrain.shader index 1326bd0eb..b60ca2a3c 100644 --- a/Content/Editor/MaterialTemplates/Terrain.shader +++ b/Content/Editor/MaterialTemplates/Terrain.shader @@ -2,6 +2,7 @@ // Version: @0 #define MATERIAL 1 +#define USE_PER_VIEW_CONSTANTS 1 @3 // Enables/disables smooth terrain chunks LOD transitions (with morphing higher LOD near edges to the lower LOD in the neighbour) #define USE_SMOOTH_LOD_TRANSITION 1 @@ -16,15 +17,7 @@ @7 // Primary constant buffer (with additional material parameters) META_CB_BEGIN(0, Data) -float4x4 ViewProjectionMatrix; float4x4 WorldMatrix; -float4x4 ViewMatrix; -float3 ViewPos; -float ViewFar; -float3 ViewDir; -float TimeParam; -float4 ViewInfo; -float4 ScreenSize; float3 WorldInvScale; float WorldDeterminantSign; float PerInstanceRandom; diff --git a/Content/Editor/MaterialTemplates/VolumeParticle.shader b/Content/Editor/MaterialTemplates/VolumeParticle.shader index c0fc57e54..c21e7c3bb 100644 --- a/Content/Editor/MaterialTemplates/VolumeParticle.shader +++ b/Content/Editor/MaterialTemplates/VolumeParticle.shader @@ -2,6 +2,7 @@ // Version: @0 #define MATERIAL 1 +#define USE_PER_VIEW_CONSTANTS 1 @3 #include "./Flax/Common.hlsl" @@ -11,17 +12,9 @@ // Primary constant buffer (with additional material parameters) META_CB_BEGIN(0, Data) -float4x4 ViewProjectionMatrix; float4x4 InverseViewProjectionMatrix; -float4x4 ViewMatrix; float4x4 WorldMatrix; float4x4 WorldMatrixInverseTransposed; -float3 ViewPos; -float ViewFar; -float3 ViewDir; -float TimeParam; -float4 ViewInfo; -float4 ScreenSize; float3 GridSize; float PerInstanceRandom; float Dummy0; diff --git a/Source/Engine/Content/Assets/Material.cpp b/Source/Engine/Content/Assets/Material.cpp index 7acc6dec7..f6de35df7 100644 --- a/Source/Engine/Content/Assets/Material.cpp +++ b/Source/Engine/Content/Assets/Material.cpp @@ -482,7 +482,7 @@ void Material::InitCompilationOptions(ShaderCompilationOptions& options) options.Macros.Add({ "MATERIAL_TESSELLATION", "MATERIAL_TESSELLATION_PHONG" }); break; } - options.Macros.Add({ "MAX_TESSELLATION_FACTOR", Numbers[info.MaxTessellationFactor] }); + options.Macros.Add({ "MAX_TESSELLATION_FACTOR", Numbers[Math::Min(info.MaxTessellationFactor, ARRAY_COUNT(Numbers) - 1)] }); } // Helper macros (used by the parser) diff --git a/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp b/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp index 6ca243fc1..54ca0e137 100644 --- a/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp @@ -12,17 +12,9 @@ #include "Engine/Renderer/DrawCall.h" PACK_STRUCT(struct DecalMaterialShaderData { - Matrix ViewProjectionMatrix; Matrix WorldMatrix; - Matrix ViewMatrix; Matrix InvWorld; Matrix SVPositionToWorld; - Float3 ViewPos; - float ViewFar; - Float3 ViewDir; - float TimeParam; - Float4 ViewInfo; - Float4 ScreenSize; }); DrawPass DecalMaterialShader::GetDrawModes() const @@ -58,15 +50,7 @@ void DecalMaterialShader::Bind(BindParameters& params) // Setup material constants { - Matrix::Transpose(view.Frustum.GetMatrix(), materialData->ViewProjectionMatrix); Matrix::Transpose(drawCall.World, materialData->WorldMatrix); - Matrix::Transpose(view.View, materialData->ViewMatrix); - materialData->ViewPos = view.Position; - materialData->ViewFar = view.Far; - materialData->ViewDir = view.Direction; - materialData->TimeParam = params.TimeParam; - materialData->ViewInfo = view.ViewInfo; - materialData->ScreenSize = view.ScreenSize; // Matrix for transformation from world space to decal object space Matrix invWorld; diff --git a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp index 9f03f81ca..4879c7896 100644 --- a/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/DeferredMaterialShader.cpp @@ -17,23 +17,11 @@ #include "Engine/Graphics/RenderTask.h" PACK_STRUCT(struct DeferredMaterialShaderData { - Matrix ViewProjectionMatrix; Matrix WorldMatrix; - Matrix ViewMatrix; - Matrix PrevViewProjectionMatrix; Matrix PrevWorldMatrix; - Matrix MainViewProjectionMatrix; - Float4 MainScreenSize; - Float3 ViewPos; - float ViewFar; - Float3 ViewDir; - float TimeParam; - Float4 ViewInfo; - Float4 ScreenSize; Float2 Dummy0; float LODDitherFactor; float PerInstanceRandom; - Float4 TemporalAAJitter; Float3 GeometrySize; float WorldDeterminantSign; }); @@ -56,6 +44,7 @@ bool DeferredMaterialShader::CanUseInstancing(InstancingHandler& handler) const void DeferredMaterialShader::Bind(BindParameters& params) { + //PROFILE_CPU(); // Prepare auto context = params.GPUContext; auto& view = params.RenderContext.View; @@ -81,23 +70,11 @@ void DeferredMaterialShader::Bind(BindParameters& params) // Setup material constants { - Matrix::Transpose(view.Frustum.GetMatrix(), materialData->ViewProjectionMatrix); Matrix::Transpose(drawCall.World, materialData->WorldMatrix); - Matrix::Transpose(view.View, materialData->ViewMatrix); Matrix::Transpose(drawCall.Surface.PrevWorld, materialData->PrevWorldMatrix); - Matrix::Transpose(view.PrevViewProjection, materialData->PrevViewProjectionMatrix); - Matrix::Transpose(view.MainViewProjection, materialData->MainViewProjectionMatrix); - materialData->MainScreenSize = view.MainScreenSize; - materialData->ViewPos = view.Position; - materialData->ViewFar = view.Far; - materialData->ViewDir = view.Direction; - materialData->TimeParam = params.TimeParam; - materialData->ViewInfo = view.ViewInfo; - materialData->ScreenSize = view.ScreenSize; materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign; materialData->LODDitherFactor = drawCall.Surface.LODDitherFactor; materialData->PerInstanceRandom = drawCall.PerInstanceRandom; - materialData->TemporalAAJitter = view.TemporalAAJitter; materialData->GeometrySize = drawCall.Surface.GeometrySize; } diff --git a/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp b/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp index ec3b800fe..02ec26d94 100644 --- a/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/DeformableMaterialShader.cpp @@ -15,23 +15,14 @@ #include "Engine/Graphics/RenderTask.h" PACK_STRUCT(struct DeformableMaterialShaderData { - Matrix ViewProjectionMatrix; Matrix WorldMatrix; Matrix LocalMatrix; - Matrix ViewMatrix; - Float3 ViewPos; - float ViewFar; - Float3 ViewDir; - float TimeParam; - Float4 ViewInfo; - Float4 ScreenSize; Float3 Dummy0; float WorldDeterminantSign; float MeshMinZ; float Segment; float ChunksPerSegment; float PerInstanceRandom; - Float4 TemporalAAJitter; Float3 GeometrySize; float MeshMaxZ; }); @@ -69,23 +60,14 @@ void DeformableMaterialShader::Bind(BindParameters& params) // Setup material constants { - Matrix::Transpose(view.Frustum.GetMatrix(), materialData->ViewProjectionMatrix); Matrix::Transpose(drawCall.World, materialData->WorldMatrix); Matrix::Transpose(drawCall.Deformable.LocalMatrix, materialData->LocalMatrix); - Matrix::Transpose(view.View, materialData->ViewMatrix); - materialData->ViewPos = view.Position; - materialData->ViewFar = view.Far; - materialData->ViewDir = view.Direction; - materialData->TimeParam = params.TimeParam; - materialData->ViewInfo = view.ViewInfo; - materialData->ScreenSize = view.ScreenSize; materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign; materialData->Segment = drawCall.Deformable.Segment; materialData->ChunksPerSegment = drawCall.Deformable.ChunksPerSegment; materialData->MeshMinZ = drawCall.Deformable.MeshMinZ; materialData->MeshMaxZ = drawCall.Deformable.MeshMaxZ; materialData->PerInstanceRandom = drawCall.PerInstanceRandom; - materialData->TemporalAAJitter = view.TemporalAAJitter; materialData->GeometrySize = drawCall.Deformable.GeometrySize; } diff --git a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp index 9897063d1..9c658f9c9 100644 --- a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp @@ -16,26 +16,12 @@ #include "Engine/Renderer/Lightmaps.h" #endif -#define MAX_LOCAL_LIGHTS 4 - PACK_STRUCT(struct ForwardMaterialShaderData { - Matrix ViewProjectionMatrix; Matrix WorldMatrix; - Matrix ViewMatrix; - Matrix PrevViewProjectionMatrix; Matrix PrevWorldMatrix; - Matrix MainViewProjectionMatrix; - Float4 MainScreenSize; - Float3 ViewPos; - float ViewFar; - Float3 ViewDir; - float TimeParam; - Float4 ViewInfo; - Float4 ScreenSize; Float2 Dummy0; float LODDitherFactor; float PerInstanceRandom; - Float4 TemporalAAJitter; Float3 GeometrySize; float WorldDeterminantSign; }); @@ -89,19 +75,8 @@ void ForwardMaterialShader::Bind(BindParameters& params) // Setup material constants { - Matrix::Transpose(view.Frustum.GetMatrix(), materialData->ViewProjectionMatrix); Matrix::Transpose(drawCall.World, materialData->WorldMatrix); - Matrix::Transpose(view.View, materialData->ViewMatrix); Matrix::Transpose(drawCall.Surface.PrevWorld, materialData->PrevWorldMatrix); - Matrix::Transpose(view.PrevViewProjection, materialData->PrevViewProjectionMatrix); - Matrix::Transpose(view.MainViewProjection, materialData->MainViewProjectionMatrix); - materialData->MainScreenSize = view.MainScreenSize; - materialData->ViewPos = view.Position; - materialData->ViewFar = view.Far; - materialData->ViewDir = view.Direction; - materialData->TimeParam = params.TimeParam; - materialData->ViewInfo = view.ViewInfo; - materialData->ScreenSize = view.ScreenSize; materialData->WorldDeterminantSign = drawCall.WorldDeterminantSign; materialData->LODDitherFactor = drawCall.Surface.LODDitherFactor; materialData->PerInstanceRandom = drawCall.PerInstanceRandom; diff --git a/Source/Engine/Graphics/Materials/IMaterial.h b/Source/Engine/Graphics/Materials/IMaterial.h index 9c6eed0cf..68e83547e 100644 --- a/Source/Engine/Graphics/Materials/IMaterial.h +++ b/Source/Engine/Graphics/Materials/IMaterial.h @@ -8,6 +8,7 @@ struct MaterialParamsLink; class GPUShader; class GPUContext; class GPUTextureView; +class GPUConstantBuffer; class RenderBuffers; class SceneRenderTask; struct RenderView; @@ -157,6 +158,12 @@ public: BindParameters(::GPUContext* context, const ::RenderContext& renderContext); BindParameters(::GPUContext* context, const ::RenderContext& renderContext, const DrawCall& drawCall); BindParameters(::GPUContext* context, const ::RenderContext& renderContext, const DrawCall* firstDrawCall, int32 drawCallsCount); + + // Per-view shared constant buffer (see ViewData in MaterialCommon.hlsl). + static GPUConstantBuffer* PerViewConstants; + + // Binds the shared per-view constant buffer at slot 1 (see ViewData in MaterialCommon.hlsl) + void BindViewData(); }; /// diff --git a/Source/Engine/Graphics/Materials/MaterialShader.cpp b/Source/Engine/Graphics/Materials/MaterialShader.cpp index a81293430..ac9453e64 100644 --- a/Source/Engine/Graphics/Materials/MaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/MaterialShader.cpp @@ -4,6 +4,7 @@ #include "Engine/Core/Log.h" #include "Engine/Serialization/MemoryReadStream.h" #include "Engine/Renderer/RenderList.h" +#include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/Shaders/GPUConstantBuffer.h" #include "Engine/Graphics/Shaders/GPUShader.h" @@ -18,6 +19,21 @@ #include "DeformableMaterialShader.h" #include "VolumeParticleMaterialShader.h" +PACK_STRUCT(struct MaterialShaderDataPerView { + Matrix ViewMatrix; + Matrix ViewProjectionMatrix; + Matrix PrevViewProjectionMatrix; + Matrix MainViewProjectionMatrix; + Float4 MainScreenSize; + Float3 ViewPos; + float ViewFar; + Float3 ViewDir; + float TimeParam; + Float4 ViewInfo; + Float4 ScreenSize; + Float4 TemporalAAJitter; + }); + IMaterial::BindParameters::BindParameters(::GPUContext* context, const ::RenderContext& renderContext) : GPUContext(context) , RenderContext(renderContext) @@ -45,6 +61,37 @@ IMaterial::BindParameters::BindParameters(::GPUContext* context, const ::RenderC { } +GPUConstantBuffer* IMaterial::BindParameters::PerViewConstants = nullptr; + +void IMaterial::BindParameters::BindViewData() +{ + // Lazy-init + if (!PerViewConstants) + { + PerViewConstants = GPUDevice::Instance->CreateConstantBuffer(sizeof(MaterialShaderDataPerView), TEXT("PerViewConstants")); + } + + // Setup data + MaterialShaderDataPerView cb; + int aa1 = sizeof(MaterialShaderDataPerView); + Matrix::Transpose(RenderContext.View.Frustum.GetMatrix(), cb.ViewProjectionMatrix); + Matrix::Transpose(RenderContext.View.View, cb.ViewMatrix); + Matrix::Transpose(RenderContext.View.PrevViewProjection, cb.PrevViewProjectionMatrix); + Matrix::Transpose(RenderContext.View.MainViewProjection, cb.MainViewProjectionMatrix); + cb.MainScreenSize = RenderContext.View.MainScreenSize; + cb.ViewPos = RenderContext.View.Position; + cb.ViewFar = RenderContext.View.Far; + cb.ViewDir = RenderContext.View.Direction; + cb.TimeParam = TimeParam; + cb.ViewInfo = RenderContext.View.ViewInfo; + cb.ScreenSize = RenderContext.View.ScreenSize; + cb.TemporalAAJitter = RenderContext.View.TemporalAAJitter; + + // Update constants + GPUContext->UpdateCB(PerViewConstants, &cb); + GPUContext->BindCB(1, PerViewConstants); +} + GPUPipelineState* MaterialShader::PipelineStateCache::InitPS(CullMode mode, bool wireframe) { Desc.CullMode = mode; diff --git a/Source/Engine/Graphics/Materials/MaterialShader.h b/Source/Engine/Graphics/Materials/MaterialShader.h index d48e5d16f..1faa78eee 100644 --- a/Source/Engine/Graphics/Materials/MaterialShader.h +++ b/Source/Engine/Graphics/Materials/MaterialShader.h @@ -10,7 +10,7 @@ /// /// Current materials shader version. /// -#define MATERIAL_GRAPH_VERSION 158 +#define MATERIAL_GRAPH_VERSION 159 class Material; class GPUShader; diff --git a/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp b/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp index 196108608..a994d0e3f 100644 --- a/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/ParticleMaterialShader.cpp @@ -15,15 +15,7 @@ #include "Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.h" PACK_STRUCT(struct ParticleMaterialShaderData { - Matrix ViewProjectionMatrix; Matrix WorldMatrix; - Matrix ViewMatrix; - Float3 ViewPos; - float ViewFar; - Float3 ViewDir; - float TimeParam; - Float4 ViewInfo; - Float4 ScreenSize; uint32 SortedIndicesOffset; float PerInstanceRandom; int32 ParticleStride; @@ -109,15 +101,7 @@ void ParticleMaterialShader::Bind(BindParameters& params) static StringView ParticleScaleOffset(TEXT("Scale")); static StringView ParticleModelFacingModeOffset(TEXT("ModelFacingMode")); - Matrix::Transpose(view.Frustum.GetMatrix(), materialData->ViewProjectionMatrix); Matrix::Transpose(drawCall.World, materialData->WorldMatrix); - Matrix::Transpose(view.View, materialData->ViewMatrix); - materialData->ViewPos = view.Position; - materialData->ViewFar = view.Far; - materialData->ViewDir = view.Direction; - materialData->TimeParam = params.TimeParam; - materialData->ViewInfo = view.ViewInfo; - materialData->ScreenSize = view.ScreenSize; materialData->SortedIndicesOffset = drawCall.Particle.Particles->GPU.SortedIndices && params.RenderContext.View.Pass != DrawPass::Depth ? sortedIndicesOffset : 0xFFFFFFFF; materialData->PerInstanceRandom = drawCall.PerInstanceRandom; materialData->ParticleStride = drawCall.Particle.Particles->Stride; diff --git a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp index bcdb4ee83..7b3d17658 100644 --- a/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/TerrainMaterialShader.cpp @@ -16,15 +16,7 @@ #include "Engine/Terrain/TerrainPatch.h" PACK_STRUCT(struct TerrainMaterialShaderData { - Matrix ViewProjectionMatrix; Matrix WorldMatrix; - Matrix ViewMatrix; - Float3 ViewPos; - float ViewFar; - Float3 ViewDir; - float TimeParam; - Float4 ViewInfo; - Float4 ScreenSize; Float3 WorldInvScale; float WorldDeterminantSign; float PerInstanceRandom; @@ -74,15 +66,7 @@ void TerrainMaterialShader::Bind(BindParameters& params) // Setup material constants { - Matrix::Transpose(view.Frustum.GetMatrix(), materialData->ViewProjectionMatrix); Matrix::Transpose(drawCall.World, materialData->WorldMatrix); - Matrix::Transpose(view.View, materialData->ViewMatrix); - materialData->ViewPos = view.Position; - materialData->ViewFar = view.Far; - materialData->ViewDir = view.Direction; - materialData->TimeParam = params.TimeParam; - materialData->ViewInfo = view.ViewInfo; - materialData->ScreenSize = view.ScreenSize; const float scaleX = Float3(drawCall.World.M11, drawCall.World.M12, drawCall.World.M13).Length(); const float scaleY = Float3(drawCall.World.M21, drawCall.World.M22, drawCall.World.M23).Length(); const float scaleZ = Float3(drawCall.World.M31, drawCall.World.M32, drawCall.World.M33).Length(); diff --git a/Source/Engine/Graphics/Materials/VolumeParticleMaterialShader.cpp b/Source/Engine/Graphics/Materials/VolumeParticleMaterialShader.cpp index 42d8ec87e..06b5a66d2 100644 --- a/Source/Engine/Graphics/Materials/VolumeParticleMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/VolumeParticleMaterialShader.cpp @@ -15,17 +15,9 @@ #include "Engine/Particles/Graph/CPU/ParticleEmitterGraph.CPU.h" PACK_STRUCT(struct VolumeParticleMaterialShaderData { - Matrix ViewProjectionMatrix; Matrix InverseViewProjectionMatrix; - Matrix ViewMatrix; Matrix WorldMatrix; Matrix WorldMatrixInverseTransposed; - Float3 ViewPos; - float ViewFar; - Float3 ViewDir; - float TimeParam; - Float4 ViewInfo; - Float4 ScreenSize; Float3 GridSize; float PerInstanceRandom; float Dummy0; @@ -83,17 +75,9 @@ void VolumeParticleMaterialShader::Bind(BindParameters& params) // Setup material constants { - Matrix::Transpose(view.Frustum.GetMatrix(), materialData->ViewProjectionMatrix); Matrix::Transpose(view.IVP, materialData->InverseViewProjectionMatrix); - Matrix::Transpose(view.View, materialData->ViewMatrix); Matrix::Transpose(drawCall.World, materialData->WorldMatrix); Matrix::Invert(drawCall.World, materialData->WorldMatrixInverseTransposed); - materialData->ViewPos = view.Position; - materialData->ViewFar = view.Far; - materialData->ViewDir = view.Direction; - materialData->TimeParam = params.TimeParam; - materialData->ViewInfo = view.ViewInfo; - materialData->ScreenSize = view.ScreenSize; materialData->GridSize = customData->GridSize; materialData->PerInstanceRandom = drawCall.PerInstanceRandom; materialData->VolumetricFogMaxDistance = customData->VolumetricFogMaxDistance; diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp index 300b1baeb..74ebdde32 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUContextDX11.cpp @@ -1,6 +1,5 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. -#include "Engine/Profiler/ProfilerCPU.h" #if GRAPHICS_API_DIRECTX11 #include "GPUContextDX11.h" @@ -349,7 +348,6 @@ void GPUContextDX11::BindUA(int32 slot, GPUResourceView* view) void GPUContextDX11::BindVB(const Span& vertexBuffers, const uint32* vertexBuffersOffsets) { - PROFILE_CPU(); ASSERT(vertexBuffers.Length() >= 0 && vertexBuffers.Length() <= GPU_MAX_VB_BINDED); bool vbEdited = false; @@ -374,7 +372,6 @@ void GPUContextDX11::BindVB(const Span& vertexBuffers, const uint32* void GPUContextDX11::BindIB(GPUBuffer* indexBuffer) { - PROFILE_CPU(); const auto ibDX11 = static_cast(indexBuffer); if (ibDX11 != _ibHandle) { @@ -455,7 +452,6 @@ void GPUContextDX11::ResolveMultisample(GPUTexture* sourceMultisampleTexture, GP void GPUContextDX11::DrawInstanced(uint32 verticesCount, uint32 instanceCount, int32 startInstance, int32 startVertex) { - PROFILE_CPU(); onDrawCall(); if (instanceCount > 1) _context->DrawInstanced(verticesCount, instanceCount, startVertex, startInstance); @@ -466,7 +462,6 @@ void GPUContextDX11::DrawInstanced(uint32 verticesCount, uint32 instanceCount, i void GPUContextDX11::DrawIndexedInstanced(uint32 indicesCount, uint32 instanceCount, int32 startInstance, int32 startVertex, int32 startIndex) { - PROFILE_CPU(); onDrawCall(); if (instanceCount > 1) _context->DrawIndexedInstanced(indicesCount, instanceCount, startIndex, startVertex, startInstance); @@ -477,7 +472,6 @@ void GPUContextDX11::DrawIndexedInstanced(uint32 indicesCount, uint32 instanceCo void GPUContextDX11::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs) { - PROFILE_CPU(); ASSERT(bufferForArgs && bufferForArgs->GetFlags() & GPUBufferFlags::Argument); const auto bufferForArgsDX11 = static_cast(bufferForArgs); @@ -489,7 +483,6 @@ void GPUContextDX11::DrawInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offs void GPUContextDX11::DrawIndexedInstancedIndirect(GPUBuffer* bufferForArgs, uint32 offsetForArgs) { - PROFILE_CPU(); ASSERT(bufferForArgs && bufferForArgs->GetFlags() & GPUBufferFlags::Argument); const auto bufferForArgsDX11 = static_cast(bufferForArgs); @@ -880,7 +873,6 @@ void GPUContextDX11::flushOM() void GPUContextDX11::onDrawCall() { - PROFILE_CPU(); flushCBs(); flushSRVs(); flushUAVs(); diff --git a/Source/Engine/Level/Actors/Skybox.cpp b/Source/Engine/Level/Actors/Skybox.cpp index 162d515cc..784cdaee8 100644 --- a/Source/Engine/Level/Actors/Skybox.cpp +++ b/Source/Engine/Level/Actors/Skybox.cpp @@ -104,6 +104,7 @@ void Skybox::ApplySky(GPUContext* context, RenderContext& renderContext, const M drawCall.WorldDeterminantSign = Math::FloatSelect(world.RotDeterminant(), 1, -1); drawCall.PerInstanceRandom = GetPerInstanceRandom(); MaterialBase::BindParameters bindParams(context, renderContext, drawCall); + bindParams.BindViewData(); // Check if use custom material if (CustomMaterial) diff --git a/Source/Engine/Renderer/Editor/MaterialComplexity.cpp b/Source/Engine/Renderer/Editor/MaterialComplexity.cpp index b20e1e976..569050f5e 100644 --- a/Source/Engine/Renderer/Editor/MaterialComplexity.cpp +++ b/Source/Engine/Renderer/Editor/MaterialComplexity.cpp @@ -126,6 +126,7 @@ void MaterialComplexityMaterialShader::Draw(RenderContext& renderContext, GPUCon PROFILE_GPU_CPU_NAMED("Decals"); DrawCall drawCall; MaterialBase::BindParameters bindParams(context, renderContext, drawCall); + bindParams.BindViewData(); drawCall.WorldDeterminantSign = 1.0f; context->SetRenderTarget(lightBuffer); for (int32 i = 0; i < decals.Count(); i++) diff --git a/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp b/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp index e0ed4ae31..cd1918988 100644 --- a/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp +++ b/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp @@ -48,6 +48,7 @@ void QuadOverdrawPass::Render(RenderContext& renderContext, GPUContext* context, Platform::MemoryClear(&drawCall, sizeof(DrawCall)); drawCall.PerInstanceRandom = 1.0f; MaterialBase::BindParameters bindParams(context, renderContext, drawCall); + bindParams.BindViewData(); renderContext.View.Pass = DrawPass::QuadOverdraw; context->SetRenderTarget(*renderContext.Buffers->DepthBuffer, (GPUTextureView*)nullptr); renderContext.List->ExecuteDrawCalls(renderContext, DrawCallsListType::GBuffer); diff --git a/Source/Engine/Renderer/GBufferPass.cpp b/Source/Engine/Renderer/GBufferPass.cpp index 1ee90a7cd..87ce7a432 100644 --- a/Source/Engine/Renderer/GBufferPass.cpp +++ b/Source/Engine/Renderer/GBufferPass.cpp @@ -433,6 +433,7 @@ void GBufferPass::DrawDecals(RenderContext& renderContext, GPUTextureView* light // Prepare DrawCall drawCall; MaterialBase::BindParameters bindParams(context, renderContext, drawCall); + bindParams.BindViewData(); drawCall.Material = nullptr; drawCall.WorldDeterminantSign = 1.0f; diff --git a/Source/Engine/Renderer/RenderList.cpp b/Source/Engine/Renderer/RenderList.cpp index 7a75ac147..95abc11be 100644 --- a/Source/Engine/Renderer/RenderList.cpp +++ b/Source/Engine/Renderer/RenderList.cpp @@ -695,6 +695,7 @@ DRAW: // Execute draw calls MaterialBase::BindParameters bindParams(context, renderContext); bindParams.Input = input; + bindParams.BindViewData(); if (useInstancing) { int32 instanceBufferOffset = 0; diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp index 710312ab6..10fde8f51 100644 --- a/Source/Engine/Renderer/Renderer.cpp +++ b/Source/Engine/Renderer/Renderer.cpp @@ -119,6 +119,7 @@ void RendererService::Dispose() { PassList[i]->Dispose(); } + SAFE_DELETE_GPU_RESOURCE(IMaterial::BindParameters::PerViewConstants); } void RenderAntiAliasingPass(RenderContext& renderContext, GPUTexture* input, GPUTextureView* output) diff --git a/Source/Engine/Renderer/VolumetricFogPass.cpp b/Source/Engine/Renderer/VolumetricFogPass.cpp index 3185fad6f..6fb9c3ce3 100644 --- a/Source/Engine/Renderer/VolumetricFogPass.cpp +++ b/Source/Engine/Renderer/VolumetricFogPass.cpp @@ -536,6 +536,7 @@ void VolumetricFogPass::Render(RenderContext& renderContext) customData.GridSize = cache.GridSize; customData.VolumetricFogMaxDistance = cache.Data.VolumetricFogMaxDistance; bindParams.CustomData = &customData; + bindParams.BindViewData(); for (auto& drawCall : renderContext.List->VolumetricFogParticles) { diff --git a/Source/Shaders/MaterialCommon.hlsl b/Source/Shaders/MaterialCommon.hlsl index 60ba7e298..86f720cd6 100644 --- a/Source/Shaders/MaterialCommon.hlsl +++ b/Source/Shaders/MaterialCommon.hlsl @@ -55,6 +55,9 @@ #ifndef USE_DITHERED_LOD_TRANSITION #define USE_DITHERED_LOD_TRANSITION 0 #endif +#ifndef USE_PER_VIEW_CONSTANTS +#define USE_PER_VIEW_CONSTANTS 0 +#endif #ifndef MATERIAL_TESSELLATION #define MATERIAL_TESSELLATION MATERIAL_TESSELLATION_NONE #endif @@ -88,6 +91,25 @@ struct Material #endif }; +// Secondary constant buffer (with per-view constants at slot 1) +#if USE_PER_VIEW_CONSTANTS +cbuffer ViewData : register(b1) +{ + float4x4 ViewMatrix; + float4x4 ViewProjectionMatrix; + float4x4 PrevViewProjectionMatrix; + float4x4 MainViewProjectionMatrix; + float4 MainScreenSize; + float3 ViewPos; + float ViewFar; + float3 ViewDir; + float TimeParam; + float4 ViewInfo; + float4 ScreenSize; + float4 TemporalAAJitter; +}; +#endif + struct ModelInput { float3 Position : POSITION; From 373350df1e0a85c05561d30bc4f6a4ae27a4c129 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 27 Nov 2022 12:07:10 +0100 Subject: [PATCH 24/83] Improve stability of `RenderListBuffer` resizing when multiple threads add and resize at the same time --- Source/Engine/Renderer/RenderListBuffer.h | 54 ++++++++++++++++------- 1 file changed, 37 insertions(+), 17 deletions(-) diff --git a/Source/Engine/Renderer/RenderListBuffer.h b/Source/Engine/Renderer/RenderListBuffer.h index 01af1677c..ed2d0b41a 100644 --- a/Source/Engine/Renderer/RenderListBuffer.h +++ b/Source/Engine/Renderer/RenderListBuffer.h @@ -23,7 +23,8 @@ public: private: volatile int64 _count; volatile int64 _capacity; - volatile int64 _threads = 0; + volatile int64 _threadsAdding = 0; + volatile int64 _threadsResizing = 0; AllocationData _allocation; CriticalSection _locker; @@ -298,13 +299,11 @@ public: /// /// The item to add. /// Index of the added element. - int32 Add(const T& item) + FORCE_INLINE int32 Add(const T& item) { const int32 index = AddOne(); - auto ptr = _allocation.Get(); Memory::ConstructItems(_allocation.Get() + index, &item, 1); - ASSERT(ptr == _allocation.Get()); - Platform::InterlockedDecrement(&_threads); + Platform::InterlockedDecrement(&_threadsAdding); return index; } @@ -313,25 +312,47 @@ public: /// /// The item to add. /// Index of the added element. - int32 Add(T&& item) + FORCE_INLINE int32 Add(T&& item) { const int32 index = AddOne(); - auto ptr = _allocation.Get(); Memory::MoveItems(_allocation.Get() + index, &item, 1); - ASSERT(ptr == _allocation.Get()); - Platform::InterlockedDecrement(&_threads); + Platform::InterlockedDecrement(&_threadsAdding); return index; } private: - FORCE_INLINE int32 AddOne() + int32 AddOne() { - Platform::InterlockedIncrement(&_threads); - const int32 count = (int32)Platform::AtomicRead(&_count); - const int32 capacity = (int32)Platform::AtomicRead(&_capacity); + Platform::InterlockedIncrement(&_threadsAdding); + int32 count = (int32)Platform::AtomicRead(&_count); + int32 capacity = (int32)Platform::AtomicRead(&_capacity); const int32 minCapacity = GetMinCapacity(count); - if (minCapacity > capacity) - EnsureCapacity(minCapacity); + if (minCapacity > capacity || Platform::AtomicRead(&_threadsResizing)) // Resize if not enough space or someone else is already doing it (don't add mid-resizing) + { + // Move from adding to resizing + Platform::InterlockedIncrement(&_threadsResizing); + Platform::InterlockedDecrement(&_threadsAdding); + + // Wait for all threads to stop adding items before resizing can happen + while (Platform::AtomicRead(&_threadsAdding)) + Platform::Sleep(0); + + // Thread-safe resizing + _locker.Lock(); + capacity = (int32)Platform::AtomicRead(&_capacity); + if (capacity < minCapacity) + { + capacity = _allocation.CalculateCapacityGrow(capacity, minCapacity); + count = (int32)Platform::AtomicRead(&_count); + _allocation.Relocate(capacity, count, count); + Platform::AtomicStore(&_capacity, capacity); + } + _locker.Unlock(); + + // Move from resizing to adding + Platform::InterlockedIncrement(&_threadsAdding); + Platform::InterlockedDecrement(&_threadsResizing); + } return (int32)Platform::InterlockedIncrement(&_count) - 1; } @@ -342,7 +363,7 @@ private: int32 capacity = count + slack; { // Round up to the next power of 2 and multiply by 2 - capacity++; + capacity--; capacity |= capacity >> 1; capacity |= capacity >> 2; capacity |= capacity >> 4; @@ -351,6 +372,5 @@ private: capacity = (capacity + 1) * 2; } return capacity; - return count + slack; } }; From 3da7e8d7baf7b612917308d97d5da2887aa3dc11 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 27 Nov 2022 20:33:39 +0100 Subject: [PATCH 25/83] Additional improvement for RenderListBuffer --- Source/Engine/Renderer/RenderListBuffer.h | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Renderer/RenderListBuffer.h b/Source/Engine/Renderer/RenderListBuffer.h index ed2d0b41a..6e817d554 100644 --- a/Source/Engine/Renderer/RenderListBuffer.h +++ b/Source/Engine/Renderer/RenderListBuffer.h @@ -334,6 +334,7 @@ private: Platform::InterlockedDecrement(&_threadsAdding); // Wait for all threads to stop adding items before resizing can happen + RETRY: while (Platform::AtomicRead(&_threadsAdding)) Platform::Sleep(0); @@ -342,16 +343,24 @@ private: capacity = (int32)Platform::AtomicRead(&_capacity); if (capacity < minCapacity) { + if (Platform::AtomicRead(&_threadsAdding)) + { + // Other thread entered during mutex locking so give them a chance to do safe resizing + _locker.Unlock(); + goto RETRY; + } capacity = _allocation.CalculateCapacityGrow(capacity, minCapacity); count = (int32)Platform::AtomicRead(&_count); _allocation.Relocate(capacity, count, count); Platform::AtomicStore(&_capacity, capacity); } - _locker.Unlock(); - + // Move from resizing to adding Platform::InterlockedIncrement(&_threadsAdding); Platform::InterlockedDecrement(&_threadsResizing); + + // Let other thread enter resizing-area + _locker.Unlock(); } return (int32)Platform::InterlockedIncrement(&_count) - 1; } From 08c035e7d8a504a75f881022428a658a71997021 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 27 Nov 2022 20:33:45 +0100 Subject: [PATCH 26/83] Update engine materials --- Content/Editor/Camera/M_Camera.flax | 4 ++-- Content/Editor/CubeTexturePreviewMaterial.flax | 4 ++-- Content/Editor/DebugMaterials/DDGIDebugProbes.flax | 4 ++-- Content/Editor/DebugMaterials/SingleColor/Decal.flax | 4 ++-- Content/Editor/DebugMaterials/SingleColor/Particle.flax | 4 ++-- Content/Editor/DebugMaterials/SingleColor/Surface.flax | 4 ++-- .../Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax | 4 ++-- Content/Editor/DebugMaterials/SingleColor/Terrain.flax | 4 ++-- Content/Editor/DefaultFontMaterial.flax | 4 ++-- Content/Editor/Gizmo/FoliageBrushMaterial.flax | 4 ++-- Content/Editor/Gizmo/Material.flax | 4 ++-- Content/Editor/Gizmo/MaterialWire.flax | 4 ++-- Content/Editor/Gizmo/SelectionOutlineMaterial.flax | 2 +- Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax | 4 ++-- Content/Editor/Highlight Material.flax | 4 ++-- Content/Editor/Icons/IconsMaterial.flax | 4 ++-- Content/Editor/IesProfilePreviewMaterial.flax | 2 +- Content/Editor/Particles/Particle Material Color.flax | 4 ++-- Content/Editor/Particles/Smoke Material.flax | 4 ++-- Content/Editor/SpriteMaterial.flax | 4 ++-- Content/Editor/Terrain/Circle Brush Material.flax | 4 ++-- Content/Editor/Terrain/Highlight Terrain Material.flax | 4 ++-- Content/Editor/TexturePreviewMaterial.flax | 2 +- Content/Editor/Wires Debug Material.flax | 4 ++-- Content/Engine/DefaultDeformableMaterial.flax | 4 ++-- Content/Engine/DefaultMaterial.flax | 4 ++-- Content/Engine/DefaultTerrainMaterial.flax | 4 ++-- Content/Engine/SingleColorMaterial.flax | 4 ++-- Content/Engine/SkyboxMaterial.flax | 4 ++-- 29 files changed, 55 insertions(+), 55 deletions(-) diff --git a/Content/Editor/Camera/M_Camera.flax b/Content/Editor/Camera/M_Camera.flax index 942c1c206..768ed42d6 100644 --- a/Content/Editor/Camera/M_Camera.flax +++ b/Content/Editor/Camera/M_Camera.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6fb3d1a76a6084ac6b6d9dc314a39de3a2374e4859fa48371898a03774014f4d -size 30375 +oid sha256:ec25eba344fed990157e902029f7b113e4fda7ed5630a6b3b693d5c07351a178 +size 30138 diff --git a/Content/Editor/CubeTexturePreviewMaterial.flax b/Content/Editor/CubeTexturePreviewMaterial.flax index c4a3c4910..fd3d482bf 100644 --- a/Content/Editor/CubeTexturePreviewMaterial.flax +++ b/Content/Editor/CubeTexturePreviewMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:ba08eacf44d782dab98947b0527cedbfc6d856e29082f4462bfead451b91088c -size 31928 +oid sha256:2cf6beb5cefcfd91c758b7940b7ed26f435c5e5144233d88c5daf274e8b05c1e +size 31691 diff --git a/Content/Editor/DebugMaterials/DDGIDebugProbes.flax b/Content/Editor/DebugMaterials/DDGIDebugProbes.flax index 9724ef8e9..fd74958c4 100644 --- a/Content/Editor/DebugMaterials/DDGIDebugProbes.flax +++ b/Content/Editor/DebugMaterials/DDGIDebugProbes.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:06781580ffe1eb1e2719c7ff95d7a5b61f63915322eb0a6819dcacecd36a8234 -size 41698 +oid sha256:2405a01ca57fed4112695e699036aa63a77e5140dadd7de957a353992ada02ca +size 41461 diff --git a/Content/Editor/DebugMaterials/SingleColor/Decal.flax b/Content/Editor/DebugMaterials/SingleColor/Decal.flax index 6da0cdf6f..0c3b3b6c0 100644 --- a/Content/Editor/DebugMaterials/SingleColor/Decal.flax +++ b/Content/Editor/DebugMaterials/SingleColor/Decal.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4b1aab4e1e133bae2c5458a37f57282867e3d0d48031f8e95d1bf2079ee7b8e3 -size 7822 +oid sha256:e47d5133f12b96d0ce9cde651032b9ede2eec0a099d3702d02bf26a31c9ec051 +size 7696 diff --git a/Content/Editor/DebugMaterials/SingleColor/Particle.flax b/Content/Editor/DebugMaterials/SingleColor/Particle.flax index 045dbe719..30db32463 100644 --- a/Content/Editor/DebugMaterials/SingleColor/Particle.flax +++ b/Content/Editor/DebugMaterials/SingleColor/Particle.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:347bd333764b02cff7baacc44dd5674e3b1b10585addc09cf56c770672463b3a -size 31872 +oid sha256:7a509d2985b590d20d892189684d31ffcf71e0306637ddb93948d8a9649168c5 +size 31753 diff --git a/Content/Editor/DebugMaterials/SingleColor/Surface.flax b/Content/Editor/DebugMaterials/SingleColor/Surface.flax index 378c6dc0e..f60f7c4cf 100644 --- a/Content/Editor/DebugMaterials/SingleColor/Surface.flax +++ b/Content/Editor/DebugMaterials/SingleColor/Surface.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2b09a3b31ca32a8c0258cf9e5c155767a3814ee70c7227295a68e2057cd9e5c7 -size 30271 +oid sha256:b091889f827c292b2656aa64af9b9101a1eb465b7c9818e6358b2928d9f69c29 +size 30034 diff --git a/Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax b/Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax index cadafbf0f..0bbf43c36 100644 --- a/Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax +++ b/Content/Editor/DebugMaterials/SingleColor/SurfaceAdditive.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fe53e551ab6e52a96b38357f84f2c476774ac83bb41ccfc6b42002ced3595f69 -size 32156 +oid sha256:8e7af2e0901a62301e6cfbb7df915e04486073dbeee0904adea99774ee9d93d5 +size 31919 diff --git a/Content/Editor/DebugMaterials/SingleColor/Terrain.flax b/Content/Editor/DebugMaterials/SingleColor/Terrain.flax index 3ad14132c..20220b081 100644 --- a/Content/Editor/DebugMaterials/SingleColor/Terrain.flax +++ b/Content/Editor/DebugMaterials/SingleColor/Terrain.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6f4830a241b622db1303f64a74b55701b67e18aa945ed18e6e34c6294ba0401b -size 21364 +oid sha256:07d8e970f92010b4fdb3a058415a758d87d2117bf7668b1fa4471a13fc623177 +size 21238 diff --git a/Content/Editor/DefaultFontMaterial.flax b/Content/Editor/DefaultFontMaterial.flax index 3fbe66858..d93a64e18 100644 --- a/Content/Editor/DefaultFontMaterial.flax +++ b/Content/Editor/DefaultFontMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:d9ecb02780ecef92fec46a63eefcb0a6df3b49092d3cbbd76a1dd85f54e2f2f8 -size 30450 +oid sha256:25f8315d4bfdc65c101a6b8b423b999d058321f158ad4fc98bffe74678b8b2d3 +size 30213 diff --git a/Content/Editor/Gizmo/FoliageBrushMaterial.flax b/Content/Editor/Gizmo/FoliageBrushMaterial.flax index dbee01142..a776b52a1 100644 --- a/Content/Editor/Gizmo/FoliageBrushMaterial.flax +++ b/Content/Editor/Gizmo/FoliageBrushMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:973c78d9fff14fef54b236827e3be453837d1690ff63fcff56ad9095fcbc8212 -size 36500 +oid sha256:fd05cf1d1f5e1f2d7e1546712ac0513f08a58b7aaca081112e56d1cc4ebbb690 +size 36263 diff --git a/Content/Editor/Gizmo/Material.flax b/Content/Editor/Gizmo/Material.flax index 11cfc7c29..66f72fd47 100644 --- a/Content/Editor/Gizmo/Material.flax +++ b/Content/Editor/Gizmo/Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:9e61189aa35d9423ff2b1ef348bafe9dd09a1f493ead1445b213fcf9e9c63003 -size 32694 +oid sha256:a1a0beaec89af72a7622512963b3a431c61fad77d289794e2fde2e256f7b3f37 +size 32457 diff --git a/Content/Editor/Gizmo/MaterialWire.flax b/Content/Editor/Gizmo/MaterialWire.flax index 6123e2eb5..532a49b86 100644 --- a/Content/Editor/Gizmo/MaterialWire.flax +++ b/Content/Editor/Gizmo/MaterialWire.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7ba72a1b4c78e1f236655a945b5ea56be5689f034f2c7149ff587f903f0c3e6e -size 31907 +oid sha256:3938bb1381efc2842f73f514dcb3289f29fda2504c2550a25e807080dc8150b0 +size 31670 diff --git a/Content/Editor/Gizmo/SelectionOutlineMaterial.flax b/Content/Editor/Gizmo/SelectionOutlineMaterial.flax index 2eeb20bdc..20cb250ad 100644 --- a/Content/Editor/Gizmo/SelectionOutlineMaterial.flax +++ b/Content/Editor/Gizmo/SelectionOutlineMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b084fc0204a03379c7fade0b4af1b88e4e92f793c030912ba4ff74d7a2793ab6 +oid sha256:c68d577cc0d761c5ba02992b666f2ceb85c6178a5b2639b14bbcabdc449a1c03 size 16202 diff --git a/Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax b/Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax index d2db1f717..539fa76ad 100644 --- a/Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax +++ b/Content/Editor/Gizmo/VertexColorsPreviewMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4963d6a5379957e9acc105cc8a02ca23dcb3dbdb075fc67795099ab4e7c70460 -size 31384 +oid sha256:145a977ccd4fc5f0ef8dc7411331a414e473c13cc3a7fde8b9fa9cb02f3156a1 +size 31147 diff --git a/Content/Editor/Highlight Material.flax b/Content/Editor/Highlight Material.flax index 3ed98f6a9..78fd05c06 100644 --- a/Content/Editor/Highlight Material.flax +++ b/Content/Editor/Highlight Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:82d8cec265c0d1fd2af41c7a9ad39eef7142605953e6ef99af3ecfc226125202 -size 30506 +oid sha256:53f86e6b1f6d1f9c31845a86a028a67937f79b90b878783601b752b1c82f67e2 +size 30269 diff --git a/Content/Editor/Icons/IconsMaterial.flax b/Content/Editor/Icons/IconsMaterial.flax index 2bcf695ec..9b6e5e1e6 100644 --- a/Content/Editor/Icons/IconsMaterial.flax +++ b/Content/Editor/Icons/IconsMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1ebeda0318c3b795b351b920505961dbbaa86746e31169dd2cf99789168c8134 -size 30434 +oid sha256:4751716e158f8390e4f451e4eb64df71472a4b1f822247995be4417a81169880 +size 30197 diff --git a/Content/Editor/IesProfilePreviewMaterial.flax b/Content/Editor/IesProfilePreviewMaterial.flax index 4c79f17de..097ca7846 100644 --- a/Content/Editor/IesProfilePreviewMaterial.flax +++ b/Content/Editor/IesProfilePreviewMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:631816568de3e512e082d2baa09252b4b0cf3e91cd50d67d2000ebddee447133 +oid sha256:cddc591a3af95c1c49983ee0e220ec39ad93e9af4a113d20cb2d5ded9f3230f4 size 18217 diff --git a/Content/Editor/Particles/Particle Material Color.flax b/Content/Editor/Particles/Particle Material Color.flax index 32617ea9b..2847afa57 100644 --- a/Content/Editor/Particles/Particle Material Color.flax +++ b/Content/Editor/Particles/Particle Material Color.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:fa9333a2439288de8476c75f77f267941a809028af8816ce3007b5d0c311983e -size 30064 +oid sha256:357608bdb965c0bc4391cccb8c2ffacdc7eda4542e3bf09e81f9d899626e06b5 +size 29945 diff --git a/Content/Editor/Particles/Smoke Material.flax b/Content/Editor/Particles/Smoke Material.flax index 32a4a87f7..a3c824681 100644 --- a/Content/Editor/Particles/Smoke Material.flax +++ b/Content/Editor/Particles/Smoke Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7968133ccd667d578ebe1ad318fb331cdd3b34b63edc8311bc27a5535fac2aab -size 37252 +oid sha256:6fa22067784d57637da65339a71a722360a441ecb4c266242e65212dbe2db1be +size 37133 diff --git a/Content/Editor/SpriteMaterial.flax b/Content/Editor/SpriteMaterial.flax index 14ea7e24c..8cfcdb81b 100644 --- a/Content/Editor/SpriteMaterial.flax +++ b/Content/Editor/SpriteMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:93be68ffd8a353a43a7ca13a9d6936106853d20328517843202737e2c68b616a -size 31463 +oid sha256:7dc760c37c70008e1d8e71f392138d54d4a6308df768381864994027474f94e3 +size 31226 diff --git a/Content/Editor/Terrain/Circle Brush Material.flax b/Content/Editor/Terrain/Circle Brush Material.flax index 9c5a6d00e..730130f85 100644 --- a/Content/Editor/Terrain/Circle Brush Material.flax +++ b/Content/Editor/Terrain/Circle Brush Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:4c66e2033cefeb8700e6b7b892d83c9095198b6585dce8be7819d0ce3faadc65 -size 27745 +oid sha256:131dac4676de0b4ac8257cd450b7538307383143d352265b062f6689d5215374 +size 27619 diff --git a/Content/Editor/Terrain/Highlight Terrain Material.flax b/Content/Editor/Terrain/Highlight Terrain Material.flax index 49fd0c889..3ee054ccf 100644 --- a/Content/Editor/Terrain/Highlight Terrain Material.flax +++ b/Content/Editor/Terrain/Highlight Terrain Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2badc7148cdb2c37e848da13c97c53d893f7a78476fca0831a3560e60ca004ad -size 21417 +oid sha256:adf85e5679b8a0a4f78663d0a119e1819641a0460100595654fe31649b798c1d +size 21291 diff --git a/Content/Editor/TexturePreviewMaterial.flax b/Content/Editor/TexturePreviewMaterial.flax index 872c1ffb9..90235d453 100644 --- a/Content/Editor/TexturePreviewMaterial.flax +++ b/Content/Editor/TexturePreviewMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6386b57f2ce05d6ccf6fe48476984e57ad518555ef75ce2f201df585b907ba99 +oid sha256:26ff727713fd57c857f9a21e369f3a91ae3188e95cb9d762cac523d8c663262a size 10413 diff --git a/Content/Editor/Wires Debug Material.flax b/Content/Editor/Wires Debug Material.flax index c6d145425..f58128c37 100644 --- a/Content/Editor/Wires Debug Material.flax +++ b/Content/Editor/Wires Debug Material.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:6e15453bba567485c48b793d95a80aa478b0a4fa8ddc21e9da212543f9b36e68 -size 30506 +oid sha256:f1ab66e68b7d4e237232e4abac2be1763b4149109a619901b00862a3a86639e5 +size 30269 diff --git a/Content/Engine/DefaultDeformableMaterial.flax b/Content/Engine/DefaultDeformableMaterial.flax index ccb86f7e5..1b90f7fc3 100644 --- a/Content/Engine/DefaultDeformableMaterial.flax +++ b/Content/Engine/DefaultDeformableMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:160dc0e3664b01b2adf088a59956924d338225a9ab8b655f995e769b04083e4f -size 19066 +oid sha256:c58b87b135659215bbea0094368511c1b925fc82df35d2e6403ccbbcd34e9322 +size 18914 diff --git a/Content/Engine/DefaultMaterial.flax b/Content/Engine/DefaultMaterial.flax index 60b879d82..8c54ba2c8 100644 --- a/Content/Engine/DefaultMaterial.flax +++ b/Content/Engine/DefaultMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2c41c04042b019a88517b9e936cf47953fca5f7e6ea8ce6c4786226cd69ee49c -size 32302 +oid sha256:2fb9906c87a1e11261ca8a12fde8a5e808827599d3f423ebfd2437bd5c26d375 +size 32065 diff --git a/Content/Engine/DefaultTerrainMaterial.flax b/Content/Engine/DefaultTerrainMaterial.flax index 5fdee2807..8787991a0 100644 --- a/Content/Engine/DefaultTerrainMaterial.flax +++ b/Content/Engine/DefaultTerrainMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:534d192941f05e3a47a70da8d303adfc899b78052eac113a75444eba2d12a632 -size 23507 +oid sha256:e7676a6523be037dbfa10e2957c2175f650978e7850af443f4c859f687f5f89f +size 23381 diff --git a/Content/Engine/SingleColorMaterial.flax b/Content/Engine/SingleColorMaterial.flax index 82f5963a0..ede999b2c 100644 --- a/Content/Engine/SingleColorMaterial.flax +++ b/Content/Engine/SingleColorMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b902ab6d3aebdab9f644a7445f426fe4522f1ef82a3d967e9ee2ca2662e86f35 -size 30472 +oid sha256:26fe92bc72d726fde4811aee6056f3b8ed0797a433d5a76b07c24dd20bc42199 +size 30235 diff --git a/Content/Engine/SkyboxMaterial.flax b/Content/Engine/SkyboxMaterial.flax index b8a7be3ea..97875e653 100644 --- a/Content/Engine/SkyboxMaterial.flax +++ b/Content/Engine/SkyboxMaterial.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8442a3c6551ad910c6662509822ebe9f6dd7e3225894414df38799faa90b5163 -size 31670 +oid sha256:46f557106d4b4b7768cdeb0db8da1d1ae40637495afef2fe71b3591d82063f55 +size 31433 From 7cfde78198d9b30ac3cc6eb8fa148f4b379e98b4 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 27 Nov 2022 21:05:20 +0100 Subject: [PATCH 27/83] Code style fix --- Source/Editor/Windows/ContentWindow.cs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Source/Editor/Windows/ContentWindow.cs b/Source/Editor/Windows/ContentWindow.cs index 3cac8c434..22808a1f1 100644 --- a/Source/Editor/Windows/ContentWindow.cs +++ b/Source/Editor/Windows/ContentWindow.cs @@ -131,7 +131,7 @@ namespace FlaxEditor.Windows ScrollBars = ScrollBars.Both, Parent = _split.Panel1, }; - + // Content structure tree _tree = new Tree(false) { @@ -179,7 +179,7 @@ namespace FlaxEditor.Windows ScrollBars = ScrollBars.Vertical, Parent = _split.Panel2, }; - + // Content View _view = new ContentView { @@ -899,8 +899,10 @@ namespace FlaxEditor.Windows public override bool OnMouseDown(Float2 location, MouseButton button) { // Navigate through directories using the side mouse buttons - if (button == MouseButton.Extended1) NavigateBackward(); - else if (button == MouseButton.Extended2) NavigateForward(); + if (button == MouseButton.Extended1) + NavigateBackward(); + else if (button == MouseButton.Extended2) + NavigateForward(); return base.OnMouseDown(location, button); } From 4a9a01a89e5161f8adbd1336559809285dc9b068 Mon Sep 17 00:00:00 2001 From: Chandler Cox Date: Sun, 27 Nov 2022 14:23:01 -0600 Subject: [PATCH 28/83] Moved check and ops to also fix issue #683 --- Source/Editor/GUI/Docking/DockHintWindow.cs | 10 ++++++++++ Source/Editor/GUI/Docking/FloatWindowDockPanel.cs | 10 ---------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/Editor/GUI/Docking/DockHintWindow.cs b/Source/Editor/GUI/Docking/DockHintWindow.cs index 50be41766..0f7780ae9 100644 --- a/Source/Editor/GUI/Docking/DockHintWindow.cs +++ b/Source/Editor/GUI/Docking/DockHintWindow.cs @@ -37,6 +37,16 @@ namespace FlaxEditor.GUI.Docking // Focus window window.Focus(); + // Check if window is maximized and restore window. + if (window.IsMaximized) + { + // Restore window and set position to mouse. + var mousePos = window.MousePosition; + var previousSize = window.Size; + window.Restore(); + window.Position = FlaxEngine.Input.MouseScreenPosition - mousePos * window.Size / previousSize; + } + // Calculate dragging offset and move window to the destination position var mouseScreenPosition = FlaxEngine.Input.MouseScreenPosition; diff --git a/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs b/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs index f892c8237..07585d4cd 100644 --- a/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs +++ b/Source/Editor/GUI/Docking/FloatWindowDockPanel.cs @@ -51,16 +51,6 @@ namespace FlaxEditor.GUI.Docking if (_window == null) return; - // Check if window is maximized - if (_window.IsMaximized) - { - // Restore window and set position to mouse. - var mousePos = _window.MousePosition; - var previousSize = _window.Size; - _window.Restore(); - _window.Window.Position = FlaxEngine.Input.MouseScreenPosition - mousePos * _window.Size / previousSize; - } - // Create docking hint window DockHintWindow.Create(this); } From db6aab1cf6142be4bcfc872a99f381af9986508a Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 28 Nov 2022 20:34:26 +0100 Subject: [PATCH 29/83] Fix regression in memory allocators --- Source/Engine/Core/Memory/Allocation.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Core/Memory/Allocation.h b/Source/Engine/Core/Memory/Allocation.h index 9ae127805..80da810a8 100644 --- a/Source/Engine/Core/Memory/Allocation.h +++ b/Source/Engine/Core/Memory/Allocation.h @@ -105,7 +105,9 @@ public: FORCE_INLINE int32 CalculateCapacityGrow(int32 capacity, int32 minCapacity) const { - if (capacity == 0) + if (capacity < minCapacity) + capacity = minCapacity; + if (capacity < 8) { capacity = 8; } @@ -120,8 +122,6 @@ public: capacity |= capacity >> 16; capacity = (capacity + 1) * 2; } - if (capacity < minCapacity) - capacity = minCapacity; return capacity; } From 69ad8bc67202a642fed53f47149977155e5ed96c Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 28 Nov 2022 20:34:50 +0100 Subject: [PATCH 30/83] Fix tests hanging if scripting compilation fails (eg. build tool issue) --- Source/Engine/Tests/TestMain.cpp | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/Source/Engine/Tests/TestMain.cpp b/Source/Engine/Tests/TestMain.cpp index 6dd3c8873..68998e3e0 100644 --- a/Source/Engine/Tests/TestMain.cpp +++ b/Source/Engine/Tests/TestMain.cpp @@ -26,6 +26,13 @@ TestsRunnerService TestsRunnerServiceInstance; void TestsRunnerService::Update() { + // End if failed to perform a startup + if (ScriptsBuilder::LastCompilationFailed()) + { + Engine::RequestExit(-1); + return; + } + // Wait for Editor to be ready for running tests (eg. scripting loaded) if (!ScriptsBuilder::IsReady() || !Scripting::IsEveryAssemblyLoaded() || From 3f3697fbfa706144364b1c4e197ba843f00f55ed Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 28 Nov 2022 23:35:27 +0100 Subject: [PATCH 31/83] Code style cleanup #837 --- Source/Engine/Tools/AudioTool/WaveDecoder.cpp | 4 +- .../Tools/ModelTool/ModelTool.OpenFBX.cpp | 52 +++++++++++-------- Source/Engine/Tools/ModelTool/ModelTool.cpp | 16 ++---- .../TextureTool/TextureTool.DirectXTex.cpp | 16 +++--- 4 files changed, 41 insertions(+), 47 deletions(-) diff --git a/Source/Engine/Tools/AudioTool/WaveDecoder.cpp b/Source/Engine/Tools/AudioTool/WaveDecoder.cpp index 0336e965d..d93891615 100644 --- a/Source/Engine/Tools/AudioTool/WaveDecoder.cpp +++ b/Source/Engine/Tools/AudioTool/WaveDecoder.cpp @@ -101,7 +101,7 @@ bool WaveDecoder::ParseHeader(AudioDataInfo& info) } } - // PE: Support wav with "extra format bytes", just ignore not needed. + // Support wav with "extra format bytes", just ignore not needed. while (totalread < subChunkSize) { uint8 singlebyte; @@ -167,7 +167,7 @@ void WaveDecoder::Read(byte* samples, uint32 numSamples) samples[i] = *((uint8*)&val); } } - // IEEE float need to be converted into signed PCM data + // IEEE float need to be converted into signed PCM data else if (mFormat == WAVE_FORMAT_IEEE_FLOAT) { AudioTool::ConvertFromFloat((const float*)samples, (int32*)samples, numSamples); diff --git a/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp b/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp index cea29f7fb..493068892 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.OpenFBX.cpp @@ -229,48 +229,54 @@ struct OpenFbxImporterData ImportMaterialTexture(result, mat, ofbx::Texture::EMISSIVE, material.Emissive.TextureIndex, TextureEntry::TypeHint::ColorRGB); ImportMaterialTexture(result, mat, ofbx::Texture::NORMAL, material.Normals.TextureIndex, TextureEntry::TypeHint::Normals); - // PE: FBX dont always store normal maps inside the object. + // FBX don't always store normal maps inside the object if (material.Diffuse.TextureIndex != -1 && material.Normals.TextureIndex == -1) { - // PE: If missing , try to locate a normal map in the same path as the diffuse. + // If missing, try to locate a normal map in the same path as the diffuse const String srcFolder = String(StringUtils::GetDirectoryName(result.Textures[material.Diffuse.TextureIndex].FilePath)); const String srcName = StringUtils::GetFileNameWithoutExtension(result.Textures[material.Diffuse.TextureIndex].FilePath); String srcSearch; - const int32 num = srcName.FindLast('_'); String srcSmallName = srcName; if (num != -1) - { srcSmallName = srcName.Substring(0, num); - } - bool bNormal = false; - for (int iext = 0; iext < 6; iext++) + bool isNormal = false; + for (int32 iExt = 0; iExt < 6; iExt++) { - String sext = TEXT(".dds"); - if (iext == 1) sext = TEXT(".png"); - if (iext == 2) sext = TEXT(".jpg"); - if (iext == 3) sext = TEXT(".jpeg"); - if (iext == 4) sext = TEXT(".tif"); - if (iext == 5) sext = TEXT(".tga"); - for (int i = 0; i < 5; i++) + String sExit = TEXT(".dds"); + if (iExt == 1) + sExit = TEXT(".png"); + else if (iExt == 2) + sExit = TEXT(".jpg"); + else if (iExt == 3) + sExit = TEXT(".jpeg"); + else if (iExt == 4) + sExit = TEXT(".tif"); + else if (iExt == 5) + sExit = TEXT(".tga"); + for (int32 i = 0; i < 5; i++) { - String sfind = TEXT("_normal" + sext); - if (i == 1) sfind = TEXT("_n" + sext); - if (i == 2) sfind = TEXT("_nm" + sext); - if (i == 3) sfind = TEXT("_nmp" + sext); - if (i == 4) sfind = TEXT("_nor" + sext); - srcSearch = srcFolder + TEXT("/") + srcSmallName + sfind; + String sFind = TEXT("_normal" + sExit); + if (i == 1) + sFind = TEXT("_n" + sExit); + else if (i == 2) + sFind = TEXT("_nm" + sExit); + else if (i == 3) + sFind = TEXT("_nmp" + sExit); + else if (i == 4) + sFind = TEXT("_nor" + sExit); + srcSearch = srcFolder + TEXT("/") + srcSmallName + sFind; if (FileSystem::FileExists(srcSearch)) { - bNormal = true; + isNormal = true; break; } } - if (bNormal) + if (isNormal) break; } - if (bNormal) + if (isNormal) { auto& texture = result.Textures.AddOne(); texture.FilePath = srcSearch; diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index ae8e8fe7b..bdd87d510 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -1275,25 +1275,17 @@ bool ModelTool::ImportModel(const String& path, ModelData& meshData, Options& op // Trim the animation keyframes range if need to if (options.Duration == AnimationDuration::Custom) { - // PE: This is wrong, FramesRange is Frame Index start end, not the frame time. - // PE: To extract Frame Index you has to enter Frame*FramesPerSecond or it will not work. - // PE: This also makes another problem as the "length" get wrong and your not able to loop animatons. - // const float start = (float)(options.FramesRange.X / data.Animation.FramesPerSecond); - // const float end = (float)(options.FramesRange.Y / data.Animation.FramesPerSecond); - // data.Animation.Duration = (end - start); // *data.Animation.FramesPerSecond; - - // PE: Custom animation import , frame index start and end, is now correct and the real index. - const float start = (float)(options.FramesRange.X); - const float end = (float)(options.FramesRange.Y); + // Custom animation import, frame index start and end + const float start = options.FramesRange.X; + const float end = options.FramesRange.Y; for (int32 i = 0; i < data.Animation.Channels.Count(); i++) { auto& anim = data.Animation.Channels[i]; - anim.Position.Trim(start, end); anim.Rotation.Trim(start, end); anim.Scale.Trim(start, end); } - data.Animation.Duration = (end - start); + data.Animation.Duration = end - start; } // Change the sampling rate if need to diff --git a/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp b/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp index 540c8e186..d25523406 100644 --- a/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp +++ b/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp @@ -624,16 +624,12 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path } bool bKeepAsIs = false; - if (!options.FlipY &&options.Compress && type == ImageType::DDS && mipLevels == sourceMipLevels && DirectX::IsCompressed(sourceDxgiFormat)) + if (!options.FlipY && options.Compress && type == ImageType::DDS && mipLevels == sourceMipLevels && DirectX::IsCompressed(sourceDxgiFormat) && !DirectX::IsSRGB(sourceDxgiFormat)) { - if (!DirectX::IsSRGB(sourceDxgiFormat)) - { - // PE: Keep image in the current compressed format (artist choice) so we dont have to run the slow mipmap generation. - // PE: Also converting a BC1 normal map to BC5 will not improve it but just use double gpu mem. - bKeepAsIs = true; - targetDxgiFormat = sourceDxgiFormat; - targetFormat = ToPixelFormat(currentImage->GetMetadata().format); - } + // Keep image in the current compressed format (artist choice) so we don't have to run the slow mipmap generation + bKeepAsIs = true; + targetDxgiFormat = sourceDxgiFormat; + targetFormat = ToPixelFormat(currentImage->GetMetadata().format); } // Decompress if texture is compressed (next steps need decompressed input data, for eg. mip maps generation or format changing) @@ -897,7 +893,7 @@ bool TextureTool::ConvertDirectXTex(TextureData& dst, const TextureData& src, co return true; } } - // Check if convert data + // Check if convert data else if (inImage->GetMetadata().format != dstFormatDxgi) { result = DirectX::Convert(inImage->GetImages(), inImage->GetImageCount(), inImage->GetMetadata(), dstFormatDxgi, DirectX::TEX_FILTER_DEFAULT, DirectX::TEX_THRESHOLD_DEFAULT, dstImage); From 9e1692e3e0f67d49bafa27b6416f7a5fac8e11bb Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Tue, 29 Nov 2022 08:41:52 +0100 Subject: [PATCH 32/83] Code style cleanup #837 --- .../TextureTool/TextureTool.DirectXTex.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp b/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp index d25523406..4b5fb4897 100644 --- a/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp +++ b/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp @@ -623,17 +623,17 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path sliceData.Mips.Resize(mipLevels); } - bool bKeepAsIs = false; + bool keepAsIs = false; if (!options.FlipY && options.Compress && type == ImageType::DDS && mipLevels == sourceMipLevels && DirectX::IsCompressed(sourceDxgiFormat) && !DirectX::IsSRGB(sourceDxgiFormat)) { // Keep image in the current compressed format (artist choice) so we don't have to run the slow mipmap generation - bKeepAsIs = true; + keepAsIs = true; targetDxgiFormat = sourceDxgiFormat; targetFormat = ToPixelFormat(currentImage->GetMetadata().format); } // Decompress if texture is compressed (next steps need decompressed input data, for eg. mip maps generation or format changing) - if (!bKeepAsIs && DirectX::IsCompressed(sourceDxgiFormat)) + if (!keepAsIs && DirectX::IsCompressed(sourceDxgiFormat)) { auto& tmpImg = GET_TMP_IMG(); @@ -649,7 +649,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path } // Fix sRGB problem - if (!bKeepAsIs && DirectX::IsSRGB(sourceDxgiFormat)) + if (!keepAsIs && DirectX::IsSRGB(sourceDxgiFormat)) { sourceDxgiFormat = ToDxgiFormat(PixelFormatExtensions::ToNonsRGB(ToPixelFormat(sourceDxgiFormat))); ((DirectX::TexMetadata&)currentImage->GetMetadata()).format = sourceDxgiFormat; @@ -658,7 +658,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path } // Remove alpha if source texture has it but output should not, valid for compressed output only (DirectX seams to use alpha to pre-multiply colors because BC1 format has no place for alpha) - if (!bKeepAsIs && DirectX::HasAlpha(sourceDxgiFormat) && options.Type == TextureFormatType::ColorRGB && options.Compress) + if (!keepAsIs && DirectX::HasAlpha(sourceDxgiFormat) && options.Type == TextureFormatType::ColorRGB && options.Compress) { auto& tmpImg = GET_TMP_IMG(); @@ -683,7 +683,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path } // Check flip/rotate source image - if (!bKeepAsIs && options.FlipY) + if (!keepAsIs && options.FlipY) { auto& tmpImg = GET_TMP_IMG(); @@ -700,7 +700,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path } // Generate mip maps chain - if (!bKeepAsIs && useMipLevels && options.GenerateMipMaps) + if (!keepAsIs && useMipLevels && options.GenerateMipMaps) { auto& tmpImg = GET_TMP_IMG(); @@ -723,7 +723,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path } // Preserve mipmap alpha coverage (if requested) - if (!bKeepAsIs && DirectX::HasAlpha(currentImage->GetMetadata().format) && options.PreserveAlphaCoverage && useMipLevels) + if (!keepAsIs && DirectX::HasAlpha(currentImage->GetMetadata().format) && options.PreserveAlphaCoverage && useMipLevels) { auto& tmpImg = GET_TMP_IMG(); @@ -755,7 +755,7 @@ bool TextureTool::ImportTextureDirectXTex(ImageType type, const StringView& path ASSERT((int32)currentImage->GetMetadata().mipLevels >= mipLevels); // Compress mip maps or convert image - if (!bKeepAsIs && targetDxgiFormat != sourceDxgiFormat) + if (!keepAsIs && targetDxgiFormat != sourceDxgiFormat) { auto& tmpImg = GET_TMP_IMG(); From ee84d53cdca42b811822f0f39ef660313cedb68c Mon Sep 17 00:00:00 2001 From: Preben Eriksen Date: Tue, 29 Nov 2022 11:09:34 +0100 Subject: [PATCH 33/83] PE: Support normal generation when using assimp importer. --- .../Tools/ModelTool/ModelTool.Assimp.cpp | 33 ++++++++++++------- 1 file changed, 21 insertions(+), 12 deletions(-) diff --git a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp index 6d06961dd..7f3cfbba0 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.Assimp.cpp @@ -248,18 +248,6 @@ bool ProcessMesh(ImportedModelData& result, AssimpImporterData& data, const aiMe } } - // Normals - if (aMesh->mNormals) - { - mesh.Normals.Set((const Float3*)aMesh->mNormals, aMesh->mNumVertices); - } - - // Tangents - if (aMesh->mTangents) - { - mesh.Tangents.Set((const Float3*)aMesh->mTangents, aMesh->mNumVertices); - } - // Indices const int32 indicesCount = aMesh->mNumFaces * 3; mesh.Indices.Resize(indicesCount, false); @@ -277,6 +265,27 @@ bool ProcessMesh(ImportedModelData& result, AssimpImporterData& data, const aiMe mesh.Indices[i++] = face->mIndices[2]; } + // Normals + if (data.Options.CalculateNormals || !aMesh->mNormals) + { + // Support generation of normals when using assimp. + if (mesh.GenerateNormals(data.Options.SmoothingNormalsAngle)) + { + errorMsg = TEXT("Failed to generate normals."); + return true; + } + } + else if (aMesh->mNormals) + { + mesh.Normals.Set((const Float3*)aMesh->mNormals, aMesh->mNumVertices); + } + + // Tangents + if (aMesh->mTangents) + { + mesh.Tangents.Set((const Float3*)aMesh->mTangents, aMesh->mNumVertices); + } + // Lightmap UVs if (data.Options.LightmapUVsSource == ModelLightmapUVsSource::Disable) { From 96742404fd32943479ce3c68dce80a2c0b1d47e2 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Tue, 29 Nov 2022 13:45:01 +0100 Subject: [PATCH 34/83] Various improvements for network objects despawning --- .../Engine/Networking/NetworkReplicator.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp index 3ca095f04..7a32f767d 100644 --- a/Source/Engine/Networking/NetworkReplicator.cpp +++ b/Source/Engine/Networking/NetworkReplicator.cpp @@ -165,6 +165,7 @@ namespace #if !COMPILE_WITHOUT_CSHARP Dictionary CSharpCachedNames; #endif + Array DespawnedObjects; } class NetworkReplicationService : public EngineService @@ -232,9 +233,12 @@ NetworkReplicatedObject* ResolveObject(Guid objectId, Guid parentId, char object obj->GetTypeHandle() == objectType && !IdsRemappingTable.ContainsValue(item.ObjectId)) { - // Boost future lookups by using indirection - NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Remap object ID={} into object {}:{}", objectId, item.ToString(), obj->GetType().ToString()); - IdsRemappingTable.Add(objectId, item.ObjectId); + if (NetworkManager::IsClient()) + { + // Boost future lookups by using indirection + NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Remap object ID={} into object {}:{}", objectId, item.ToString(), obj->GetType().ToString()); + IdsRemappingTable.Add(objectId, item.ObjectId); + } return &item; } @@ -587,8 +591,11 @@ void NetworkReplicator::DespawnObject(ScriptingObject* obj) } // Delete object locally + NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Despawn object {}", item.ObjectId); + DespawnedObjects.Add(item.ObjectId); if (item.AsNetworkObject) item.AsNetworkObject->OnNetworkDespawn(); + Objects.Remove(it); DeleteNetworkObject(obj); } @@ -745,6 +752,7 @@ void NetworkInternal::NetworkReplicatorClientDisconnected(NetworkClient* client) despawn.Targets = MoveTemp(item.TargetClientIds); // Delete object locally + NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Despawn object {}", item.ObjectId); if (item.AsNetworkObject) item.AsNetworkObject->OnNetworkDespawn(); DeleteNetworkObject(obj); @@ -779,6 +787,7 @@ void NetworkInternal::NetworkReplicatorClear() SAFE_DELETE(CachedReadStream); NewClients.Clear(); CachedTargets.Clear(); + DespawnedObjects.Clear(); } void NetworkInternal::NetworkReplicatorPreUpdate() @@ -1025,6 +1034,8 @@ void NetworkInternal::OnNetworkMessageObjectReplicate(NetworkEvent& event, Netwo NetworkMessageObjectReplicate msgData; event.Message.ReadStructure(msgData); ScopeLock lock(ObjectsLock); + if (DespawnedObjects.Contains(msgData.ObjectId)) + return; // Skip replicating not-existing objects NetworkReplicatedObject* e = ResolveObject(msgData.ObjectId, msgData.ParentId, msgData.ObjectTypeName); if (e) { @@ -1227,6 +1238,8 @@ void NetworkInternal::OnNetworkMessageObjectDespawn(NetworkEvent& event, Network return; // Remove object + NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Despawn object {}", msgData.ObjectId); + DespawnedObjects.Add(msgData.ObjectId); if (item.AsNetworkObject) item.AsNetworkObject->OnNetworkDespawn(); Objects.Remove(obj); From a819d657dba69011b047c6496886cd4137cf8825 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 30 Nov 2022 12:30:30 +0100 Subject: [PATCH 35/83] Refactor network object spawnign to batch all subobjects with a single spawn message to reduce invalid objects linkage on different clients --- Source/Engine/Networking/NetworkMessage.h | 17 +- .../Engine/Networking/NetworkReplicator.cpp | 344 ++++++++++++------ 2 files changed, 252 insertions(+), 109 deletions(-) diff --git a/Source/Engine/Networking/NetworkMessage.h b/Source/Engine/Networking/NetworkMessage.h index aa610f058..4d0bc4330 100644 --- a/Source/Engine/Networking/NetworkMessage.h +++ b/Source/Engine/Networking/NetworkMessage.h @@ -83,13 +83,26 @@ public: /// Should be of the same length as length or longer. /// /// The minimal amount of bytes that the buffer contains. - FORCE_INLINE void ReadBytes(uint8* bytes, const int numBytes) + FORCE_INLINE void ReadBytes(uint8* bytes, const int32 numBytes) { ASSERT(Position + numBytes < BufferSize); Platform::MemoryCopy(bytes, Buffer + Position, numBytes); Position += numBytes; } + /// + /// Skips bytes from the message. + /// + /// Amount of bytes to skip. + /// Pointer to skipped data beginning. + FORCE_INLINE void* SkipBytes(const int32 numBytes) + { + ASSERT(Position + numBytes < BufferSize); + byte* result = Buffer + Position; + Position += numBytes; + return result; + } + template FORCE_INLINE void WriteStructure(const T& data) { @@ -225,7 +238,7 @@ public: /// FORCE_INLINE Guid ReadGuid() { - Guid value = Guid(); + Guid value; ReadBytes((uint8*)&value, sizeof(Guid)); return value; } diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp index 7a32f767d..f08f13da1 100644 --- a/Source/Engine/Networking/NetworkReplicator.cpp +++ b/Source/Engine/Networking/NetworkReplicator.cpp @@ -15,6 +15,7 @@ #include "Engine/Core/Log.h" #include "Engine/Core/Collections/HashSet.h" #include "Engine/Core/Collections/Dictionary.h" +#include "Engine/Core/Collections/ChunkedArray.h" #include "Engine/Core/Types/DataContainer.h" #include "Engine/Platform/CriticalSection.h" #include "Engine/Engine/EngineService.h" @@ -51,11 +52,16 @@ PACK_STRUCT(struct NetworkMessageObjectReplicate PACK_STRUCT(struct NetworkMessageObjectSpawn { NetworkMessageIDs ID = NetworkMessageIDs::ObjectSpawn; + uint32 OwnerClientId; + Guid PrefabId; + uint16 ItemsCount; + }); + +PACK_STRUCT(struct NetworkMessageObjectSpawnItem + { Guid ObjectId; Guid ParentId; - Guid PrefabId; Guid PrefabObjectID; - uint32 OwnerClientId; char ObjectTypeName[128]; // TODO: introduce networked-name to synchronize unique names as ushort (less data over network) }); @@ -135,6 +141,11 @@ struct SpawnItem NetworkObjectRole Role; }; +struct SpawnGroup +{ + Array> Items; +}; + struct DespawnItem { Guid Id; @@ -309,35 +320,54 @@ FORCE_INLINE void GetNetworkName(char buffer[128], const StringAnsiView& name) buffer[name.Length()] = 0; } -void SendObjectSpawnMessage(const NetworkReplicatedObject& item, ScriptingObject* obj) +void SendObjectSpawnMessage(const SpawnGroup& group, const Array& clients) { - NetworkMessageObjectSpawn msgData; - msgData.ObjectId = item.ObjectId; - msgData.ParentId = item.ParentId; const bool isClient = NetworkManager::IsClient(); - if (isClient) - { - // Remap local client object ids into server ids - IdsRemappingTable.KeyOf(msgData.ObjectId, &msgData.ObjectId); - IdsRemappingTable.KeyOf(msgData.ParentId, &msgData.ParentId); - } - msgData.PrefabId = Guid::Empty; - msgData.PrefabObjectID = Guid::Empty; - auto* objScene = ScriptingObject::Cast(obj); - if (objScene && objScene->HasPrefabLink()) - { - msgData.PrefabId = objScene->GetPrefabID(); - msgData.PrefabObjectID = objScene->GetPrefabObjectID(); - } - msgData.OwnerClientId = item.OwnerClientId; - GetNetworkName(msgData.ObjectTypeName, obj->GetType().Fullname); auto* peer = NetworkManager::Peer; NetworkMessage msg = peer->BeginSendMessage(); + NetworkMessageObjectSpawn msgData; + msgData.ItemsCount = group.Items.Count(); + { + // The first object is a root of the group (eg. prefab instance root actor) + SpawnItem* e = group.Items[0]; + ScriptingObject* obj = e->Object.Get(); + msgData.OwnerClientId = e->OwnerClientId; + auto* objScene = ScriptingObject::Cast(obj); + msgData.PrefabId = objScene && objScene->HasPrefabLink() ? objScene->GetPrefabID() : Guid::Empty; + + // Setup clients that should receive this spawn message + auto it = Objects.Find(obj->GetID()); + auto& item = it->Item; + BuildCachedTargets(clients, item.TargetClientIds); + } msg.WriteStructure(msgData); + for (SpawnItem* e : group.Items) + { + ScriptingObject* obj = e->Object.Get(); + auto it = Objects.Find(obj->GetID()); + auto& item = it->Item; + + // Add object into spawn message + NetworkMessageObjectSpawnItem msgDataItem; + msgDataItem.ObjectId = item.ObjectId; + msgDataItem.ParentId = item.ParentId; + if (isClient) + { + // Remap local client object ids into server ids + IdsRemappingTable.KeyOf(msgDataItem.ObjectId, &msgDataItem.ObjectId); + IdsRemappingTable.KeyOf(msgDataItem.ParentId, &msgDataItem.ParentId); + } + msgDataItem.PrefabObjectID = Guid::Empty; + auto* objScene = ScriptingObject::Cast(obj); + if (objScene && objScene->HasPrefabLink()) + msgDataItem.PrefabObjectID = objScene->GetPrefabObjectID(); + GetNetworkName(msgDataItem.ObjectTypeName, obj->GetType().Fullname); + msg.WriteStructure(msgDataItem); + } if (isClient) - peer->EndSendMessage(NetworkChannelType::ReliableOrdered, msg); + peer->EndSendMessage(NetworkChannelType::Reliable, msg); else - peer->EndSendMessage(NetworkChannelType::ReliableOrdered, msg, CachedTargets); + peer->EndSendMessage(NetworkChannelType::Reliable, msg, CachedTargets); } void SendObjectRoleMessage(const NetworkReplicatedObject& item, const NetworkClient* excludedClient = nullptr) @@ -394,6 +424,44 @@ SceneObject* FindPrefabObject(Actor* a, const Guid& prefabObjectId) return result; } +void SetupObjectSpawnGroupItem(ScriptingObject* obj, Array>& spawnGroups, SpawnItem& spawnItem) +{ + // Check if can fit this object into any of the existing groups (eg. script which can be spawned with parent actor) + SpawnGroup* group = nullptr; + for (auto& g : spawnGroups) + { + ScriptingObject* groupRoot = g.Items[0]->Object.Get(); + if (IsParentOf(obj, groupRoot)) + { + // Reuse existing group (append) + g.Items.Add(&spawnItem); + group = &g; + break; + } + } + if (group) + return; + + // Check if can override any of the existing groups (eg. actor which should be spawned before scripts) + for (auto& g : spawnGroups) + { + ScriptingObject* groupRoot = g.Items[0]->Object.Get(); + if (IsParentOf(groupRoot, obj)) + { + // Reuse existing group (as a root) + g.Items.Insert(0, &spawnItem); + group = &g; + break; + } + } + if (group) + return; + + // Create new group + group = &spawnGroups.AddOne(); + group->Items.Add(&spawnItem); +} + #if !COMPILE_WITHOUT_CSHARP #include "Engine/Scripting/ManagedCLR/MUtils.h" @@ -814,14 +882,29 @@ void NetworkInternal::NetworkReplicatorUpdate() // Sync any previously spawned objects with late-joining clients PROFILE_CPU_NAMED("NewClients"); // TODO: try iterative loop over several frames to reduce both server and client perf-spikes in case of large amount of spawned objects + ChunkedArray spawnItems; + Array> spawnGroups; for (auto it = Objects.Begin(); it.IsNotEnd(); ++it) { auto& item = it->Item; ScriptingObject* obj = item.Object.Get(); if (!obj || !item.Spawned) continue; - BuildCachedTargets(NewClients, item.TargetClientIds); - SendObjectSpawnMessage(item, obj); + + // Setup spawn item for this object + auto& spawnItem = spawnItems.AddOne(); + spawnItem.Object = obj; + spawnItem.Targets.Link(item.TargetClientIds); + spawnItem.OwnerClientId = item.OwnerClientId; + spawnItem.Role = item.Role; + + SetupObjectSpawnGroupItem(obj, spawnGroups, spawnItem); + } + + // Groups of objects to spawn + for (SpawnGroup& g : spawnGroups) + { + SendObjectSpawnMessage(g, NewClients); } NewClients.Clear(); } @@ -865,9 +948,11 @@ void NetworkInternal::NetworkReplicatorUpdate() if (SpawnQueue.Count() != 0) { PROFILE_CPU_NAMED("SpawnQueue"); + + // Propagate hierarchical ownership from spawned parent to spawned child objects (eg. spawned script and spawned actor with set hierarchical ownership on actor which should affect script too) + // TODO: maybe we can propagate ownership within spawn groups only? for (SpawnItem& e : SpawnQueue) { - // Propagate hierarchical ownership from spawned parent to spawned child objects (eg. spawned script and spawned actor with set hierarchical ownership on actor which should affect script too) if (e.HasOwnership && e.HierarchicalOwnership) { for (auto& q : SpawnQueue) @@ -881,6 +966,10 @@ void NetworkInternal::NetworkReplicatorUpdate() } } } + + // Batch spawned objects into groups (eg. player actor with scripts and child actors merged as a single spawn message) + // That's because NetworkReplicator::SpawnObject can be called in separate for different actors/scripts of a single prefab instance but we want to spawn it at once over the network + Array> spawnGroups; for (SpawnItem& e : SpawnQueue) { ScriptingObject* obj = e.Object.Get(); @@ -913,11 +1002,16 @@ void NetworkInternal::NetworkReplicatorUpdate() MISSING_CODE("Sending TargetClientIds over to server for partial object replication."); item.TargetClientIds = MoveTemp(e.Targets); } - - NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Spawn object ID={}", item.ToString()); - BuildCachedTargets(NetworkManager::Clients, item.TargetClientIds); - SendObjectSpawnMessage(item, obj); item.Spawned = true; + NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Spawn object ID={}", item.ToString()); + + SetupObjectSpawnGroupItem(obj, spawnGroups, e); + } + + // Spawn groups of objects + for (SpawnGroup& g : spawnGroups) + { + SendObjectSpawnMessage(g, NetworkManager::Clients); } SpawnQueue.Clear(); } @@ -1085,102 +1179,135 @@ void NetworkInternal::OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkCl { NetworkMessageObjectSpawn msgData; event.Message.ReadStructure(msgData); + auto* msgDataItems = (NetworkMessageObjectSpawnItem*)event.Message.SkipBytes(msgData.ItemsCount * sizeof(NetworkMessageObjectSpawnItem)); + if (msgData.ItemsCount == 0) + return; ScopeLock lock(ObjectsLock); - NetworkReplicatedObject* e = ResolveObject(msgData.ObjectId, msgData.ParentId, msgData.ObjectTypeName); - if (e) + + // Check if that object has been already spawned + auto& rootItem = msgDataItems[0]; + NetworkReplicatedObject* root = ResolveObject(rootItem.ObjectId, rootItem.ParentId, rootItem.ObjectTypeName); + if (root) { - auto& item = *e; - item.Spawned = true; - if (NetworkManager::IsClient()) + // Object already exists locally so just synchronize the ownership (and mark as spawned) + for (int32 i = 0; i < msgData.ItemsCount; i++) { - // Server always knows the best so update ownership of the existing object - item.OwnerClientId = msgData.OwnerClientId; - if (item.Role == NetworkObjectRole::OwnedAuthoritative) - item.Role = NetworkObjectRole::Replicated; - } - else if (item.OwnerClientId != msgData.OwnerClientId) - { - // Other client spawned object with a different owner - // TODO: send reply message to inform about proper object ownership that client - } - } - else - { - // Recreate object locally - ScriptingObject* obj = nullptr; - const NetworkReplicatedObject* parent = ResolveObject(msgData.ParentId); - if (msgData.PrefabId.IsValid()) - { - Actor* prefabInstance = nullptr; - Actor* parentActor = parent && parent->Object && parent->Object->Is() ? parent->Object.As() : nullptr; - if (parentActor && parentActor->GetPrefabID() == msgData.PrefabId) + auto& msgDataItem = msgDataItems[i]; + NetworkReplicatedObject* e = ResolveObject(msgDataItem.ObjectId, msgDataItem.ParentId, msgDataItem.ObjectTypeName); + auto& item = *e; + item.Spawned = true; + if (NetworkManager::IsClient()) { - // Reuse parent object as prefab instance - prefabInstance = parentActor; + // Server always knows the best so update ownership of the existing object + item.OwnerClientId = msgData.OwnerClientId; + if (item.Role == NetworkObjectRole::OwnedAuthoritative) + item.Role = NetworkObjectRole::Replicated; } - else if (parentActor = Scripting::TryFindObject(msgData.ParentId)) + else if (item.OwnerClientId != msgData.OwnerClientId) { - // Try to find that spawned prefab (eg. prefab with networked script was spawned before so now we need to link it) - for (Actor* child : parentActor->Children) + // Other client spawned object with a different owner + // TODO: send reply message to inform about proper object ownership that client + } + } + return; + } + + // Recreate object locally (spawn only root) + ScriptingObject* obj = nullptr; + Actor* prefabInstance = nullptr; + if (msgData.PrefabId.IsValid()) + { + const NetworkReplicatedObject* parent = ResolveObject(rootItem.ParentId); + Actor* parentActor = parent && parent->Object && parent->Object->Is() ? parent->Object.As() : nullptr; + if (parentActor && parentActor->GetPrefabID() == msgData.PrefabId) + { + // Reuse parent object as prefab instance + prefabInstance = parentActor; + } + else if (parentActor = Scripting::TryFindObject(rootItem.ParentId)) + { + // Try to find that spawned prefab (eg. prefab with networked script was spawned before so now we need to link it) + for (Actor* child : parentActor->Children) + { + if (child->GetPrefabID() == msgData.PrefabId) { - if (child->GetPrefabID() == msgData.PrefabId) + if (Objects.Contains(child->GetID())) { - if (Objects.Contains(child->GetID())) + obj = FindPrefabObject(child, rootItem.PrefabObjectID); + if (Objects.Contains(obj->GetID())) { - obj = FindPrefabObject(child, msgData.PrefabObjectID); - if (Objects.Contains(obj->GetID())) - { - // Other instance with already spawned network object - obj = nullptr; - } - else - { - // Reuse already spawned object within a parent - prefabInstance = child; - break; - } + // Other instance with already spawned network object + obj = nullptr; + } + else + { + // Reuse already spawned object within a parent + prefabInstance = child; + break; } } } } + } + if (!prefabInstance) + { + // Spawn prefab + auto prefab = (Prefab*)LoadAsset(msgData.PrefabId, Prefab::TypeInitializer); + if (!prefab) + { + NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to find prefab {}", msgData.PrefabId.ToString()); + return; + } + prefabInstance = PrefabManager::SpawnPrefab(prefab, nullptr, nullptr); if (!prefabInstance) { - // Spawn prefab - auto prefab = (Prefab*)LoadAsset(msgData.PrefabId, Prefab::TypeInitializer); - if (!prefab) - { - NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to find prefab {}", msgData.PrefabId.ToString()); - return; - } - prefabInstance = PrefabManager::SpawnPrefab(prefab, nullptr, nullptr); - if (!prefabInstance) - { - NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to spawn object type {}", msgData.PrefabId.ToString()); - return; - } - } - if (!obj) - obj = FindPrefabObject(prefabInstance, msgData.PrefabObjectID); - if (!obj) - { - NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to find object {} in prefab {}", msgData.PrefabObjectID.ToString(), msgData.PrefabId.ToString()); - Delete(prefabInstance); + NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to spawn object type {}", msgData.PrefabId.ToString()); return; } } - else + if (!obj) + obj = FindPrefabObject(prefabInstance, rootItem.PrefabObjectID); + if (!obj) { - // Spawn object - const ScriptingTypeHandle objectType = Scripting::FindScriptingType(msgData.ObjectTypeName); - obj = ScriptingObject::NewObject(objectType); + NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to find object {} in prefab {}", rootItem.PrefabObjectID.ToString(), msgData.PrefabId.ToString()); + Delete(prefabInstance); + return; + } + } + else + { + // Spawn object + if (msgData.ItemsCount != 1) + { + NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Only prefab object spawning can contain more than one object (for type {})", String(rootItem.ObjectTypeName)); + return; + } + const ScriptingTypeHandle objectType = Scripting::FindScriptingType(rootItem.ObjectTypeName); + obj = ScriptingObject::NewObject(objectType); + if (!obj) + { + NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to spawn object type {}", String(rootItem.ObjectTypeName)); + return; + } + } + + // Setup all newly spawned objects + for (int32 i = 0; i < msgData.ItemsCount; i++) + { + auto& msgDataItem = msgDataItems[i]; + if (i != 0) + { + obj = FindPrefabObject(prefabInstance, msgDataItem.PrefabObjectID); if (!obj) { - NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to spawn object type {}", String(msgData.ObjectTypeName)); + NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Failed to find object {} in prefab {}", msgDataItem.PrefabObjectID.ToString(), msgData.PrefabId.ToString()); + Delete(prefabInstance); return; } } if (!obj->IsRegistered()) obj->RegisterObject(); + const NetworkReplicatedObject* parent = ResolveObject(msgDataItem.ParentId); // Add object to the list NetworkReplicatedObject item; @@ -1200,24 +1327,27 @@ void NetworkInternal::OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkCl Objects.Add(MoveTemp(item)); // Boost future lookups by using indirection - NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Remap object ID={} into object {}:{}", msgData.ObjectId, item.ToString(), obj->GetType().ToString()); - IdsRemappingTable.Add(msgData.ObjectId, item.ObjectId); + NETWORK_REPLICATOR_LOG(Info, "[NetworkReplicator] Remap object ID={} into object {}:{}", msgDataItem.ObjectId, item.ToString(), obj->GetType().ToString()); + IdsRemappingTable.Add(msgDataItem.ObjectId, item.ObjectId); // Automatic parenting for scene objects auto sceneObject = ScriptingObject::Cast(obj); if (sceneObject) { - if (parent && parent->Object.Get() && parent->Object->Is()) + if (parent && parent + -> + Object.Get() && parent->Object->Is() + ) sceneObject->SetParent(parent->Object.As()); - else if (auto* parentActor = Scripting::TryFindObject(msgData.ParentId)) + else if (auto* parentActor = Scripting::TryFindObject(msgDataItem.ParentId)) sceneObject->SetParent(parentActor); } if (item.AsNetworkObject) item.AsNetworkObject->OnNetworkSpawn(); - - // TODO: if we're server then spawn this object further on other clients (use TargetClientIds for that object - eg. object spawned by client on client for certain set of other clients only) } + + // TODO: if we're server then spawn this object further on other clients (use TargetClientIds for that object - eg. object spawned by client on client for certain set of other clients only) } void NetworkInternal::OnNetworkMessageObjectDespawn(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer) From e5b4ce06b97067825524164a4fa7d3f9e99c3f6c Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 30 Nov 2022 16:19:32 +0100 Subject: [PATCH 36/83] Add support for C# properties automatic replication codegen --- .../Build/Plugins/NetworkingPlugin.cs | 99 ++++++++++++++++--- .../Tools/Flax.Build/Utilities/MonoCecil.cs | 7 +- 2 files changed, 86 insertions(+), 20 deletions(-) diff --git a/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs b/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs index 236ac1113..fec2034d8 100644 --- a/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs +++ b/Source/Tools/Flax.Build/Build/Plugins/NetworkingPlugin.cs @@ -49,6 +49,7 @@ namespace Flax.Build.Plugins internal const string Network = "Network"; internal const string NetworkReplicated = "NetworkReplicated"; + internal const string NetworkReplicatedAttribute = "FlaxEngine.NetworkReplicatedAttribute"; internal const string NetworkRpc = "NetworkRpc"; private const string Thunk1 = "INetworkSerializable_Serialize"; private const string Thunk2 = "INetworkSerializable_Deserialize"; @@ -555,7 +556,14 @@ namespace Flax.Build.Plugins var isNetworkReplicated = false; foreach (FieldDefinition f in type.Fields) { - if (!f.HasAttribute("FlaxEngine.NetworkReplicatedAttribute")) + if (!f.HasAttribute(NetworkReplicatedAttribute)) + continue; + isNetworkReplicated = true; + break; + } + foreach (PropertyDefinition p in type.Properties) + { + if (!p.HasAttribute(NetworkReplicatedAttribute)) continue; isNetworkReplicated = true; break; @@ -697,9 +705,17 @@ namespace Flax.Build.Plugins // Serialize all type fields marked with NetworkReplicated attribute foreach (FieldDefinition f in type.Fields) { - if (!f.HasAttribute("FlaxEngine.NetworkReplicatedAttribute")) + if (!f.HasAttribute(NetworkReplicatedAttribute)) continue; - GenerateSerializerType(type, serialize, ref failed, f, f.FieldType, il, networkStream); + GenerateSerializerType(type, serialize, ref failed, f, null, f.FieldType, il, networkStream); + } + + // Serialize all type properties marked with NetworkReplicated attribute + foreach (PropertyDefinition p in type.Properties) + { + if (!p.HasAttribute(NetworkReplicatedAttribute)) + continue; + GenerateSerializerType(type, serialize, ref failed, null, p, p.PropertyType, il, networkStream); } if (serialize) @@ -779,8 +795,31 @@ namespace Flax.Build.Plugins } } - private static void GenerateSerializerType(TypeDefinition type, bool serialize, ref bool failed, FieldReference field, TypeReference valueType, ILProcessor il, TypeDefinition networkStreamType) + private static void GenerateSerializerType(TypeDefinition type, bool serialize, ref bool failed, FieldReference field, PropertyDefinition property, TypeReference valueType, ILProcessor il, TypeDefinition networkStreamType) { + if (field == null && property == null) + throw new ArgumentException(); + var propertyGetOpCode = OpCodes.Call; + var propertySetOpCode = OpCodes.Call; + if (property != null) + { + if (property.GetMethod == null) + { + Log.Error($"Missing getter method for property '{property.Name}' of type {valueType.FullName} in {type.FullName} for automatic replication."); + failed = true; + return; + } + if (property.SetMethod == null) + { + Log.Error($"Missing setter method for property '{property.Name}' of type {valueType.FullName} in {type.FullName} for automatic replication."); + failed = true; + return; + } + if (property.GetMethod.IsVirtual) + propertyGetOpCode = OpCodes.Callvirt; + if (property.SetMethod.IsVirtual) + propertySetOpCode = OpCodes.Callvirt; + } ModuleDefinition module = type.Module; TypeDefinition valueTypeDef = valueType.Resolve(); if (_inBuildSerializers.TryGetValue(valueType.FullName, out var serializer)) @@ -791,7 +830,10 @@ namespace Flax.Build.Plugins { il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldfld, field); + if (field != null) + il.Emit(OpCodes.Ldfld, field); + else + il.Emit(propertyGetOpCode, property.GetMethod); m = networkStreamType.GetMethod(serializer.WriteMethod); } else @@ -802,7 +844,12 @@ namespace Flax.Build.Plugins } il.Emit(OpCodes.Callvirt, module.ImportReference(m)); if (!serialize) - il.Emit(OpCodes.Stfld, field); + { + if (field != null) + il.Emit(OpCodes.Stfld, field); + else + il.Emit(propertySetOpCode, property.SetMethod); + } } else if (valueType.IsScriptingObject()) { @@ -813,7 +860,10 @@ namespace Flax.Build.Plugins { il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldfld, field); + if (field != null) + il.Emit(OpCodes.Ldfld, field); + else + il.Emit(propertyGetOpCode, property.GetMethod); il.Emit(OpCodes.Dup); Instruction jmp1 = il.Create(OpCodes.Nop); il.Emit(OpCodes.Brtrue_S, jmp1); @@ -849,7 +899,10 @@ namespace Flax.Build.Plugins var tryFind = scriptingObjectType.Resolve().GetMethod("TryFind", 2); il.Emit(OpCodes.Call, module.ImportReference(tryFind)); il.Emit(OpCodes.Castclass, valueType); - il.Emit(OpCodes.Stfld, field); + if (field != null) + il.Emit(OpCodes.Stfld, field); + else + il.Emit(propertySetOpCode, property.SetMethod); } } else if (valueTypeDef.IsEnum) @@ -860,7 +913,10 @@ namespace Flax.Build.Plugins { il.Emit(OpCodes.Ldarg_1); il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldfld, field); + if (field != null) + il.Emit(OpCodes.Ldfld, field); + else + il.Emit(propertyGetOpCode, property.GetMethod); var m = networkStreamType.GetMethod("WriteUInt32"); il.Emit(OpCodes.Callvirt, module.ImportReference(m)); } @@ -870,7 +926,10 @@ namespace Flax.Build.Plugins il.Emit(OpCodes.Ldarg_1); var m = networkStreamType.GetMethod("ReadUInt32"); il.Emit(OpCodes.Callvirt, module.ImportReference(m)); - il.Emit(OpCodes.Stfld, field); + if (field != null) + il.Emit(OpCodes.Stfld, field); + else + il.Emit(propertySetOpCode, property.SetMethod); } } else if (valueType.IsValueType) @@ -878,7 +937,10 @@ namespace Flax.Build.Plugins // Invoke structure generated serializer // TODO: check if this type has generated serialization code il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldflda, field); + if (field != null) + il.Emit(OpCodes.Ldflda, field); + else + il.Emit(propertyGetOpCode, property.GetMethod); il.Emit(OpCodes.Ldarg_1); var m = valueTypeDef.GetMethod(serialize ? Thunk1 : Thunk2); il.Emit(OpCodes.Call, module.ImportReference(m)); @@ -898,7 +960,10 @@ namespace Flax.Build.Plugins // [] array2 = Array1; il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldfld, field); + if (field != null) + il.Emit(OpCodes.Ldfld, field); + else + il.Emit(propertyGetOpCode, property.GetMethod); // int num2 = ((array2 != null) ? array2.Length : 0); il.Emit(OpCodes.Dup); @@ -923,7 +988,10 @@ namespace Flax.Build.Plugins // fixed (* bytes2 = Array1) il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_0); - il.Emit(OpCodes.Ldfld, field); + if (field != null) + il.Emit(OpCodes.Ldfld, field); + else + il.Emit(propertyGetOpCode, property.GetMethod); il.Emit(OpCodes.Dup); il.Emit(OpCodes.Stloc, varStart + 2); Instruction jmp3 = il.Create(OpCodes.Nop); @@ -961,6 +1029,9 @@ namespace Flax.Build.Plugins } else { + if (field == null) + throw new NotImplementedException("TODO: add support for array property replication"); + // int num = stream.ReadInt32(); il.Emit(OpCodes.Nop); il.Emit(OpCodes.Ldarg_1); @@ -1019,7 +1090,7 @@ namespace Flax.Build.Plugins else { // Unknown type - Log.Error($"Not supported type '{valueType.FullName}' on {field.Name} in {type.FullName} for automatic replication."); + Log.Error($"Not supported type '{valueType.FullName}' on {(field?.Name ?? property.Name)} in {type.FullName} for automatic replication."); failed = true; } } diff --git a/Source/Tools/Flax.Build/Utilities/MonoCecil.cs b/Source/Tools/Flax.Build/Utilities/MonoCecil.cs index 6bedab2e6..eb9ced342 100644 --- a/Source/Tools/Flax.Build/Utilities/MonoCecil.cs +++ b/Source/Tools/Flax.Build/Utilities/MonoCecil.cs @@ -11,12 +11,7 @@ namespace Flax.Build /// internal static class MonoCecil { - public static bool HasAttribute(this TypeDefinition type, string fullName) - { - return type.CustomAttributes.Any(x => x.AttributeType.FullName == fullName); - } - - public static bool HasAttribute(this FieldDefinition type, string fullName) + public static bool HasAttribute(this ICustomAttributeProvider type, string fullName) { return type.CustomAttributes.Any(x => x.AttributeType.FullName == fullName); } From e4840d35d668b9fdc78064892c9449f03810a4c9 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 30 Nov 2022 16:19:46 +0100 Subject: [PATCH 37/83] Adjust network transform precision --- Source/Engine/Networking/Components/NetworkTransform.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Networking/Components/NetworkTransform.cpp b/Source/Engine/Networking/Components/NetworkTransform.cpp index 1a6303009..13686917b 100644 --- a/Source/Engine/Networking/Components/NetworkTransform.cpp +++ b/Source/Engine/Networking/Components/NetworkTransform.cpp @@ -26,7 +26,7 @@ static_assert((int32)NetworkTransform::ReplicationComponents::All + 1 == 512, "I namespace { // Percentage of local error that is acceptable (eg. 4 frames error) - constexpr float Precision = 4.0f; + constexpr float Precision = 8.0f; template FORCE_INLINE bool IsWithinPrecision(const Vector3Base& currentDelta, const Vector3Base& targetDelta) From a3a001633b67fec052897df6203e2ae4f5c23d2a Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 30 Nov 2022 17:18:58 +0100 Subject: [PATCH 38/83] Fix Custom Editors groups regression --- .../CustomEditors/Editors/GenericEditor.cs | 40 ++++++++++++++----- Source/Editor/Surface/SurfaceUtils.cs | 4 +- Source/Editor/Surface/VisjectSurfaceWindow.cs | 4 +- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/Source/Editor/CustomEditors/Editors/GenericEditor.cs b/Source/Editor/CustomEditors/Editors/GenericEditor.cs index 39b1ca531..8a3f98560 100644 --- a/Source/Editor/CustomEditors/Editors/GenericEditor.cs +++ b/Source/Editor/CustomEditors/Editors/GenericEditor.cs @@ -225,7 +225,8 @@ namespace FlaxEditor.CustomEditors.Editors } private static HashSet _visibleIfPropertiesListsCache; - private static Dictionary _groups; + private static Stack> _groups; + private static List> _groupsPool; private VisibleIfCache[] _visibleIfCaches; private bool _isNull; @@ -514,17 +515,38 @@ namespace FlaxEditor.CustomEditors.Editors menu.Show(groupPanel, location); } - internal static void OnGroupUsage() + internal static void OnGroupsBegin() { - if (_groups != null) - _groups.Clear(); + if (_groups == null) + _groups = new Stack>(); + if (_groupsPool == null) + _groupsPool = new List>(); + Dictionary group; + if (_groupsPool.Count != 0) + { + group = _groupsPool[0]; + _groupsPool.RemoveAt(0); + } + else + { + group = new Dictionary(); + } + _groups.Push(group); + } + + internal static void OnGroupsEnd() + { + var groups = _groups.Pop(); + groups.Clear(); + _groupsPool.Add(groups); } internal static LayoutElementsContainer OnGroup(LayoutElementsContainer layout, EditorDisplayAttribute display) { if (display?.Group != null) { - if (_groups != null && _groups.TryGetValue(display.Group, out var group)) + var groups = _groups.Peek(); + if (groups.TryGetValue(display.Group, out var group)) { // Reuse group layout = group; @@ -532,12 +554,10 @@ namespace FlaxEditor.CustomEditors.Editors else { // Add new group - if (_groups == null) - _groups = new Dictionary(); group = layout.Group(display.Group); group.Panel.Tag = group; group.Panel.MouseButtonRightClicked += OnGroupPanelMouseButtonRightClicked; - _groups.Add(display.Group, group); + groups.Add(display.Group, group); layout = group; } } @@ -713,7 +733,7 @@ namespace FlaxEditor.CustomEditors.Editors items.Sort(); // Add items - OnGroupUsage(); + OnGroupsBegin(); for (int i = 0; i < items.Count; i++) { var item = items[i]; @@ -759,7 +779,7 @@ namespace FlaxEditor.CustomEditors.Editors } while (c != null); } } - OnGroupUsage(); + OnGroupsEnd(); } /// diff --git a/Source/Editor/Surface/SurfaceUtils.cs b/Source/Editor/Surface/SurfaceUtils.cs index 59d90c916..c69dfdf52 100644 --- a/Source/Editor/Surface/SurfaceUtils.cs +++ b/Source/Editor/Surface/SurfaceUtils.cs @@ -285,7 +285,7 @@ namespace FlaxEditor.Surface internal static void DisplayGraphParameters(LayoutElementsContainer layout, GraphParameterData[] data, GetGraphParameterDelegate getter, SetGraphParameterDelegate setter, ValueContainer values, GetGraphParameterDelegate defaultValueGetter = null, CustomPropertySpawnDelegate propertySpawn = null) { - CustomEditors.Editors.GenericEditor.OnGroupUsage(); + CustomEditors.Editors.GenericEditor.OnGroupsBegin(); for (int i = 0; i < data.Length; i++) { ref var e = ref data[i]; @@ -332,7 +332,7 @@ namespace FlaxEditor.Surface else propertySpawn(itemLayout, valueContainer, ref e); } - CustomEditors.Editors.GenericEditor.OnGroupUsage(); + CustomEditors.Editors.GenericEditor.OnGroupsEnd(); } internal static string GetMethodDisplayName(string methodName) diff --git a/Source/Editor/Surface/VisjectSurfaceWindow.cs b/Source/Editor/Surface/VisjectSurfaceWindow.cs index 788eb7a96..43a664866 100644 --- a/Source/Editor/Surface/VisjectSurfaceWindow.cs +++ b/Source/Editor/Surface/VisjectSurfaceWindow.cs @@ -372,7 +372,7 @@ namespace FlaxEditor.Surface return; } var parameters = window.VisjectSurface.Parameters; - CustomEditors.Editors.GenericEditor.OnGroupUsage(); + CustomEditors.Editors.GenericEditor.OnGroupsBegin(); for (int i = 0; i < parameters.Count; i++) { var p = parameters[i]; @@ -429,7 +429,7 @@ namespace FlaxEditor.Surface var property = itemLayout.AddPropertyItem(propertyLabel, tooltipText); property.Property("Value", propertyValue); } - CustomEditors.Editors.GenericEditor.OnGroupUsage(); + CustomEditors.Editors.GenericEditor.OnGroupsEnd(); // Parameters creating var newParameterTypes = window.NewParameterTypes; From 8694d9f9b427c633df99fb9c67caa3b264b6725c Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 30 Nov 2022 18:06:39 +0100 Subject: [PATCH 39/83] Fix helper mouse button up event on drag drop end on Windows Regression from 4efd411045439dbc92ee39c6be43de0a5d039a70 --- Source/Engine/Platform/Windows/WindowsWindow.DragDrop.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/Engine/Platform/Windows/WindowsWindow.DragDrop.cpp b/Source/Engine/Platform/Windows/WindowsWindow.DragDrop.cpp index e836f3e21..3bb697208 100644 --- a/Source/Engine/Platform/Windows/WindowsWindow.DragDrop.cpp +++ b/Source/Engine/Platform/Windows/WindowsWindow.DragDrop.cpp @@ -8,6 +8,7 @@ #include "Engine/Core/Collections/Array.h" #include "Engine/Engine/Engine.h" +#include "Engine/Engine/Screen.h" #include "Engine/Platform/IGuiData.h" #include "Engine/Input/Input.h" #include "Engine/Input/Mouse.h" @@ -621,7 +622,11 @@ DragDropEffect WindowsWindow::DoDragDrop(const StringView& data) // Fix hanging mouse state (Windows doesn't send WM_LBUTTONUP when we end the drag and drop) if (Input::GetMouseButton(MouseButton::Left)) - Input::Mouse->OnMouseUp(Input::Mouse->GetPosition(), MouseButton::Left, this); + { + ::POINT point; + ::GetCursorPos(&point); + Input::Mouse->OnMouseUp(Float2((float)point.x, (float)point.y), MouseButton::Left, this); + } return SUCCEEDED(result) ? dropEffectFromOleEnum(dwEffect) : DragDropEffect::None; } From 12f8a15b8b7efaf3df7989218bd8b93411298d27 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Wed, 30 Nov 2022 18:07:27 +0100 Subject: [PATCH 40/83] Remove unused include --- Source/Engine/Platform/Windows/WindowsWindow.DragDrop.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Engine/Platform/Windows/WindowsWindow.DragDrop.cpp b/Source/Engine/Platform/Windows/WindowsWindow.DragDrop.cpp index 3bb697208..86662a993 100644 --- a/Source/Engine/Platform/Windows/WindowsWindow.DragDrop.cpp +++ b/Source/Engine/Platform/Windows/WindowsWindow.DragDrop.cpp @@ -8,7 +8,6 @@ #include "Engine/Core/Collections/Array.h" #include "Engine/Engine/Engine.h" -#include "Engine/Engine/Screen.h" #include "Engine/Platform/IGuiData.h" #include "Engine/Input/Input.h" #include "Engine/Input/Mouse.h" From 7486bc640f035380de251027a381819f18e07918 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 30 Nov 2022 22:05:58 +0100 Subject: [PATCH 41/83] Add network profiler tab with network driver data sent/received --- Source/Editor/Windows/Profiler/Network.cs | 87 +++++++++++++++++++ .../Editor/Windows/Profiler/ProfilerWindow.cs | 1 + .../Engine/Networking/Drivers/ENetDriver.cpp | 2 + Source/Engine/Networking/NetworkStats.h | 10 +++ 4 files changed, 100 insertions(+) create mode 100644 Source/Editor/Windows/Profiler/Network.cs diff --git a/Source/Editor/Windows/Profiler/Network.cs b/Source/Editor/Windows/Profiler/Network.cs new file mode 100644 index 000000000..ef4f2f7ea --- /dev/null +++ b/Source/Editor/Windows/Profiler/Network.cs @@ -0,0 +1,87 @@ +// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. + +using FlaxEngine; +using FlaxEngine.GUI; + +namespace FlaxEditor.Windows.Profiler +{ + /// + /// The network profiling mode. + /// + /// + internal sealed class Network : ProfilerMode + { + private readonly SingleChart _dataSentChart; + private readonly SingleChart _dataReceivedChart; + private FlaxEngine.Networking.NetworkDriverStats _prevStats; + + public Network() + : base("Network") + { + // Layout + var panel = new Panel(ScrollBars.Vertical) + { + AnchorPreset = AnchorPresets.StretchAll, + Offsets = Margin.Zero, + Parent = this, + }; + var layout = new VerticalPanel + { + AnchorPreset = AnchorPresets.HorizontalStretchTop, + Offsets = Margin.Zero, + IsScrollable = true, + Parent = panel, + }; + + // Charts + _dataSentChart = new SingleChart + { + Title = "Data Sent", + FormatSample = FormatSampleBytes, + Parent = layout, + }; + _dataSentChart.SelectedSampleChanged += OnSelectedSampleChanged; + _dataReceivedChart = new SingleChart + { + Title = "Data Received", + FormatSample = FormatSampleBytes, + Parent = layout, + }; + _dataReceivedChart.SelectedSampleChanged += OnSelectedSampleChanged; + } + + private static string FormatSampleBytes(float v) + { + return (uint)v + " bytes"; + } + + /// + public override void Clear() + { + _dataSentChart.Clear(); + _dataReceivedChart.Clear(); + } + + /// + public override void Update(ref SharedUpdateData sharedData) + { + var peer = FlaxEngine.Networking.NetworkManager.Peer; + if (peer == null) + { + _prevStats = new FlaxEngine.Networking.NetworkDriverStats(); + return; + } + var stats = peer.NetworkDriver.GetStats(); + _dataSentChart.AddSample(Mathf.Max((long)stats.TotalDataSent - (long)_prevStats.TotalDataSent, 0)); + _dataReceivedChart.AddSample(Mathf.Max((long)stats.TotalDataReceived - (long)_prevStats.TotalDataReceived, 0)); + _prevStats = stats; + } + + /// + public override void UpdateView(int selectedFrame, bool showOnlyLastUpdateEvents) + { + _dataSentChart.SelectedSampleIndex = selectedFrame; + _dataReceivedChart.SelectedSampleIndex = selectedFrame; + } + } +} diff --git a/Source/Editor/Windows/Profiler/ProfilerWindow.cs b/Source/Editor/Windows/Profiler/ProfilerWindow.cs index 4d1ad9ba1..d85cc159a 100644 --- a/Source/Editor/Windows/Profiler/ProfilerWindow.cs +++ b/Source/Editor/Windows/Profiler/ProfilerWindow.cs @@ -182,6 +182,7 @@ namespace FlaxEditor.Windows.Profiler AddMode(new CPU()); AddMode(new GPU()); AddMode(new Memory()); + AddMode(new Network()); // Init view _frameIndex = -1; diff --git a/Source/Engine/Networking/Drivers/ENetDriver.cpp b/Source/Engine/Networking/Drivers/ENetDriver.cpp index adff7525a..9eac8a0f9 100644 --- a/Source/Engine/Networking/Drivers/ENetDriver.cpp +++ b/Source/Engine/Networking/Drivers/ENetDriver.cpp @@ -254,6 +254,8 @@ NetworkDriverStats ENetDriver::GetStats(NetworkConnection target) if (peer) { stats.RTT = (float)peer->roundTripTime; + stats.TotalDataSent = peer->totalDataSent; + stats.TotalDataReceived = peer->totalDataReceived; } return stats; } diff --git a/Source/Engine/Networking/NetworkStats.h b/Source/Engine/Networking/NetworkStats.h index eaa1daedb..d9ebd4d91 100644 --- a/Source/Engine/Networking/NetworkStats.h +++ b/Source/Engine/Networking/NetworkStats.h @@ -16,6 +16,16 @@ API_STRUCT(Namespace="FlaxEngine.Networking") struct FLAXENGINE_API NetworkDrive /// The mean round trip time (RTT), in milliseconds, between sending a reliable packet and receiving its acknowledgement. Also known as ping time. /// API_FIELD() float RTT = 0.0f; + + /// + /// Total amount of data bytes sent by this client. + /// + API_FIELD() uint32 TotalDataSent = 0; + + /// + /// Total amount of data bytes received by this client. + /// + API_FIELD() uint32 TotalDataReceived = 0; }; template<> From cfffc76aa65ef4d7e43ed8e1599c83770736ef7a Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 2 Dec 2022 10:04:46 +0100 Subject: [PATCH 42/83] Fix potential crash --- Source/Engine/Physics/Colliders/CharacterController.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/Engine/Physics/Colliders/CharacterController.cpp b/Source/Engine/Physics/Colliders/CharacterController.cpp index e6bd8cd52..b12472555 100644 --- a/Source/Engine/Physics/Colliders/CharacterController.cpp +++ b/Source/Engine/Physics/Colliders/CharacterController.cpp @@ -272,6 +272,9 @@ RigidBody* CharacterController::GetAttachedRigidBody() const void CharacterController::OnActiveTransformChanged() { + if (!_shape) + return; + // Change actor transform (but with locking) ASSERT(!_isUpdatingTransform); _isUpdatingTransform = true; From 0f19fc64fd0125fb01a472380248b33a5fdb83e2 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 2 Dec 2022 10:05:07 +0100 Subject: [PATCH 43/83] Add `SceneReference` to C++ scripting API --- Source/Engine/Content/SceneReference.h | 18 ++++++++++++++++++ Source/Engine/Engine/SceneReference.cs | 10 +--------- 2 files changed, 19 insertions(+), 9 deletions(-) create mode 100644 Source/Engine/Content/SceneReference.h diff --git a/Source/Engine/Content/SceneReference.h b/Source/Engine/Content/SceneReference.h new file mode 100644 index 000000000..c1e405f4e --- /dev/null +++ b/Source/Engine/Content/SceneReference.h @@ -0,0 +1,18 @@ +// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. + +#pragma once + +#include "Engine/Core/Types/Guid.h" + +/// +/// Represents the reference to the scene asset. Stores the unique ID of the scene to reference. Can be used to load the selected scene. +/// +API_STRUCT(NoDefault) struct FLAXENGINE_API SceneReference +{ + DECLARE_SCRIPTING_TYPE_STRUCTURE(SceneReference); + + /// + /// The identifier of the scene asset (and the scene object). + /// + API_FIELD() Guid ID; +}; diff --git a/Source/Engine/Engine/SceneReference.cs b/Source/Engine/Engine/SceneReference.cs index 760da842a..c3f22c061 100644 --- a/Source/Engine/Engine/SceneReference.cs +++ b/Source/Engine/Engine/SceneReference.cs @@ -4,16 +4,8 @@ using System; namespace FlaxEngine { - /// - /// Represents the reference to the scene asset. Stores the unique ID of the scene to reference. Can be used to load the selected scene. - /// - public struct SceneReference : IComparable, IComparable, IComparable + partial struct SceneReference : IComparable, IComparable, IComparable { - /// - /// The identifier of the scene asset (and the scene object). - /// - public Guid ID; - /// /// Initializes a new instance of the class. /// From eae8fd7ef905f2a10faef4c730a30c321d77151d Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 2 Dec 2022 10:05:32 +0100 Subject: [PATCH 44/83] Add `AdditionalScenes` to `BuildSettings` --- Source/Editor/Cooker/Steps/DeployDataStep.cpp | 2 ++ Source/Engine/Core/Config/BuildSettings.h | 7 +++++++ 2 files changed, 9 insertions(+) diff --git a/Source/Editor/Cooker/Steps/DeployDataStep.cpp b/Source/Editor/Cooker/Steps/DeployDataStep.cpp index 3973c4039..7c8b599c6 100644 --- a/Source/Editor/Cooker/Steps/DeployDataStep.cpp +++ b/Source/Editor/Cooker/Steps/DeployDataStep.cpp @@ -115,6 +115,8 @@ bool DeployDataStep::Perform(CookingData& data) auto& buildSettings = *BuildSettings::Get(); for (auto& e : buildSettings.AdditionalAssets) data.AddRootAsset(e.GetID()); + for (auto& e : buildSettings.AdditionalScenes) + data.AddRootAsset(e.ID); Array files; for (auto& e : buildSettings.AdditionalAssetFolders) { diff --git a/Source/Engine/Core/Config/BuildSettings.h b/Source/Engine/Core/Config/BuildSettings.h index 471818ddc..9f3e69cd4 100644 --- a/Source/Engine/Core/Config/BuildSettings.h +++ b/Source/Engine/Core/Config/BuildSettings.h @@ -6,6 +6,7 @@ #include "Engine/Serialization/Serialization.h" #include "Engine/Content/Asset.h" #include "Engine/Content/AssetReference.h" +#include "Engine/Content/SceneReference.h" /// /// The game building rendering settings. @@ -50,6 +51,12 @@ public: /// API_FIELD(Attributes="EditorOrder(1000), EditorDisplay(\"Additional Data\")") Array> AdditionalAssets; + + /// + /// The list of additional scenes to include into build (into root assets set). + /// + API_FIELD(Attributes="EditorOrder(1000), EditorDisplay(\"Additional Data\")") + Array AdditionalScenes; /// /// The list of additional folders with assets to include into build (into root assets set). Paths relative to the project directory (or absolute). From adcffab78a70ea3948e3e87c1e27ea7f050af7ca Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 2 Dec 2022 10:36:52 +0100 Subject: [PATCH 45/83] Match C# string serialization in network stream to C++ impl --- Source/Engine/Networking/NetworkStream.cs | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/Source/Engine/Networking/NetworkStream.cs b/Source/Engine/Networking/NetworkStream.cs index f489ca5e2..0371bb7c1 100644 --- a/Source/Engine/Networking/NetworkStream.cs +++ b/Source/Engine/Networking/NetworkStream.cs @@ -236,17 +236,15 @@ namespace FlaxEngine.Networking public void WriteString(string value) { // Note: Make sure that this is consistent with the C++ message API! - if (value == null) { - WriteUInt16(0); + WriteInt32(0); return; } - var data = Encoding.Unicode.GetBytes(value); - var dataLength = data.Length; var stringLength = value.Length; - WriteUInt16((ushort)stringLength); // TODO: Use 1-byte length when possible - WriteBytes(data, dataLength); + WriteInt32(stringLength); + fixed (char* ptr = value) + WriteData(new IntPtr(ptr), value.Length * 2); } /// @@ -255,13 +253,11 @@ namespace FlaxEngine.Networking public string ReadString() { // Note: Make sure that this is consistent with the C++ message API! - - var stringLength = ReadUInt16(); // In chars + var stringLength = ReadInt32(); if (stringLength == 0) return string.Empty; - var dataLength = stringLength * sizeof(char); // In bytes + var dataLength = stringLength * sizeof(char); var bytes = stackalloc char[stringLength]; - ReadBytes((byte*)bytes, dataLength); return new string(bytes, 0, stringLength); } From f61100deca2247931e0ed39384642e6158c0adfd Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 2 Dec 2022 10:55:12 +0100 Subject: [PATCH 46/83] Cleanup for networking impl --- Source/Engine/Networking/NetworkReplicator.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp index f08f13da1..ad1ffebe5 100644 --- a/Source/Engine/Networking/NetworkReplicator.cpp +++ b/Source/Engine/Networking/NetworkReplicator.cpp @@ -31,7 +31,7 @@ #include "Engine/Threading/ThreadLocal.h" // Enables verbose logging for Network Replicator actions (dev-only) -#define NETWORK_REPLICATOR_DEBUG_LOG 1 +#define NETWORK_REPLICATOR_DEBUG_LOG 0 #if NETWORK_REPLICATOR_DEBUG_LOG #define NETWORK_REPLICATOR_LOG(messageType, format, ...) LOG(messageType, format, ##__VA_ARGS__) @@ -757,6 +757,11 @@ void NetworkReplicator::SetObjectOwnership(ScriptingObject* obj, uint32 ownerCli } } +void DirtyObjectImpl(NetworkReplicatedObject& item, ScriptingObject* obj) +{ + // TODO: implement objects state replication frequency and dirtying +} + void NetworkReplicator::DirtyObject(ScriptingObject* obj) { ScopeLock lock(ObjectsLock); @@ -766,7 +771,7 @@ void NetworkReplicator::DirtyObject(ScriptingObject* obj) auto& item = it->Item; if (item.Object != obj || item.Role != NetworkObjectRole::OwnedAuthoritative) return; - // TODO: implement objects state replication frequency and dirtying + DirtyObjectImpl(item, obj); } Dictionary NetworkRpcInfo::RPCsTable; @@ -1167,7 +1172,9 @@ void NetworkInternal::OnNetworkMessageObjectReplicate(NetworkEvent& event, Netwo if (item.AsNetworkObject) item.AsNetworkObject->OnNetworkDeserialize(); - // TODO: speed up replication of client-owned object to other clients from server + // Speed up replication of client-owned objects to other clients from server to reduce lag (data has to go from client to server and then to other clients) + if (NetworkManager::IsServer()) + DirtyObjectImpl(item, obj); } else { From 6458d7e0db0f16de2c0fffd5bbd38bbf1d4ca0a5 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 2 Dec 2022 12:18:08 +0100 Subject: [PATCH 47/83] Add support for sending replicated object data in parts --- Source/Engine/Networking/NetworkInternal.h | 2 + Source/Engine/Networking/NetworkManager.cpp | 1 + Source/Engine/Networking/NetworkMessage.h | 6 +- .../Engine/Networking/NetworkReplicator.cpp | 242 ++++++++++++++---- 4 files changed, 197 insertions(+), 54 deletions(-) diff --git a/Source/Engine/Networking/NetworkInternal.h b/Source/Engine/Networking/NetworkInternal.h index d063a0ca3..dd01210a1 100644 --- a/Source/Engine/Networking/NetworkInternal.h +++ b/Source/Engine/Networking/NetworkInternal.h @@ -10,6 +10,7 @@ enum class NetworkMessageIDs : uint8 Handshake, HandshakeReply, ObjectReplicate, + ObjectReplicatePart, ObjectSpawn, ObjectDespawn, ObjectRole, @@ -27,6 +28,7 @@ public: static void NetworkReplicatorPreUpdate(); static void NetworkReplicatorUpdate(); static void OnNetworkMessageObjectReplicate(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer); + static void OnNetworkMessageObjectReplicatePart(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer); static void OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer); static void OnNetworkMessageObjectDespawn(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer); static void OnNetworkMessageObjectRole(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer); diff --git a/Source/Engine/Networking/NetworkManager.cpp b/Source/Engine/Networking/NetworkManager.cpp index 72634230a..ef5060e73 100644 --- a/Source/Engine/Networking/NetworkManager.cpp +++ b/Source/Engine/Networking/NetworkManager.cpp @@ -129,6 +129,7 @@ namespace OnNetworkMessageHandshake, OnNetworkMessageHandshakeReply, NetworkInternal::OnNetworkMessageObjectReplicate, + NetworkInternal::OnNetworkMessageObjectReplicatePart, NetworkInternal::OnNetworkMessageObjectSpawn, NetworkInternal::OnNetworkMessageObjectDespawn, NetworkInternal::OnNetworkMessageObjectRole, diff --git a/Source/Engine/Networking/NetworkMessage.h b/Source/Engine/Networking/NetworkMessage.h index 4d0bc4330..fa6119e89 100644 --- a/Source/Engine/Networking/NetworkMessage.h +++ b/Source/Engine/Networking/NetworkMessage.h @@ -69,7 +69,7 @@ public: /// The amount of bytes to write from the bytes pointer. FORCE_INLINE void WriteBytes(uint8* bytes, const int numBytes) { - ASSERT(Position + numBytes < BufferSize); + ASSERT(Position + numBytes <= BufferSize); Platform::MemoryCopy(Buffer + Position, bytes, numBytes); Position += numBytes; Length = Position; @@ -85,7 +85,7 @@ public: /// The minimal amount of bytes that the buffer contains. FORCE_INLINE void ReadBytes(uint8* bytes, const int32 numBytes) { - ASSERT(Position + numBytes < BufferSize); + ASSERT(Position + numBytes <= BufferSize); Platform::MemoryCopy(bytes, Buffer + Position, numBytes); Position += numBytes; } @@ -97,7 +97,7 @@ public: /// Pointer to skipped data beginning. FORCE_INLINE void* SkipBytes(const int32 numBytes) { - ASSERT(Position + numBytes < BufferSize); + ASSERT(Position + numBytes <= BufferSize); byte* result = Buffer + Position; Position += numBytes; return result; diff --git a/Source/Engine/Networking/NetworkReplicator.cpp b/Source/Engine/Networking/NetworkReplicator.cpp index ad1ffebe5..0b3202b60 100644 --- a/Source/Engine/Networking/NetworkReplicator.cpp +++ b/Source/Engine/Networking/NetworkReplicator.cpp @@ -12,7 +12,6 @@ #include "NetworkRpc.h" #include "INetworkSerializable.h" #include "INetworkObject.h" -#include "Engine/Core/Log.h" #include "Engine/Core/Collections/HashSet.h" #include "Engine/Core/Collections/Dictionary.h" #include "Engine/Core/Collections/ChunkedArray.h" @@ -34,6 +33,7 @@ #define NETWORK_REPLICATOR_DEBUG_LOG 0 #if NETWORK_REPLICATOR_DEBUG_LOG +#include "Engine/Core/Log.h" #define NETWORK_REPLICATOR_LOG(messageType, format, ...) LOG(messageType, format, ##__VA_ARGS__) #else #define NETWORK_REPLICATOR_LOG(messageType, format, ...) @@ -47,6 +47,18 @@ PACK_STRUCT(struct NetworkMessageObjectReplicate Guid ParentId; char ObjectTypeName[128]; // TODO: introduce networked-name to synchronize unique names as ushort (less data over network) uint16 DataSize; + uint16 PartsCount; + }); + +PACK_STRUCT(struct NetworkMessageObjectReplicatePart + { + NetworkMessageIDs ID = NetworkMessageIDs::ObjectReplicatePart; + uint32 OwnerFrame; + uint16 DataSize; + uint16 PartsCount; + uint16 PartStart; + uint16 PartSize; + Guid ObjectId; // TODO: introduce networked-ids to synchronize unique ids as ushort (less data over network) }); PACK_STRUCT(struct NetworkMessageObjectSpawn @@ -131,6 +143,15 @@ struct Serializer void* Tags[2]; }; +struct ReplicateItem +{ + ScriptingObjectReference Object; + Guid ObjectId; + uint16 PartsLeft; + uint32 OwnerFrame; + Array Data; +}; + struct SpawnItem { ScriptingObjectReference Object; @@ -164,6 +185,7 @@ namespace { CriticalSection ObjectsLock; HashSet Objects; + Array ReplicationParts; Array SpawnQueue; Array DespawnQueue; Array RpcQueue; @@ -462,6 +484,81 @@ void SetupObjectSpawnGroupItem(ScriptingObject* obj, ArrayItems.Add(&spawnItem); } +void DirtyObjectImpl(NetworkReplicatedObject& item, ScriptingObject* obj) +{ + // TODO: implement objects state replication frequency and dirtying +} + +template +ReplicateItem* AddObjectReplicateItem(NetworkEvent& event, const MessageType& msgData, uint16 partStart, uint16 partSize) +{ + // Reuse or add part item + ReplicateItem* replicateItem = nullptr; + for (auto& e : ReplicationParts) + { + if (e.OwnerFrame == msgData.OwnerFrame && e.Data.Count() == msgData.DataSize && e.ObjectId == msgData.ObjectId) + { + // Reuse + replicateItem = &e; + break; + } + } + if (!replicateItem) + { + // Add + replicateItem = &ReplicationParts.AddOne(); + replicateItem->ObjectId = msgData.ObjectId; + replicateItem->PartsLeft = msgData.PartsCount; + replicateItem->OwnerFrame = msgData.OwnerFrame; + replicateItem->Data.Resize(msgData.DataSize); + } + + // Copy part data + ASSERT(replicateItem->PartsLeft > 0); + replicateItem->PartsLeft--; + ASSERT(partStart + partSize <= replicateItem->Data.Count()); + const void* partData = event.Message.SkipBytes(partSize); + Platform::MemoryCopy(replicateItem->Data.Get() + partStart, partData, partSize); + + return replicateItem; +} + +void InvokeObjectReplication(NetworkReplicatedObject& item, uint32 ownerFrame, byte* data, uint32 dataSize) +{ + ScriptingObject* obj = item.Object.Get(); + if (!obj) + return; + + // Skip replication if we own the object (eg. late replication message after ownership change) + if (item.Role == NetworkObjectRole::OwnedAuthoritative) + return; + + // Drop object replication if it has old data (eg. newer message was already processed due to unordered channel usage) + if (item.LastOwnerFrame >= ownerFrame) + return; + item.LastOwnerFrame = ownerFrame; + + // Setup message reading stream + if (CachedReadStream == nullptr) + CachedReadStream = New(); + NetworkStream* stream = CachedReadStream; + stream->Initialize(data, dataSize); + + // Deserialize object + const bool failed = NetworkReplicator::InvokeSerializer(obj->GetTypeHandle(), obj, stream, false); + if (failed) + { + //NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Cannot serialize object {} of type {} (missing serialization logic)", item.ToString(), obj->GetType().ToString()); + } + + if (item.AsNetworkObject) + item.AsNetworkObject->OnNetworkDeserialize(); + + // Speed up replication of client-owned objects to other clients from server to reduce lag (data has to go from client to server and then to other clients) + if (NetworkManager::IsServer()) + DirtyObjectImpl(item, obj); +} + #if !COMPILE_WITHOUT_CSHARP #include "Engine/Scripting/ManagedCLR/MUtils.h" @@ -757,11 +854,6 @@ void NetworkReplicator::SetObjectOwnership(ScriptingObject* obj, uint32 ownerCli } } -void DirtyObjectImpl(NetworkReplicatedObject& item, ScriptingObject* obj) -{ - // TODO: implement objects state replication frequency and dirtying -} - void NetworkReplicator::DirtyObject(ScriptingObject* obj) { ScopeLock lock(ObjectsLock); @@ -853,6 +945,7 @@ void NetworkInternal::NetworkReplicatorClear() Objects.Remove(it); } } + RpcQueue.Clear(); SpawnQueue.Clear(); DespawnQueue.Clear(); IdsRemappingTable.Clear(); @@ -1021,6 +1114,31 @@ void NetworkInternal::NetworkReplicatorUpdate() SpawnQueue.Clear(); } + // Apply parts replication + for (int32 i = ReplicationParts.Count() - 1; i >= 0; i--) + { + auto& e = ReplicationParts[i]; + if (e.PartsLeft > 0) + { + // TODO: remove replication items after some TTL to prevent memory leaks + continue; + } + ScriptingObject* obj = e.Object.Get(); + if (obj) + { + auto it = Objects.Find(obj->GetID()); + if (it != Objects.End()) + { + auto& item = it->Item; + + // Replicate from all collected parts data + InvokeObjectReplication(item, e.OwnerFrame, e.Data.Get(), e.Data.Count()); + } + } + + ReplicationParts.RemoveAt(i); + } + // Brute force synchronize all networked objects with clients // TODO: introduce NetworkReplicationHierarchy to optimize objects replication in large worlds (eg. batched culling networked scene objects that are too far from certain client to be relevant) // TODO: per-object sync interval (in frames) - could be scaled by hierarchy (eg. game could slow down sync rate for objects far from player) @@ -1066,10 +1184,27 @@ void NetworkInternal::NetworkReplicatorUpdate() } GetNetworkName(msgData.ObjectTypeName, obj->GetType().Fullname); msgData.DataSize = size; - // TODO: split object data (eg. more messages) if needed + const uint32 msgMaxData = peer->Config.MessageSize - sizeof(NetworkMessageObjectReplicate); + const uint32 partMaxData = peer->Config.MessageSize - sizeof(NetworkMessageObjectReplicatePart); + 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) + msgData.PartsCount = partsCount; NetworkMessage msg = peer->BeginSendMessage(); msg.WriteStructure(msgData); - msg.WriteBytes(stream->GetBuffer(), size); + msg.WriteBytes(stream->GetBuffer(), msgDataSize); if (isClient) peer->EndSendMessage(NetworkChannelType::Unreliable, msg); else @@ -1079,6 +1214,27 @@ void NetworkInternal::NetworkReplicatorUpdate() peer->EndSendMessage(NetworkChannelType::Unreliable, msg, CachedTargets); } + // Send all other parts + for (uint32 partIndex = 1; partIndex < partsCount; partIndex++) + { + NetworkMessageObjectReplicatePart msgDataPart; + msgDataPart.OwnerFrame = msgData.OwnerFrame; + msgDataPart.ObjectId = msgData.ObjectId; + msgDataPart.DataSize = msgData.DataSize; + msgDataPart.PartsCount = msgData.PartsCount; + msgDataPart.PartStart = dataStart; + msgDataPart.PartSize = Math::Min(size - dataStart, partMaxData); + msg = peer->BeginSendMessage(); + msg.WriteStructure(msgDataPart); + msg.WriteBytes(stream->GetBuffer() + msgDataPart.PartStart, msgDataPart.PartSize); + dataStart += msgDataPart.PartSize; + if (isClient) + peer->EndSendMessage(NetworkChannelType::Unreliable, msg); + else + peer->EndSendMessage(NetworkChannelType::Unreliable, msg, CachedTargets); + } + ASSERT_LOW_LAYER(dataStart == size); + // TODO: stats for bytes send per object type } } @@ -1136,52 +1292,39 @@ void NetworkInternal::OnNetworkMessageObjectReplicate(NetworkEvent& event, Netwo if (DespawnedObjects.Contains(msgData.ObjectId)) return; // Skip replicating not-existing objects NetworkReplicatedObject* e = ResolveObject(msgData.ObjectId, msgData.ParentId, msgData.ObjectTypeName); - if (e) + if (!e) + return; + auto& item = *e; + + // Reject event from someone who is not an object owner + if (client && item.OwnerClientId != client->ClientId) + return; + + if (msgData.PartsCount == 1) { - auto& item = *e; - ScriptingObject* obj = item.Object.Get(); - if (!obj) - return; - - // Reject event from someone who is not an object owner - if (client && item.OwnerClientId != client->ClientId) - return; - - // Skip replication if we own the object (eg. late replication message after ownership change) - if (item.Role == NetworkObjectRole::OwnedAuthoritative) - return; - - // Drop object replication if it has old data (eg. newer message was already processed due to unordered channel usage) - if (item.LastOwnerFrame >= msgData.OwnerFrame) - return; - item.LastOwnerFrame = msgData.OwnerFrame; - - // Setup message reading stream - if (CachedReadStream == nullptr) - CachedReadStream = New(); - NetworkStream* stream = CachedReadStream; - stream->Initialize(event.Message.Buffer + event.Message.Position, msgData.DataSize); - - // Deserialize object - const bool failed = NetworkReplicator::InvokeSerializer(obj->GetTypeHandle(), obj, stream, false); - if (failed) - { - //NETWORK_REPLICATOR_LOG(Error, "[NetworkReplicator] Cannot serialize object {} of type {} (missing serialization logic)", item.ToString(), obj->GetType().ToString()); - } - - if (item.AsNetworkObject) - item.AsNetworkObject->OnNetworkDeserialize(); - - // Speed up replication of client-owned objects to other clients from server to reduce lag (data has to go from client to server and then to other clients) - if (NetworkManager::IsServer()) - DirtyObjectImpl(item, obj); + // Replicate + InvokeObjectReplication(item, msgData.OwnerFrame, event.Message.Buffer + event.Message.Position, msgData.DataSize); } else { - // TODO: put message to the queue to be resolved later (eg. object replication came before spawn packet) - use TTL to prevent memory overgrowing + // Add to replication from multiple parts + const uint16 msgMaxData = peer->Config.MessageSize - sizeof(NetworkMessageObjectReplicate); + ReplicateItem* replicateItem = AddObjectReplicateItem(event, msgData, 0, msgMaxData); + replicateItem->Object = e->Object; } } +void NetworkInternal::OnNetworkMessageObjectReplicatePart(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer) +{ + NetworkMessageObjectReplicatePart msgData; + event.Message.ReadStructure(msgData); + ScopeLock lock(ObjectsLock); + if (DespawnedObjects.Contains(msgData.ObjectId)) + return; // Skip replicating not-existing objects + + AddObjectReplicateItem(event, msgData, msgData.PartStart, msgData.PartSize); +} + void NetworkInternal::OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkClient* client, NetworkPeer* peer) { NetworkMessageObjectSpawn msgData; @@ -1341,10 +1484,7 @@ void NetworkInternal::OnNetworkMessageObjectSpawn(NetworkEvent& event, NetworkCl auto sceneObject = ScriptingObject::Cast(obj); if (sceneObject) { - if (parent && parent - -> - Object.Get() && parent->Object->Is() - ) + if (parent && parent->Object.Get() && parent->Object->Is()) sceneObject->SetParent(parent->Object.As()); else if (auto* parentActor = Scripting::TryFindObject(msgDataItem.ParentId)) sceneObject->SetParent(parentActor); From 98c29c4a4efd7c728cf75775386a34d99375dffe Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 3 Dec 2022 10:42:58 +0100 Subject: [PATCH 48/83] Optimize compilation time --- Source/Editor/Analytics/EditorAnalytics.cpp | 1 + Source/Engine/Core/Types/Guid.h | 16 +++--------- Source/Engine/Core/Types/Pair.h | 8 +++--- Source/Engine/Foliage/Foliage.h | 4 +-- .../Async/DefaultGPUTasksExecutor.cpp | 3 ++- .../Graphics/Async/GPUTasksExecutor.cpp | 1 + .../Engine/Graphics/Async/GPUTasksExecutor.h | 1 - .../Engine/Graphics/Async/GPUTasksManager.cpp | 22 ++++++---------- .../Engine/Graphics/Async/GPUTasksManager.h | 25 +++---------------- Source/Engine/Graphics/DynamicBuffer.cpp | 2 ++ Source/Engine/Graphics/GPUDevice.cpp | 14 ++++++++--- Source/Engine/Graphics/GPUDevice.h | 17 ++++++++----- Source/Engine/Graphics/GPUSwapChain.cpp | 1 + Source/Engine/Graphics/Graphics.cpp | 4 ++- .../Materials/DecalMaterialShader.cpp | 2 ++ .../Materials/ForwardMaterialShader.cpp | 1 + .../Graphics/Materials/GUIMaterialShader.cpp | 2 ++ .../Graphics/Materials/MaterialShader.cpp | 1 + .../Materials/MaterialShaderFeatures.cpp | 1 + .../Materials/PostFxMaterialShader.cpp | 2 ++ Source/Engine/Graphics/Models/Mesh.cpp | 2 ++ Source/Engine/Graphics/Models/ModelLOD.cpp | 1 + Source/Engine/Graphics/Models/SkinnedMesh.cpp | 3 +++ .../Graphics/Models/SkinnedMeshDrawData.cpp | 1 + .../Graphics/Models/SkinnedModelLOD.cpp | 1 + Source/Engine/Graphics/RenderTargetPool.cpp | 1 + Source/Engine/Graphics/RenderTools.cpp | 1 + .../Shaders/Cache/ShaderAssetBase.cpp | 1 + .../Engine/Graphics/Textures/GPUSampler.cpp | 1 + .../GraphicsDevice/Null/GPUDeviceNull.cpp | 6 +++-- .../Vulkan/GPUDeviceVulkan.Layers.cpp | 1 + .../GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp | 5 ++-- .../Vulkan/GPUPipelineStateVulkan.cpp | 3 ++- .../GraphicsDevice/Vulkan/GPUShaderVulkan.cpp | 3 ++- .../Vulkan/GPUSwapChainVulkan.cpp | 1 + .../Vulkan/GPUTextureVulkan.cpp | 1 + Source/Engine/Level/Actors/AnimatedModel.cpp | 1 + .../Engine/Level/Actors/EnvironmentProbe.cpp | 1 + .../Level/Actors/ExponentialHeightFog.cpp | 1 + Source/Engine/Level/Actors/SplineModel.cpp | 4 ++- Source/Engine/Level/Actors/StaticModel.cpp | 1 + Source/Engine/Localization/LocalizedString.h | 4 +-- .../Particles/Graph/GPU/GPUParticles.cpp | 1 + Source/Engine/Particles/Particles.cpp | 1 + Source/Engine/Profiler/ProfilerGPU.cpp | 2 ++ Source/Engine/Render2D/FontTextureAtlas.cpp | 1 + Source/Engine/Render2D/Render2D.cpp | 1 + .../Renderer/Editor/LightmapUVsDensity.cpp | 1 + .../Renderer/Editor/QuadOverdrawPass.cpp | 1 + .../Engine/Renderer/Editor/VertexColors.cpp | 1 + Source/Engine/Renderer/ForwardPass.cpp | 1 + .../GI/DynamicDiffuseGlobalIllumination.cpp | 1 + .../Renderer/GI/GlobalSurfaceAtlasPass.cpp | 2 ++ .../Renderer/GlobalSignDistanceFieldPass.cpp | 5 ++-- Source/Engine/Renderer/LightPass.cpp | 1 + Source/Engine/Renderer/ReflectionsPass.cpp | 1 + .../Renderer/ScreenSpaceReflectionsPass.cpp | 1 + Source/Engine/Renderer/ShadowsPass.cpp | 1 + Source/Engine/Renderer/Utils/BitonicSort.cpp | 1 + Source/Engine/Renderer/Utils/MultiScaler.cpp | 1 + Source/Engine/Renderer/VolumetricFogPass.cpp | 1 + .../ShadowsOfMordor/Builder.BuildCache.cpp | 1 + .../Engine/ShadowsOfMordor/Builder.Charts.cpp | 1 + .../Engine/ShadowsOfMordor/Builder.Jobs.cpp | 1 + Source/Engine/ShadowsOfMordor/Builder.cpp | 3 +++ Source/Engine/Terrain/TerrainManager.cpp | 1 + .../TextureTool/TextureTool.DirectXTex.cpp | 1 + 67 files changed, 128 insertions(+), 77 deletions(-) diff --git a/Source/Editor/Analytics/EditorAnalytics.cpp b/Source/Editor/Analytics/EditorAnalytics.cpp index 009b0e8ca..daa01a306 100644 --- a/Source/Editor/Analytics/EditorAnalytics.cpp +++ b/Source/Editor/Analytics/EditorAnalytics.cpp @@ -7,6 +7,7 @@ #include "Engine/Core/Log.h" #include "Engine/Core/Math/Vector2.h" #include "Engine/Core/Types/DateTime.h" +#include "Engine/Core/Types/TimeSpan.h" #include "Editor/Editor.h" #include "Editor/ProjectInfo.h" #include "Engine/Engine/EngineService.h" diff --git a/Source/Engine/Core/Types/Guid.h b/Source/Engine/Core/Types/Guid.h index 721d75385..cb92f7eeb 100644 --- a/Source/Engine/Core/Types/Guid.h +++ b/Source/Engine/Core/Types/Guid.h @@ -88,22 +88,14 @@ public: } public: - // Compares two Guids for equality - // @param left The first Guid to compare - // @param right The second Guid to compare - // @returns True if the Guids are equal, otherwise false - friend bool operator==(const Guid& left, const Guid& right) + bool operator==(const Guid& other) const { - return ((left.A ^ right.A) | (left.B ^ right.B) | (left.C ^ right.C) | (left.D ^ right.D)) == 0; + return ((A ^ other.A) | (B ^ other.B) | (C ^ other.C) | (D ^ other.D)) == 0; } - // Compares two Guids for inequality - // @param left The first Guid to compare - // @param right The second Guid to compare - // @returns True if the GUIDs are not equal, otherwise false - friend bool operator!=(const Guid& left, const Guid& right) + bool operator!=(const Guid& other) const { - return ((left.A ^ right.A) | (left.B ^ right.B) | (left.C ^ right.C) | (left.D ^ right.D)) != 0; + return ((A ^ other.A) | (B ^ other.B) | (C ^ other.C) | (D ^ other.D)) != 0; } // Provides access to the GUIDs components diff --git a/Source/Engine/Core/Types/Pair.h b/Source/Engine/Core/Types/Pair.h index 339a8ddfe..deedf1eb5 100644 --- a/Source/Engine/Core/Types/Pair.h +++ b/Source/Engine/Core/Types/Pair.h @@ -81,14 +81,14 @@ public: return *this; } - friend bool operator==(const Pair& a, const Pair& b) + bool operator==(const Pair& other) const { - return a.First == b.First && a.Second == b.Second; + return First == other.First && Second == other.Second; } - friend bool operator!=(const Pair& a, const Pair& b) + bool operator!=(const Pair& other) const { - return a.First != b.First || a.Second != b.Second; + return First != other.First || Second != other.Second; } }; diff --git a/Source/Engine/Foliage/Foliage.h b/Source/Engine/Foliage/Foliage.h index 4bb770612..86c54b49d 100644 --- a/Source/Engine/Foliage/Foliage.h +++ b/Source/Engine/Foliage/Foliage.h @@ -154,9 +154,9 @@ private: const Mesh* Geo; int32 Lightmap; - friend bool operator==(const DrawKey& lhs, const DrawKey& rhs) + bool operator==(const DrawKey& other) const { - return lhs.Mat == rhs.Mat && lhs.Geo == rhs.Geo && lhs.Lightmap == rhs.Lightmap; + return Mat == other.Mat && Geo == other.Geo && Lightmap == other.Lightmap; } friend uint32 GetHash(const DrawKey& key) diff --git a/Source/Engine/Graphics/Async/DefaultGPUTasksExecutor.cpp b/Source/Engine/Graphics/Async/DefaultGPUTasksExecutor.cpp index 680fb8684..dc5a30235 100644 --- a/Source/Engine/Graphics/Async/DefaultGPUTasksExecutor.cpp +++ b/Source/Engine/Graphics/Async/DefaultGPUTasksExecutor.cpp @@ -3,6 +3,7 @@ #include "DefaultGPUTasksExecutor.h" #include "GPUTasksContext.h" #include "GPUTask.h" +#include "GPUTasksManager.h" #include "Engine/Graphics/GPUDevice.h" DefaultGPUTasksExecutor::DefaultGPUTasksExecutor() @@ -30,7 +31,7 @@ void DefaultGPUTasksExecutor::FrameEnd() // Default implementation performs async operations on end of the frame which is synchronized with a rendering thread GPUTask* buffer[32]; - const int32 count = GPUDevice::Instance->TasksManager.RequestWork(buffer, 32); + const int32 count = GPUDevice::Instance->GetTasksManager()->RequestWork(buffer, 32); for (int32 i = 0; i < count; i++) { _context->Run(buffer[i]); diff --git a/Source/Engine/Graphics/Async/GPUTasksExecutor.cpp b/Source/Engine/Graphics/Async/GPUTasksExecutor.cpp index 5c5c6164e..631310134 100644 --- a/Source/Engine/Graphics/Async/GPUTasksExecutor.cpp +++ b/Source/Engine/Graphics/Async/GPUTasksExecutor.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. #include "GPUTasksExecutor.h" +#include "Engine/Core/Log.h" #include "Engine/Graphics/GPUDevice.h" GPUTasksExecutor::~GPUTasksExecutor() diff --git a/Source/Engine/Graphics/Async/GPUTasksExecutor.h b/Source/Engine/Graphics/Async/GPUTasksExecutor.h index 63c2e3af1..71fce2052 100644 --- a/Source/Engine/Graphics/Async/GPUTasksExecutor.h +++ b/Source/Engine/Graphics/Async/GPUTasksExecutor.h @@ -37,7 +37,6 @@ public: /// /// Gets the context list. /// - /// GPU contexts FORCE_INLINE const Array* GetContextList() const { return &_contextList; diff --git a/Source/Engine/Graphics/Async/GPUTasksManager.cpp b/Source/Engine/Graphics/Async/GPUTasksManager.cpp index bbd5bff7f..2cbe31f47 100644 --- a/Source/Engine/Graphics/Async/GPUTasksManager.cpp +++ b/Source/Engine/Graphics/Async/GPUTasksManager.cpp @@ -7,26 +7,13 @@ void GPUTask::Enqueue() { - GPUDevice::Instance->TasksManager._tasks.Add(this); + GPUDevice::Instance->GetTasksManager()->_tasks.Add(this); } -GPUTasksManager::GPUTasksManager(GPUDevice* device) - : _device(device) - , _executor(nullptr) - , _bufferIndex(0) +GPUTasksManager::GPUTasksManager() { _buffers[0].EnsureCapacity(64); _buffers[1].EnsureCapacity(64); - - // Setup executor - SetExecutor(device->CreateTasksExecutor()); - ASSERT(_executor != nullptr); -} - -GPUTasksManager::~GPUTasksManager() -{ - // Ensure that Dispose has been called - ASSERT(_executor == nullptr); } void GPUTasksManager::SetExecutor(GPUTasksExecutor* value) @@ -114,3 +101,8 @@ int32 GPUTasksManager::RequestWork(GPUTask** buffer, int32 maxCount) return count; } + +String GPUTasksManager::ToString() const +{ + return TEXT("GPU Tasks Manager"); +} diff --git a/Source/Engine/Graphics/Async/GPUTasksManager.h b/Source/Engine/Graphics/Async/GPUTasksManager.h index 25639a6fb..e9f2eb18b 100644 --- a/Source/Engine/Graphics/Async/GPUTasksManager.h +++ b/Source/Engine/Graphics/Async/GPUTasksManager.h @@ -22,30 +22,17 @@ class GPUTasksManager : public Object, public NonCopyable friend GPUTask; private: - GPUDevice* _device; - GPUTasksExecutor* _executor; + GPUTasksExecutor* _executor = nullptr; ConcurrentTaskQueue _tasks; Array _buffers[2]; - int32 _bufferIndex; - -private: - GPUTasksManager(GPUDevice* device); - ~GPUTasksManager(); + int32 _bufferIndex = 0; public: - /// - /// Gets the parent Graphics Device. - /// - /// The device. - FORCE_INLINE GPUDevice* GetDevice() const - { - return _device; - } + GPUTasksManager(); /// /// Gets the GPU tasks executor. /// - /// The tasks executor. FORCE_INLINE GPUTasksExecutor* GetExecutor() const { return _executor; @@ -60,7 +47,6 @@ public: /// /// Gets the amount of enqueued tasks to perform. /// - /// The tasks count. FORCE_INLINE int32 GetTaskCount() const { return _tasks.Count(); @@ -94,8 +80,5 @@ public: public: // [Object] - String ToString() const override - { - return TEXT("GPU Tasks Manager"); - } + String ToString() const override; }; diff --git a/Source/Engine/Graphics/DynamicBuffer.cpp b/Source/Engine/Graphics/DynamicBuffer.cpp index d4db1b957..1b0c7249e 100644 --- a/Source/Engine/Graphics/DynamicBuffer.cpp +++ b/Source/Engine/Graphics/DynamicBuffer.cpp @@ -1,10 +1,12 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. #include "DynamicBuffer.h" +#include "GPUContext.h" #include "PixelFormatExtensions.h" #include "GPUDevice.h" #include "Engine/Core/Log.h" #include "Engine/Core/Utilities.h" +#include "Engine/Core/Math/Math.h" #include "Engine/Threading/Threading.h" DynamicBuffer::DynamicBuffer(uint32 initialCapacity, uint32 stride, const String& name) diff --git a/Source/Engine/Graphics/GPUDevice.cpp b/Source/Engine/Graphics/GPUDevice.cpp index b9f1aeba2..133aed0bb 100644 --- a/Source/Engine/Graphics/GPUDevice.cpp +++ b/Source/Engine/Graphics/GPUDevice.cpp @@ -9,10 +9,12 @@ #include "Graphics.h" #include "Shaders/GPUShader.h" #include "Async/DefaultGPUTasksExecutor.h" +#include "Async/GPUTasksManager.h" #include "Engine/Content/Assets/Shader.h" #include "Engine/Content/Assets/Material.h" #include "Engine/Content/Content.h" #include "Engine/Content/SoftAssetReference.h" +#include "Engine/Core/Log.h" #include "Engine/Render2D/Render2D.h" #include "Engine/Engine/CommandLine.h" #include "Engine/Engine/Engine.h" @@ -263,6 +265,7 @@ struct GPUDevice::PrivateData AssetReference DefaultNormalMap; AssetReference DefaultWhiteTexture; AssetReference DefaultBlackTexture; + GPUTasksManager TasksManager; }; GPUDevice* GPUDevice::Instance = nullptr; @@ -277,7 +280,6 @@ GPUDevice::GPUDevice(RendererType type, ShaderProfile profile) , _shaderProfile(profile) , _featureLevel(RenderTools::GetFeatureLevel(profile)) , _res(New()) - , TasksManager(this) , TotalGraphicsMemory(0) , QuadShader(nullptr) , CurrentTask(nullptr) @@ -296,6 +298,7 @@ GPUDevice::~GPUDevice() bool GPUDevice::Init() { + _res->TasksManager.SetExecutor(CreateTasksExecutor()); LOG(Info, "Total graphics memory: {0}", Utilities::BytesToText(TotalGraphicsMemory)); return false; } @@ -492,7 +495,7 @@ void GPUDevice::Draw() // Begin frame context->FrameBegin(); RenderBegin(); - TasksManager.FrameBegin(); + _res->TasksManager.FrameBegin(); Render2D::BeginFrame(); // Perform actual drawing @@ -502,7 +505,7 @@ void GPUDevice::Draw() // End frame Render2D::EndFrame(); - TasksManager.FrameEnd(); + _res->TasksManager.FrameEnd(); RenderEnd(); context->FrameEnd(); @@ -520,6 +523,11 @@ uint64 GPUDevice::GetMemoryUsage() const return Resources.GetMemoryUsage(); } +GPUTasksManager* GPUDevice::GetTasksManager() const +{ + return &_res->TasksManager; +} + MaterialBase* GPUDevice::GetDefaultMaterial() const { return _res->DefaultMaterial; diff --git a/Source/Engine/Graphics/GPUDevice.h b/Source/Engine/Graphics/GPUDevice.h index 5f0f6175c..cae2e86dc 100644 --- a/Source/Engine/Graphics/GPUDevice.h +++ b/Source/Engine/Graphics/GPUDevice.h @@ -3,8 +3,9 @@ #pragma once #include "Engine/Platform/Platform.h" +#include "Engine/Core/Enums.h" +#include "Engine/Core/NonCopyable.h" #include "Engine/Scripting/ScriptingObject.h" -#include "Async/GPUTasksManager.h" #include "GPUResourcesCollection.h" #include "GPUAdapter.h" #include "GPULimits.h" @@ -20,7 +21,11 @@ class GPUTexture; class GPUBuffer; class GPUSampler; class GPUPipelineState; +class GPUConstantBuffer; +class GPUTasksContext; +class GPUTasksExecutor; class GPUSwapChain; +class GPUTasksManager; class Shader; class Model; class Material; @@ -105,11 +110,6 @@ public: /// GPUResourcesCollection Resources; - /// - /// GPU asynchronous work manager. - /// - GPUTasksManager TasksManager; - public: /// /// The total amount of graphics memory in bytes. @@ -220,6 +220,11 @@ public: /// API_PROPERTY() uint64 GetMemoryUsage() const; + /// + /// Gets the GPU asynchronous work manager. + /// + GPUTasksManager* GetTasksManager() const; + /// /// Gets the default material. /// diff --git a/Source/Engine/Graphics/GPUSwapChain.cpp b/Source/Engine/Graphics/GPUSwapChain.cpp index 8dc7f0eee..4d33db407 100644 --- a/Source/Engine/Graphics/GPUSwapChain.cpp +++ b/Source/Engine/Graphics/GPUSwapChain.cpp @@ -4,6 +4,7 @@ #include "GPUDevice.h" #include "Textures/GPUTexture.h" #include "Engine/Core/Log.h" +#include "Engine/Threading/Task.h" class GPUSwapChainDownloadTask : public Task { diff --git a/Source/Engine/Graphics/Graphics.cpp b/Source/Engine/Graphics/Graphics.cpp index bfa897fbd..307b95a21 100644 --- a/Source/Engine/Graphics/Graphics.cpp +++ b/Source/Engine/Graphics/Graphics.cpp @@ -3,6 +3,8 @@ #include "Graphics.h" #include "GPUDevice.h" #include "PixelFormatExtensions.h" +#include "Async/GPUTasksManager.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Config/GraphicsSettings.h" #include "Engine/Engine/CommandLine.h" #include "Engine/Engine/EngineService.h" @@ -194,7 +196,7 @@ void GraphicsService::BeforeExit() if (GPUDevice::Instance) { // Start disposing - GPUDevice::Instance->TasksManager.Dispose(); + GPUDevice::Instance->GetTasksManager()->Dispose(); } } diff --git a/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp b/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp index 54ca0e137..9e44708e7 100644 --- a/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/DecalMaterialShader.cpp @@ -2,7 +2,9 @@ #include "DecalMaterialShader.h" #include "MaterialParams.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Math/OrientedBoundingBox.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Graphics/RenderBuffers.h" diff --git a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp index 9c658f9c9..4328e051c 100644 --- a/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/ForwardMaterialShader.cpp @@ -3,6 +3,7 @@ #include "ForwardMaterialShader.h" #include "MaterialShaderFeatures.h" #include "MaterialParams.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPULimits.h" #include "Engine/Graphics/RenderView.h" diff --git a/Source/Engine/Graphics/Materials/GUIMaterialShader.cpp b/Source/Engine/Graphics/Materials/GUIMaterialShader.cpp index cc2d61775..10c12816e 100644 --- a/Source/Engine/Graphics/Materials/GUIMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/GUIMaterialShader.cpp @@ -2,7 +2,9 @@ #include "GUIMaterialShader.h" #include "MaterialParams.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Math/Viewport.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Graphics/RenderView.h" diff --git a/Source/Engine/Graphics/Materials/MaterialShader.cpp b/Source/Engine/Graphics/Materials/MaterialShader.cpp index ac9453e64..22e126d30 100644 --- a/Source/Engine/Graphics/Materials/MaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/MaterialShader.cpp @@ -6,6 +6,7 @@ #include "Engine/Renderer/RenderList.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/GPUDevice.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/Shaders/GPUConstantBuffer.h" #include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Engine/Time.h" diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp index ed67a0c94..f2e9ffa8a 100644 --- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp +++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp @@ -8,6 +8,7 @@ #if USE_EDITOR #include "Engine/Renderer/Lightmaps.h" #endif +#include "Engine/Graphics/GPUContext.h" #include "Engine/Level/Scene/Lightmap.h" #include "Engine/Level/Actors/EnvironmentProbe.h" diff --git a/Source/Engine/Graphics/Materials/PostFxMaterialShader.cpp b/Source/Engine/Graphics/Materials/PostFxMaterialShader.cpp index ff1ff3fb6..6201f1181 100644 --- a/Source/Engine/Graphics/Materials/PostFxMaterialShader.cpp +++ b/Source/Engine/Graphics/Materials/PostFxMaterialShader.cpp @@ -2,6 +2,8 @@ #include "PostFxMaterialShader.h" #include "MaterialParams.h" +#include "Engine/Core/Log.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/Shaders/GPUShader.h" diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp index db56f3dcc..7cbb5119d 100644 --- a/Source/Engine/Graphics/Models/Mesh.cpp +++ b/Source/Engine/Graphics/Models/Mesh.cpp @@ -4,6 +4,7 @@ #include "ModelInstanceEntry.h" #include "Engine/Content/Assets/Material.h" #include "Engine/Content/Assets/Model.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Math/Transform.h" #include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" @@ -11,6 +12,7 @@ #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Renderer/RenderList.h" #include "Engine/Serialization/MemoryReadStream.h" +#include "Engine/Threading/Task.h" #include "Engine/Threading/Threading.h" #if USE_MONO #include diff --git a/Source/Engine/Graphics/Models/ModelLOD.cpp b/Source/Engine/Graphics/Models/ModelLOD.cpp index 8aa150d84..3f37177f1 100644 --- a/Source/Engine/Graphics/Models/ModelLOD.cpp +++ b/Source/Engine/Graphics/Models/ModelLOD.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. #include "ModelLOD.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Math/Transform.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Serialization/MemoryReadStream.h" diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.cpp b/Source/Engine/Graphics/Models/SkinnedMesh.cpp index f7d5b83ca..d7984d378 100644 --- a/Source/Engine/Graphics/Models/SkinnedMesh.cpp +++ b/Source/Engine/Graphics/Models/SkinnedMesh.cpp @@ -4,12 +4,15 @@ #include "ModelInstanceEntry.h" #include "Engine/Content/Assets/Material.h" #include "Engine/Content/Assets/SkinnedModel.h" +#include "Engine/Core/Log.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Level/Scene/Scene.h" #include "Engine/Renderer/RenderList.h" #include "Engine/Serialization/MemoryReadStream.h" #include "Engine/Profiler/ProfilerCPU.h" +#include "Engine/Threading/Task.h" #include "Engine/Threading/Threading.h" #if USE_MONO #include diff --git a/Source/Engine/Graphics/Models/SkinnedMeshDrawData.cpp b/Source/Engine/Graphics/Models/SkinnedMeshDrawData.cpp index 6f620cea0..6a6b11afe 100644 --- a/Source/Engine/Graphics/Models/SkinnedMeshDrawData.cpp +++ b/Source/Engine/Graphics/Models/SkinnedMeshDrawData.cpp @@ -3,6 +3,7 @@ #include "SkinnedMeshDrawData.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Animations/Config.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Math/Matrix.h" #include "Engine/Core/Math/Matrix3x4.h" diff --git a/Source/Engine/Graphics/Models/SkinnedModelLOD.cpp b/Source/Engine/Graphics/Models/SkinnedModelLOD.cpp index 4508d9940..3356e35d0 100644 --- a/Source/Engine/Graphics/Models/SkinnedModelLOD.cpp +++ b/Source/Engine/Graphics/Models/SkinnedModelLOD.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. #include "SkinnedModelLOD.h" +#include "Engine/Core/Log.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Content/Assets/Model.h" #include "Engine/Serialization/MemoryReadStream.h" diff --git a/Source/Engine/Graphics/RenderTargetPool.cpp b/Source/Engine/Graphics/RenderTargetPool.cpp index 26fa3f6ac..5db3ed27d 100644 --- a/Source/Engine/Graphics/RenderTargetPool.cpp +++ b/Source/Engine/Graphics/RenderTargetPool.cpp @@ -2,6 +2,7 @@ #include "RenderTargetPool.h" #include "GPUDevice.h" +#include "Engine/Core/Log.h" #include "Engine/Engine/Engine.h" struct Entry diff --git a/Source/Engine/Graphics/RenderTools.cpp b/Source/Engine/Graphics/RenderTools.cpp index 912b0ed48..7b498c7d5 100644 --- a/Source/Engine/Graphics/RenderTools.cpp +++ b/Source/Engine/Graphics/RenderTools.cpp @@ -9,6 +9,7 @@ #include "RenderTask.h" #include "Engine/Content/Assets/Model.h" #include "Engine/Content/Assets/SkinnedModel.h" +#include "Engine/Core/Log.h" #include "Engine/Engine/Time.h" const Char* ToString(RendererType value) diff --git a/Source/Engine/Graphics/Shaders/Cache/ShaderAssetBase.cpp b/Source/Engine/Graphics/Shaders/Cache/ShaderAssetBase.cpp index 656424a8b..caebcfc3c 100644 --- a/Source/Engine/Graphics/Shaders/Cache/ShaderAssetBase.cpp +++ b/Source/Engine/Graphics/Shaders/Cache/ShaderAssetBase.cpp @@ -3,6 +3,7 @@ #include "ShaderAssetBase.h" #include "ShaderStorage.h" #include "ShaderCacheManager.h" +#include "Engine/Core/Log.h" #include "Engine/Engine/CommandLine.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/Shaders/GPUShader.h" diff --git a/Source/Engine/Graphics/Textures/GPUSampler.cpp b/Source/Engine/Graphics/Textures/GPUSampler.cpp index 6a1ed592b..8541a447e 100644 --- a/Source/Engine/Graphics/Textures/GPUSampler.cpp +++ b/Source/Engine/Graphics/Textures/GPUSampler.cpp @@ -2,6 +2,7 @@ #include "GPUSampler.h" #include "GPUSamplerDescription.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Types/String.h" #include "Engine/Graphics/GPUDevice.h" diff --git a/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.cpp b/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.cpp index b0b980913..97f9082b8 100644 --- a/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.cpp +++ b/Source/Engine/GraphicsDevice/Null/GPUDeviceNull.cpp @@ -12,6 +12,8 @@ #include "GPUBufferNull.h" #include "GPUSamplerNull.h" #include "GPUSwapChainNull.h" +#include "Engine/Core/Log.h" +#include "Engine/Graphics/Async/GPUTasksManager.h" GPUDeviceNull::GPUDeviceNull() : GPUDevice(RendererType::Null, ShaderProfile::Unknown) @@ -89,13 +91,13 @@ void GPUDeviceNull::Draw() auto context = GetMainContext(); RenderBegin(); - TasksManager.FrameBegin(); + GetTasksManager()->FrameBegin(); context->FrameBegin(); // don't render anything context->FrameEnd(); - TasksManager.FrameEnd(); + GetTasksManager()->FrameEnd(); RenderEnd(); DrawEnd(); diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.Layers.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.Layers.cpp index 522fc1a89..35078629d 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.Layers.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.Layers.cpp @@ -3,6 +3,7 @@ #include "GPUDeviceVulkan.h" #include "RenderToolsVulkan.h" #include "Config.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Collections/ArrayExtensions.h" #include "Engine/Core/Collections/Sorting.h" diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp index 84735cbe3..470469aa1 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp @@ -20,13 +20,14 @@ #include "Config.h" #include "CmdBufferVulkan.h" #include "FlaxEngine.Gen.h" +#include "Engine/Core/Log.h" +#include "Engine/Core/Utilities.h" +#include "Engine/Core/Math/Color32.h" #include "Engine/Core/Collections/ArrayExtensions.h" #include "Engine/Platform/FileSystem.h" #include "Engine/Platform/File.h" #include "Engine/Graphics/Textures/GPUSamplerDescription.h" #include "Engine/Graphics/PixelFormatExtensions.h" -#include "Engine/Core/Utilities.h" -#include "Engine/Core/Math/Color32.h" #include "Engine/Engine/Engine.h" #include "Engine/Engine/Globals.h" #include "Engine/Engine/CommandLine.h" diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUPipelineStateVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUPipelineStateVulkan.cpp index 0cccccf38..5699970b3 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUPipelineStateVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUPipelineStateVulkan.cpp @@ -4,9 +4,10 @@ #include "GPUPipelineStateVulkan.h" #include "RenderToolsVulkan.h" -#include "Engine/Profiler/ProfilerCPU.h" #include "DescriptorSetVulkan.h" #include "GPUShaderProgramVulkan.h" +#include "Engine/Core/Log.h" +#include "Engine/Profiler/ProfilerCPU.h" GPUShaderProgramCSVulkan::~GPUShaderProgramCSVulkan() { diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.cpp index 43205574b..bcfed887e 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.cpp @@ -8,8 +8,9 @@ #include "RenderToolsVulkan.h" #include "CmdBufferVulkan.h" #include "Types.h" -#include "Engine/Serialization/MemoryReadStream.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Types/DataContainer.h" +#include "Engine/Serialization/MemoryReadStream.h" #include "Engine/Graphics/PixelFormatExtensions.h" #if PLATFORM_DESKTOP diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp index b16fe6caa..377ef19ef 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUSwapChainVulkan.cpp @@ -8,6 +8,7 @@ #include "GPUAdapterVulkan.h" #include "GPUContextVulkan.h" #include "CmdBufferVulkan.h" +#include "Engine/Core/Log.h" #include "Engine/Graphics/GPULimits.h" void BackBufferVulkan::Setup(GPUSwapChainVulkan* window, VkImage backbuffer, PixelFormat format, VkExtent3D extent) diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp index eb4466ab8..29510f67d 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.cpp @@ -6,6 +6,7 @@ #include "GPUBufferVulkan.h" #include "GPUContextVulkan.h" #include "RenderToolsVulkan.h" +#include "Engine/Core/Log.h" #include "Engine/Graphics/PixelFormatExtensions.h" #include "Engine/Graphics/Textures/TextureData.h" diff --git a/Source/Engine/Level/Actors/AnimatedModel.cpp b/Source/Engine/Level/Actors/AnimatedModel.cpp index 9ee6bd511..3b65c53a9 100644 --- a/Source/Engine/Level/Actors/AnimatedModel.cpp +++ b/Source/Engine/Level/Actors/AnimatedModel.cpp @@ -9,6 +9,7 @@ #if USE_EDITOR #include "Editor/Editor.h" #endif +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Level/Scene/Scene.h" diff --git a/Source/Engine/Level/Actors/EnvironmentProbe.cpp b/Source/Engine/Level/Actors/EnvironmentProbe.cpp index ee2dca8cc..61dd8834b 100644 --- a/Source/Engine/Level/Actors/EnvironmentProbe.cpp +++ b/Source/Engine/Level/Actors/EnvironmentProbe.cpp @@ -12,6 +12,7 @@ #include "Engine/Content/Content.h" #include "Engine/ContentExporters/AssetExporters.h" #include "Engine/ContentImporters/AssetsImportingManager.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Serialization/Serialization.h" #include "Engine/Level/Scene/Scene.h" diff --git a/Source/Engine/Level/Actors/ExponentialHeightFog.cpp b/Source/Engine/Level/Actors/ExponentialHeightFog.cpp index 45de21532..14d222df8 100644 --- a/Source/Engine/Level/Actors/ExponentialHeightFog.cpp +++ b/Source/Engine/Level/Actors/ExponentialHeightFog.cpp @@ -4,6 +4,7 @@ #include "DirectionalLight.h" #include "Engine/Core/Math/Color.h" #include "Engine/Content/Content.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Renderer/RenderList.h" #include "Engine/Serialization/Serialization.h" #include "Engine/Graphics/RenderView.h" diff --git a/Source/Engine/Level/Actors/SplineModel.cpp b/Source/Engine/Level/Actors/SplineModel.cpp index 67cd56f9c..68f3637db 100644 --- a/Source/Engine/Level/Actors/SplineModel.cpp +++ b/Source/Engine/Level/Actors/SplineModel.cpp @@ -2,12 +2,14 @@ #include "SplineModel.h" #include "Spline.h" -#include "Engine/Engine/Engine.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Math/Matrix3x4.h" +#include "Engine/Engine/Engine.h" #include "Engine/Serialization/Serialization.h" #include "Engine/Graphics/GPUBufferDescription.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPUBuffer.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/RenderTools.h" #include "Engine/Level/Scene/SceneRendering.h" diff --git a/Source/Engine/Level/Actors/StaticModel.cpp b/Source/Engine/Level/Actors/StaticModel.cpp index 6fc9c86a3..539e3caf0 100644 --- a/Source/Engine/Level/Actors/StaticModel.cpp +++ b/Source/Engine/Level/Actors/StaticModel.cpp @@ -4,6 +4,7 @@ #include "Engine/Engine/Engine.h" #include "Engine/Graphics/GPUBuffer.h" #include "Engine/Graphics/GPUBufferDescription.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Serialization/Serialization.h" diff --git a/Source/Engine/Localization/LocalizedString.h b/Source/Engine/Localization/LocalizedString.h index 1af61283a..00a48c26d 100644 --- a/Source/Engine/Localization/LocalizedString.h +++ b/Source/Engine/Localization/LocalizedString.h @@ -34,9 +34,9 @@ public: LocalizedString& operator=(const StringView& value); LocalizedString& operator=(String&& value) noexcept; - friend bool operator==(const LocalizedString& a, const LocalizedString& b) + bool operator==(const LocalizedString& other) const { - return a.Id == b.Id && a.Value == b.Value; + return Id == other.Id && Value == other.Value; } friend bool operator!=(const LocalizedString& a, const LocalizedString& b) diff --git a/Source/Engine/Particles/Graph/GPU/GPUParticles.cpp b/Source/Engine/Particles/Graph/GPU/GPUParticles.cpp index a5e9948f5..a59a733c1 100644 --- a/Source/Engine/Particles/Graph/GPU/GPUParticles.cpp +++ b/Source/Engine/Particles/Graph/GPU/GPUParticles.cpp @@ -8,6 +8,7 @@ #include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPUBuffer.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Graphics/Shaders/GPUConstantBuffer.h" diff --git a/Source/Engine/Particles/Particles.cpp b/Source/Engine/Particles/Particles.cpp index 82c747846..faf8ee270 100644 --- a/Source/Engine/Particles/Particles.cpp +++ b/Source/Engine/Particles/Particles.cpp @@ -12,6 +12,7 @@ #include "Engine/Graphics/GPUPipelineStatePermutations.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/DynamicBuffer.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/RenderTools.h" #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Renderer/DrawCall.h" diff --git a/Source/Engine/Profiler/ProfilerGPU.cpp b/Source/Engine/Profiler/ProfilerGPU.cpp index cbad72e75..fa9ebd94a 100644 --- a/Source/Engine/Profiler/ProfilerGPU.cpp +++ b/Source/Engine/Profiler/ProfilerGPU.cpp @@ -3,9 +3,11 @@ #if COMPILE_WITH_PROFILER #include "ProfilerGPU.h" +#include "Engine/Core/Log.h" #include "Engine/Engine/Engine.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPUTimerQuery.h" +#include "Engine/Graphics/GPUContext.h" RenderStatsData RenderStatsData::Counter; diff --git a/Source/Engine/Render2D/FontTextureAtlas.cpp b/Source/Engine/Render2D/FontTextureAtlas.cpp index 88bc47e0d..75e63dda0 100644 --- a/Source/Engine/Render2D/FontTextureAtlas.cpp +++ b/Source/Engine/Render2D/FontTextureAtlas.cpp @@ -6,6 +6,7 @@ #include "Engine/Graphics/PixelFormat.h" #include "Engine/Graphics/PixelFormatExtensions.h" #include "Engine/Graphics/GPUDevice.h" +#include "Engine/Graphics/Async/GPUTask.h" REGISTER_BINARY_ASSET(FontTextureAtlas, "FlaxEngine.FontTextureAtlas", true); diff --git a/Source/Engine/Render2D/Render2D.cpp b/Source/Engine/Render2D/Render2D.cpp index d929bdb5c..200a77121 100644 --- a/Source/Engine/Render2D/Render2D.cpp +++ b/Source/Engine/Render2D/Render2D.cpp @@ -20,6 +20,7 @@ #include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Graphics/Shaders/GPUConstantBuffer.h" #include "Engine/Animations/AnimationUtils.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Math/Half.h" #include "Engine/Core/Math/Math.h" #include "Engine/Engine/EngineService.h" diff --git a/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp b/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp index 44b947906..2e8232762 100644 --- a/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp +++ b/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp @@ -6,6 +6,7 @@ #include "Engine/Content/Content.h" #include "Engine/Content/Assets/Model.h" #include "Engine/Graphics/GPUDevice.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUPipelineState.h" #include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Graphics/Shaders/GPUConstantBuffer.h" diff --git a/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp b/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp index cd1918988..3033e4afe 100644 --- a/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp +++ b/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp @@ -8,6 +8,7 @@ #include "Engine/Content/Assets/Material.h" #include "Engine/Level/Actors/Decal.h" #include "Engine/Graphics/GPUDevice.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/RenderBuffers.h" diff --git a/Source/Engine/Renderer/Editor/VertexColors.cpp b/Source/Engine/Renderer/Editor/VertexColors.cpp index 4b4a8fc3c..173fbf472 100644 --- a/Source/Engine/Renderer/Editor/VertexColors.cpp +++ b/Source/Engine/Renderer/Editor/VertexColors.cpp @@ -5,6 +5,7 @@ #include "VertexColors.h" #include "Engine/Content/Content.h" #include "Engine/Graphics/GPUDevice.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUPipelineState.h" #include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Graphics/Shaders/GPUConstantBuffer.h" diff --git a/Source/Engine/Renderer/ForwardPass.cpp b/Source/Engine/Renderer/ForwardPass.cpp index b853b71c4..214d725d9 100644 --- a/Source/Engine/Renderer/ForwardPass.cpp +++ b/Source/Engine/Renderer/ForwardPass.cpp @@ -6,6 +6,7 @@ #include "Engine/Content/Assets/Model.h" #include "Engine/Content/Assets/Shader.h" #include "Engine/Content/Content.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/RenderBuffers.h" #include "Engine/Graphics/RenderTargetPool.h" diff --git a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp index 979e33a1c..ecd104bd4 100644 --- a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp +++ b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp @@ -14,6 +14,7 @@ #include "Engine/Content/Content.h" #include "Engine/Debug/DebugDraw.h" #include "Engine/Engine/Time.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/Graphics.h" #include "Engine/Graphics/RenderTask.h" diff --git a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp index 81bfbe831..d6901b7ee 100644 --- a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp +++ b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp @@ -11,10 +11,12 @@ #include "Engine/Engine/Engine.h" #include "Engine/Content/Content.h" #include "Engine/Core/Config/GraphicsSettings.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/RenderBuffers.h" #include "Engine/Graphics/RenderTargetPool.h" +#include "Engine/Graphics/Async/GPUSyncPoint.h" #include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Level/Actors/StaticModel.h" #include "Engine/Level/Scene/SceneRendering.h" diff --git a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp index 5e724388b..48427b8ed 100644 --- a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp +++ b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp @@ -6,6 +6,7 @@ #include "Engine/Core/Collections/HashSet.h" #include "Engine/Engine/Engine.h" #include "Engine/Content/Content.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/Graphics.h" #include "Engine/Graphics/RenderTask.h" @@ -117,9 +118,9 @@ struct RasterizeChunkKey Hash += RasterizeChunkKeyHashResolution * RasterizeChunkKeyHashResolution * RasterizeChunkKeyHashResolution; } - friend bool operator==(const RasterizeChunkKey& a, const RasterizeChunkKey& b) + bool operator==(const RasterizeChunkKey& other) const { - return a.Hash == b.Hash && a.Coord == b.Coord && a.Layer == b.Layer; + return Hash == other.Hash && Coord == other.Coord && Layer == other.Layer; } }; diff --git a/Source/Engine/Renderer/LightPass.cpp b/Source/Engine/Renderer/LightPass.cpp index 5f0bf9de8..0d7fccb47 100644 --- a/Source/Engine/Renderer/LightPass.cpp +++ b/Source/Engine/Renderer/LightPass.cpp @@ -9,6 +9,7 @@ #include "Engine/Graphics/RenderTargetPool.h" #include "Engine/Content/Assets/CubeTexture.h" #include "Engine/Content/Content.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/RenderTask.h" PACK_STRUCT(struct PerLight{ diff --git a/Source/Engine/Renderer/ReflectionsPass.cpp b/Source/Engine/Renderer/ReflectionsPass.cpp index f453e1a41..952f45e54 100644 --- a/Source/Engine/Renderer/ReflectionsPass.cpp +++ b/Source/Engine/Renderer/ReflectionsPass.cpp @@ -6,6 +6,7 @@ #include "ScreenSpaceReflectionsPass.h" #include "Engine/Core/Collections/Sorting.h" #include "Engine/Content/Content.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/RenderBuffers.h" #include "Engine/Graphics/RenderTools.h" #include "Engine/Graphics/RenderTask.h" diff --git a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp index f809707b2..4464ce599 100644 --- a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp +++ b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp @@ -15,6 +15,7 @@ #include "Engine/Platform/Window.h" #include "Utils/MultiScaler.h" #include "Engine/Engine/Engine.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/RenderTask.h" #define RESOLVE_PASS_OUTPUT_FORMAT PixelFormat::R16G16B16A16_Float diff --git a/Source/Engine/Renderer/ShadowsPass.cpp b/Source/Engine/Renderer/ShadowsPass.cpp index 9449c2290..1d7ea1c6c 100644 --- a/Source/Engine/Renderer/ShadowsPass.cpp +++ b/Source/Engine/Renderer/ShadowsPass.cpp @@ -8,6 +8,7 @@ #include "Engine/Graphics/RenderBuffers.h" #include "Engine/Graphics/PixelFormatExtensions.h" #include "Engine/Content/Content.h" +#include "Engine/Graphics/GPUContext.h" #if USE_EDITOR #include "Engine/Renderer/Lightmaps.h" #endif diff --git a/Source/Engine/Renderer/Utils/BitonicSort.cpp b/Source/Engine/Renderer/Utils/BitonicSort.cpp index 08d9ba843..4ebe03e6b 100644 --- a/Source/Engine/Renderer/Utils/BitonicSort.cpp +++ b/Source/Engine/Renderer/Utils/BitonicSort.cpp @@ -3,6 +3,7 @@ #include "BitonicSort.h" #include "Engine/Content/Content.h" #include "Engine/Graphics/GPUBuffer.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPULimits.h" #define INDIRECT_ARGS_STRIDE 12 diff --git a/Source/Engine/Renderer/Utils/MultiScaler.cpp b/Source/Engine/Renderer/Utils/MultiScaler.cpp index 2b8d8ae80..9f65c8fd6 100644 --- a/Source/Engine/Renderer/Utils/MultiScaler.cpp +++ b/Source/Engine/Renderer/Utils/MultiScaler.cpp @@ -3,6 +3,7 @@ #include "MultiScaler.h" #include "Engine/Graphics/Textures/GPUTexture.h" #include "Engine/Content/Content.h" +#include "Engine/Graphics/GPUContext.h" PACK_STRUCT(struct Data { Float2 TexelSize; diff --git a/Source/Engine/Renderer/VolumetricFogPass.cpp b/Source/Engine/Renderer/VolumetricFogPass.cpp index 6fb9c3ce3..552103b14 100644 --- a/Source/Engine/Renderer/VolumetricFogPass.cpp +++ b/Source/Engine/Renderer/VolumetricFogPass.cpp @@ -11,6 +11,7 @@ #include "Engine/Content/Assets/CubeTexture.h" #include "Engine/Content/Content.h" #include "Engine/Engine/Engine.h" +#include "Engine/Graphics/GPUContext.h" // Must match shader source int32 VolumetricFogGridInjectionGroupSize = 4; diff --git a/Source/Engine/ShadowsOfMordor/Builder.BuildCache.cpp b/Source/Engine/ShadowsOfMordor/Builder.BuildCache.cpp index 8b5d694ab..a7da9908a 100644 --- a/Source/Engine/ShadowsOfMordor/Builder.BuildCache.cpp +++ b/Source/Engine/ShadowsOfMordor/Builder.BuildCache.cpp @@ -6,6 +6,7 @@ #include "Engine/Content/Content.h" #include "Engine/ContentImporters/AssetsImportingManager.h" #include "Engine/ContentImporters/ImportTexture.h" +#include "Engine/Core/Log.h" #include "Engine/Graphics/GPUBuffer.h" #include "Engine/Graphics/GPUBufferDescription.h" #include "Engine/Graphics/GPUDevice.h" diff --git a/Source/Engine/ShadowsOfMordor/Builder.Charts.cpp b/Source/Engine/ShadowsOfMordor/Builder.Charts.cpp index 9586ac997..306ba3ddc 100644 --- a/Source/Engine/ShadowsOfMordor/Builder.Charts.cpp +++ b/Source/Engine/ShadowsOfMordor/Builder.Charts.cpp @@ -6,6 +6,7 @@ #include "Engine/Core/Math/Math.h" #include "Engine/Core/Collections/Sorting.h" #include "Engine/ContentImporters/ImportTexture.h" +#include "Engine/Core/Log.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Level/SceneQuery.h" #include "Engine/Level/Scene/Lightmap.h" diff --git a/Source/Engine/ShadowsOfMordor/Builder.Jobs.cpp b/Source/Engine/ShadowsOfMordor/Builder.Jobs.cpp index cffbb6043..ab210a451 100644 --- a/Source/Engine/ShadowsOfMordor/Builder.Jobs.cpp +++ b/Source/Engine/ShadowsOfMordor/Builder.Jobs.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. #include "Builder.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Types/TimeSpan.h" #include "Engine/Engine/Engine.h" #include "Engine/Renderer/Renderer.h" diff --git a/Source/Engine/ShadowsOfMordor/Builder.cpp b/Source/Engine/ShadowsOfMordor/Builder.cpp index 3c82a8ba1..e62f9cc5c 100644 --- a/Source/Engine/ShadowsOfMordor/Builder.cpp +++ b/Source/Engine/ShadowsOfMordor/Builder.cpp @@ -5,11 +5,14 @@ #include "Engine/Level/Scene/Scene.h" #include "Engine/Level/Level.h" #include "Engine/Content/Content.h" +#include "Engine/Core/Log.h" +#include "Engine/Core/Types/TimeSpan.h" #include "Engine/Engine/EngineService.h" #include "Engine/Engine/Globals.h" #include "Engine/Threading/ThreadSpawner.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPUBuffer.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUPipelineState.h" #include "Engine/Graphics/RenderTargetPool.h" #include "Engine/Graphics/Shaders/GPUShader.h" diff --git a/Source/Engine/Terrain/TerrainManager.cpp b/Source/Engine/Terrain/TerrainManager.cpp index 2d8af5153..58baa2f98 100644 --- a/Source/Engine/Terrain/TerrainManager.cpp +++ b/Source/Engine/Terrain/TerrainManager.cpp @@ -12,6 +12,7 @@ #include "Engine/Engine/EngineService.h" #include "Engine/Content/Assets/MaterialBase.h" #include "Engine/Content/AssetReference.h" +#include "Engine/Core/Log.h" #include "Engine/Renderer/DrawCall.h" // Must match structure defined in Terrain.shader diff --git a/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp b/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp index 4b5fb4897..7baa7493c 100644 --- a/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp +++ b/Source/Engine/Tools/TextureTool/TextureTool.DirectXTex.cpp @@ -9,6 +9,7 @@ #include "Engine/Platform/CriticalSection.h" #include "Engine/Platform/ConditionVariable.h" #include "Engine/Graphics/RenderTools.h" +#include "Engine/Graphics/Async/GPUTask.h" #include "Engine/Graphics/Textures/TextureUtils.h" #include "Engine/Graphics/Textures/TextureData.h" #include "Engine/Graphics/PixelFormatExtensions.h" From 950289db9f93af31525a2cfb62cb60f47785b99f Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 3 Dec 2022 11:23:26 +0100 Subject: [PATCH 49/83] Fix crash when drawing scene in async and content streaming updates model residency --- Source/Engine/Level/Scene/SceneRendering.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Level/Scene/SceneRendering.cpp b/Source/Engine/Level/Scene/SceneRendering.cpp index 07990cb79..55d3946e3 100644 --- a/Source/Engine/Level/Scene/SceneRendering.cpp +++ b/Source/Engine/Level/Scene/SceneRendering.cpp @@ -42,9 +42,21 @@ FORCE_INLINE bool FrustumsListCull(const BoundingSphere& bounds, const ArrayScenes.Add(this); + + // Add additional lock during scene rendering (prevents any Actors cache modifications on content streaming threads - eg. when model residency changes) + Locker.Lock(); + } + else if (category == PostRender) + { + // Release additional lock + Locker.Unlock(); + } auto& view = renderContextBatch.GetMainContext().View; - for (auto& renderContext : renderContextBatch.Contexts) - renderContext.List->Scenes.Add(this); auto& list = Actors[(int32)category]; _drawListData = list.Get(); _drawListSize = list.Count(); From df45ac46b1d55ec52f20b81a1f05b5ca13cdf481 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 3 Dec 2022 12:23:39 +0100 Subject: [PATCH 50/83] Optimize various debug views performance --- Source/Engine/Content/Assets/Model.cpp | 2 + Source/Engine/Graphics/Models/Mesh.cpp | 18 +++++++ Source/Engine/Graphics/Models/ModelLOD.h | 9 ++++ Source/Engine/Renderer/Editor/LODPreview.cpp | 23 ++------- .../Renderer/Editor/LightmapUVsDensity.cpp | 51 +++++-------------- .../Renderer/Editor/LightmapUVsDensity.h | 4 -- .../Renderer/Editor/MaterialComplexity.cpp | 2 + Source/Engine/Renderer/GBufferPass.cpp | 13 +++++ Source/Engine/Renderer/GBufferPass.h | 14 +++++ Source/Engine/Renderer/Renderer.cpp | 3 ++ 10 files changed, 78 insertions(+), 61 deletions(-) diff --git a/Source/Engine/Content/Assets/Model.cpp b/Source/Engine/Content/Assets/Model.cpp index 9c7110692..c57b9c7be 100644 --- a/Source/Engine/Content/Assets/Model.cpp +++ b/Source/Engine/Content/Assets/Model.cpp @@ -722,6 +722,7 @@ bool Model::Init(const Span& meshesCountPerLod) { auto& lod = LODs[lodIndex]; lod._model = this; + lod._lodIndex = lodIndex; lod.ScreenSize = 1.0f; const int32 meshesCount = meshesCountPerLod[lodIndex]; if (meshesCount <= 0 || meshesCount > MODEL_MAX_MESHES) @@ -922,6 +923,7 @@ Asset::LoadResult Model::load() { auto& lod = LODs[lodIndex]; lod._model = this; + lod._lodIndex = lodIndex; // Screen Size stream->ReadFloat(&lod.ScreenSize); diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp index 7cbb5119d..5e5e3eae8 100644 --- a/Source/Engine/Graphics/Models/Mesh.cpp +++ b/Source/Engine/Graphics/Models/Mesh.cpp @@ -14,6 +14,9 @@ #include "Engine/Serialization/MemoryReadStream.h" #include "Engine/Threading/Task.h" #include "Engine/Threading/Threading.h" +#if USE_EDITOR +#include "Engine/Renderer/GBufferPass.h" +#endif #if USE_MONO #include #endif @@ -436,6 +439,11 @@ void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, cons drawCall.Surface.LODDitherFactor = 0.0f; drawCall.WorldDeterminantSign = Math::FloatSelect(world.RotDeterminant(), 1, -1); drawCall.PerInstanceRandom = perInstanceRandom; +#if USE_EDITOR + const ViewMode viewMode = renderContext.View.Mode; + if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::VertexColors) + GBufferPass::AddIndexBufferToModelLOD(_indexBuffer, &((Model*)_model)->LODs[_lodIndex]); +#endif // Push draw call to the render list renderContext.List->AddDrawCall(renderContext, drawModes, flags, drawCall, receiveDecals); @@ -497,6 +505,11 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float drawCall.Surface.LODDitherFactor = lodDitherFactor; drawCall.WorldDeterminantSign = Math::FloatSelect(drawCall.World.RotDeterminant(), 1, -1); drawCall.PerInstanceRandom = info.PerInstanceRandom; +#if USE_EDITOR + const ViewMode viewMode = renderContext.View.Mode; + if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::VertexColors) + GBufferPass::AddIndexBufferToModelLOD(_indexBuffer, &((Model*)_model)->LODs[_lodIndex]); +#endif // Push draw call to the render list renderContext.List->AddDrawCall(renderContext, drawModes, info.Flags, drawCall, entry.ReceiveDecals); @@ -552,6 +565,11 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in drawCall.Surface.LODDitherFactor = lodDitherFactor; drawCall.WorldDeterminantSign = Math::FloatSelect(drawCall.World.RotDeterminant(), 1, -1); drawCall.PerInstanceRandom = info.PerInstanceRandom; +#if USE_EDITOR + const ViewMode viewMode = renderContextBatch.GetMainContext().View.Mode; + if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::VertexColors) + GBufferPass::AddIndexBufferToModelLOD(_indexBuffer, &((Model*)_model)->LODs[_lodIndex]); +#endif // Push draw call to the render lists const auto shadowsMode = (ShadowsCastingMode)(entry.ShadowsMode & slot.ShadowsMode); diff --git a/Source/Engine/Graphics/Models/ModelLOD.h b/Source/Engine/Graphics/Models/ModelLOD.h index 1f44ae39f..9c4c852b4 100644 --- a/Source/Engine/Graphics/Models/ModelLOD.h +++ b/Source/Engine/Graphics/Models/ModelLOD.h @@ -17,6 +17,7 @@ API_CLASS(NoSpawn) class FLAXENGINE_API ModelLOD : public ScriptingObject friend Mesh; private: Model* _model = nullptr; + int32 _lodIndex = 0; uint32 _verticesCount; public: @@ -40,6 +41,14 @@ public: return Meshes.HasItems() && Meshes.Last().IsInitialized(); } + /// + /// Gets the model LOD index. + /// + API_PROPERTY() FORCE_INLINE int32 GetLODIndex() const + { + return _lodIndex; + } + /// /// Gets the vertex count for this model LOD level. /// diff --git a/Source/Engine/Renderer/Editor/LODPreview.cpp b/Source/Engine/Renderer/Editor/LODPreview.cpp index 612de21a8..eb4ce7b6a 100644 --- a/Source/Engine/Renderer/Editor/LODPreview.cpp +++ b/Source/Engine/Renderer/Editor/LODPreview.cpp @@ -10,6 +10,7 @@ #include "Engine/Graphics/RenderTask.h" #include "Engine/Renderer/DrawCall.h" #include "Engine/Renderer/RenderList.h" +#include "Engine/Renderer/GBufferPass.h" LODPreviewMaterialShader::LODPreviewMaterialShader() { @@ -47,26 +48,10 @@ void LODPreviewMaterialShader::Bind(BindParameters& params) // Find the LOD that produced this draw call int32 lodIndex = 0; auto& drawCall = *params.FirstDrawCall; - for (auto& e : Content::GetAssetsRaw()) + const ModelLOD* drawCallModelLod; + if (GBufferPass::IndexBufferToModelLOD.TryGet(drawCall.Geometry.IndexBuffer, drawCallModelLod)) { - auto model = ScriptingObject::Cast(e.Value); - if (!model) - continue; - bool found = false; - for (const auto& lod : model->LODs) - { - for (const auto& mesh : lod.Meshes) - { - if (mesh.GetIndexBuffer() == drawCall.Geometry.IndexBuffer) - { - lodIndex = mesh.GetLODIndex(); - found = true; - break; - } - } - } - if (found) - break; + lodIndex = drawCallModelLod->GetLODIndex(); } // Bind diff --git a/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp b/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp index 2e8232762..ebaa86e2b 100644 --- a/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp +++ b/Source/Engine/Renderer/Editor/LightmapUVsDensity.cpp @@ -7,6 +7,7 @@ #include "Engine/Content/Assets/Model.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPUContext.h" +#include "Engine/Renderer/GBufferPass.h" #include "Engine/Graphics/GPUPipelineState.h" #include "Engine/Graphics/Shaders/GPUShader.h" #include "Engine/Graphics/Shaders/GPUConstantBuffer.h" @@ -125,7 +126,9 @@ void LightmapUVsDensityMaterialShader::Bind(BindParameters& params) float scaleInLightmap = 1.0f; if (params.RenderContext.Task) { - if (params.RenderContext.Task->ActorsSource & ActorsSources::CustomActors) + // Skip this lookup as it's too slow + + /*if (params.RenderContext.Task->ActorsSource & ActorsSources::CustomActors) { for (auto actor : params.RenderContext.Task->CustomActors) { @@ -142,33 +145,7 @@ void LightmapUVsDensityMaterialShader::Bind(BindParameters& params) if (drawCallActor) break; } - } - } - - // Find the model that produced this draw call - const Model* drawCallModel = nullptr; - const ModelLOD* drawCallModelLod = nullptr; - const Mesh* drawCallMesh = nullptr; - for (auto& e : Content::GetAssetsRaw()) - { - auto model = ScriptingObject::Cast(e.Value); - if (!model) - continue; - for (const auto& lod : model->LODs) - { - for (const auto& mesh : lod.Meshes) - { - if (mesh.GetIndexBuffer() == drawCall.Geometry.IndexBuffer) - { - drawCallModel = model; - drawCallModelLod = &lod; - drawCallMesh = &mesh; - break; - } - } - } - if (drawCallModel) - break; + }*/ } // Bind constants @@ -188,21 +165,19 @@ void LightmapUVsDensityMaterialShader::Bind(BindParameters& params) data.LightmapTexelsPerWorldUnit = ShadowsOfMordor::LightmapTexelsPerWorldUnit; data.LightmapSize = 1024.0f; data.LightmapArea = drawCall.Surface.LightmapUVsArea; - if (drawCallModel) + const ModelLOD* drawCallModelLod; + if (GBufferPass::IndexBufferToModelLOD.TryGet(drawCall.Geometry.IndexBuffer, drawCallModelLod)) { // Calculate current lightmap slot size for the object (matches the ShadowsOfMordor calculations when baking the lighting) float globalObjectsScale = 1.0f; int32 atlasSize = 1024; int32 chartsPadding = 3; - if (drawCallActor) + const Scene* drawCallScene = drawCallActor ? drawCallActor->GetScene() : (Level::Scenes.Count() != 0 ? Level::Scenes[0] : nullptr); + if (drawCallScene) { - const Scene* drawCallScene = drawCallActor->GetScene(); - if (drawCallScene) - { - globalObjectsScale = drawCallScene->Info.LightmapSettings.GlobalObjectsScale; - atlasSize = (int32)drawCallScene->Info.LightmapSettings.AtlasSize; - chartsPadding = drawCallScene->Info.LightmapSettings.ChartsPadding; - } + globalObjectsScale = drawCallScene->Info.LightmapSettings.GlobalObjectsScale; + atlasSize = (int32)drawCallScene->Info.LightmapSettings.AtlasSize; + chartsPadding = drawCallScene->Info.LightmapSettings.ChartsPadding; } BoundingBox box = drawCallModelLod->GetBox(drawCall.World); Float3 size = box.GetSize(); @@ -219,7 +194,7 @@ void LightmapUVsDensityMaterialShader::Bind(BindParameters& params) const int32 maximumChartSize = atlasSize - chartsPadding * 2; int32 width = Math::Clamp(Math::CeilToInt(scale), ShadowsOfMordor::LightmapMinChartSize, maximumChartSize); int32 height = Math::Clamp(Math::CeilToInt(scale), ShadowsOfMordor::LightmapMinChartSize, maximumChartSize); - float invSize = 1.0f / atlasSize; + float invSize = 1.0f / (float)atlasSize; data.LightmapArea = Rectangle(0, 0, width * invSize, height * invSize); data.LightmapSize = (float)atlasSize; } diff --git a/Source/Engine/Renderer/Editor/LightmapUVsDensity.h b/Source/Engine/Renderer/Editor/LightmapUVsDensity.h index 9c293ca57..99ece19a5 100644 --- a/Source/Engine/Renderer/Editor/LightmapUVsDensity.h +++ b/Source/Engine/Renderer/Editor/LightmapUVsDensity.h @@ -17,27 +17,23 @@ class GPUPipelineState; class LightmapUVsDensityMaterialShader : public IMaterial { private: - AssetReference _shader; AssetReference _gridTexture; GPUPipelineState* _ps = nullptr; MaterialInfo _info; public: - LightmapUVsDensityMaterialShader(); virtual ~LightmapUVsDensityMaterialShader() { } private: - #if COMPILE_WITH_DEV_ENV void OnShaderReloading(Asset* obj); #endif public: - // [IMaterial] const MaterialInfo& GetInfo() const override; GPUShader* GetShader() const override; diff --git a/Source/Engine/Renderer/Editor/MaterialComplexity.cpp b/Source/Engine/Renderer/Editor/MaterialComplexity.cpp index 569050f5e..4aa18beda 100644 --- a/Source/Engine/Renderer/Editor/MaterialComplexity.cpp +++ b/Source/Engine/Renderer/Editor/MaterialComplexity.cpp @@ -102,6 +102,8 @@ MaterialComplexityMaterialShader::MaterialComplexityMaterialShader() void MaterialComplexityMaterialShader::DebugOverrideDrawCallsMaterial(RenderContext& renderContext) { + PROFILE_CPU(); + // Cache 'ready' state for wrappers bool isReady[ARRAY_COUNT(_wrappers) + 1]; for (int32 i = 0; i < ARRAY_COUNT(_wrappers); i++) diff --git a/Source/Engine/Renderer/GBufferPass.cpp b/Source/Engine/Renderer/GBufferPass.cpp index 87ce7a432..2d5f6eadf 100644 --- a/Source/Engine/Renderer/GBufferPass.cpp +++ b/Source/Engine/Renderer/GBufferPass.cpp @@ -27,6 +27,11 @@ PACK_STRUCT(struct GBufferPassData{ int32 ViewMode; }); +#if USE_EDITOR +Dictionary GBufferPass::IndexBufferToModelLOD; +CriticalSection GBufferPass::Locker; +#endif + String GBufferPass::ToString() const { return TEXT("GBufferPass"); @@ -97,6 +102,7 @@ void GBufferPass::Dispose() SAFE_DELETE(_vertexColors); SAFE_DELETE(_lodPreview); SAFE_DELETE(_materialComplexity); + IndexBufferToModelLOD.SetCapacity(0); #endif } @@ -106,6 +112,7 @@ void DebugOverrideDrawCallsMaterial(const RenderContext& renderContext, IMateria { if (!material->IsReady()) return; + PROFILE_CPU(); IMaterial::InstancingHandler handler; const bool canUseInstancing = material->CanUseInstancing(handler); const auto drawModes = material->GetDrawModes(); @@ -318,6 +325,12 @@ GPUTextureView* GBufferPass::RenderSkybox(RenderContext& renderContext, GPUConte #if USE_EDITOR +void GBufferPass::PreOverrideDrawCalls(RenderContext& renderContext) +{ + // Clear cache before scene drawing + IndexBufferToModelLOD.Clear(); +} + void GBufferPass::OverrideDrawCalls(RenderContext& renderContext) { // Override draw calls material to use material debug shader diff --git a/Source/Engine/Renderer/GBufferPass.h b/Source/Engine/Renderer/GBufferPass.h index 81a65a108..61ed58a23 100644 --- a/Source/Engine/Renderer/GBufferPass.h +++ b/Source/Engine/Renderer/GBufferPass.h @@ -3,6 +3,9 @@ #pragma once #include "RendererPass.h" +#if USE_EDITOR +#include "Engine/Core/Collections/Dictionary.h" +#endif /// /// Rendering scene to the GBuffer @@ -46,6 +49,17 @@ public: GPUTextureView* RenderSkybox(RenderContext& renderContext, GPUContext* context); #if USE_EDITOR + // Temporary cache for faster debug previews drawing (used only during frame rendering). + static Dictionary IndexBufferToModelLOD; + static CriticalSection Locker; + + FORCE_INLINE static void AddIndexBufferToModelLOD(GPUBuffer* indexBuffer, const ModelLOD* modelLod) + { + Locker.Lock(); + IndexBufferToModelLOD[indexBuffer] = modelLod; + Locker.Unlock(); + } + void PreOverrideDrawCalls(RenderContext& renderContext); void OverrideDrawCalls(RenderContext& renderContext); void DrawMaterialComplexity(RenderContext& renderContext, GPUContext* context, GPUTextureView* lightBuffer); #endif diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp index 10fde8f51..0a2aefab5 100644 --- a/Source/Engine/Renderer/Renderer.cpp +++ b/Source/Engine/Renderer/Renderer.cpp @@ -347,6 +347,9 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont } if (drawShadows) ShadowsPass::Instance()->SetupShadows(renderContext, renderContextBatch); +#if USE_EDITOR + GBufferPass::Instance()->PreOverrideDrawCalls(renderContext); +#endif // Dispatch drawing (via JobSystem - multiple job batches for every scene) JobSystem::SetJobStartingOnDispatch(false); From 2b6e3cf99327b5e859484ca0236d7aaedd0b46bc Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 3 Dec 2022 13:10:47 +0100 Subject: [PATCH 51/83] Fix lod preview typo in df45ac46b1d55ec52f20b81a1f05b5ca13cdf481 --- Source/Engine/Graphics/Models/Mesh.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp index 5e5e3eae8..ee2ed5de6 100644 --- a/Source/Engine/Graphics/Models/Mesh.cpp +++ b/Source/Engine/Graphics/Models/Mesh.cpp @@ -441,7 +441,7 @@ void Mesh::Draw(const RenderContext& renderContext, MaterialBase* material, cons drawCall.PerInstanceRandom = perInstanceRandom; #if USE_EDITOR const ViewMode viewMode = renderContext.View.Mode; - if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::VertexColors) + if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::LODPreview) GBufferPass::AddIndexBufferToModelLOD(_indexBuffer, &((Model*)_model)->LODs[_lodIndex]); #endif @@ -507,7 +507,7 @@ void Mesh::Draw(const RenderContext& renderContext, const DrawInfo& info, float drawCall.PerInstanceRandom = info.PerInstanceRandom; #if USE_EDITOR const ViewMode viewMode = renderContext.View.Mode; - if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::VertexColors) + if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::LODPreview) GBufferPass::AddIndexBufferToModelLOD(_indexBuffer, &((Model*)_model)->LODs[_lodIndex]); #endif @@ -567,7 +567,7 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in drawCall.PerInstanceRandom = info.PerInstanceRandom; #if USE_EDITOR const ViewMode viewMode = renderContextBatch.GetMainContext().View.Mode; - if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::VertexColors) + if (viewMode == ViewMode::LightmapUVsDensity || viewMode == ViewMode::LODPreview) GBufferPass::AddIndexBufferToModelLOD(_indexBuffer, &((Model*)_model)->LODs[_lodIndex]); #endif From b85d58db85c86026bf4269f7de505e4ed5eaaafa Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 3 Dec 2022 13:17:24 +0100 Subject: [PATCH 52/83] Mark UWP platform as deprecated --- Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp | 2 ++ Source/Editor/Windows/GameCookerWindow.cs | 1 + 2 files changed, 3 insertions(+) diff --git a/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp b/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp index f9331dc66..01f8a1a83 100644 --- a/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp +++ b/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp @@ -497,6 +497,8 @@ bool UWPPlatformTools::OnPerformAOT(CookingData& data, AotConfig& config, const bool UWPPlatformTools::OnPostProcess(CookingData& data) { + LOG(Error, "UWP (Windows Store) platform has been deprecated and soon will be removed!"); + // Special case for UWP // FlaxEngine.dll cannot be added to the solution as `Content` item (due to conflicts with C++ /CX FlaxEngine.dll) // Use special directory for it (generated UWP project handles this case and copies lib to the output) diff --git a/Source/Editor/Windows/GameCookerWindow.cs b/Source/Editor/Windows/GameCookerWindow.cs index e2fb99464..89dec1c4e 100644 --- a/Source/Editor/Windows/GameCookerWindow.cs +++ b/Source/Editor/Windows/GameCookerWindow.cs @@ -257,6 +257,7 @@ namespace FlaxEditor.Windows break; case PlatformType.UWP: name = "Windows Store"; + layout.Label("UWP (Windows Store) platform has been deprecated and soon will be removed!", TextAlignment.Center).Label.TextColor = Color.Red; break; case PlatformType.Linux: name = "Linux"; From a0a087fc91e43f686c443e3e561337631b69a068 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sat, 3 Dec 2022 13:17:24 +0100 Subject: [PATCH 53/83] Mark UWP platform as deprecated --- Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp | 2 ++ Source/Editor/Windows/GameCookerWindow.cs | 1 + 2 files changed, 3 insertions(+) diff --git a/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp b/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp index f9331dc66..01f8a1a83 100644 --- a/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp +++ b/Source/Editor/Cooker/Platform/UWP/UWPPlatformTools.cpp @@ -497,6 +497,8 @@ bool UWPPlatformTools::OnPerformAOT(CookingData& data, AotConfig& config, const bool UWPPlatformTools::OnPostProcess(CookingData& data) { + LOG(Error, "UWP (Windows Store) platform has been deprecated and soon will be removed!"); + // Special case for UWP // FlaxEngine.dll cannot be added to the solution as `Content` item (due to conflicts with C++ /CX FlaxEngine.dll) // Use special directory for it (generated UWP project handles this case and copies lib to the output) diff --git a/Source/Editor/Windows/GameCookerWindow.cs b/Source/Editor/Windows/GameCookerWindow.cs index 58b7ac5cc..86e6aa86c 100644 --- a/Source/Editor/Windows/GameCookerWindow.cs +++ b/Source/Editor/Windows/GameCookerWindow.cs @@ -257,6 +257,7 @@ namespace FlaxEditor.Windows break; case PlatformType.UWP: name = "Windows Store"; + layout.Label("UWP (Windows Store) platform has been deprecated and soon will be removed!", TextAlignment.Center).Label.TextColor = Color.Red; break; case PlatformType.Linux: name = "Linux"; From 7eae43962495b33eb0bb6edaeccf6d51c7205580 Mon Sep 17 00:00:00 2001 From: Ari Vuollet Date: Sun, 4 Dec 2022 18:09:07 +0200 Subject: [PATCH 54/83] Fix RunProcess not working in development builds Works around a possible compiler bug caused by db6aab1cf6142be4bcfc872a99f381af9986508a --- Source/Engine/Platform/Windows/WindowsPlatform.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/Source/Engine/Platform/Windows/WindowsPlatform.cpp b/Source/Engine/Platform/Windows/WindowsPlatform.cpp index 1e4337016..6cec9376a 100644 --- a/Source/Engine/Platform/Windows/WindowsPlatform.cpp +++ b/Source/Engine/Platform/Windows/WindowsPlatform.cpp @@ -1079,7 +1079,6 @@ int32 WindowsPlatform::RunProcess(const StringView& cmdLine, const StringView& w HANDLE stdOutRead = nullptr; HANDLE stdErrRead = nullptr; - Array attributeList; if (captureStdOut) { @@ -1101,8 +1100,7 @@ int32 WindowsPlatform::RunProcess(const StringView& cmdLine, const StringView& w SIZE_T bufferSize = 0; if (!InitializeProcThreadAttributeList(nullptr, 1, 0, &bufferSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - attributeList.Resize((int32)bufferSize); - startupInfoEx.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)attributeList.Get(); + startupInfoEx.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)Allocate(sizeof(byte) * bufferSize, 16); if (!InitializeProcThreadAttributeList(startupInfoEx.lpAttributeList, 1, 0, &bufferSize)) { LOG(Warning, "InitializeProcThreadAttributeList failed"); @@ -1176,6 +1174,7 @@ ERROR_EXIT: if (startupInfoEx.lpAttributeList != nullptr) { DeleteProcThreadAttributeList(startupInfoEx.lpAttributeList); + Allocator::Free(startupInfoEx.lpAttributeList); } return result; From 7e434932aefe6bf7105cc5ad58c671f70e85782d Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 4 Dec 2022 18:21:18 +0100 Subject: [PATCH 55/83] Fix Development build issue with Flax.Build running in Development mode --- Source/Engine/Platform/Windows/WindowsPlatform.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/Source/Engine/Platform/Windows/WindowsPlatform.cpp b/Source/Engine/Platform/Windows/WindowsPlatform.cpp index 1e4337016..56d84cd9c 100644 --- a/Source/Engine/Platform/Windows/WindowsPlatform.cpp +++ b/Source/Engine/Platform/Windows/WindowsPlatform.cpp @@ -1079,7 +1079,6 @@ int32 WindowsPlatform::RunProcess(const StringView& cmdLine, const StringView& w HANDLE stdOutRead = nullptr; HANDLE stdErrRead = nullptr; - Array attributeList; if (captureStdOut) { @@ -1101,8 +1100,7 @@ int32 WindowsPlatform::RunProcess(const StringView& cmdLine, const StringView& w SIZE_T bufferSize = 0; if (!InitializeProcThreadAttributeList(nullptr, 1, 0, &bufferSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - attributeList.Resize((int32)bufferSize); - startupInfoEx.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)attributeList.Get(); + startupInfoEx.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)Allocator::Allocate(bufferSize); if (!InitializeProcThreadAttributeList(startupInfoEx.lpAttributeList, 1, 0, &bufferSize)) { LOG(Warning, "InitializeProcThreadAttributeList failed"); @@ -1126,9 +1124,6 @@ int32 WindowsPlatform::RunProcess(const StringView& cmdLine, const StringView& w goto ERROR_EXIT; } - if (environmentStr) - Allocator::Free(environmentStr); - if (stdOutRead != nullptr) { // Keep reading std output and std error streams until process is running @@ -1177,6 +1172,10 @@ ERROR_EXIT: { DeleteProcThreadAttributeList(startupInfoEx.lpAttributeList); } + if (environmentStr) + Allocator::Free(environmentStr); + if (startupInfoEx.lpAttributeList) + Allocator::Free(startupInfoEx.lpAttributeList); return result; } From f8734db1e18d2b1c0c8b51ccec69f54db15eed02 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 4 Dec 2022 18:22:38 +0100 Subject: [PATCH 56/83] Revert "Fix Development build issue with Flax.Build running in Development mode" This reverts commit 7e434932aefe6bf7105cc5ad58c671f70e85782d. --- Source/Engine/Platform/Windows/WindowsPlatform.cpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Source/Engine/Platform/Windows/WindowsPlatform.cpp b/Source/Engine/Platform/Windows/WindowsPlatform.cpp index 56d84cd9c..1e4337016 100644 --- a/Source/Engine/Platform/Windows/WindowsPlatform.cpp +++ b/Source/Engine/Platform/Windows/WindowsPlatform.cpp @@ -1079,6 +1079,7 @@ int32 WindowsPlatform::RunProcess(const StringView& cmdLine, const StringView& w HANDLE stdOutRead = nullptr; HANDLE stdErrRead = nullptr; + Array attributeList; if (captureStdOut) { @@ -1100,7 +1101,8 @@ int32 WindowsPlatform::RunProcess(const StringView& cmdLine, const StringView& w SIZE_T bufferSize = 0; if (!InitializeProcThreadAttributeList(nullptr, 1, 0, &bufferSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - startupInfoEx.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)Allocator::Allocate(bufferSize); + attributeList.Resize((int32)bufferSize); + startupInfoEx.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)attributeList.Get(); if (!InitializeProcThreadAttributeList(startupInfoEx.lpAttributeList, 1, 0, &bufferSize)) { LOG(Warning, "InitializeProcThreadAttributeList failed"); @@ -1124,6 +1126,9 @@ int32 WindowsPlatform::RunProcess(const StringView& cmdLine, const StringView& w goto ERROR_EXIT; } + if (environmentStr) + Allocator::Free(environmentStr); + if (stdOutRead != nullptr) { // Keep reading std output and std error streams until process is running @@ -1172,10 +1177,6 @@ ERROR_EXIT: { DeleteProcThreadAttributeList(startupInfoEx.lpAttributeList); } - if (environmentStr) - Allocator::Free(environmentStr); - if (startupInfoEx.lpAttributeList) - Allocator::Free(startupInfoEx.lpAttributeList); return result; } From 5a50656249c26fd54c5b62e4acafdeee7b2933a1 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Sun, 4 Dec 2022 18:23:40 +0100 Subject: [PATCH 57/83] Fix --- Source/Engine/Platform/Windows/WindowsPlatform.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/Engine/Platform/Windows/WindowsPlatform.cpp b/Source/Engine/Platform/Windows/WindowsPlatform.cpp index 6cec9376a..d732e8d2b 100644 --- a/Source/Engine/Platform/Windows/WindowsPlatform.cpp +++ b/Source/Engine/Platform/Windows/WindowsPlatform.cpp @@ -1100,7 +1100,7 @@ int32 WindowsPlatform::RunProcess(const StringView& cmdLine, const StringView& w SIZE_T bufferSize = 0; if (!InitializeProcThreadAttributeList(nullptr, 1, 0, &bufferSize) && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - startupInfoEx.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)Allocate(sizeof(byte) * bufferSize, 16); + startupInfoEx.lpAttributeList = (LPPROC_THREAD_ATTRIBUTE_LIST)Allocator::Allocate(bufferSize); if (!InitializeProcThreadAttributeList(startupInfoEx.lpAttributeList, 1, 0, &bufferSize)) { LOG(Warning, "InitializeProcThreadAttributeList failed"); @@ -1124,9 +1124,6 @@ int32 WindowsPlatform::RunProcess(const StringView& cmdLine, const StringView& w goto ERROR_EXIT; } - if (environmentStr) - Allocator::Free(environmentStr); - if (stdOutRead != nullptr) { // Keep reading std output and std error streams until process is running @@ -1176,6 +1173,8 @@ ERROR_EXIT: DeleteProcThreadAttributeList(startupInfoEx.lpAttributeList); Allocator::Free(startupInfoEx.lpAttributeList); } + if (environmentStr) + Allocator::Free(environmentStr); return result; } From f426c756967d8ffdd18bf70ff8753f4c5ea3b74c Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Tue, 6 Dec 2022 11:43:19 +0100 Subject: [PATCH 58/83] Fix recursive binary modules usage in scripting --- .../Build/NativeCpp/Builder.NativeCpp.cs | 49 ++++++++++++++----- .../Build/NativeCpp/CompileEnvironment.cs | 2 +- 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs b/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs index 9dba593a1..050afbad3 100644 --- a/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs +++ b/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs @@ -31,6 +31,25 @@ namespace Flax.Build public IGrouping[] BinaryModules; public BuildTargetInfo BuildInfo; public Dictionary ReferenceBuilds = new Dictionary(); + + public BuildTargetBinaryModuleInfo FinReferenceBuildModule(string name) + { + if (BuildInfo != null && BuildInfo.BinaryModules != null) + { + foreach (var e in BuildInfo.BinaryModules) + { + if (string.Equals(e.Name, name, StringComparison.Ordinal)) + return e; + } + } + foreach (var e in ReferenceBuilds) + { + var q = e.Value.FinReferenceBuildModule(name); + if (q != null) + return q; + } + return null; + } } public class BuildTargetBinaryModuleInfo @@ -751,6 +770,7 @@ namespace Flax.Build buildData.BinaryModules = GetBinaryModules(project, target, buildData.Modules); // Inject binary modules symbols import/export defines + var moduleNamesUsed = new HashSet(); for (int i = 0; i < buildData.BinaryModules.Length; i++) { var binaryModule = buildData.BinaryModules[i]; @@ -765,22 +785,28 @@ namespace Flax.Build moduleOptions.CompileEnv.PreprocessorDefinitions.Add(binaryModuleNameUpper + (target.UseSymbolsExports ? "_API=" + toolchain.DllExport : "_API=")); // Import symbols from binary modules containing the referenced modules (from this project only, external ones are handled via ReferenceBuilds below) - foreach (var moduleName in moduleOptions.PrivateDependencies) + foreach (var moduleName in moduleOptions.PrivateDependencies.Concat(moduleOptions.PublicDependencies)) { var dependencyModule = buildData.Rules.GetModule(moduleName); - if (dependencyModule != null && !string.IsNullOrEmpty(dependencyModule.BinaryModuleName) && dependencyModule.BinaryModuleName != binaryModule.Key && IsModuleFromProject(dependencyModule, project) && buildData.Modules.TryGetValue(dependencyModule, out var dependencyOptions)) - { - // Import symbols from referenced binary module - moduleOptions.CompileEnv.PreprocessorDefinitions.Add(dependencyModule.BinaryModuleName.ToUpperInvariant() + "_API=" + toolchain.DllImport); - } - } - foreach (var moduleName in moduleOptions.PublicDependencies) - { - var dependencyModule = buildData.Rules.GetModule(moduleName); - if (dependencyModule != null && !string.IsNullOrEmpty(dependencyModule.BinaryModuleName) && dependencyModule.BinaryModuleName != binaryModule.Key && IsModuleFromProject(dependencyModule, project) && buildData.Modules.TryGetValue(dependencyModule, out var dependencyOptions)) + if (dependencyModule != null && + !string.IsNullOrEmpty(dependencyModule.BinaryModuleName) && + dependencyModule.BinaryModuleName != binaryModule.Key && + !moduleNamesUsed.Contains(dependencyModule.BinaryModuleName) && + GetModuleProject(dependencyModule, project) != null && + buildData.Modules.TryGetValue(dependencyModule, out var dependencyOptions)) { // Import symbols from referenced binary module moduleOptions.CompileEnv.PreprocessorDefinitions.Add(dependencyModule.BinaryModuleName.ToUpperInvariant() + "_API=" + toolchain.DllImport); + + var dependencyModuleBuild = buildData.FinReferenceBuildModule(moduleName); + if (dependencyModuleBuild != null) + { + // Link against the referenced binary module + if (toolchain.UseImportLibraryWhenLinking) + moduleOptions.LinkEnv.InputLibraries.Add(Path.ChangeExtension(dependencyModuleBuild.NativePath, toolchain.Platform.StaticLibraryFileExtension)); + else + moduleOptions.LinkEnv.InputLibraries.Add(dependencyModuleBuild.NativePath); + } } } } @@ -825,6 +851,7 @@ namespace Flax.Build } } } + moduleNamesUsed.Clear(); } } diff --git a/Source/Tools/Flax.Build/Build/NativeCpp/CompileEnvironment.cs b/Source/Tools/Flax.Build/Build/NativeCpp/CompileEnvironment.cs index 522099c62..2579dadd0 100644 --- a/Source/Tools/Flax.Build/Build/NativeCpp/CompileEnvironment.cs +++ b/Source/Tools/Flax.Build/Build/NativeCpp/CompileEnvironment.cs @@ -150,7 +150,7 @@ namespace Flax.Build.NativeCpp /// /// The collection of defines with preprocessing symbol for a source files. /// - public readonly List PreprocessorDefinitions = new List(); + public readonly HashSet PreprocessorDefinitions = new HashSet(); /// /// The additional paths to add to the list of directories searched for include files. From 3017010ef463a47adda7c4d9f827c4c3683980e2 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 7 Dec 2022 15:27:40 +0100 Subject: [PATCH 59/83] Minor adjustments to the profiling tools code --- Source/Editor/Windows/Profiler/CPU.cs | 1 - Source/Editor/Windows/Profiler/GPU.cs | 1 - Source/Editor/Windows/Profiler/ProfilerMode.cs | 8 ++++++++ Source/Engine/Profiler/ProfilerCPU.h | 2 +- Source/Engine/Profiler/ProfilerGPU.h | 2 +- Source/Engine/Profiler/ProfilingTools.h | 6 +++--- 6 files changed, 13 insertions(+), 7 deletions(-) diff --git a/Source/Editor/Windows/Profiler/CPU.cs b/Source/Editor/Windows/Profiler/CPU.cs index 23f74aa94..65a18ab2f 100644 --- a/Source/Editor/Windows/Profiler/CPU.cs +++ b/Source/Editor/Windows/Profiler/CPU.cs @@ -205,7 +205,6 @@ namespace FlaxEditor.Windows.Profiler /// public override void OnDestroy() { - Clear(); _timelineLabelsCache?.Clear(); _timelineEventsCache?.Clear(); _tableRowsCache?.Clear(); diff --git a/Source/Editor/Windows/Profiler/GPU.cs b/Source/Editor/Windows/Profiler/GPU.cs index 94e827095..571493f89 100644 --- a/Source/Editor/Windows/Profiler/GPU.cs +++ b/Source/Editor/Windows/Profiler/GPU.cs @@ -166,7 +166,6 @@ namespace FlaxEditor.Windows.Profiler /// public override void OnDestroy() { - Clear(); _timelineEventsCache?.Clear(); _tableRowsCache?.Clear(); diff --git a/Source/Editor/Windows/Profiler/ProfilerMode.cs b/Source/Editor/Windows/Profiler/ProfilerMode.cs index 9b885f886..6d8b81cba 100644 --- a/Source/Editor/Windows/Profiler/ProfilerMode.cs +++ b/Source/Editor/Windows/Profiler/ProfilerMode.cs @@ -83,6 +83,14 @@ namespace FlaxEditor.Windows.Profiler { } + /// + public override void OnDestroy() + { + Clear(); + + base.OnDestroy(); + } + /// /// Initializes this instance. /// diff --git a/Source/Engine/Profiler/ProfilerCPU.h b/Source/Engine/Profiler/ProfilerCPU.h index b4a4bfdc4..491974ca8 100644 --- a/Source/Engine/Profiler/ProfilerCPU.h +++ b/Source/Engine/Profiler/ProfilerCPU.h @@ -22,7 +22,7 @@ public: /// /// Represents single CPU profiling event data. /// - API_STRUCT() struct Event + API_STRUCT(NoDefault) struct Event { DECLARE_SCRIPTING_TYPE_MINIMAL(Event); diff --git a/Source/Engine/Profiler/ProfilerGPU.h b/Source/Engine/Profiler/ProfilerGPU.h index caba96b6e..97eacbec3 100644 --- a/Source/Engine/Profiler/ProfilerGPU.h +++ b/Source/Engine/Profiler/ProfilerGPU.h @@ -24,7 +24,7 @@ public: /// /// Represents single CPU profiling event data. /// - API_STRUCT() struct Event + API_STRUCT(NoDefault) struct Event { DECLARE_SCRIPTING_TYPE_MINIMAL(Event); diff --git a/Source/Engine/Profiler/ProfilingTools.h b/Source/Engine/Profiler/ProfilingTools.h index 28115fcda..dd3d149cb 100644 --- a/Source/Engine/Profiler/ProfilingTools.h +++ b/Source/Engine/Profiler/ProfilingTools.h @@ -19,7 +19,7 @@ public: /// /// The GPU memory stats. /// - API_STRUCT() struct MemoryStatsGPU + API_STRUCT(NoDefault) struct MemoryStatsGPU { DECLARE_SCRIPTING_TYPE_MINIMAL(MemoryStatsGPU); @@ -37,7 +37,7 @@ public: /// /// Engine profiling data header. Contains main info and stats. /// - API_STRUCT() struct MainStats + API_STRUCT(NoDefault) struct MainStats { DECLARE_SCRIPTING_TYPE_MINIMAL(MainStats); @@ -90,7 +90,7 @@ public: /// /// The CPU thread stats. /// - API_STRUCT() struct ThreadStats + API_STRUCT(NoDefault) struct ThreadStats { DECLARE_SCRIPTING_TYPE_MINIMAL(ThreadStats); From f2c594569d37aac0bf729626ebffa0bed731dfd8 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 7 Dec 2022 15:32:23 +0100 Subject: [PATCH 60/83] Remove `GPUResourcesCollection` and use `GPUDevice` instead to simplify code --- Source/Engine/Graphics/GPUDevice.cpp | 89 ++++++++++++++- Source/Engine/Graphics/GPUDevice.h | 25 +++-- Source/Engine/Graphics/GPUResource.h | 4 +- .../Graphics/GPUResourcesCollection.cpp | 101 ------------------ .../Engine/Graphics/GPUResourcesCollection.h | 71 ------------ 5 files changed, 105 insertions(+), 185 deletions(-) delete mode 100644 Source/Engine/Graphics/GPUResourcesCollection.cpp delete mode 100644 Source/Engine/Graphics/GPUResourcesCollection.h diff --git a/Source/Engine/Graphics/GPUDevice.cpp b/Source/Engine/Graphics/GPUDevice.cpp index 133aed0bb..22b0c84fd 100644 --- a/Source/Engine/Graphics/GPUDevice.cpp +++ b/Source/Engine/Graphics/GPUDevice.cpp @@ -10,18 +10,19 @@ #include "Shaders/GPUShader.h" #include "Async/DefaultGPUTasksExecutor.h" #include "Async/GPUTasksManager.h" +#include "Engine/Core/Log.h" +#include "Engine/Core/Utilities.h" +#include "Engine/Core/Types/StringBuilder.h" #include "Engine/Content/Assets/Shader.h" #include "Engine/Content/Assets/Material.h" #include "Engine/Content/Content.h" #include "Engine/Content/SoftAssetReference.h" -#include "Engine/Core/Log.h" #include "Engine/Render2D/Render2D.h" #include "Engine/Engine/CommandLine.h" #include "Engine/Engine/Engine.h" #include "Engine/Engine/EngineService.h" #include "Engine/Profiler/Profiler.h" #include "Engine/Renderer/RenderList.h" -#include "Engine/Core/Utilities.h" GPUPipelineState* GPUPipelineState::Spawn(const SpawnParams& params) { @@ -280,6 +281,7 @@ GPUDevice::GPUDevice(RendererType type, ShaderProfile profile) , _shaderProfile(profile) , _featureLevel(RenderTools::GetFeatureLevel(profile)) , _res(New()) + , _resources(1024) , TotalGraphicsMemory(0) , QuadShader(nullptr) , CurrentTask(nullptr) @@ -367,8 +369,69 @@ bool GPUDevice::CanDraw() return true; } +void GPUDevice::AddResource(GPUResource* resource) +{ + Locker.Lock(); + ASSERT(resource && !_resources.Contains(resource)); + _resources.Add(resource); + Locker.Unlock(); +} + +void GPUDevice::RemoveResource(GPUResource* resource) +{ + Locker.Lock(); + ASSERT(resource && _resources.Contains(resource)); + _resources.Remove(resource); + Locker.Unlock(); +} + +void GPUDevice::DumpResourcesToLog() const +{ + StringBuilder output; + Locker.Lock(); + + output.AppendFormat(TEXT("GPU Resources dump. Count: {0}, total GPU memory used: {1}"), _resources.Count(), Utilities::BytesToText(GetMemoryUsage())); + output.AppendLine(); + output.AppendLine(); + + for (int32 typeIndex = 0; typeIndex < GPUResource::ResourceType_Count; typeIndex++) + { + const auto type = static_cast(typeIndex); + + output.AppendFormat(TEXT("Group: {0}s"), GPUResource::ToString(type)); + output.AppendLine(); + + int32 count = 0; + uint64 memUsage = 0; + for (int32 i = 0; i < _resources.Count(); i++) + { + const GPUResource* resource = _resources[i]; + if (resource->GetResourceType() == type) + { + count++; + memUsage += resource->GetMemoryUsage(); + auto str = resource->ToString(); + if (str.HasChars()) + { + output.Append(TEXT('\t')); + output.Append(str); + output.AppendLine(); + } + } + } + + output.AppendFormat(TEXT("Total count: {0}, memory usage: {1}"), count, Utilities::BytesToText(memUsage)); + output.AppendLine(); + output.AppendLine(); + } + + Locker.Unlock(); + LOG_STR(Info, output.ToStringView()); +} + void GPUDevice::preDispose() { + Locker.Lock(); RenderTargetPool::Flush(); // Release resources @@ -383,7 +446,12 @@ void GPUDevice::preDispose() // Release GPU resources memory and unlink from device // Note: after that no GPU resources should be used/created, only deleted - Resources.OnDeviceDispose(); + for (int32 i = _resources.Count() - 1; i >= 0 && i < _resources.Count(); i--) + { + _resources[i]->OnDeviceDispose(); + } + _resources.Clear(); + Locker.Unlock(); } void GPUDevice::DrawBegin() @@ -520,7 +588,20 @@ void GPUDevice::Dispose() uint64 GPUDevice::GetMemoryUsage() const { - return Resources.GetMemoryUsage(); + uint64 result = 0; + Locker.Lock(); + for (int32 i = 0; i < _resources.Count(); i++) + result += _resources[i]->GetMemoryUsage(); + Locker.Unlock(); + return result; +} + +Array GPUDevice::GetResources() const +{ + Locker.Lock(); + Array result = _resources; + Locker.Unlock(); + return result; } GPUTasksManager* GPUDevice::GetTasksManager() const diff --git a/Source/Engine/Graphics/GPUDevice.h b/Source/Engine/Graphics/GPUDevice.h index cae2e86dc..890770683 100644 --- a/Source/Engine/Graphics/GPUDevice.h +++ b/Source/Engine/Graphics/GPUDevice.h @@ -3,10 +3,11 @@ #pragma once #include "Engine/Platform/Platform.h" +#include "Engine/Platform/CriticalSection.h" #include "Engine/Core/Enums.h" #include "Engine/Core/NonCopyable.h" +#include "Engine/Core/Collections/Array.h" #include "Engine/Scripting/ScriptingObject.h" -#include "GPUResourcesCollection.h" #include "GPUAdapter.h" #include "GPULimits.h" #include "Enums.h" @@ -14,6 +15,7 @@ class ITextureOwner; class RenderTask; +class GPUResource; class GPUContext; class GPUShader; class GPUTimerQuery; @@ -84,6 +86,7 @@ protected: // Private resources (hidden with declaration) struct PrivateData; PrivateData* _res; + Array _resources; protected: /// @@ -105,12 +108,6 @@ public: /// CriticalSection Locker; - /// - /// The GPU resources collection. - /// - GPUResourcesCollection Resources; - -public: /// /// The total amount of graphics memory in bytes. /// @@ -220,6 +217,11 @@ public: /// API_PROPERTY() uint64 GetMemoryUsage() const; + /// + /// Gets the list with all active GPU resources. + /// + API_PROPERTY() Array GetResources() const; + /// /// Gets the GPU asynchronous work manager. /// @@ -299,6 +301,15 @@ public: /// virtual void WaitForGPU() = 0; +public: + void AddResource(GPUResource* resource); + void RemoveResource(GPUResource* resource); + + /// + /// Dumps all GPU resources information to the log. + /// + void DumpResourcesToLog() const; + protected: virtual void preDispose(); diff --git a/Source/Engine/Graphics/GPUResource.h b/Source/Engine/Graphics/GPUResource.h index 9b4a94cd1..e07b3e7bd 100644 --- a/Source/Engine/Graphics/GPUResource.h +++ b/Source/Engine/Graphics/GPUResource.h @@ -137,7 +137,7 @@ public: #if GPU_ENABLE_RESOURCE_NAMING GPUResource::_name = name; #endif - device->Resources.Add(this); + device->AddResource(this); } /// @@ -146,7 +146,7 @@ public: virtual ~GPUResourceBase() { if (_device) - _device->Resources.Remove(this); + _device->RemoveResource(this); } public: diff --git a/Source/Engine/Graphics/GPUResourcesCollection.cpp b/Source/Engine/Graphics/GPUResourcesCollection.cpp deleted file mode 100644 index 69263aa51..000000000 --- a/Source/Engine/Graphics/GPUResourcesCollection.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. - -#include "GPUResourcesCollection.h" -#include "GPUResource.h" -#include "Engine/Core/Log.h" -#include "Engine/Core/Types/StringBuilder.h" -#include "Engine/Core/Utilities.h" - -uint64 GPUResourcesCollection::GetMemoryUsage() const -{ - uint64 result = 0; - _locker.Lock(); - - for (int32 i = 0; i < _collection.Count(); i++) - result += _collection[i]->GetMemoryUsage(); - - _locker.Unlock(); - return result; -} - -void GPUResourcesCollection::OnDeviceDispose() -{ - _locker.Lock(); - - for (int32 i = _collection.Count() - 1; i >= 0 && i < _collection.Count(); i--) - { - _collection[i]->OnDeviceDispose(); - } - _collection.Clear(); - - _locker.Unlock(); -} - -void GPUResourcesCollection::DumpToLog() const -{ - StringBuilder sb; - DumpToLog(sb); - LOG_STR(Info, sb.ToString()); -} - -void GPUResourcesCollection::DumpToLog(StringBuilder& output) const -{ - _locker.Lock(); - - output.AppendFormat(TEXT("GPU Resources dump. Count: {0}, total GPU memory used: {1}"), _collection.Count(), Utilities::BytesToText(GetMemoryUsage())); - output.AppendLine(); - output.AppendLine(); - - for (int32 typeIndex = 0; typeIndex < GPUResource::ResourceType_Count; typeIndex++) - { - const auto type = static_cast(typeIndex); - - output.AppendFormat(TEXT("Group: {0}s"), GPUResource::ToString(type)); - output.AppendLine(); - - int32 count = 0; - uint64 memUsage = 0; - for (int32 i = 0; i < _collection.Count(); i++) - { - const auto resource = _collection[i]; - if (resource->GetResourceType() == type) - { - count++; - memUsage += resource->GetMemoryUsage(); - auto str = resource->ToString(); - if (str.HasChars()) - { - output.Append(TEXT('\t')); - output.Append(str); - output.AppendLine(); - } - } - } - - output.AppendFormat(TEXT("Total count: {0}, memory usage: {1}"), count, Utilities::BytesToText(memUsage)); - output.AppendLine(); - output.AppendLine(); - } - - _locker.Unlock(); -} - -void GPUResourcesCollection::Add(GPUResource* resource) -{ - _locker.Lock(); - - ASSERT(resource && _collection.Contains(resource) == false); - _collection.Add(resource); - - _locker.Unlock(); -} - -void GPUResourcesCollection::Remove(GPUResource* resource) -{ - _locker.Lock(); - - ASSERT(resource && _collection.Contains(resource) == true); - _collection.Remove(resource); - - _locker.Unlock(); -} diff --git a/Source/Engine/Graphics/GPUResourcesCollection.h b/Source/Engine/Graphics/GPUResourcesCollection.h deleted file mode 100644 index e285cbea3..000000000 --- a/Source/Engine/Graphics/GPUResourcesCollection.h +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. - -#pragma once - -#include "Engine/Core/Collections/Array.h" -#include "Engine/Platform/Platform.h" -#include "Engine/Platform/CriticalSection.h" - -class GPUResource; -class StringBuilder; - -/// -/// GPU Resources collection container -/// -class GPUResourcesCollection -{ -private: - CriticalSection _locker; - Array _collection; - -public: - /// - /// Initializes a new instance of the class. - /// - GPUResourcesCollection() - : _collection(1024) - { - } - - /// - /// Finalizes an instance of the class. - /// - ~GPUResourcesCollection() - { - } - -public: - /// - /// Gets the total memory usage (in bytes). - /// - /// GPU memory usage (in bytes). - uint64 GetMemoryUsage() const; - - /// - /// Called when device is being disposed. - /// - void OnDeviceDispose(); - - /// - /// Dumps all resources information to the log. - /// - void DumpToLog() const; - - /// - /// Dumps all resources information to the log. - /// - void DumpToLog(StringBuilder& output) const; - -public: - /// - /// Adds the specified resource to the collection. - /// - /// The resource. - void Add(GPUResource* resource); - - /// - /// Removes the specified resource from the collection. - /// - /// The resource. - void Remove(GPUResource* resource); -}; From df82a0f5d045895c46a33847f573f4abb8696c28 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Thu, 8 Dec 2022 16:30:37 +0100 Subject: [PATCH 61/83] Add **GPU Memory profiler** to Editor --- Source/Editor/GUI/Row.cs | 71 +++++ Source/Editor/Windows/Profiler/MemoryGPU.cs | 280 ++++++++++++++++++ .../Editor/Windows/Profiler/ProfilerWindow.cs | 1 + .../Engine/Content/Loading/ContentLoadTask.h | 10 +- .../Content/Loading/ContentLoadingManager.cpp | 5 + Source/Engine/Engine/Base/GameBase.h | 2 - Source/Engine/Graphics/Async/GPUTask.h | 33 +-- .../Engine/Graphics/Async/GPUTasksContext.cpp | 1 + .../Engine/Graphics/Async/GPUTasksManager.cpp | 34 +++ Source/Engine/Graphics/GPUBuffer.cpp | 9 +- Source/Engine/Graphics/GPUBuffer.h | 3 +- Source/Engine/Graphics/GPUDevice.cpp | 18 +- Source/Engine/Graphics/GPUDevice.h | 11 +- Source/Engine/Graphics/GPUPipelineState.h | 2 +- Source/Engine/Graphics/GPUResource.h | 52 ++-- Source/Engine/Graphics/GPUSwapChain.cpp | 4 +- Source/Engine/Graphics/GPUSwapChain.h | 2 +- Source/Engine/Graphics/GPUTimerQuery.h | 10 +- Source/Engine/Graphics/Models/Mesh.cpp | 2 +- Source/Engine/Graphics/Models/Types.h | 11 +- .../Graphics/Shaders/Cache/ShaderStorage.h | 8 +- .../Graphics/Shaders/GPUConstantBuffer.h | 4 +- Source/Engine/Graphics/Shaders/GPUShader.cpp | 4 +- Source/Engine/Graphics/Shaders/GPUShader.h | 2 +- .../Engine/Graphics/Textures/GPUSampler.cpp | 9 +- Source/Engine/Graphics/Textures/GPUSampler.h | 3 +- .../Engine/Graphics/Textures/GPUTexture.cpp | 13 +- Source/Engine/Graphics/Textures/GPUTexture.h | 3 +- .../Graphics/Textures/StreamingTexture.cpp | 1 + .../DirectX/DX12/CommandSignatureDX12.h | 4 +- .../DirectX/DX12/DescriptorHeapDX12.cpp | 4 +- .../DirectX/DX12/DescriptorHeapDX12.h | 6 +- .../DirectX/DX12/GPUContextDX12.cpp | 46 ++- .../DirectX/DX12/UploadBufferDX12.h | 4 +- .../Vulkan/DescriptorSetVulkan.h | 2 +- .../GraphicsDevice/Vulkan/GPUBufferVulkan.cpp | 1 + .../Vulkan/GPUContextVulkan.cpp | 32 +- .../GraphicsDevice/Vulkan/GPUShaderVulkan.h | 4 +- Source/Engine/Level/Types.h | 2 +- Source/Engine/Physics/Types.h | 1 - .../ShadersCompilation/Parser/ShaderMeta.h | 3 +- Source/Engine/Terrain/TerrainPatch.cpp | 1 + Source/Engine/Threading/MainThreadTask.cpp | 2 +- Source/Engine/Threading/Task.h | 10 +- Source/Engine/Threading/ThreadPool.cpp | 6 + Source/Engine/Threading/ThreadPoolTask.h | 6 +- Source/Engine/Utilities/Screenshot.cpp | 1 + 47 files changed, 548 insertions(+), 195 deletions(-) create mode 100644 Source/Editor/Windows/Profiler/MemoryGPU.cs diff --git a/Source/Editor/GUI/Row.cs b/Source/Editor/GUI/Row.cs index 5bec5d1f1..2e672ac49 100644 --- a/Source/Editor/GUI/Row.cs +++ b/Source/Editor/GUI/Row.cs @@ -1,5 +1,6 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. +using System; using FlaxEngine; using FlaxEngine.GUI; @@ -192,4 +193,74 @@ namespace FlaxEditor.GUI } } } + + /// + /// The table row that contains events for mouse interaction. + /// + [HideInEditor] + public class ClickableRow : Row + { + private bool _leftClick; + private bool _isRightDown; + + /// + /// The double click event. + /// + public Action DoubleClick; + + /// + /// The left mouse button click event. + /// + public Action LeftClick; + + /// + /// The right mouse button click event. + /// + public Action RightClick; + + /// + public override bool OnMouseDoubleClick(Float2 location, MouseButton button) + { + DoubleClick?.Invoke(); + + return base.OnMouseDoubleClick(location, button); + } + + /// + public override bool OnMouseDown(Float2 location, MouseButton button) + { + if (button == MouseButton.Left) + _leftClick = true; + else if (button == MouseButton.Right) + _isRightDown = true; + + return base.OnMouseDown(location, button); + } + + /// + public override bool OnMouseUp(Float2 location, MouseButton button) + { + if (button == MouseButton.Left && _leftClick) + { + _leftClick = false; + LeftClick?.Invoke(); + } + else if (button == MouseButton.Right && _isRightDown) + { + _isRightDown = false; + RightClick?.Invoke(); + } + + return base.OnMouseUp(location, button); + } + + /// + public override void OnMouseLeave() + { + _leftClick = false; + _isRightDown = false; + + base.OnMouseLeave(); + } + } } diff --git a/Source/Editor/Windows/Profiler/MemoryGPU.cs b/Source/Editor/Windows/Profiler/MemoryGPU.cs new file mode 100644 index 000000000..b288819da --- /dev/null +++ b/Source/Editor/Windows/Profiler/MemoryGPU.cs @@ -0,0 +1,280 @@ +// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. + +using System; +using System.Collections.Generic; +using FlaxEditor.GUI; +using FlaxEngine; +using FlaxEngine.GUI; + +namespace FlaxEditor.Windows.Profiler +{ + /// + /// The GPU Memory profiling mode. + /// + /// + internal sealed class MemoryGPU : ProfilerMode + { + private struct Resource + { + public string Name; + public GPUResourceType Type; + public ulong MemoryUsage; + public Guid AssetId; + } + + private readonly SingleChart _memoryUsageChart; + private readonly Table _table; + private SamplesBuffer _resources; + private List _tableRowsCache; + private string[] _resourceTypesNames; + private Dictionary _assetPathToId; + private Dictionary _resourceCache; + + public MemoryGPU() + : base("GPU Memory") + { + // Layout + var panel = new Panel(ScrollBars.Vertical) + { + AnchorPreset = AnchorPresets.StretchAll, + Offsets = Margin.Zero, + Parent = this, + }; + var layout = new VerticalPanel + { + AnchorPreset = AnchorPresets.HorizontalStretchTop, + Offsets = Margin.Zero, + IsScrollable = true, + Parent = panel, + }; + + // Chart + _memoryUsageChart = new SingleChart + { + Title = "GPU Memory Usage", + FormatSample = v => Utilities.Utils.FormatBytesCount((int)v), + Parent = layout, + }; + _memoryUsageChart.SelectedSampleChanged += OnSelectedSampleChanged; + + // Table + var headerColor = Style.Current.LightBackground; + _table = new Table + { + Columns = new[] + { + new ColumnDefinition + { + UseExpandCollapseMode = true, + CellAlignment = TextAlignment.Near, + Title = "Resource", + TitleBackgroundColor = headerColor, + }, + new ColumnDefinition + { + Title = "Type", + CellAlignment = TextAlignment.Center, + TitleBackgroundColor = headerColor, + }, + new ColumnDefinition + { + Title = "Memory Usage", + TitleBackgroundColor = headerColor, + FormatValue = v => Utilities.Utils.FormatBytesCount((ulong)v), + }, + }, + Parent = layout, + }; + _table.Splits = new[] + { + 0.6f, + 0.2f, + 0.2f, + }; + } + + /// + public override void Clear() + { + _memoryUsageChart.Clear(); + _resources?.Clear(); + _assetPathToId?.Clear(); + _resourceCache?.Clear(); + } + + /// + public override void Update(ref SharedUpdateData sharedData) + { + _memoryUsageChart.AddSample(sharedData.Stats.MemoryGPU.Used); + + if (_resourceCache == null) + _resourceCache = new Dictionary(); + if (_assetPathToId == null) + _assetPathToId = new Dictionary(); + + // Capture current GPU resources usage info + var gpuResources = GPUDevice.Instance.Resources; + var resources = new Resource[gpuResources.Length]; + for (int i = 0; i < resources.Length; i++) + { + var gpuResource = gpuResources[i]; + + // Try to reuse cached resource info + var gpuResourceId = gpuResource.ID; + if (!_resourceCache.TryGetValue(gpuResourceId, out var resource)) + { + resource = new Resource + { + Name = gpuResource.Name, + Type = gpuResource.ResourceType, + }; + + // Detect asset path in the resource name + int ext = resource.Name.LastIndexOf(".flax", StringComparison.OrdinalIgnoreCase); + if (ext != -1) + { + var assetPath = resource.Name.Substring(0, ext + 5); + if (!_assetPathToId.TryGetValue(assetPath, out resource.AssetId)) + { + var asset = FlaxEngine.Content.GetAsset(assetPath); + if (asset != null) + resource.AssetId = asset.ID; + _assetPathToId.Add(assetPath, resource.AssetId); + } + } + + _resourceCache.Add(gpuResourceId, resource); + } + + resource.MemoryUsage = gpuResource.MemoryUsage; + if (resource.MemoryUsage == 1) + resource.MemoryUsage = 0; // Sometimes GPU backend fakes memory usage as 1 to mark as allocated but not resided in actual GPU memory + resources[i] = resource; + } + Array.Sort(resources, SortResources); + if (_resources == null) + _resources = new SamplesBuffer(); + _resources.Add(resources); + } + + /// + public override void UpdateView(int selectedFrame, bool showOnlyLastUpdateEvents) + { + _memoryUsageChart.SelectedSampleIndex = selectedFrame; + + if (_resources == null) + return; + if (_tableRowsCache == null) + _tableRowsCache = new List(); + if (_resourceTypesNames == null) + _resourceTypesNames = new string[(int)GPUResourceType.MAX] + { + "Render Target", + "Texture", + "Cube Texture", + "Volume Texture", + "Buffer", + "Shader", + "Pipeline State", + "Descriptor", + "Query", + "Sampler", + }; + UpdateTable(); + } + + /// + public override void OnDestroy() + { + _resources?.Clear(); + _resourceCache?.Clear(); + _assetPathToId?.Clear(); + _tableRowsCache?.Clear(); + + base.OnDestroy(); + } + + private static int SortResources(Resource a, Resource b) + { + return (int)(b.MemoryUsage - a.MemoryUsage); + } + + private void UpdateTable() + { + _table.IsLayoutLocked = true; + int idx = 0; + while (_table.Children.Count > idx) + { + var child = _table.Children[idx]; + if (child is ClickableRow row) + { + _tableRowsCache.Add(row); + child.Parent = null; + } + else + { + idx++; + } + } + _table.LockChildrenRecursive(); + + UpdateTableInner(); + + _table.UnlockChildrenRecursive(); + _table.PerformLayout(); + } + + private void UpdateTableInner() + { + if (_resources.Count == 0) + return; + var resources = _resources.Get(_memoryUsageChart.SelectedSampleIndex); + if (resources == null || resources.Length == 0) + return; + + // Add rows + var rowColor2 = Style.Current.Background * 1.4f; + var contentDatabase = Editor.Instance.ContentDatabase; + for (int i = 0; i < resources.Length; i++) + { + ref var e = ref resources[i]; + + ClickableRow row; + if (_tableRowsCache.Count != 0) + { + // Reuse row + var last = _tableRowsCache.Count - 1; + row = _tableRowsCache[last]; + _tableRowsCache.RemoveAt(last); + } + else + { + // Allocate new row + row = new ClickableRow { Values = new object[3] }; + } + + // Setup row data + row.Values[0] = e.Name; + row.Values[1] = _resourceTypesNames[(int)e.Type]; + row.Values[2] = e.MemoryUsage; + + // Setup row interactions + row.TooltipText = null; + row.DoubleClick = null; + var assetItem = contentDatabase.FindAsset(e.AssetId); + if (assetItem != null) + { + row.Values[0] = assetItem.NamePath; + assetItem.UpdateTooltipText(); + row.TooltipText = assetItem.TooltipText; + row.DoubleClick = () => { Editor.Instance.ContentEditing.Open(assetItem); }; + } + + // Add row to the table + row.Width = _table.Width; + row.BackgroundColor = i % 2 == 0 ? rowColor2 : Color.Transparent; + row.Parent = _table; + } + } + } +} diff --git a/Source/Editor/Windows/Profiler/ProfilerWindow.cs b/Source/Editor/Windows/Profiler/ProfilerWindow.cs index d85cc159a..1bf7fc7f4 100644 --- a/Source/Editor/Windows/Profiler/ProfilerWindow.cs +++ b/Source/Editor/Windows/Profiler/ProfilerWindow.cs @@ -181,6 +181,7 @@ namespace FlaxEditor.Windows.Profiler AddMode(new Overall()); AddMode(new CPU()); AddMode(new GPU()); + AddMode(new MemoryGPU()); AddMode(new Memory()); AddMode(new Network()); diff --git a/Source/Engine/Content/Loading/ContentLoadTask.h b/Source/Engine/Content/Loading/ContentLoadTask.h index c36438ccc..d7f0e32d4 100644 --- a/Source/Engine/Content/Loading/ContentLoadTask.h +++ b/Source/Engine/Content/Loading/ContentLoadTask.h @@ -3,7 +3,6 @@ #pragma once #include "Engine/Threading/Task.h" -#include "Engine/Core/Types/String.h" class Asset; class LoadingThread; @@ -46,7 +45,6 @@ public: /// /// Gets a task type. /// - /// The type. FORCE_INLINE Type GetType() const { return _type; @@ -68,13 +66,7 @@ protected: public: // [Task] - String ToString() const override - { - return String::Format(TEXT("Content Load Task {0} ({1})"), - ToString(GetType()), - ::ToString(GetState()) - ); - } + String ToString() const override; protected: // [Task] diff --git a/Source/Engine/Content/Loading/ContentLoadingManager.cpp b/Source/Engine/Content/Loading/ContentLoadingManager.cpp index dedb2761f..000177c7e 100644 --- a/Source/Engine/Content/Loading/ContentLoadingManager.cpp +++ b/Source/Engine/Content/Loading/ContentLoadingManager.cpp @@ -211,6 +211,11 @@ void ContentLoadingManagerService::Dispose() Tasks.CancelAll(); } +String ContentLoadTask::ToString() const +{ + return String::Format(TEXT("Content Load Task {0} ({1})"), ToString(GetType()), (int32)GetState()); +} + void ContentLoadTask::Enqueue() { Tasks.Add(this); diff --git a/Source/Engine/Engine/Base/GameBase.h b/Source/Engine/Engine/Base/GameBase.h index 1e927a1cb..31396490b 100644 --- a/Source/Engine/Engine/Base/GameBase.h +++ b/Source/Engine/Engine/Base/GameBase.h @@ -2,8 +2,6 @@ #pragma once -#include "Engine/Core/Enums.h" - /// /// Build game header flags. /// diff --git a/Source/Engine/Graphics/Async/GPUTask.h b/Source/Engine/Graphics/Async/GPUTask.h index e4fa29864..38bfae056 100644 --- a/Source/Engine/Graphics/Async/GPUTask.h +++ b/Source/Engine/Graphics/Async/GPUTask.h @@ -4,7 +4,6 @@ #include "Engine/Threading/Task.h" #include "Engine/Platform/Platform.h" -#include "Engine/Core/Log.h" #include "GPUTasksContext.h" class GPUResource; @@ -89,32 +88,7 @@ public: /// Executes this task. /// /// The context. - void Execute(GPUTasksContext* context) - { - // Begin - ASSERT(IsQueued() && _context == nullptr); - _state = TaskState::Running; - - // Perform an operation - const auto result = run(context); - - // Process result - if (IsCancelRequested()) - { - _state = TaskState::Canceled; - } - else if (result != Result::Ok) - { - LOG(Warning, "\'{0}\' failed with result: {1}", ToString(), ToString(result)); - OnFail(); - } - else - { - // Save task completion point (for synchronization) - _syncPoint = context->GetCurrentSyncPoint(); - _context = context; - } - } + void Execute(GPUTasksContext* context); /// /// Action fired when asynchronous operation has been synchronized with a GPU @@ -154,10 +128,7 @@ protected: public: // [Task] - String ToString() const override - { - return String::Format(TEXT("GPU Async Task {0} ({1})"), ToString(GetType()), ::ToString(GetState())); - } + String ToString() const override; protected: // [Task] diff --git a/Source/Engine/Graphics/Async/GPUTasksContext.cpp b/Source/Engine/Graphics/Async/GPUTasksContext.cpp index 0800e5a22..75355f6de 100644 --- a/Source/Engine/Graphics/Async/GPUTasksContext.cpp +++ b/Source/Engine/Graphics/Async/GPUTasksContext.cpp @@ -2,6 +2,7 @@ #include "GPUTasksContext.h" #include "GPUTask.h" +#include "Engine/Core/Log.h" #include "Engine/Graphics/GPUDevice.h" #include "Engine/Threading/Threading.h" diff --git a/Source/Engine/Graphics/Async/GPUTasksManager.cpp b/Source/Engine/Graphics/Async/GPUTasksManager.cpp index 2cbe31f47..a81b1f14d 100644 --- a/Source/Engine/Graphics/Async/GPUTasksManager.cpp +++ b/Source/Engine/Graphics/Async/GPUTasksManager.cpp @@ -3,8 +3,42 @@ #include "GPUTasksManager.h" #include "GPUTask.h" #include "GPUTasksExecutor.h" +#include "Engine/Core/Log.h" +#include "Engine/Core/Types/String.h" #include "Engine/Graphics/GPUDevice.h" +void GPUTask::Execute(GPUTasksContext* context) +{ + // Begin + ASSERT(IsQueued() && _context == nullptr); + _state = TaskState::Running; + + // Perform an operation + const auto result = run(context); + + // Process result + if (IsCancelRequested()) + { + _state = TaskState::Canceled; + } + else if (result != Result::Ok) + { + LOG(Warning, "\'{0}\' failed with result: {1}", ToString(), ToString(result)); + OnFail(); + } + else + { + // Save task completion point (for synchronization) + _syncPoint = context->GetCurrentSyncPoint(); + _context = context; + } +} + +String GPUTask::ToString() const +{ + return String::Format(TEXT("GPU Async Task {0} ({1})"), ToString(GetType()), (int32)GetState()); +} + void GPUTask::Enqueue() { GPUDevice::Instance->GetTasksManager()->_tasks.Add(this); diff --git a/Source/Engine/Graphics/GPUBuffer.cpp b/Source/Engine/Graphics/GPUBuffer.cpp index 3aae13789..4900e73e2 100644 --- a/Source/Engine/Graphics/GPUBuffer.cpp +++ b/Source/Engine/Graphics/GPUBuffer.cpp @@ -395,14 +395,9 @@ String GPUBuffer::ToString() const #endif } -GPUResource::ResourceType GPUBuffer::GetResourceType() const +GPUResourceType GPUBuffer::GetResourceType() const { - return ResourceType::Buffer; -} - -GPUResource::ObjectType GPUBuffer::GetObjectType() const -{ - return ObjectType::Buffer; + return GPUResourceType::Buffer; } void GPUBuffer::OnReleaseGPU() diff --git a/Source/Engine/Graphics/GPUBuffer.h b/Source/Engine/Graphics/GPUBuffer.h index 785be2cc3..9af530e9c 100644 --- a/Source/Engine/Graphics/GPUBuffer.h +++ b/Source/Engine/Graphics/GPUBuffer.h @@ -205,8 +205,7 @@ protected: public: // [GPUResource] String ToString() const override; - ResourceType GetResourceType() const final override; - ObjectType GetObjectType() const final override; + GPUResourceType GetResourceType() const final override; protected: // [GPUResource] diff --git a/Source/Engine/Graphics/GPUDevice.cpp b/Source/Engine/Graphics/GPUDevice.cpp index 22b0c84fd..14d8ff63a 100644 --- a/Source/Engine/Graphics/GPUDevice.cpp +++ b/Source/Engine/Graphics/GPUDevice.cpp @@ -23,6 +23,7 @@ #include "Engine/Engine/EngineService.h" #include "Engine/Profiler/Profiler.h" #include "Engine/Renderer/RenderList.h" +#include "Engine/Scripting/Enums.h" GPUPipelineState* GPUPipelineState::Spawn(const SpawnParams& params) { @@ -79,9 +80,9 @@ bool GPUPipelineState::Init(const Description& desc) return false; } -GPUResource::ResourceType GPUPipelineState::GetResourceType() const +GPUResourceType GPUPipelineState::GetResourceType() const { - return ResourceType::PipelineState; + return GPUResourceType::PipelineState; } GPUPipelineState::Description GPUPipelineState::Description::Default = @@ -193,16 +194,13 @@ GPUResource::~GPUResource() #endif } -GPUResource::ObjectType GPUResource::GetObjectType() const -{ - return ObjectType::Other; -} - uint64 GPUResource::GetMemoryUsage() const { return _memoryUsage; } +static_assert((GPU_ENABLE_RESOURCE_NAMING) == (!BUILD_RELEASE), "Update build condition on around GPUResource Name property getter/setter."); + #if GPU_ENABLE_RESOURCE_NAMING String GPUResource::GetName() const @@ -394,11 +392,11 @@ void GPUDevice::DumpResourcesToLog() const output.AppendLine(); output.AppendLine(); - for (int32 typeIndex = 0; typeIndex < GPUResource::ResourceType_Count; typeIndex++) + for (int32 typeIndex = 0; typeIndex < (int32)GPUResourceType::MAX; typeIndex++) { - const auto type = static_cast(typeIndex); + const auto type = static_cast(typeIndex); - output.AppendFormat(TEXT("Group: {0}s"), GPUResource::ToString(type)); + output.AppendFormat(TEXT("Group: {0}s"), ScriptingEnum::ToString(type)); output.AppendLine(); int32 count = 0; diff --git a/Source/Engine/Graphics/GPUDevice.h b/Source/Engine/Graphics/GPUDevice.h index 890770683..ca63d233a 100644 --- a/Source/Engine/Graphics/GPUDevice.h +++ b/Source/Engine/Graphics/GPUDevice.h @@ -4,7 +4,6 @@ #include "Engine/Platform/Platform.h" #include "Engine/Platform/CriticalSection.h" -#include "Engine/Core/Enums.h" #include "Engine/Core/NonCopyable.h" #include "Engine/Core/Collections/Array.h" #include "Engine/Scripting/ScriptingObject.h" @@ -43,7 +42,15 @@ public: /// /// Graphics Device states that describe its lifetime. /// - DECLARE_ENUM_6(DeviceState, Missing, Created, Ready, Removed, Disposing, Disposed); + enum class DeviceState + { + Missing = 0, + Created, + Ready, + Removed, + Disposing, + Disposed + }; /// /// Describes a video output display mode. diff --git a/Source/Engine/Graphics/GPUPipelineState.h b/Source/Engine/Graphics/GPUPipelineState.h index 497548e00..538c83a10 100644 --- a/Source/Engine/Graphics/GPUPipelineState.h +++ b/Source/Engine/Graphics/GPUPipelineState.h @@ -160,5 +160,5 @@ public: public: // [GPUResource] - ResourceType GetResourceType() const final override; + GPUResourceType GetResourceType() const final override; }; diff --git a/Source/Engine/Graphics/GPUResource.h b/Source/Engine/Graphics/GPUResource.h index e07b3e7bd..05f409b9c 100644 --- a/Source/Engine/Graphics/GPUResource.h +++ b/Source/Engine/Graphics/GPUResource.h @@ -2,7 +2,6 @@ #pragma once -#include "Engine/Core/Enums.h" #include "Engine/Scripting/ScriptingObject.h" #include "Config.h" @@ -12,23 +11,41 @@ #define SAFE_DELETE_GPU_RESOURCE(x) if (x) { (x)->DeleteObjectNow(); (x) = nullptr; } #define SAFE_DELETE_GPU_RESOURCES(x) for (auto& e : (x)) if (e) { e->DeleteObjectNow(); e = nullptr; } +/// +/// GPU resources types. +/// +API_ENUM() enum class GPUResourceType +{ + // GPU render target texture + RenderTarget = 0, + // GPU texture + Texture, + // GPU cube texture (cubemap) + CubeTexture, + // GPU volume texture (3D) + VolumeTexture, + // GPU buffer + Buffer, + // GPU shader + Shader, + // GPU pipeline state object (PSO) + PipelineState, + // GPU binding descriptor + Descriptor, + // GPU timer query + Query, + // GPU texture sampler + Sampler, + + MAX +}; + /// /// The base class for all GPU resources. /// API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API GPUResource : public ScriptingObject { DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUResource); -public: - /// - /// GPU Resources types. - /// - DECLARE_ENUM_10(ResourceType, RenderTarget, Texture, CubeTexture, VolumeTexture, Buffer, Shader, PipelineState, Descriptor, Query, Sampler); - - /// - /// GPU Resources object types. Used to detect Texture objects from subset of Types: RenderTarget, Texture, CubeTexture, VolumeTexture which use the same API object. - /// - DECLARE_ENUM_3(ObjectType, Texture, Buffer, Other); - protected: uint64 _memoryUsage = 0; #if GPU_ENABLE_RESOURCE_NAMING @@ -65,21 +82,16 @@ public: public: /// - /// Gets the resource type. + /// Gets the GPU resource type. /// - virtual ResourceType GetResourceType() const = 0; - - /// - /// Gets resource object type. - /// - virtual ObjectType GetObjectType() const; + API_PROPERTY() virtual GPUResourceType GetResourceType() const = 0; /// /// Gets amount of GPU memory used by this resource (in bytes). It's a rough estimation. GPU memory may be fragmented, compressed or sub-allocated so the actual memory pressure from this resource may vary (also depends on the current graphics backend). /// API_PROPERTY() uint64 GetMemoryUsage() const; -#if GPU_ENABLE_RESOURCE_NAMING +#if !BUILD_RELEASE /// /// Gets the resource name. /// diff --git a/Source/Engine/Graphics/GPUSwapChain.cpp b/Source/Engine/Graphics/GPUSwapChain.cpp index 4d33db407..bd2ac858b 100644 --- a/Source/Engine/Graphics/GPUSwapChain.cpp +++ b/Source/Engine/Graphics/GPUSwapChain.cpp @@ -95,7 +95,7 @@ String GPUSwapChain::ToString() const #endif } -GPUResource::ResourceType GPUSwapChain::GetResourceType() const +GPUResourceType GPUSwapChain::GetResourceType() const { - return ResourceType::Texture; + return GPUResourceType::Texture; } diff --git a/Source/Engine/Graphics/GPUSwapChain.h b/Source/Engine/Graphics/GPUSwapChain.h index 97777cd6e..738aeaf40 100644 --- a/Source/Engine/Graphics/GPUSwapChain.h +++ b/Source/Engine/Graphics/GPUSwapChain.h @@ -160,5 +160,5 @@ public: public: // [GPUResource] String ToString() const override; - ResourceType GetResourceType() const final override; + GPUResourceType GetResourceType() const final override; }; diff --git a/Source/Engine/Graphics/GPUTimerQuery.h b/Source/Engine/Graphics/GPUTimerQuery.h index e4763ac4f..75fa06738 100644 --- a/Source/Engine/Graphics/GPUTimerQuery.h +++ b/Source/Engine/Graphics/GPUTimerQuery.h @@ -48,14 +48,8 @@ public: { return TEXT("TimerQuery"); } - - ResourceType GetResourceType() const final override + GPUResourceType GetResourceType() const final override { - return ResourceType::Query; - } - - ObjectType GetObjectType() const final override - { - return ObjectType::Other; + return GPUResourceType::Query; } }; diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp index ee2ed5de6..b75db1949 100644 --- a/Source/Engine/Graphics/Models/Mesh.cpp +++ b/Source/Engine/Graphics/Models/Mesh.cpp @@ -251,7 +251,7 @@ bool Mesh::Load(uint32 vertices, uint32 triangles, void* vb0, void* vb1, void* v // Create GPU buffers #if GPU_ENABLE_RESOURCE_NAMING -#define MESH_BUFFER_NAME(postfix) GetModel()->ToString() + TEXT(postfix) +#define MESH_BUFFER_NAME(postfix) GetModel()->GetPath() + TEXT(postfix) #else #define MESH_BUFFER_NAME(postfix) String::Empty #endif diff --git a/Source/Engine/Graphics/Models/Types.h b/Source/Engine/Graphics/Models/Types.h index 2272a3a08..a8492b999 100644 --- a/Source/Engine/Graphics/Models/Types.h +++ b/Source/Engine/Graphics/Models/Types.h @@ -2,7 +2,6 @@ #pragma once -#include "Engine/Core/Enums.h" #include "Engine/Core/Math/Packed.h" #include "Engine/Core/Math/Vector2.h" #include "Engine/Core/Math/Vector3.h" @@ -23,7 +22,15 @@ struct RenderView; /// /// Importing model lightmap UVs source /// -DECLARE_ENUM_6(ModelLightmapUVsSource, Disable, Generate, Channel0, Channel1, Channel2, Channel3); +enum class ModelLightmapUVsSource +{ + Disable = 0, + Generate, + Channel0, + Channel1, + Channel2, + Channel3 +}; /// /// The mesh buffer types. diff --git a/Source/Engine/Graphics/Shaders/Cache/ShaderStorage.h b/Source/Engine/Graphics/Shaders/Cache/ShaderStorage.h index 3fabbb5b7..b4660c8d1 100644 --- a/Source/Engine/Graphics/Shaders/Cache/ShaderStorage.h +++ b/Source/Engine/Graphics/Shaders/Cache/ShaderStorage.h @@ -3,7 +3,6 @@ #pragma once #include "Engine/Core/Types/BaseTypes.h" -#include "Engine/Core/Enums.h" #include "Engine/Graphics/Config.h" #include "Engine/Graphics/Materials/MaterialInfo.h" #include "../Config.h" @@ -31,7 +30,12 @@ public: /// /// Different shader cache storage modes (disabled, inside asset and in project cache) /// - DECLARE_ENUM_3(CachingMode, Disabled, AssetInternal, ProjectCache); + enum class CachingMode + { + Disabled = 0, + AssetInternal, + ProjectCache + }; /// /// Current shaders caching mode to use diff --git a/Source/Engine/Graphics/Shaders/GPUConstantBuffer.h b/Source/Engine/Graphics/Shaders/GPUConstantBuffer.h index 0c63ac6f5..9376a3ab9 100644 --- a/Source/Engine/Graphics/Shaders/GPUConstantBuffer.h +++ b/Source/Engine/Graphics/Shaders/GPUConstantBuffer.h @@ -23,8 +23,8 @@ public: public: // [GPUResource] - ResourceType GetResourceType() const override + GPUResourceType GetResourceType() const override { - return ResourceType::Buffer; + return GPUResourceType::Buffer; } }; diff --git a/Source/Engine/Graphics/Shaders/GPUShader.cpp b/Source/Engine/Graphics/Shaders/GPUShader.cpp index 7e50b0009..4f3428510 100644 --- a/Source/Engine/Graphics/Shaders/GPUShader.cpp +++ b/Source/Engine/Graphics/Shaders/GPUShader.cpp @@ -190,9 +190,9 @@ GPUShaderProgram* GPUShader::GetShader(ShaderStage stage, const StringAnsiView& return shader; } -GPUResource::ResourceType GPUShader::GetResourceType() const +GPUResourceType GPUShader::GetResourceType() const { - return ResourceType::Shader; + return GPUResourceType::Shader; } void GPUShader::OnReleaseGPU() diff --git a/Source/Engine/Graphics/Shaders/GPUShader.h b/Source/Engine/Graphics/Shaders/GPUShader.h index bbc9c4dad..610f09d18 100644 --- a/Source/Engine/Graphics/Shaders/GPUShader.h +++ b/Source/Engine/Graphics/Shaders/GPUShader.h @@ -182,7 +182,7 @@ protected: public: // [GPUResource] - ResourceType GetResourceType() const final override; + GPUResourceType GetResourceType() const final override; protected: // [GPUResource] diff --git a/Source/Engine/Graphics/Textures/GPUSampler.cpp b/Source/Engine/Graphics/Textures/GPUSampler.cpp index 8541a447e..6eb61ec33 100644 --- a/Source/Engine/Graphics/Textures/GPUSampler.cpp +++ b/Source/Engine/Graphics/Textures/GPUSampler.cpp @@ -101,14 +101,9 @@ String GPUSampler::ToString() const #endif } -GPUResource::ResourceType GPUSampler::GetResourceType() const +GPUResourceType GPUSampler::GetResourceType() const { - return ResourceType::Sampler; -} - -GPUResource::ObjectType GPUSampler::GetObjectType() const -{ - return ObjectType::Other; + return GPUResourceType::Sampler; } void GPUSampler::OnReleaseGPU() diff --git a/Source/Engine/Graphics/Textures/GPUSampler.h b/Source/Engine/Graphics/Textures/GPUSampler.h index 6f5760320..010f4f339 100644 --- a/Source/Engine/Graphics/Textures/GPUSampler.h +++ b/Source/Engine/Graphics/Textures/GPUSampler.h @@ -43,8 +43,7 @@ protected: public: // [GPUResource] String ToString() const override; - ResourceType GetResourceType() const final override; - ObjectType GetObjectType() const final override; + GPUResourceType GetResourceType() const final override; protected: // [GPUResource] diff --git a/Source/Engine/Graphics/Textures/GPUTexture.cpp b/Source/Engine/Graphics/Textures/GPUTexture.cpp index 167dfab60..d9112ffc6 100644 --- a/Source/Engine/Graphics/Textures/GPUTexture.cpp +++ b/Source/Engine/Graphics/Textures/GPUTexture.cpp @@ -575,18 +575,13 @@ String GPUTexture::ToString() const #endif } -GPUResource::ResourceType GPUTexture::GetResourceType() const +GPUResourceType GPUTexture::GetResourceType() const { if (IsVolume()) - return ResourceType::VolumeTexture; + return GPUResourceType::VolumeTexture; if (IsCubeMap()) - return ResourceType::CubeTexture; - return IsRegularTexture() ? ResourceType::Texture : ResourceType::RenderTarget; -} - -GPUResource::ObjectType GPUTexture::GetObjectType() const -{ - return ObjectType::Texture; + return GPUResourceType::CubeTexture; + return IsRegularTexture() ? GPUResourceType::Texture : GPUResourceType::RenderTarget; } void GPUTexture::OnReleaseGPU() diff --git a/Source/Engine/Graphics/Textures/GPUTexture.h b/Source/Engine/Graphics/Textures/GPUTexture.h index bb1aa1eb2..f15607567 100644 --- a/Source/Engine/Graphics/Textures/GPUTexture.h +++ b/Source/Engine/Graphics/Textures/GPUTexture.h @@ -573,8 +573,7 @@ protected: public: // [GPUResource] String ToString() const override; - ResourceType GetResourceType() const final override; - ObjectType GetObjectType() const final override; + GPUResourceType GetResourceType() const final override; protected: // [GPUResource] diff --git a/Source/Engine/Graphics/Textures/StreamingTexture.cpp b/Source/Engine/Graphics/Textures/StreamingTexture.cpp index 5af397dbe..4aca9a04d 100644 --- a/Source/Engine/Graphics/Textures/StreamingTexture.cpp +++ b/Source/Engine/Graphics/Textures/StreamingTexture.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. #include "StreamingTexture.h" +#include "Engine/Core/Log.h" #include "Engine/Threading/Threading.h" #include "Engine/Streaming/StreamingGroup.h" #include "Engine/Content/Loading/ContentLoadingManager.h" diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/CommandSignatureDX12.h b/Source/Engine/GraphicsDevice/DirectX/DX12/CommandSignatureDX12.h index 757779d28..5c366edad 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/CommandSignatureDX12.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/CommandSignatureDX12.h @@ -190,9 +190,9 @@ public: public: // [GPUResourceDX12] - ResourceType GetResourceType() const override + GPUResourceType GetResourceType() const override { - return ResourceType::Descriptor; + return GPUResourceType::Descriptor; } protected: diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/DescriptorHeapDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/DescriptorHeapDX12.cpp index 0f117029d..ad494f468 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/DescriptorHeapDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/DescriptorHeapDX12.cpp @@ -128,9 +128,9 @@ void DescriptorHeapWithSlotsDX12::ReleaseSlot(uint32 index) value &= ~mask; } -GPUResource::ResourceType DescriptorHeapWithSlotsDX12::GetResourceType() const +GPUResourceType DescriptorHeapWithSlotsDX12::GetResourceType() const { - return ResourceType::Descriptor; + return GPUResourceType::Descriptor; } DescriptorHeapPoolDX12::DescriptorHeapPoolDX12(GPUDeviceDX12* device, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 descriptorsCountPerHeap, bool shaderVisible) diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/DescriptorHeapDX12.h b/Source/Engine/GraphicsDevice/DirectX/DX12/DescriptorHeapDX12.h index 24610ea19..5a0c1bb01 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/DescriptorHeapDX12.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/DescriptorHeapDX12.h @@ -87,7 +87,7 @@ public: public: // [GPUResourceDX12] - ResourceType GetResourceType() const final override; + GPUResourceType GetResourceType() const final override; protected: @@ -170,9 +170,9 @@ public: public: // [GPUResourceDX12] - ResourceType GetResourceType() const final override + GPUResourceType GetResourceType() const final override { - return ResourceType::Descriptor; + return GPUResourceType::Descriptor; } protected: diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp index 2f189af5a..9cad9a636 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp @@ -1299,25 +1299,23 @@ void GPUContextDX12::CopyResource(GPUResource* dstResource, GPUResource* srcReso auto dstResourceDX12 = dynamic_cast(dstResource); auto srcResourceDX12 = dynamic_cast(srcResource); + auto dstBufferDX12 = dynamic_cast(dstResource); + auto srcBufferDX12 = dynamic_cast(srcResource); + auto dstTextureDX12 = dynamic_cast(dstResource); + auto srcTextureDX12 = dynamic_cast(srcResource); SetResourceState(dstResourceDX12, D3D12_RESOURCE_STATE_COPY_DEST); SetResourceState(srcResourceDX12, D3D12_RESOURCE_STATE_COPY_SOURCE); flushRBs(); - auto srcType = srcResource->GetObjectType(); - auto dstType = dstResource->GetObjectType(); - // Buffer -> Buffer - if (srcType == GPUResource::ObjectType::Buffer && dstType == GPUResource::ObjectType::Buffer) + if (srcBufferDX12 && dstBufferDX12) { _commandList->CopyResource(dstResourceDX12->GetResource(), srcResourceDX12->GetResource()); } // Texture -> Texture - else if (srcType == GPUResource::ObjectType::Texture && dstType == GPUResource::ObjectType::Texture) + else if (srcTextureDX12 && dstTextureDX12) { - auto dstTextureDX12 = static_cast(dstResource); - auto srcTextureDX12 = static_cast(srcResource); - if (dstTextureDX12->IsStaging()) { // Staging Texture -> Staging Texture @@ -1388,32 +1386,26 @@ void GPUContextDX12::CopySubresource(GPUResource* dstResource, uint32 dstSubreso { ASSERT(dstResource && srcResource); - auto srcType = srcResource->GetObjectType(); - auto dstType = dstResource->GetObjectType(); - + auto dstResourceDX12 = dynamic_cast(dstResource); + auto srcResourceDX12 = dynamic_cast(srcResource); + auto dstBufferDX12 = dynamic_cast(dstResource); + auto srcBufferDX12 = dynamic_cast(srcResource); + auto dstTextureDX12 = dynamic_cast(dstResource); + auto srcTextureDX12 = dynamic_cast(srcResource); + + SetResourceState(dstResourceDX12, D3D12_RESOURCE_STATE_COPY_DEST); + SetResourceState(srcResourceDX12, D3D12_RESOURCE_STATE_COPY_SOURCE); + flushRBs(); + // Buffer -> Buffer - if (srcType == GPUResource::ObjectType::Buffer && dstType == GPUResource::ObjectType::Buffer) + if (srcBufferDX12 && dstBufferDX12) { - auto dstBufferDX12 = dynamic_cast(dstResource); - auto srcBufferDX12 = dynamic_cast(srcResource); - - SetResourceState(dstBufferDX12, D3D12_RESOURCE_STATE_COPY_DEST); - SetResourceState(srcBufferDX12, D3D12_RESOURCE_STATE_COPY_SOURCE); - flushRBs(); - uint64 bytesCount = srcResource->GetMemoryUsage(); _commandList->CopyBufferRegion(dstBufferDX12->GetResource(), 0, srcBufferDX12->GetResource(), 0, bytesCount); } // Texture -> Texture - else if (srcType == GPUResource::ObjectType::Texture && dstType == GPUResource::ObjectType::Texture) + else if (srcTextureDX12 && dstTextureDX12) { - auto dstTextureDX12 = static_cast(dstResource); - auto srcTextureDX12 = static_cast(srcResource); - - SetResourceState(dstTextureDX12, D3D12_RESOURCE_STATE_COPY_DEST); - SetResourceState(srcTextureDX12, D3D12_RESOURCE_STATE_COPY_SOURCE); - flushRBs(); - if (srcTextureDX12->IsStaging() || dstTextureDX12->IsStaging()) { Log::NotImplementedException(TEXT("Copy region of staging resources is not supported yet.")); diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/UploadBufferDX12.h b/Source/Engine/GraphicsDevice/DirectX/DX12/UploadBufferDX12.h index dfff8b203..13963c43e 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/UploadBufferDX12.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/UploadBufferDX12.h @@ -56,9 +56,9 @@ public: public: // [GPUResourceDX12] - ResourceType GetResourceType() const final override + GPUResourceType GetResourceType() const final override { - return ResourceType::Buffer; + return GPUResourceType::Buffer; } // [ResourceOwnerDX12] diff --git a/Source/Engine/GraphicsDevice/Vulkan/DescriptorSetVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/DescriptorSetVulkan.h index 695da1be9..832bee851 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/DescriptorSetVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/DescriptorSetVulkan.h @@ -87,7 +87,7 @@ namespace DescriptorSet return ShaderStage::Geometry; default: CRASH; - return static_cast(ShaderStage_Count); + return (ShaderStage)ShaderStage_Count; } } diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp index 6e4301c39..e4e432f98 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUBufferVulkan.cpp @@ -5,6 +5,7 @@ #include "GPUBufferVulkan.h" #include "GPUContextVulkan.h" #include "RenderToolsVulkan.h" +#include "Engine/Core/Log.h" #include "Engine/Threading/Threading.h" #include "Engine/Graphics/Async/Tasks/GPUUploadBufferTask.h" diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp index bc768f64c..546f3d59e 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp @@ -1493,17 +1493,13 @@ void GPUContextVulkan::CopyResource(GPUResource* dstResource, GPUResource* srcRe if (cmdBuffer->IsInsideRenderPass()) EndRenderPass(); - auto dstTextureVulkan = static_cast(dstResource); - auto srcTextureVulkan = static_cast(srcResource); - - auto dstBufferVulkan = static_cast(dstResource); - auto srcBufferVulkan = static_cast(srcResource); - - const auto srcType = srcResource->GetObjectType(); - const auto dstType = dstResource->GetObjectType(); + auto dstTextureVulkan = dynamic_cast(dstResource); + auto srcTextureVulkan = dynamic_cast(srcResource); + auto dstBufferVulkan = dynamic_cast(dstResource); + auto srcBufferVulkan = dynamic_cast(srcResource); // Buffer -> Buffer - if (srcType == GPUResource::ObjectType::Buffer && dstType == GPUResource::ObjectType::Buffer) + if (srcBufferVulkan && dstBufferVulkan) { // Transition resources AddBufferBarrier(dstBufferVulkan, VK_ACCESS_TRANSFER_WRITE_BIT); @@ -1519,7 +1515,7 @@ void GPUContextVulkan::CopyResource(GPUResource* dstResource, GPUResource* srcRe vkCmdCopyBuffer(cmdBuffer->GetHandle(), srcBufferVulkan->GetHandle(), dstBufferVulkan->GetHandle(), 1, &bufferCopy); } // Texture -> Texture - else if (srcType == GPUResource::ObjectType::Texture && dstType == GPUResource::ObjectType::Texture) + else if (srcTextureVulkan && dstTextureVulkan) { if (dstTextureVulkan->IsStaging()) { @@ -1632,17 +1628,13 @@ void GPUContextVulkan::CopySubresource(GPUResource* dstResource, uint32 dstSubre if (cmdBuffer->IsInsideRenderPass()) EndRenderPass(); - auto dstTextureVulkan = static_cast(dstResource); - auto srcTextureVulkan = static_cast(srcResource); - - auto dstBufferVulkan = static_cast(dstResource); - auto srcBufferVulkan = static_cast(srcResource); - - auto srcType = srcResource->GetObjectType(); - auto dstType = dstResource->GetObjectType(); + auto dstTextureVulkan = dynamic_cast(dstResource); + auto srcTextureVulkan = dynamic_cast(srcResource); + auto dstBufferVulkan = dynamic_cast(dstResource); + auto srcBufferVulkan = dynamic_cast(srcResource); // Buffer -> Buffer - if (srcType == GPUResource::ObjectType::Buffer && dstType == GPUResource::ObjectType::Buffer) + if (srcBufferVulkan && dstBufferVulkan) { ASSERT(dstSubresource == 0 && srcSubresource == 0); @@ -1660,7 +1652,7 @@ void GPUContextVulkan::CopySubresource(GPUResource* dstResource, uint32 dstSubre vkCmdCopyBuffer(cmdBuffer->GetHandle(), srcBufferVulkan->GetHandle(), dstBufferVulkan->GetHandle(), 1, &bufferCopy); } // Texture -> Texture - else if (srcType == GPUResource::ObjectType::Texture && dstType == GPUResource::ObjectType::Texture) + else if (srcTextureVulkan && dstTextureVulkan) { const int32 dstMipMaps = dstTextureVulkan->MipLevels(); const int32 dstMipIndex = dstSubresource % dstMipMaps; diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.h index 06bf21bda..42731d5d3 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUShaderVulkan.h @@ -67,9 +67,9 @@ public: public: // [GPUResourceVulkan] - ResourceType GetResourceType() const final override + GPUResourceType GetResourceType() const final override { - return ResourceType::Buffer; + return GPUResourceType::Buffer; } // [ResourceOwnerVulkan] diff --git a/Source/Engine/Level/Types.h b/Source/Engine/Level/Types.h index 559646236..c07eabf4f 100644 --- a/Source/Engine/Level/Types.h +++ b/Source/Engine/Level/Types.h @@ -3,7 +3,7 @@ #pragma once #include "Engine/Core/Config.h" -#include "Engine/Core/Enums.h" +#include "Engine/Core/Types/BaseTypes.h" // Level system types class SceneObject; diff --git a/Source/Engine/Physics/Types.h b/Source/Engine/Physics/Types.h index f2f3f7621..9e9e9a127 100644 --- a/Source/Engine/Physics/Types.h +++ b/Source/Engine/Physics/Types.h @@ -2,7 +2,6 @@ #pragma once -#include "Engine/Core/Enums.h" #include "Engine/Core/Config.h" #include "Engine/Core/Math/Vector2.h" #include "Engine/Core/Math/Vector3.h" diff --git a/Source/Engine/ShadersCompilation/Parser/ShaderMeta.h b/Source/Engine/ShadersCompilation/Parser/ShaderMeta.h index 2ef7ca171..462c06432 100644 --- a/Source/Engine/ShadersCompilation/Parser/ShaderMeta.h +++ b/Source/Engine/ShadersCompilation/Parser/ShaderMeta.h @@ -119,9 +119,8 @@ public: public: /// - /// Gets shader function meta stage type + /// Gets shader function meta stage type. /// - /// Shader Stage type virtual ShaderStage GetStage() const = 0; }; diff --git a/Source/Engine/Terrain/TerrainPatch.cpp b/Source/Engine/Terrain/TerrainPatch.cpp index 9b104c489..51a6d9610 100644 --- a/Source/Engine/Terrain/TerrainPatch.cpp +++ b/Source/Engine/Terrain/TerrainPatch.cpp @@ -3,6 +3,7 @@ #include "TerrainPatch.h" #include "Terrain.h" #include "Engine/Serialization/Serialization.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Math/Color32.h" #include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Physics/Physics.h" diff --git a/Source/Engine/Threading/MainThreadTask.cpp b/Source/Engine/Threading/MainThreadTask.cpp index 0febc8bc4..2cda99834 100644 --- a/Source/Engine/Threading/MainThreadTask.cpp +++ b/Source/Engine/Threading/MainThreadTask.cpp @@ -35,7 +35,7 @@ void MainThreadTask::RunAll(float dt) String MainThreadTask::ToString() const { - return String::Format(TEXT("Main Thread Task ({0})"), ::ToString(GetState())); + return String::Format(TEXT("Main Thread Task ({0})"), (int32)GetState()); } void MainThreadTask::Enqueue() diff --git a/Source/Engine/Threading/Task.h b/Source/Engine/Threading/Task.h index 8f12696d7..a464ae52f 100644 --- a/Source/Engine/Threading/Task.h +++ b/Source/Engine/Threading/Task.h @@ -13,7 +13,15 @@ /// /// Represents the current stage in the lifecycle of a Task. /// -DECLARE_ENUM_EX_6(TaskState, int64, 0, Created, Failed, Canceled, Queued, Running, Finished); +enum class TaskState : int64 +{ + Created = 0, + Failed, + Canceled, + Queued, + Running, + Finished +}; /// /// Represents an asynchronous operation. diff --git a/Source/Engine/Threading/ThreadPool.cpp b/Source/Engine/Threading/ThreadPool.cpp index 30a89cf00..1d61c6eff 100644 --- a/Source/Engine/Threading/ThreadPool.cpp +++ b/Source/Engine/Threading/ThreadPool.cpp @@ -7,6 +7,7 @@ #include "ConcurrentTaskQueue.h" #include "Engine/Core/Log.h" #include "Engine/Core/Math/Math.h" +#include "Engine/Core/Types/String.h" #include "Engine/Engine/Globals.h" #include "Engine/Engine/EngineService.h" #include "Engine/Platform/ConditionVariable.h" @@ -27,6 +28,11 @@ namespace ThreadPoolImpl CriticalSection JobsMutex; } +String ThreadPoolTask::ToString() const +{ + return String::Format(TEXT("Thread Pool Task ({0})"), (int32)GetState()); +} + void ThreadPoolTask::Enqueue() { ThreadPoolImpl::Jobs.Add(this); diff --git a/Source/Engine/Threading/ThreadPoolTask.h b/Source/Engine/Threading/ThreadPoolTask.h index 179615f7f..c7a9156c7 100644 --- a/Source/Engine/Threading/ThreadPoolTask.h +++ b/Source/Engine/Threading/ThreadPoolTask.h @@ -3,7 +3,6 @@ #pragma once #include "Task.h" -#include "Engine/Core/Types/String.h" class ThreadPool; @@ -28,10 +27,7 @@ protected: public: // [Task] - String ToString() const override - { - return String::Format(TEXT("Thread Pool Task ({0})"), ::ToString(GetState())); - } + String ToString() const override; protected: diff --git a/Source/Engine/Utilities/Screenshot.cpp b/Source/Engine/Utilities/Screenshot.cpp index e7e9c12ad..e69506b5f 100644 --- a/Source/Engine/Utilities/Screenshot.cpp +++ b/Source/Engine/Utilities/Screenshot.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. #include "Screenshot.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Math/Math.h" #include "Engine/Graphics/RenderTask.h" #include "Engine/Platform/FileSystem.h" From 9c2104391bacafad8ed28ade2ac4445055b3168d Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Thu, 8 Dec 2022 16:30:51 +0100 Subject: [PATCH 62/83] Add profile events to editor profiler window --- .../Editor/Windows/Profiler/ProfilerWindow.cs | 32 +++++++++++++++---- 1 file changed, 26 insertions(+), 6 deletions(-) diff --git a/Source/Editor/Windows/Profiler/ProfilerWindow.cs b/Source/Editor/Windows/Profiler/ProfilerWindow.cs index 1bf7fc7f4..827cc674f 100644 --- a/Source/Editor/Windows/Profiler/ProfilerWindow.cs +++ b/Source/Editor/Windows/Profiler/ProfilerWindow.cs @@ -52,10 +52,8 @@ namespace FlaxEditor.Windows.Profiler if (_frameIndex != value) { _frameIndex = value; - UpdateButtons(); - if (_tabs.SelectedTab is ProfilerMode mode) - mode.UpdateView(_frameIndex, _showOnlyLastUpdateEvents); + UpdateView(); } } } @@ -71,10 +69,8 @@ namespace FlaxEditor.Windows.Profiler if (_showOnlyLastUpdateEvents != value) { _showOnlyLastUpdateEvents = value; - UpdateButtons(); - if (_tabs.SelectedTab is ProfilerMode mode) - mode.UpdateView(_frameIndex, _showOnlyLastUpdateEvents); + UpdateView(); } } } @@ -152,7 +148,9 @@ namespace FlaxEditor.Windows.Profiler if (_tabs.Children[i] is ProfilerMode mode) { mode.Clear(); + FlaxEngine.Profiler.BeginEvent("ProfilerWindow.UpdateView"); mode.UpdateView(ViewFrameIndex, _showOnlyLastUpdateEvents); + FlaxEngine.Profiler.EndEvent(); } } @@ -162,7 +160,11 @@ namespace FlaxEditor.Windows.Profiler private void OnSelectedTabChanged(Tabs tabs) { if (tabs.SelectedTab is ProfilerMode mode) + { + FlaxEngine.Profiler.BeginEvent("ProfilerWindow.UpdateView"); mode.UpdateView(ViewFrameIndex, _showOnlyLastUpdateEvents); + FlaxEngine.Profiler.EndEvent(); + } } private void UpdateButtons() @@ -174,6 +176,16 @@ namespace FlaxEditor.Windows.Profiler _showOnlyLastUpdateEventsButton.Checked = _showOnlyLastUpdateEvents; } + private void UpdateView() + { + if (_tabs.SelectedTab is ProfilerMode mode) + { + FlaxEngine.Profiler.BeginEvent("ProfilerWindow.UpdateView"); + mode.UpdateView(_frameIndex, _showOnlyLastUpdateEvents); + FlaxEngine.Profiler.EndEvent(); + } + } + /// public override void OnInit() { @@ -208,11 +220,19 @@ namespace FlaxEditor.Windows.Profiler for (int i = 0; i < _tabs.ChildrenCount; i++) { if (_tabs.Children[i] is ProfilerMode mode) + { + FlaxEngine.Profiler.BeginEvent(mode.GetType().FullName); mode.Update(ref sharedData); + FlaxEngine.Profiler.EndEvent(); + } } { if (_tabs.SelectedTab is ProfilerMode mode) + { + FlaxEngine.Profiler.BeginEvent("ProfilerWindow.UpdateView"); mode.UpdateView(_frameIndex, _showOnlyLastUpdateEvents); + FlaxEngine.Profiler.EndEvent(); + } } sharedData.End(); From d544c4374449ffdf88afbfa30518d6233e5ed2cd Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Thu, 8 Dec 2022 16:30:58 +0100 Subject: [PATCH 63/83] Style fix --- Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs b/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs index 050afbad3..8c143eefb 100644 --- a/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs +++ b/Source/Tools/Flax.Build/Build/NativeCpp/Builder.NativeCpp.cs @@ -798,7 +798,7 @@ namespace Flax.Build // Import symbols from referenced binary module moduleOptions.CompileEnv.PreprocessorDefinitions.Add(dependencyModule.BinaryModuleName.ToUpperInvariant() + "_API=" + toolchain.DllImport); - var dependencyModuleBuild = buildData.FinReferenceBuildModule(moduleName); + var dependencyModuleBuild = buildData.FinReferenceBuildModule(moduleName); if (dependencyModuleBuild != null) { // Link against the referenced binary module From b33ce8d264cd20432e90de5a007c88a9d5760ff4 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 9 Dec 2022 11:26:35 +0100 Subject: [PATCH 64/83] Add pooled render targets naming for easier GPU memory usage debugging --- Source/Engine/Graphics/RenderBuffers.cpp | 2 ++ Source/Engine/Graphics/RenderTargetPool.h | 7 +++++++ Source/Engine/Render2D/Render2D.cpp | 2 ++ Source/Engine/Renderer/AmbientOcclusionPass.cpp | 4 ++++ Source/Engine/Renderer/AntiAliasing/SMAA.cpp | 2 ++ Source/Engine/Renderer/AntiAliasing/TAA.cpp | 3 +++ Source/Engine/Renderer/ColorGradingPass.cpp | 1 + Source/Engine/Renderer/DepthOfFieldPass.cpp | 6 ++++++ Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp | 3 +++ Source/Engine/Renderer/EyeAdaptationPass.cpp | 4 +++- Source/Engine/Renderer/ForwardPass.cpp | 1 + Source/Engine/Renderer/GBufferPass.cpp | 1 + .../Renderer/GI/DynamicDiffuseGlobalIllumination.cpp | 2 +- Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp | 2 +- Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp | 3 +++ Source/Engine/Renderer/LightPass.cpp | 1 + Source/Engine/Renderer/MotionBlurPass.cpp | 5 +++++ Source/Engine/Renderer/PostProcessingPass.cpp | 2 ++ Source/Engine/Renderer/ReflectionsPass.cpp | 2 +- Source/Engine/Renderer/RenderList.cpp | 4 ++++ Source/Engine/Renderer/Renderer.cpp | 1 + Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp | 6 ++++++ Source/Engine/Renderer/VolumetricFogPass.cpp | 5 +++++ Source/Engine/ShadowsOfMordor/Builder.DoWork.cpp | 2 ++ Source/Engine/ShadowsOfMordor/Builder.Jobs.cpp | 2 ++ 25 files changed, 69 insertions(+), 4 deletions(-) diff --git a/Source/Engine/Graphics/RenderBuffers.cpp b/Source/Engine/Graphics/RenderBuffers.cpp index 6edceab8e..345b666cf 100644 --- a/Source/Engine/Graphics/RenderBuffers.cpp +++ b/Source/Engine/Graphics/RenderBuffers.cpp @@ -95,6 +95,7 @@ GPUTexture* RenderBuffers::RequestHalfResDepth(GPUContext* context) auto tempDesc = GPUTextureDescription::New2D(halfDepthWidth, halfDepthHeight, halfDepthFormat); tempDesc.Flags = GPUTextureFlags::ShaderResource | GPUTextureFlags::DepthStencil; HalfResDepth = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(HalfResDepth, "HalfResDepth"); } else if (HalfResDepth->Width() != halfDepthWidth || HalfResDepth->Height() != halfDepthHeight || HalfResDepth->Format() != halfDepthFormat) { @@ -103,6 +104,7 @@ GPUTexture* RenderBuffers::RequestHalfResDepth(GPUContext* context) auto tempDesc = GPUTextureDescription::New2D(halfDepthWidth, halfDepthHeight, halfDepthFormat); tempDesc.Flags = GPUTextureFlags::ShaderResource | GPUTextureFlags::DepthStencil; HalfResDepth = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(HalfResDepth, "HalfResDepth"); } // Generate depth diff --git a/Source/Engine/Graphics/RenderTargetPool.h b/Source/Engine/Graphics/RenderTargetPool.h index cba7a325d..aeb9766a8 100644 --- a/Source/Engine/Graphics/RenderTargetPool.h +++ b/Source/Engine/Graphics/RenderTargetPool.h @@ -30,3 +30,10 @@ public: /// The reference to temporary target to release. API_FUNCTION() static void Release(GPUTexture* rt); }; + +// Utility to set name to the pooled render target (compiled-put in Release builds) +#if GPU_ENABLE_RESOURCE_NAMING +#define RENDER_TARGET_POOL_SET_NAME(rt, name) rt->SetName(TEXT(name)); +#else +#define RENDER_TARGET_POOL_SET_NAME(rt, name) +#endif diff --git a/Source/Engine/Render2D/Render2D.cpp b/Source/Engine/Render2D/Render2D.cpp index 200a77121..80087eaec 100644 --- a/Source/Engine/Render2D/Render2D.cpp +++ b/Source/Engine/Render2D/Render2D.cpp @@ -1070,6 +1070,8 @@ void DrawBatch(int32 startIndex, int32 count) auto desc = GPUTextureDescription::New2D(renderTargetWidth, renderTargetHeight, PS_Blur_Format); auto blurA = RenderTargetPool::Get(desc); auto blurB = RenderTargetPool::Get(desc); + RENDER_TARGET_POOL_SET_NAME(blurA, "Render2D.BlurA"); + RENDER_TARGET_POOL_SET_NAME(blurB, "Render2D.BlurB"); // Prepare blur data BlurData data; diff --git a/Source/Engine/Renderer/AmbientOcclusionPass.cpp b/Source/Engine/Renderer/AmbientOcclusionPass.cpp index 6be56e534..a6c5d1062 100644 --- a/Source/Engine/Renderer/AmbientOcclusionPass.cpp +++ b/Source/Engine/Renderer/AmbientOcclusionPass.cpp @@ -307,13 +307,17 @@ void AmbientOcclusionPass::InitRTs(const RenderContext& renderContext) // TODO: maybe instead of using whole mip chain request only SSAO_DEPTH_MIP_LEVELS? tempDesc = GPUTextureDescription::New2D((int32)m_halfSizeX, (int32)m_halfSizeY, 0, SSAO_DEPTH_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget | GPUTextureFlags::PerMipViews); m_halfDepths[i] = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(m_halfDepths[i], "SSAO.HalfDepth"); } tempDesc = GPUTextureDescription::New2D((int32)m_halfSizeX, (int32)m_halfSizeY, SSAO_AO_RESULT_FORMAT); m_pingPongHalfResultA = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(m_pingPongHalfResultA, "SSAO.ResultsHalfA"); tempDesc = GPUTextureDescription::New2D((int32)m_halfSizeX, (int32)m_halfSizeY, SSAO_AO_RESULT_FORMAT); m_pingPongHalfResultB = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(m_pingPongHalfResultA, "SSAO.ResultsHalfB"); tempDesc = GPUTextureDescription::New2D((int32)m_halfSizeX, (int32)m_halfSizeY, SSAO_AO_RESULT_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget, 4); m_finalResults = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(m_finalResults, "SSAO.Results"); } void AmbientOcclusionPass::ReleaseRTs(const RenderContext& renderContext) diff --git a/Source/Engine/Renderer/AntiAliasing/SMAA.cpp b/Source/Engine/Renderer/AntiAliasing/SMAA.cpp index 4eafc89ee..95ad564c8 100644 --- a/Source/Engine/Renderer/AntiAliasing/SMAA.cpp +++ b/Source/Engine/Renderer/AntiAliasing/SMAA.cpp @@ -112,6 +112,8 @@ void SMAA::Render(RenderContext& renderContext, GPUTexture* input, GPUTextureVie const auto tempDesc = GPUTextureDescription::New2D((int32)renderContext.View.ScreenSize.X, (int32)renderContext.View.ScreenSize.Y, PixelFormat::R8G8B8A8_UNorm); auto edges = RenderTargetPool::Get(tempDesc); auto weights = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(edges, "SMAA.Edges"); + RENDER_TARGET_POOL_SET_NAME(weights,"SMAA.Weights"); // Bind constants Data data; diff --git a/Source/Engine/Renderer/AntiAliasing/TAA.cpp b/Source/Engine/Renderer/AntiAliasing/TAA.cpp index 08ca199f2..63038ae27 100644 --- a/Source/Engine/Renderer/AntiAliasing/TAA.cpp +++ b/Source/Engine/Renderer/AntiAliasing/TAA.cpp @@ -92,6 +92,7 @@ void TAA::Render(const RenderContext& renderContext, GPUTexture* input, GPUTextu { // Missing temporal buffer renderContext.Buffers->TemporalAA = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(renderContext.Buffers->TemporalAA, "TemporalAA"); resetHistory = true; } else if (renderContext.Buffers->TemporalAA->Width() != tempDesc.Width || renderContext.Buffers->TemporalAA->Height() != tempDesc.Height) @@ -99,10 +100,12 @@ void TAA::Render(const RenderContext& renderContext, GPUTexture* input, GPUTextu // Wrong size temporal buffer RenderTargetPool::Release(renderContext.Buffers->TemporalAA); renderContext.Buffers->TemporalAA = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(renderContext.Buffers->TemporalAA, "TemporalAA"); resetHistory = true; } auto inputHistory = renderContext.Buffers->TemporalAA; const auto outputHistory = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(outputHistory, "TemporalAA"); // Duplicate the current frame to the history buffer if need to reset the temporal history float blendStrength = 1.0f; diff --git a/Source/Engine/Renderer/ColorGradingPass.cpp b/Source/Engine/Renderer/ColorGradingPass.cpp index 64a6ed631..d9fb645de 100644 --- a/Source/Engine/Renderer/ColorGradingPass.cpp +++ b/Source/Engine/Renderer/ColorGradingPass.cpp @@ -148,6 +148,7 @@ GPUTexture* ColorGradingPass::RenderLUT(RenderContext& renderContext) lutDesc = GPUTextureDescription::New2D(LutSize * LutSize, LutSize, 1, _lutFormat); } const auto lut = RenderTargetPool::Get(lutDesc); + RENDER_TARGET_POOL_SET_NAME(lut, "ColorGrading.LUT"); // Prepare the parameters Data data; diff --git a/Source/Engine/Renderer/DepthOfFieldPass.cpp b/Source/Engine/Renderer/DepthOfFieldPass.cpp index f80441d00..e3a76ad84 100644 --- a/Source/Engine/Renderer/DepthOfFieldPass.cpp +++ b/Source/Engine/Renderer/DepthOfFieldPass.cpp @@ -288,6 +288,7 @@ GPUTexture* DepthOfFieldPass::Render(RenderContext& renderContext, GPUTexture* i // Depth/blur generation pass auto tempDesc = GPUTextureDescription::New2D(cocWidth, cocHeight, DOF_DEPTH_BLUR_FORMAT, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget | GPUTextureFlags::UnorderedAccess); GPUTexture* depthBlurTarget = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(depthBlurTarget, "DOF.Blur"); context->SetViewportAndScissors((float)cocWidth, (float)cocHeight); context->SetRenderTarget(*depthBlurTarget); context->BindSR(0, depthBuffer); @@ -299,6 +300,7 @@ GPUTexture* DepthOfFieldPass::Render(RenderContext& renderContext, GPUTexture* i auto dofFormat = renderContext.Buffers->GetOutputFormat(); tempDesc = GPUTextureDescription::New2D(dofWidth, dofHeight, dofFormat); GPUTexture* dofInput = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(dofInput, "DOF.Output"); // Do the bokeh point generation, or just do a copy if disabled bool isBokehGenerationEnabled = dofSettings.BokehEnabled && _platformSupportsBokeh && dofSettings.BokehBrightness > 0.0f && dofSettings.BokehSize > 0.0f; @@ -354,6 +356,8 @@ GPUTexture* DepthOfFieldPass::Render(RenderContext& renderContext, GPUTexture* i tempDesc = GPUTextureDescription::New2D(dofWidth, dofHeight, dofFormat, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget | GPUTextureFlags::UnorderedAccess); auto dofTargetH = RenderTargetPool::Get(tempDesc); auto dofTargetV = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(dofTargetH, "DOF.TargetH"); + RENDER_TARGET_POOL_SET_NAME(dofTargetV, "DOF.TargetV"); // Horizontal pass context->BindSR(0, dofInput); @@ -400,6 +404,7 @@ GPUTexture* DepthOfFieldPass::Render(RenderContext& renderContext, GPUTexture* i { tempDesc = GPUTextureDescription::New2D(bokehTargetWidth, bokehTargetHeight, dofFormat); auto bokehTarget = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(depthBlurTarget, "DOF.Bokeh"); context->Clear(*bokehTarget, Color::Black); { @@ -423,6 +428,7 @@ GPUTexture* DepthOfFieldPass::Render(RenderContext& renderContext, GPUTexture* i // Composite the bokeh rendering results with the depth of field result tempDesc = GPUTextureDescription::New2D(dofWidth, dofHeight, dofFormat); auto compositeTarget = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(depthBlurTarget, "DOF.Composite"); context->BindSR(0, bokehTarget); context->BindSR(1, dofOutput); context->SetRenderTarget(*compositeTarget); diff --git a/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp b/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp index 3033e4afe..6b8af8ea3 100644 --- a/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp +++ b/Source/Engine/Renderer/Editor/QuadOverdrawPass.cpp @@ -31,6 +31,9 @@ void QuadOverdrawPass::Render(RenderContext& renderContext, GPUContext* context, auto lockTexture = RenderTargetPool::Get(tempDesc); auto overdrawTexture = RenderTargetPool::Get(tempDesc); auto liveCountTexture = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(lockTexture, "QuadOverdraw.Lock"); + RENDER_TARGET_POOL_SET_NAME(overdrawTexture, "QuadOverdraw.Overdraw"); + RENDER_TARGET_POOL_SET_NAME(liveCountTexture, "QuadOverdraw.LiveCount"); // Clear buffers uint32 clearValueUINT[4] = { 0 }; diff --git a/Source/Engine/Renderer/EyeAdaptationPass.cpp b/Source/Engine/Renderer/EyeAdaptationPass.cpp index ea5013a3d..1cbf46e35 100644 --- a/Source/Engine/Renderer/EyeAdaptationPass.cpp +++ b/Source/Engine/Renderer/EyeAdaptationPass.cpp @@ -118,6 +118,7 @@ void EyeAdaptationPass::Render(RenderContext& renderContext, GPUTexture* colorBu previousLuminanceMap = nullptr; } GPUTexture* currentLuminanceMap = RenderTargetPool::Get(GPUTextureDescription::New2D(1, 1, PixelFormat::R16_Float)); + RENDER_TARGET_POOL_SET_NAME(currentLuminanceMap, "EyeAdaptation.LuminanceMap"); switch (mode) { @@ -139,7 +140,8 @@ void EyeAdaptationPass::Render(RenderContext& renderContext, GPUTexture* colorBu { const Int2 luminanceMapSize(colorBuffer->Width() / 2, colorBuffer->Height() / 2); GPUTexture* luminanceMap = RenderTargetPool::Get(GPUTextureDescription::New2D(luminanceMapSize.X, luminanceMapSize.Y, 0, PixelFormat::R16_Float, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget | GPUTextureFlags::PerMipViews)); - + RENDER_TARGET_POOL_SET_NAME(luminanceMap, "EyeAdaptation.LuminanceMap"); + // Calculate the luminance for the scene color context->BindSR(0, *colorBuffer); context->SetRenderTarget(luminanceMap->View(0, 0)); diff --git a/Source/Engine/Renderer/ForwardPass.cpp b/Source/Engine/Renderer/ForwardPass.cpp index 214d725d9..fd48ef64e 100644 --- a/Source/Engine/Renderer/ForwardPass.cpp +++ b/Source/Engine/Renderer/ForwardPass.cpp @@ -109,6 +109,7 @@ void ForwardPass::Render(RenderContext& renderContext, GPUTexture* input, GPUTex const int32 distortionHeight = height; const auto tempDesc = GPUTextureDescription::New2D(distortionWidth, distortionHeight, Distortion_Pass_Output_Format); auto distortionRT = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(distortionRT, "Forward.Distortion"); // Clear distortion vectors context->Clear(distortionRT->View(), Color::Transparent); diff --git a/Source/Engine/Renderer/GBufferPass.cpp b/Source/Engine/Renderer/GBufferPass.cpp index 2d5f6eadf..3aa4c97d5 100644 --- a/Source/Engine/Renderer/GBufferPass.cpp +++ b/Source/Engine/Renderer/GBufferPass.cpp @@ -292,6 +292,7 @@ GPUTextureView* GBufferPass::RenderSkybox(RenderContext& renderContext, GPUConte skyboxData.Skybox = RenderTargetPool::Get(desc); if (!skyboxData.Skybox) return nullptr; + RENDER_TARGET_POOL_SET_NAME(skyboxData.Skybox, "GBuffer.Skybox"); dirty = true; } diff --git a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp index ecd104bd4..25c98678d 100644 --- a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp +++ b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp @@ -370,7 +370,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont // Allocate probes textures uint64 memUsage = 0; auto desc = GPUTextureDescription::New2D(probesCountTotalX, probesCountTotalY, PixelFormat::Unknown); -#define INIT_TEXTURE(texture, format, width, height) desc.Format = format; desc.Width = width; desc.Height = height; ddgiData.texture = RenderTargetPool::Get(desc); if (!ddgiData.texture) return true; memUsage += ddgiData.texture->GetMemoryUsage() +#define INIT_TEXTURE(texture, format, width, height) desc.Format = format; desc.Width = width; desc.Height = height; ddgiData.texture = RenderTargetPool::Get(desc); if (!ddgiData.texture) return true; memUsage += ddgiData.texture->GetMemoryUsage(); RENDER_TARGET_POOL_SET_NAME(ddgiData.texture, "DDGI." #texture) desc.Flags = GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess; INIT_TEXTURE(ProbesTrace, PixelFormat::R16G16B16A16_Float, probeRaysCount, Math::Min(probesCountCascade, DDGI_TRACE_RAYS_PROBES_COUNT_LIMIT)); INIT_TEXTURE(ProbesState, PixelFormat::R8G8B8A8_SNorm, probesCountTotalX, probesCountTotalY); diff --git a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp index d6901b7ee..68c9878e5 100644 --- a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp +++ b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp @@ -398,7 +398,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co auto desc = GPUTextureDescription::New2D(resolution, resolution, PixelFormat::Unknown); uint64 memUsage = 0; // TODO: try using BC4/BC5/BC7 block compression for Surface Atlas (eg. for Tiles material properties) -#define INIT_ATLAS_TEXTURE(texture, format) desc.Format = format; surfaceAtlasData.texture = RenderTargetPool::Get(desc); if (!surfaceAtlasData.texture) return true; memUsage += surfaceAtlasData.texture->GetMemoryUsage() +#define INIT_ATLAS_TEXTURE(texture, format) desc.Format = format; surfaceAtlasData.texture = RenderTargetPool::Get(desc); if (!surfaceAtlasData.texture) return true; memUsage += surfaceAtlasData.texture->GetMemoryUsage(); RENDER_TARGET_POOL_SET_NAME(surfaceAtlasData.texture, "GlobalSurfaceAtlas." #texture); INIT_ATLAS_TEXTURE(AtlasEmissive, PixelFormat::R11G11B10_Float); INIT_ATLAS_TEXTURE(AtlasGBuffer0, GBUFFER0_FORMAT); INIT_ATLAS_TEXTURE(AtlasGBuffer1, GBUFFER1_FORMAT); diff --git a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp index 48427b8ed..6e0802bd6 100644 --- a/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp +++ b/Source/Engine/Renderer/GlobalSignDistanceFieldPass.cpp @@ -435,6 +435,7 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex texture = RenderTargetPool::Get(desc); if (!texture) return true; + RENDER_TARGET_POOL_SET_NAME(texture, "GlobalSDF.Cascade"); } } desc.Width = resolutionMip * cascadesCount; @@ -451,6 +452,7 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex texture = RenderTargetPool::Get(desc); if (!texture) return true; + RENDER_TARGET_POOL_SET_NAME(texture, "GlobalSDF.Cascade"); } } uint64 memoryUsage = sdfData.Texture->GetMemoryUsage() + sdfData.TextureMip->GetMemoryUsage(); @@ -840,6 +842,7 @@ bool GlobalSignDistanceFieldPass::Render(RenderContext& renderContext, GPUContex tmpMip = RenderTargetPool::Get(desc); if (!tmpMip) return true; + RENDER_TARGET_POOL_SET_NAME(tmpMip, "GlobalSDF.Mip"); } GPUTextureView* tmpMipView = tmpMip->ViewVolume(); diff --git a/Source/Engine/Renderer/LightPass.cpp b/Source/Engine/Renderer/LightPass.cpp index 0d7fccb47..f55cc115b 100644 --- a/Source/Engine/Renderer/LightPass.cpp +++ b/Source/Engine/Renderer/LightPass.cpp @@ -234,6 +234,7 @@ void LightPass::RenderLight(RenderContextBatch& renderContextBatch, GPUTextureVi if (!shadowMask) { \ auto rtDesc = GPUTextureDescription::New2D(renderContext.Buffers->GetWidth(), renderContext.Buffers->GetHeight(), _shadowMaskFormat); \ shadowMask = RenderTargetPool::Get(rtDesc); \ + RENDER_TARGET_POOL_SET_NAME(shadowMask, "ShadowMask"); \ } \ auto shadowMaskView = shadowMask->View() diff --git a/Source/Engine/Renderer/MotionBlurPass.cpp b/Source/Engine/Renderer/MotionBlurPass.cpp index 168d35e73..301d0a3eb 100644 --- a/Source/Engine/Renderer/MotionBlurPass.cpp +++ b/Source/Engine/Renderer/MotionBlurPass.cpp @@ -304,6 +304,7 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GP // Downscale motion vectors texture down to 1/2 (with max velocity calculation 2x2 kernel) auto rtDesc = GPUTextureDescription::New2D(motionVectorsWidth / 2, motionVectorsHeight / 2, _motionVectorsFormat); const auto vMaxBuffer2 = RenderTargetPool::Get(rtDesc); + RENDER_TARGET_POOL_SET_NAME(vMaxBuffer2, "MotionBlur.VMax2"); context->SetRenderTarget(vMaxBuffer2->View()); context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height); context->BindSR(0, motionVectors->View()); @@ -314,6 +315,7 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GP rtDesc.Width /= 2; rtDesc.Height /= 2; const auto vMaxBuffer4 = RenderTargetPool::Get(rtDesc); + RENDER_TARGET_POOL_SET_NAME(vMaxBuffer4, "MotionBlur.VMax4"); context->ResetRenderTarget(); context->SetRenderTarget(vMaxBuffer4->View()); context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height); @@ -328,6 +330,7 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GP rtDesc.Width /= 2; rtDesc.Height /= 2; const auto vMaxBuffer8 = RenderTargetPool::Get(rtDesc); + RENDER_TARGET_POOL_SET_NAME(vMaxBuffer8, "MotionBlur.VMax8"); context->ResetRenderTarget(); context->SetRenderTarget(vMaxBuffer8->View()); context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height); @@ -342,6 +345,7 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GP rtDesc.Width = Math::Max(motionVectorsWidth / tileSize, 1); rtDesc.Height = Math::Max(motionVectorsHeight / tileSize, 1); auto vMaxBuffer = RenderTargetPool::Get(rtDesc); + RENDER_TARGET_POOL_SET_NAME(vMaxBuffer, "MotionBlur.VMax"); context->ResetRenderTarget(); context->SetRenderTarget(vMaxBuffer->View()); context->SetViewportAndScissors((float)rtDesc.Width, (float)rtDesc.Height); @@ -355,6 +359,7 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GP // Extract maximum velocities for the tiles based on their neighbors context->ResetRenderTarget(); auto vMaxNeighborBuffer = RenderTargetPool::Get(rtDesc); + RENDER_TARGET_POOL_SET_NAME(vMaxBuffer, "MotionBlur.VMaxNeighbor"); context->SetRenderTarget(vMaxNeighborBuffer->View()); context->BindSR(0, vMaxBuffer->View()); context->SetState(_psNeighborMax); diff --git a/Source/Engine/Renderer/PostProcessingPass.cpp b/Source/Engine/Renderer/PostProcessingPass.cpp index 99d1ccd0e..4e75e21fd 100644 --- a/Source/Engine/Renderer/PostProcessingPass.cpp +++ b/Source/Engine/Renderer/PostProcessingPass.cpp @@ -310,8 +310,10 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input, auto tempDesc = GPUTextureDescription::New2D(w2, h2, 0, output->Format(), GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget | GPUTextureFlags::PerMipViews); auto bloomTmp1 = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(bloomTmp1, "PostProcessing.Bloom"); // TODO: bloomTmp2 could be quarter res because we don't use it's first mip auto bloomTmp2 = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(bloomTmp2, "PostProcessing.Bloom"); // Check if use bloom if (useBloom) diff --git a/Source/Engine/Renderer/ReflectionsPass.cpp b/Source/Engine/Renderer/ReflectionsPass.cpp index 952f45e54..959145962 100644 --- a/Source/Engine/Renderer/ReflectionsPass.cpp +++ b/Source/Engine/Renderer/ReflectionsPass.cpp @@ -393,7 +393,7 @@ void ReflectionsPass::Render(RenderContext& renderContext, GPUTextureView* light auto tempDesc = GPUTextureDescription::New2D(renderContext.Buffers->GetWidth(), renderContext.Buffers->GetHeight(), PixelFormat::R11G11B10_Float); auto reflectionsBuffer = RenderTargetPool::Get(tempDesc); - + RENDER_TARGET_POOL_SET_NAME(reflectionsBuffer, "Reflections"); context->Clear(*reflectionsBuffer, Color::Black); // Reflection Probes pass diff --git a/Source/Engine/Renderer/RenderList.cpp b/Source/Engine/Renderer/RenderList.cpp index 95abc11be..53a5d4dc1 100644 --- a/Source/Engine/Renderer/RenderList.cpp +++ b/Source/Engine/Renderer/RenderList.cpp @@ -234,6 +234,10 @@ void RenderList::RunPostFxPass(GPUContext* context, RenderContext& renderContext auto tempDesc = inputOutput->GetDescription(); auto temp = needTempTarget ? RenderTargetPool::Get(tempDesc) : nullptr; + if (needTempTarget) + { + RENDER_TARGET_POOL_SET_NAME(temp, "RenderList.RunPostFxPassTemp"); + } auto input = inputOutput; auto output = temp; diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp index 0a2aefab5..34c32479e 100644 --- a/Source/Engine/Renderer/Renderer.cpp +++ b/Source/Engine/Renderer/Renderer.cpp @@ -388,6 +388,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont auto outputFormat = renderContext.Buffers->GetOutputFormat(); auto tempDesc = GPUTextureDescription::New2D(renderContext.Buffers->GetWidth(), renderContext.Buffers->GetHeight(), outputFormat); auto lightBuffer = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(lightBuffer, "Lighting"); #if USE_EDITOR if (renderContext.View.Mode == ViewMode::QuadOverdraw) diff --git a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp index 4464ce599..ce7e6e3f3 100644 --- a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp +++ b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp @@ -195,12 +195,16 @@ void ScreenSpaceReflectionsPass::Render(RenderContext& renderContext, GPUTexture // Prepare buffers auto tempDesc = GPUTextureDescription::New2D(width / 2, height / 2, 0, PixelFormat::R11G11B10_Float, GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget | GPUTextureFlags::PerMipViews); auto colorBuffer0 = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(colorBuffer0, "SSR.ColorBuffer0"); // TODO: maybe allocate colorBuffer1 smaller because mip0 is not used (the same as PostProcessingPass for Bloom), keep in sync to use the same buffer in frame auto colorBuffer1 = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(colorBuffer1, "SSR.ColorBuffer1"); tempDesc = GPUTextureDescription::New2D(traceWidth, traceHeight, PixelFormat::R16G16B16A16_Float); auto traceBuffer = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(traceBuffer, "SSR.TraceBuffer"); tempDesc = GPUTextureDescription::New2D(resolveWidth, resolveHeight, RESOLVE_PASS_OUTPUT_FORMAT); auto resolveBuffer = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(resolveBuffer, "SSR.ResolveBuffer"); // Pick effect settings int32 maxTraceSamples = 60; @@ -262,6 +266,7 @@ void ScreenSpaceReflectionsPass::Render(RenderContext& renderContext, GPUTexture RenderTargetPool::Release(buffers->TemporalSSR); tempDesc = GPUTextureDescription::New2D(temporalWidth, temporalHeight, RESOLVE_PASS_OUTPUT_FORMAT); buffers->TemporalSSR = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(buffers->TemporalSSR, "SSR.TemporalSSR"); } } else @@ -386,6 +391,7 @@ void ScreenSpaceReflectionsPass::Render(RenderContext& renderContext, GPUTexture { tempDesc = GPUTextureDescription::New2D(temporalWidth, temporalHeight, RESOLVE_PASS_OUTPUT_FORMAT); auto newTemporal = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(newTemporal, "SSR.TemporalSSR"); const auto oldTemporal = buffers->TemporalSSR; const auto motionVectors = buffers->MotionVectors; diff --git a/Source/Engine/Renderer/VolumetricFogPass.cpp b/Source/Engine/Renderer/VolumetricFogPass.cpp index 552103b14..44cad992b 100644 --- a/Source/Engine/Renderer/VolumetricFogPass.cpp +++ b/Source/Engine/Renderer/VolumetricFogPass.cpp @@ -254,6 +254,7 @@ GPUTextureView* VolumetricFogPass::GetLocalShadowedLightScattering(RenderContext ASSERT(renderContext.Buffers->LastFrameVolumetricFog == Engine::FrameCount); const GPUTextureDescription volumeDescRGB = GPUTextureDescription::New3D(_cache.GridSize, PixelFormat::R11G11B10_Float, GPUTextureFlags::RenderTarget | GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess); const auto texture = RenderTargetPool::Get(volumeDescRGB); + RENDER_TARGET_POOL_SET_NAME(texture, "VolumetricFog.LocalShadowedLightScattering"); renderContext.Buffers->LocalShadowedLightScattering = texture; context->Clear(texture->ViewVolume(), Color::Transparent); } @@ -496,8 +497,11 @@ void VolumetricFogPass::Render(RenderContext& renderContext) const GPUTextureDescription volumeDesc = GPUTextureDescription::New3D(cache.GridSize, PixelFormat::R16G16B16A16_Float, GPUTextureFlags::RenderTarget | GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess); const GPUTextureDescription volumeDescRGB = GPUTextureDescription::New3D(cache.GridSize, PixelFormat::R11G11B10_Float, GPUTextureFlags::RenderTarget | GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess); auto vBufferA = RenderTargetPool::Get(volumeDesc); + RENDER_TARGET_POOL_SET_NAME(vBufferA, "VolumetricFog.VBufferA"); auto vBufferB = RenderTargetPool::Get(volumeDescRGB); + RENDER_TARGET_POOL_SET_NAME(vBufferB, "VolumetricFog.VBufferB"); const auto lightScattering = RenderTargetPool::Get(volumeDesc); + RENDER_TARGET_POOL_SET_NAME(lightScattering, "VolumetricFog.LightScattering"); int32 groupCountX = Math::DivideAndRoundUp((int32)cache.GridSize.X, VolumetricFogGridInjectionGroupSize); int32 groupCountY = Math::DivideAndRoundUp((int32)cache.GridSize.Y, VolumetricFogGridInjectionGroupSize); @@ -703,6 +707,7 @@ void VolumetricFogPass::Render(RenderContext& renderContext) RenderTargetPool::Release(integratedLightScattering); } integratedLightScattering = RenderTargetPool::Get(volumeDesc); + RENDER_TARGET_POOL_SET_NAME(integratedLightScattering, "VolumetricFog.Integrated"); renderContext.Buffers->VolumetricFog = integratedLightScattering; } renderContext.Buffers->LastFrameVolumetricFog = Engine::FrameCount; diff --git a/Source/Engine/ShadowsOfMordor/Builder.DoWork.cpp b/Source/Engine/ShadowsOfMordor/Builder.DoWork.cpp index 1a04c6fa5..a14e5d9f3 100644 --- a/Source/Engine/ShadowsOfMordor/Builder.DoWork.cpp +++ b/Source/Engine/ShadowsOfMordor/Builder.DoWork.cpp @@ -186,8 +186,10 @@ bool ShadowsOfMordor::Builder::doWorkInner(DateTime buildStart) const int32 atlasSize = (int32)_scenes[_workerActiveSceneIndex]->GetSettings().AtlasSize; auto tempDesc = GPUTextureDescription::New2D(atlasSize, atlasSize, HemispheresFormatToPixelFormat[CACHE_POSITIONS_FORMAT]); _cachePositions = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(_cachePositions, "ShadowsOfMordor.Positions"); tempDesc.Format = HemispheresFormatToPixelFormat[CACHE_NORMALS_FORMAT]; _cacheNormals = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(_cachePositions, "ShadowsOfMordor.Normals"); if (_cachePositions == nullptr || _cacheNormals == nullptr) { LOG(Warning, "Failed to get textures for cache."); diff --git a/Source/Engine/ShadowsOfMordor/Builder.Jobs.cpp b/Source/Engine/ShadowsOfMordor/Builder.Jobs.cpp index ab210a451..b7ab9134f 100644 --- a/Source/Engine/ShadowsOfMordor/Builder.Jobs.cpp +++ b/Source/Engine/ShadowsOfMordor/Builder.Jobs.cpp @@ -222,8 +222,10 @@ void ShadowsOfMordor::Builder::onJobRender(GPUContext* context) auto tempDesc = GPUTextureDescription::New2D(atlasSize, atlasSize, HemispheresFormatToPixelFormat[CACHE_POSITIONS_FORMAT]); auto resultPositions = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(_cachePositions, "ShadowsOfMordor.Positions"); tempDesc.Format = HemispheresFormatToPixelFormat[CACHE_NORMALS_FORMAT]; auto resultNormals = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(_cachePositions, "ShadowsOfMordor.Normals"); if (resultPositions == nullptr || resultNormals == nullptr) { RenderTargetPool::Release(resultPositions); From 7f0c73606c8a45054b529409b5dcabe9600dffe2 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 9 Dec 2022 11:27:41 +0100 Subject: [PATCH 65/83] Improve naming various GPU resources --- Source/Engine/Content/Assets/Model.cpp | 8 +++++++- Source/Engine/Graphics/GPUResource.h | 3 ++- Source/Engine/Graphics/GPUSwapChain.cpp | 7 +++++++ Source/Engine/Graphics/GPUSwapChain.h | 4 +--- Source/Engine/Graphics/Models/SkinnedMesh.cpp | 4 ++-- Source/Engine/Tools/ModelTool/ModelTool.cpp | 3 +++ 6 files changed, 22 insertions(+), 7 deletions(-) diff --git a/Source/Engine/Content/Assets/Model.cpp b/Source/Engine/Content/Assets/Model.cpp index c57b9c7be..254a3cd11 100644 --- a/Source/Engine/Content/Assets/Model.cpp +++ b/Source/Engine/Content/Assets/Model.cpp @@ -979,7 +979,13 @@ Asset::LoadResult Model::load() ModelSDFHeader data; sdfStream.ReadBytes(&data, sizeof(data)); if (!SDF.Texture) - SDF.Texture = GPUTexture::New(); + { + String name; +#if !BUILD_RELEASE + name = GetPath() + TEXT(".SDF"); +#endif + SDF.Texture = GPUDevice::Instance->CreateTexture(name); + } if (SDF.Texture->Init(GPUTextureDescription::New3D(data.Width, data.Height, data.Depth, data.Format, GPUTextureFlags::ShaderResource, data.MipLevels))) return LoadResult::Failed; SDF.LocalToUVWMul = data.LocalToUVWMul; diff --git a/Source/Engine/Graphics/GPUResource.h b/Source/Engine/Graphics/GPUResource.h index 05f409b9c..94265a7b3 100644 --- a/Source/Engine/Graphics/GPUResource.h +++ b/Source/Engine/Graphics/GPUResource.h @@ -147,7 +147,8 @@ public: : _device(device) { #if GPU_ENABLE_RESOURCE_NAMING - GPUResource::_name = name; + if (name.HasChars()) + GPUResource::_name = name; #endif device->AddResource(this); } diff --git a/Source/Engine/Graphics/GPUSwapChain.cpp b/Source/Engine/Graphics/GPUSwapChain.cpp index bd2ac858b..43a2582ca 100644 --- a/Source/Engine/Graphics/GPUSwapChain.cpp +++ b/Source/Engine/Graphics/GPUSwapChain.cpp @@ -35,6 +35,13 @@ public: } }; +GPUSwapChain::GPUSwapChain() +{ +#if GPU_ENABLE_RESOURCE_NAMING + _name = TEXT("Swap Chain (backbuffers)"); +#endif +} + Task* GPUSwapChain::DownloadDataAsync(TextureData& result) { if (_downloadTask) diff --git a/Source/Engine/Graphics/GPUSwapChain.h b/Source/Engine/Graphics/GPUSwapChain.h index 738aeaf40..b4a8bd8bd 100644 --- a/Source/Engine/Graphics/GPUSwapChain.h +++ b/Source/Engine/Graphics/GPUSwapChain.h @@ -24,9 +24,7 @@ protected: Window* _window = nullptr; Task* _downloadTask = nullptr; - GPUSwapChain() - { - } + GPUSwapChain(); public: /// diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.cpp b/Source/Engine/Graphics/Models/SkinnedMesh.cpp index d7984d378..17c63ac8e 100644 --- a/Source/Engine/Graphics/Models/SkinnedMesh.cpp +++ b/Source/Engine/Graphics/Models/SkinnedMesh.cpp @@ -53,7 +53,7 @@ bool SkinnedMesh::Load(uint32 vertices, uint32 triangles, void* vb0, void* ib, b // Create vertex buffer #if GPU_ENABLE_RESOURCE_NAMING - vertexBuffer = GPUDevice::Instance->CreateBuffer(GetSkinnedModel()->ToString() + TEXT(".VB")); + vertexBuffer = GPUDevice::Instance->CreateBuffer(GetSkinnedModel()->GetPath() + TEXT(".VB")); #else vertexBuffer = GPUDevice::Instance->CreateBuffer(String::Empty); #endif @@ -62,7 +62,7 @@ bool SkinnedMesh::Load(uint32 vertices, uint32 triangles, void* vb0, void* ib, b // Create index buffer #if GPU_ENABLE_RESOURCE_NAMING - indexBuffer = GPUDevice::Instance->CreateBuffer(GetSkinnedModel()->ToString() + TEXT(".IB")); + indexBuffer = GPUDevice::Instance->CreateBuffer(GetSkinnedModel()->GetPath() + TEXT(".IB")); #else indexBuffer = GPUDevice::Instance->CreateBuffer(String::Empty); #endif diff --git a/Source/Engine/Tools/ModelTool/ModelTool.cpp b/Source/Engine/Tools/ModelTool/ModelTool.cpp index 9d6969a92..54800f2c5 100644 --- a/Source/Engine/Tools/ModelTool/ModelTool.cpp +++ b/Source/Engine/Tools/ModelTool/ModelTool.cpp @@ -134,6 +134,9 @@ bool ModelTool::GenerateModelSDF(Model* inputModel, ModelData* modelData, float SAFE_DELETE_GPU_RESOURCE(outputSDF->Texture); return true; } +#if !BUILD_RELEASE + outputSDF->Texture->SetName(TEXT("ModelSDF")); +#endif } // TODO: support GPU to generate model SDF on-the-fly (if called during rendering) From 202de3499f1d112c8afd546e9e935cb9cb9e9991 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 9 Dec 2022 11:28:17 +0100 Subject: [PATCH 66/83] Rename property `GetElementsCount` to `ElementsCount` in C# `GPUBufferDescription` --- Source/Engine/Graphics/GPUBufferDescription.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Engine/Graphics/GPUBufferDescription.cs b/Source/Engine/Graphics/GPUBufferDescription.cs index 9d03bb525..07572424a 100644 --- a/Source/Engine/Graphics/GPUBufferDescription.cs +++ b/Source/Engine/Graphics/GPUBufferDescription.cs @@ -9,7 +9,7 @@ namespace FlaxEngine /// /// Gets the number elements in the buffer. /// - public uint GetElementsCount => Stride > 0 ? Size / Stride : 0; + public uint ElementsCount => Stride > 0 ? Size / Stride : 0; /// /// Gets a value indicating whether this instance is a shader resource. From a809a69ca0cc49f3ba1ae751b0d649c316ca17b4 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 9 Dec 2022 11:28:39 +0100 Subject: [PATCH 67/83] Fixes for GPU resources C# object types --- Source/Engine/Graphics/GPUBuffer.cpp | 1 + Source/Engine/Graphics/GPUDevice.cpp | 7 ++++++- Source/Engine/Graphics/GPUPipelineState.h | 2 ++ Source/Engine/Graphics/GPUResource.h | 3 ++- Source/Engine/Graphics/Shaders/GPUShader.cpp | 1 + Source/Engine/Graphics/Shaders/GPUShader.h | 3 --- Source/Engine/Graphics/Textures/GPUSampler.cpp | 1 + Source/Engine/Graphics/Textures/GPUTexture.cpp | 4 +--- Source/Engine/Graphics/Textures/GPUTexture.h | 3 --- Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h | 2 +- 10 files changed, 15 insertions(+), 12 deletions(-) diff --git a/Source/Engine/Graphics/GPUBuffer.cpp b/Source/Engine/Graphics/GPUBuffer.cpp index 4900e73e2..e927904dd 100644 --- a/Source/Engine/Graphics/GPUBuffer.cpp +++ b/Source/Engine/Graphics/GPUBuffer.cpp @@ -137,6 +137,7 @@ GPUBuffer* GPUBuffer::New() } GPUBuffer::GPUBuffer() + : GPUResource(SpawnParams(Guid::New(), TypeInitializer)) { // Buffer with size 0 is considered to be invalid _desc.Size = 0; diff --git a/Source/Engine/Graphics/GPUDevice.cpp b/Source/Engine/Graphics/GPUDevice.cpp index 14d8ff63a..d82900c1b 100644 --- a/Source/Engine/Graphics/GPUDevice.cpp +++ b/Source/Engine/Graphics/GPUDevice.cpp @@ -35,6 +35,11 @@ GPUPipelineState* GPUPipelineState::New() return GPUDevice::Instance->CreatePipelineState(); } +GPUPipelineState::GPUPipelineState() + : GPUResource(SpawnParams(Guid::New(), TypeInitializer)) +{ +} + bool GPUPipelineState::Init(const Description& desc) { // Cache description in debug builds @@ -177,7 +182,7 @@ GPUPipelineState::Description GPUPipelineState::Description::DefaultFullscreenTr }; GPUResource::GPUResource() - : ScriptingObject(SpawnParams(Guid::New(), GPUResource::TypeInitializer)) + : ScriptingObject(SpawnParams(Guid::New(), TypeInitializer)) { } diff --git a/Source/Engine/Graphics/GPUPipelineState.h b/Source/Engine/Graphics/GPUPipelineState.h index 538c83a10..b73e070f2 100644 --- a/Source/Engine/Graphics/GPUPipelineState.h +++ b/Source/Engine/Graphics/GPUPipelineState.h @@ -109,6 +109,8 @@ public: protected: ShaderBindings _meta; + GPUPipelineState(); + public: #if BUILD_DEBUG /// diff --git a/Source/Engine/Graphics/GPUResource.h b/Source/Engine/Graphics/GPUResource.h index 94265a7b3..5e27d679b 100644 --- a/Source/Engine/Graphics/GPUResource.h +++ b/Source/Engine/Graphics/GPUResource.h @@ -144,7 +144,8 @@ public: /// The graphics device. /// The resource name. GPUResourceBase(DeviceType* device, const StringView& name) noexcept - : _device(device) + : BaseType() + , _device(device) { #if GPU_ENABLE_RESOURCE_NAMING if (name.HasChars()) diff --git a/Source/Engine/Graphics/Shaders/GPUShader.cpp b/Source/Engine/Graphics/Shaders/GPUShader.cpp index 4f3428510..9905bae16 100644 --- a/Source/Engine/Graphics/Shaders/GPUShader.cpp +++ b/Source/Engine/Graphics/Shaders/GPUShader.cpp @@ -59,6 +59,7 @@ uint32 GPUShaderProgramsContainer::CalculateHash(const StringAnsiView& name, int } GPUShader::GPUShader() + : GPUResource(SpawnParams(Guid::New(), TypeInitializer)) { Platform::MemoryClear(_constantBuffers, sizeof(_constantBuffers)); } diff --git a/Source/Engine/Graphics/Shaders/GPUShader.h b/Source/Engine/Graphics/Shaders/GPUShader.h index 610f09d18..435f196ce 100644 --- a/Source/Engine/Graphics/Shaders/GPUShader.h +++ b/Source/Engine/Graphics/Shaders/GPUShader.h @@ -74,9 +74,6 @@ protected: GPUShaderProgramsContainer _shaders; GPUConstantBuffer* _constantBuffers[MAX_CONSTANT_BUFFER_SLOTS]; - /// - /// Initializes a new instance of the class. - /// GPUShader(); public: diff --git a/Source/Engine/Graphics/Textures/GPUSampler.cpp b/Source/Engine/Graphics/Textures/GPUSampler.cpp index 6eb61ec33..490b01121 100644 --- a/Source/Engine/Graphics/Textures/GPUSampler.cpp +++ b/Source/Engine/Graphics/Textures/GPUSampler.cpp @@ -76,6 +76,7 @@ GPUSampler* GPUSampler::New() } GPUSampler::GPUSampler() + : GPUResource(SpawnParams(Guid::New(), TypeInitializer)) { } diff --git a/Source/Engine/Graphics/Textures/GPUTexture.cpp b/Source/Engine/Graphics/Textures/GPUTexture.cpp index d9112ffc6..4c819fea0 100644 --- a/Source/Engine/Graphics/Textures/GPUTexture.cpp +++ b/Source/Engine/Graphics/Textures/GPUTexture.cpp @@ -220,7 +220,7 @@ GPUTexture* GPUTexture::New() } GPUTexture::GPUTexture() - : GPUResource(SpawnParams(Guid::New(), GPUTexture::TypeInitializer)) + : GPUResource(SpawnParams(Guid::New(), TypeInitializer)) , _residentMipLevels(0) , _sRGB(false) , _isBlockCompressed(false) @@ -423,7 +423,6 @@ bool GPUTexture::Init(const GPUTextureDescription& desc) break; } - case TextureDimensions::VolumeTexture: { if (desc.IsDepthStencil()) @@ -461,7 +460,6 @@ bool GPUTexture::Init(const GPUTextureDescription& desc) break; } - case TextureDimensions::CubeTexture: { if (desc.HasPerSliceViews()) diff --git a/Source/Engine/Graphics/Textures/GPUTexture.h b/Source/Engine/Graphics/Textures/GPUTexture.h index f15607567..7485a51e8 100644 --- a/Source/Engine/Graphics/Textures/GPUTexture.h +++ b/Source/Engine/Graphics/Textures/GPUTexture.h @@ -79,9 +79,6 @@ protected: bool _sRGB, _isBlockCompressed; GPUTextureDescription _desc; - /// - /// Initializes a new instance of the class. - /// GPUTexture(); public: diff --git a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h index eb8a73af5..3592ba8d1 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX11/GPUDeviceDX11.h @@ -128,7 +128,7 @@ public: /// The graphics device. /// The resource name. GPUResourceDX11(GPUDeviceDX11* device, const StringView& name) noexcept - : GPUResourceBase(device, name) + : GPUResourceBase(device, name) { } }; From e5742772ae33eb49f903a86574484ddbd014cc85 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 9 Dec 2022 11:28:53 +0100 Subject: [PATCH 68/83] Add more features to GPU Memory profiler tab --- Source/Editor/GUI/Row.cs | 20 ++++++- Source/Editor/Windows/Profiler/MemoryGPU.cs | 65 ++++++++++++++++++--- 2 files changed, 75 insertions(+), 10 deletions(-) diff --git a/Source/Editor/GUI/Row.cs b/Source/Editor/GUI/Row.cs index 2e672ac49..3587dd834 100644 --- a/Source/Editor/GUI/Row.cs +++ b/Source/Editor/GUI/Row.cs @@ -218,11 +218,27 @@ namespace FlaxEditor.GUI /// public Action RightClick; + /// + /// The double click event. + /// + public Action RowDoubleClick; + + /// + /// The left mouse button click event. + /// + public Action RowLeftClick; + + /// + /// The right mouse button click event. + /// + public Action RowRightClick; + /// public override bool OnMouseDoubleClick(Float2 location, MouseButton button) { DoubleClick?.Invoke(); - + RowDoubleClick?.Invoke(this); + return base.OnMouseDoubleClick(location, button); } @@ -244,11 +260,13 @@ namespace FlaxEditor.GUI { _leftClick = false; LeftClick?.Invoke(); + RowLeftClick?.Invoke(this); } else if (button == MouseButton.Right && _isRightDown) { _isRightDown = false; RightClick?.Invoke(); + RowRightClick?.Invoke(this); } return base.OnMouseUp(location, button); diff --git a/Source/Editor/Windows/Profiler/MemoryGPU.cs b/Source/Editor/Windows/Profiler/MemoryGPU.cs index b288819da..3d1a4f7de 100644 --- a/Source/Editor/Windows/Profiler/MemoryGPU.cs +++ b/Source/Editor/Windows/Profiler/MemoryGPU.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; +using System.Text; using FlaxEditor.GUI; using FlaxEngine; using FlaxEngine.GUI; @@ -17,9 +18,11 @@ namespace FlaxEditor.Windows.Profiler private struct Resource { public string Name; + public string Tooltip; public GPUResourceType Type; public ulong MemoryUsage; public Guid AssetId; + public bool IsAssetItem; } private readonly SingleChart _memoryUsageChart; @@ -29,6 +32,7 @@ namespace FlaxEditor.Windows.Profiler private string[] _resourceTypesNames; private Dictionary _assetPathToId; private Dictionary _resourceCache; + private StringBuilder _stringBuilder; public MemoryGPU() : base("GPU Memory") @@ -111,10 +115,14 @@ namespace FlaxEditor.Windows.Profiler _resourceCache = new Dictionary(); if (_assetPathToId == null) _assetPathToId = new Dictionary(); + if (_stringBuilder == null) + _stringBuilder = new StringBuilder(); // Capture current GPU resources usage info + var contentDatabase = Editor.Instance.ContentDatabase; var gpuResources = GPUDevice.Instance.Resources; var resources = new Resource[gpuResources.Length]; + var sb = _stringBuilder; for (int i = 0; i < resources.Length; i++) { var gpuResource = gpuResources[i]; @@ -129,6 +137,35 @@ namespace FlaxEditor.Windows.Profiler Type = gpuResource.ResourceType, }; + // Create tooltip + sb.Clear(); + if (gpuResource is GPUTexture gpuTexture) + { + var desc = gpuTexture.Description; + sb.Append("Format: ").Append(desc.Format).AppendLine(); + sb.Append("Size: ").Append(desc.Width).Append('x').Append(desc.Height); + if (desc.Depth != 1) + sb.Append('x').Append(desc.Depth); + if (desc.ArraySize != 1) + sb.Append('[').Append(desc.ArraySize).Append(']'); + sb.AppendLine(); + sb.Append("Mip Levels: ").Append(desc.MipLevels).AppendLine(); + if (desc.IsMultiSample) + sb.Append("MSAA: ").Append('x').Append((int)desc.MultiSampleLevel).AppendLine(); + sb.Append("Flags: ").Append(desc.Flags).AppendLine(); + sb.Append("Usage: ").Append(desc.Usage); + } + else if (gpuResource is GPUBuffer gpuBuffer) + { + var desc = gpuBuffer.Description; + sb.Append("Format: ").Append(desc.Format).AppendLine(); + sb.Append("Stride: ").Append(desc.Stride).AppendLine(); + sb.Append("Elements: ").Append(desc.ElementsCount).AppendLine(); + sb.Append("Flags: ").Append(desc.Flags).AppendLine(); + sb.Append("Usage: ").Append(desc.Usage); + } + resource.Tooltip = _stringBuilder.ToString(); + // Detect asset path in the resource name int ext = resource.Name.LastIndexOf(".flax", StringComparison.OrdinalIgnoreCase); if (ext != -1) @@ -141,6 +178,12 @@ namespace FlaxEditor.Windows.Profiler resource.AssetId = asset.ID; _assetPathToId.Add(assetPath, resource.AssetId); } + var assetItem = contentDatabase.FindAsset(resource.AssetId); + if (assetItem != null) + { + resource.IsAssetItem = true; + resource.Name = assetItem.NamePath + resource.Name.Substring(ext + 5); // Use text after asset path to display (eg. subobject) + } } _resourceCache.Add(gpuResourceId, resource); @@ -190,6 +233,7 @@ namespace FlaxEditor.Windows.Profiler _resourceCache?.Clear(); _assetPathToId?.Clear(); _tableRowsCache?.Clear(); + _stringBuilder?.Clear(); base.OnDestroy(); } @@ -234,7 +278,6 @@ namespace FlaxEditor.Windows.Profiler // Add rows var rowColor2 = Style.Current.Background * 1.4f; - var contentDatabase = Editor.Instance.ContentDatabase; for (int i = 0; i < resources.Length; i++) { ref var e = ref resources[i]; @@ -259,15 +302,12 @@ namespace FlaxEditor.Windows.Profiler row.Values[2] = e.MemoryUsage; // Setup row interactions - row.TooltipText = null; - row.DoubleClick = null; - var assetItem = contentDatabase.FindAsset(e.AssetId); - if (assetItem != null) + row.Tag = e; + row.TooltipText = e.Tooltip; + row.RowDoubleClick = null; + if (e.IsAssetItem) { - row.Values[0] = assetItem.NamePath; - assetItem.UpdateTooltipText(); - row.TooltipText = assetItem.TooltipText; - row.DoubleClick = () => { Editor.Instance.ContentEditing.Open(assetItem); }; + row.RowDoubleClick = OnRowDoubleClickAsset; } // Add row to the table @@ -276,5 +316,12 @@ namespace FlaxEditor.Windows.Profiler row.Parent = _table; } } + + private void OnRowDoubleClickAsset(ClickableRow row) + { + var e = (Resource)row.Tag; + var assetItem = Editor.Instance.ContentDatabase.FindAsset(e.AssetId); + Editor.Instance.ContentEditing.Open(assetItem); + } } } From ed700cb0705495f8e76658b056688a84e1b3d547 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 9 Dec 2022 15:46:01 +0100 Subject: [PATCH 69/83] Add **Assets profiler** to Editor --- Source/Editor/Windows/Profiler/Assets.cs | 293 ++++++++++++++++++ .../Editor/Windows/Profiler/ProfilerWindow.cs | 3 + Source/Engine/Content/Asset.cpp | 11 + Source/Engine/Content/Asset.h | 9 +- Source/Engine/Core/Delegate.h | 8 + Source/Engine/Streaming/Streaming.cpp | 6 + 6 files changed, 326 insertions(+), 4 deletions(-) create mode 100644 Source/Editor/Windows/Profiler/Assets.cs diff --git a/Source/Editor/Windows/Profiler/Assets.cs b/Source/Editor/Windows/Profiler/Assets.cs new file mode 100644 index 000000000..9ca0e844e --- /dev/null +++ b/Source/Editor/Windows/Profiler/Assets.cs @@ -0,0 +1,293 @@ +// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. + +using System; +using System.Collections.Generic; +using System.Text; +using FlaxEditor.GUI; +using FlaxEngine; +using FlaxEngine.Json; +using FlaxEngine.GUI; +using FlaxEditor.GUI.ContextMenu; + +namespace FlaxEditor.Windows.Profiler +{ + /// + /// The Assets profiling mode. + /// + /// + internal sealed class Assets : ProfilerMode + { + private struct Resource + { + public string Name; + public string TypeName; + public int ReferencesCount; + public ulong MemoryUsage; + public Guid AssetId; + } + + private readonly SingleChart _memoryUsageChart; + private readonly Table _table; + private SamplesBuffer _resources; + private List _tableRowsCache; + private Dictionary _resourceCache; + private StringBuilder _stringBuilder; + + public Assets() + : base("Assets") + { + // Layout + var panel = new Panel(ScrollBars.Vertical) + { + AnchorPreset = AnchorPresets.StretchAll, + Offsets = Margin.Zero, + Parent = this, + }; + var layout = new VerticalPanel + { + AnchorPreset = AnchorPresets.HorizontalStretchTop, + Offsets = Margin.Zero, + IsScrollable = true, + Parent = panel, + }; + + // Chart + _memoryUsageChart = new SingleChart + { + Title = "Assets Memory Usage (CPU)", + FormatSample = v => Utilities.Utils.FormatBytesCount((int)v), + Parent = layout, + }; + _memoryUsageChart.SelectedSampleChanged += OnSelectedSampleChanged; + + // Table + var headerColor = Style.Current.LightBackground; + _table = new Table + { + Columns = new[] + { + new ColumnDefinition + { + UseExpandCollapseMode = true, + CellAlignment = TextAlignment.Near, + Title = "Resource", + TitleBackgroundColor = headerColor, + }, + new ColumnDefinition + { + Title = "Type", + CellAlignment = TextAlignment.Center, + TitleBackgroundColor = headerColor, + }, + new ColumnDefinition + { + Title = "References", + TitleBackgroundColor = headerColor, + }, + new ColumnDefinition + { + Title = "Memory Usage", + TitleBackgroundColor = headerColor, + FormatValue = v => Utilities.Utils.FormatBytesCount((ulong)v), + }, + }, + Parent = layout, + }; + _table.Splits = new[] + { + 0.6f, + 0.2f, + 0.08f, + 0.12f, + }; + } + + /// + public override void Clear() + { + _memoryUsageChart.Clear(); + _resources?.Clear(); + _resourceCache?.Clear(); + } + + /// + public override void Update(ref SharedUpdateData sharedData) + { + if (_resourceCache == null) + _resourceCache = new Dictionary(); + if (_stringBuilder == null) + _stringBuilder = new StringBuilder(); + + // Capture current assets usage info + var assets = FlaxEngine.Content.Assets; + var sb = _stringBuilder; + var resources = new Resource[assets.Length]; + var contentDatabase = Editor.Instance.ContentDatabase; + ulong totalMemoryUsage = 0; + for (int i = 0; i < resources.Length; i++) + { + var asset = assets[i]; + if (!asset) + continue; + + // Try to reuse cached resource info + var assetId = asset.ID; + if (!_resourceCache.TryGetValue(assetId, out var resource)) + { + resource = new Resource + { + Name = asset.Path, + TypeName = asset.TypeName, + AssetId = assetId, + }; + var typeNameEnding = asset.TypeName.LastIndexOf('.'); + if (typeNameEnding != -1) + resource.TypeName = resource.TypeName.Substring(typeNameEnding + 1); + var assetItem = Editor.Instance.ContentDatabase.FindAsset(assetId); + if (assetItem != null) + { + resource.Name = assetItem.NamePath; + } + if (string.IsNullOrEmpty(resource.Name) && asset.IsVirtual) + resource.Name = ""; + _resourceCache.Add(assetId, resource); + } + + resource.MemoryUsage = asset.MemoryUsage; + totalMemoryUsage += resource.MemoryUsage; + resource.ReferencesCount = asset.ReferencesCount; + resources[i] = resource; + } + _memoryUsageChart.AddSample((float)totalMemoryUsage); + Array.Sort(resources, SortResources); + if (_resources == null) + _resources = new SamplesBuffer(); + _resources.Add(resources); + } + + /// + public override void UpdateView(int selectedFrame, bool showOnlyLastUpdateEvents) + { + _memoryUsageChart.SelectedSampleIndex = selectedFrame; + + if (_resources == null) + return; + if (_tableRowsCache == null) + _tableRowsCache = new List(); + UpdateTable(); + } + + /// + public override void OnDestroy() + { + _resources?.Clear(); + _resourceCache?.Clear(); + _tableRowsCache?.Clear(); + _stringBuilder?.Clear(); + + base.OnDestroy(); + } + + private static int SortResources(Resource a, Resource b) + { + return (int)(b.MemoryUsage - a.MemoryUsage); + } + + private void UpdateTable() + { + _table.IsLayoutLocked = true; + int idx = 0; + while (_table.Children.Count > idx) + { + var child = _table.Children[idx]; + if (child is ClickableRow row) + { + _tableRowsCache.Add(row); + child.Parent = null; + } + else + { + idx++; + } + } + _table.LockChildrenRecursive(); + + UpdateTableInner(); + + _table.UnlockChildrenRecursive(); + _table.PerformLayout(); + } + + private void UpdateTableInner() + { + if (_resources.Count == 0) + return; + var resources = _resources.Get(_memoryUsageChart.SelectedSampleIndex); + if (resources == null || resources.Length == 0) + return; + + // Add rows + var rowColor2 = Style.Current.Background * 1.4f; + for (int i = 0; i < resources.Length; i++) + { + ref var e = ref resources[i]; + + ClickableRow row; + if (_tableRowsCache.Count != 0) + { + // Reuse row + var last = _tableRowsCache.Count - 1; + row = _tableRowsCache[last]; + _tableRowsCache.RemoveAt(last); + } + else + { + // Allocate new row + row = new ClickableRow { Values = new object[4] }; + row.RowDoubleClick = OnRowDoubleClick; + row.RowRightClick = OnRowRightClick; + } + + // Setup row data + row.Tag = e.AssetId; + row.Values[0] = e.Name; + row.Values[1] = e.TypeName; + row.Values[2] = e.ReferencesCount; + row.Values[3] = e.MemoryUsage; + + // Add row to the table + row.Width = _table.Width; + row.BackgroundColor = i % 2 == 0 ? rowColor2 : Color.Transparent; + row.Parent = _table; + } + } + + private void OnRowDoubleClick(ClickableRow row) + { + var assetId = (Guid)row.Tag; + var assetItem = Editor.Instance.ContentDatabase.FindAsset(assetId); + if (assetItem != null) + Editor.Instance.ContentEditing.Open(assetItem); + } + + private void OnRowRightClick(ClickableRow row) + { + var assetId = (Guid)row.Tag; + var assetItem = Editor.Instance.ContentDatabase.FindAsset(assetId); + if (assetItem != null) + { + var cm = new ContextMenu(); + ContextMenuButton b; + b = cm.AddButton("Open", () => Editor.Instance.ContentEditing.Open(assetItem)); + cm.AddButton("Show in content window", () => Editor.Instance.Windows.ContentWin.Select(assetItem)); + cm.AddButton("Show in explorer", () => FileSystem.ShowFileExplorer(System.IO.Path.GetDirectoryName(assetItem.Path))); + cm.AddButton("Select actors using this asset", () => Editor.Instance.SceneEditing.SelectActorsUsingAsset(assetItem.ID)); + cm.AddButton("Show asset references graph", () => Editor.Instance.Windows.Open(new AssetReferencesGraphWindow(Editor.Instance, assetItem))); + cm.AddButton("Copy name", () => Clipboard.Text = assetItem.NamePath); + cm.AddButton("Copy path", () => Clipboard.Text = assetItem.Path); + cm.AddButton("Copy asset ID", () => Clipboard.Text = JsonSerializer.GetStringID(assetItem.ID)); + cm.Show(row, row.PointFromScreen(Input.MouseScreenPosition)); + } + } + } +} diff --git a/Source/Editor/Windows/Profiler/ProfilerWindow.cs b/Source/Editor/Windows/Profiler/ProfilerWindow.cs index 827cc674f..a40c38ea1 100644 --- a/Source/Editor/Windows/Profiler/ProfilerWindow.cs +++ b/Source/Editor/Windows/Profiler/ProfilerWindow.cs @@ -195,6 +195,7 @@ namespace FlaxEditor.Windows.Profiler AddMode(new GPU()); AddMode(new MemoryGPU()); AddMode(new Memory()); + AddMode(new Assets()); AddMode(new Network()); // Init view @@ -206,6 +207,8 @@ namespace FlaxEditor.Windows.Profiler } UpdateButtons(); + + ScriptsBuilder.ScriptsReloadEnd += Clear; // Prevent crashes if any of the profiler tabs has some scripting types cached (eg. asset type info) } /// diff --git a/Source/Engine/Content/Asset.cpp b/Source/Engine/Content/Asset.cpp index a7aeeab3d..e761dfd1b 100644 --- a/Source/Engine/Content/Asset.cpp +++ b/Source/Engine/Content/Asset.cpp @@ -313,6 +313,17 @@ bool Asset::ShouldDeleteFileOnUnload() const #endif +uint64 Asset::GetMemoryUsage() const +{ + uint64 result = sizeof(Asset); + Locker.Lock(); + if (_loadingTask) + result += sizeof(ContentLoadTask); + result += (OnLoaded.Capacity() + OnReloading.Capacity() + OnUnloaded.Capacity()) * sizeof(EventType::FunctionType); + Locker.Unlock(); + return result; +} + void Asset::Reload() { // Virtual assets are memory-only so reloading them makes no sense diff --git a/Source/Engine/Content/Asset.h b/Source/Engine/Content/Asset.h index 6039b6b3a..410dca8ab 100644 --- a/Source/Engine/Content/Asset.h +++ b/Source/Engine/Content/Asset.h @@ -128,14 +128,17 @@ public: } #if USE_EDITOR - /// /// Determines whether this asset was marked to be deleted on unload. /// API_PROPERTY() bool ShouldDeleteFileOnUnload() const; - #endif + /// + /// Gets amount of CPU memory used by this resource (in bytes). It's a rough estimation. Memory may be fragmented, compressed or sub-allocated so the actual memory pressure from this resource may vary. + /// + API_PROPERTY() virtual uint64 GetMemoryUsage() const; + public: /// /// Reloads the asset. @@ -160,7 +163,6 @@ public: virtual void CancelStreaming(); #if USE_EDITOR - /// /// Gets the asset references. Supported only in Editor. /// @@ -184,7 +186,6 @@ public: /// /// The collection of the asset ids referenced by this asset. API_FUNCTION() Array GetReferences() const; - #endif /// diff --git a/Source/Engine/Core/Delegate.h b/Source/Engine/Core/Delegate.h index 57d685031..d8ae9a5ea 100644 --- a/Source/Engine/Core/Delegate.h +++ b/Source/Engine/Core/Delegate.h @@ -557,6 +557,14 @@ public: return count; } + /// + /// Gets the current capacity of delegate table (amount of function to store before resizing). + /// + int32 Capacity() const + { + return (int32)Platform::AtomicRead((intptr volatile*)&_size); + } + /// /// Determines whether any function is binded. /// diff --git a/Source/Engine/Streaming/Streaming.cpp b/Source/Engine/Streaming/Streaming.cpp index f7ad33dc0..d11724fe8 100644 --- a/Source/Engine/Streaming/Streaming.cpp +++ b/Source/Engine/Streaming/Streaming.cpp @@ -304,6 +304,9 @@ GPUSampler* Streaming::GetTextureGroupSampler(int32 index) if (!sampler) { sampler = GPUSampler::New(); +#if GPU_ENABLE_RESOURCE_NAMING + sampler->SetName(group.Name); +#endif sampler->Init(desc); TextureGroupSamplers[index] = sampler; } @@ -316,6 +319,9 @@ GPUSampler* Streaming::GetTextureGroupSampler(int32 index) if (!FallbackSampler) { FallbackSampler = GPUSampler::New(); +#if GPU_ENABLE_RESOURCE_NAMING + sampler->SetName(TEXT("FallbackSampler")); +#endif FallbackSampler->Init(GPUSamplerDescription::New(GPUSamplerFilter::Trilinear)); } sampler = FallbackSampler; From d4601ecb44cede2cb3650a442fb627bb76c1a040 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Fri, 9 Dec 2022 15:48:43 +0100 Subject: [PATCH 70/83] Add memory usage query for various asset types --- Source/Engine/Animations/AnimationData.h | 13 +++++++++++ Source/Engine/Animations/Curve.h | 5 +++++ Source/Engine/Content/Assets/Animation.cpp | 17 ++++++++++++++ Source/Engine/Content/Assets/Animation.h | 3 +-- Source/Engine/Content/Assets/RawDataAsset.cpp | 10 +++++++++ Source/Engine/Content/Assets/RawDataAsset.h | 4 ++++ Source/Engine/Content/BinaryAsset.cpp | 16 ++++++++++++++ Source/Engine/Content/BinaryAsset.h | 10 +-------- Source/Engine/Content/JsonAsset.cpp | 22 +++++++++++++++++++ Source/Engine/Content/JsonAsset.h | 5 +++++ .../Engine/Graphics/Textures/TextureBase.cpp | 15 +++++++++++++ Source/Engine/Graphics/Textures/TextureBase.h | 1 + Source/ThirdParty/rapidjson/document.h | 6 +++++ 13 files changed, 116 insertions(+), 11 deletions(-) diff --git a/Source/Engine/Animations/AnimationData.h b/Source/Engine/Animations/AnimationData.h index ad56e891a..082202f8a 100644 --- a/Source/Engine/Animations/AnimationData.h +++ b/Source/Engine/Animations/AnimationData.h @@ -86,6 +86,11 @@ public: { return Position.GetKeyframes().Count() + Rotation.GetKeyframes().Count() + Scale.GetKeyframes().Count(); } + + uint64 GetMemoryUsage() const + { + return NodeName.Length() * sizeof(Char) + Position.GetMemoryUsage() + Rotation.GetMemoryUsage() + Scale.GetMemoryUsage(); + } }; /// @@ -131,6 +136,14 @@ public: return static_cast(Duration / FramesPerSecond); } + uint64 GetMemoryUsage() const + { + uint64 result = RootNodeName.Length() * sizeof(Char) + Channels.Capacity() * sizeof(NodeAnimationData); + for (const auto& e : Channels) + result += e.GetMemoryUsage(); + return result; + } + /// /// Gets the total amount of keyframes in the all animation channels. /// diff --git a/Source/Engine/Animations/Curve.h b/Source/Engine/Animations/Curve.h index 8d91960e6..7105a6bdf 100644 --- a/Source/Engine/Animations/Curve.h +++ b/Source/Engine/Animations/Curve.h @@ -733,6 +733,11 @@ public: _keyframes[i].Time = _keyframes[i].Time * timeScale + timeOffset;; } + uint64 GetMemoryUsage() const + { + return _keyframes.Capacity() * sizeof(KeyFrame); + } + public: FORCE_INLINE KeyFrame& operator[](int32 index) { diff --git a/Source/Engine/Content/Assets/Animation.cpp b/Source/Engine/Content/Assets/Animation.cpp index c6ece7b3f..65a96a5fa 100644 --- a/Source/Engine/Content/Assets/Animation.cpp +++ b/Source/Engine/Content/Assets/Animation.cpp @@ -569,6 +569,23 @@ void Animation::OnSkinnedModelUnloaded(Asset* obj) MappingCache.Remove(i); } +uint64 Animation::GetMemoryUsage() const +{ + Locker.Lock(); + uint64 result = BinaryAsset::GetMemoryUsage(); + result += sizeof(Animation) - sizeof(BinaryAsset); + result += Data.GetMemoryUsage(); + result += Events.Capacity() * sizeof(Pair>); + for (const auto& e : Events) + result += e.First.Length() * sizeof(Char) + e.Second.GetMemoryUsage(); + result += NestedAnims.Capacity() * sizeof(Pair); + result += MappingCache.Capacity() * sizeof(Pair>); + for (const auto& e : MappingCache) + result += e.Value.Capacity() * sizeof(int32); + Locker.Unlock(); + return result; +} + void Animation::OnScriptingDispose() { // Dispose any events to prevent crashes (scripting is released before content) diff --git a/Source/Engine/Content/Assets/Animation.h b/Source/Engine/Content/Assets/Animation.h index 826f60c1d..ca1d3373d 100644 --- a/Source/Engine/Content/Assets/Animation.h +++ b/Source/Engine/Content/Assets/Animation.h @@ -152,7 +152,6 @@ public: const NodeToChannel* GetMapping(SkinnedModel* obj); #if USE_EDITOR - /// /// Gets the animation as serialized timeline data. Used to show it in Editor. /// @@ -173,7 +172,6 @@ public: /// The cannot be used by virtual assets. /// true failed to save data; otherwise, false. bool Save(const StringView& path = StringView::Empty); - #endif private: @@ -181,6 +179,7 @@ private: public: // [BinaryAsset] + uint64 GetMemoryUsage() const override; void OnScriptingDispose() override; protected: diff --git a/Source/Engine/Content/Assets/RawDataAsset.cpp b/Source/Engine/Content/Assets/RawDataAsset.cpp index 1b39572e4..f16b267e1 100644 --- a/Source/Engine/Content/Assets/RawDataAsset.cpp +++ b/Source/Engine/Content/Assets/RawDataAsset.cpp @@ -64,6 +64,16 @@ bool RawDataAsset::Save(const StringView& path) #endif +uint64 RawDataAsset::GetMemoryUsage() const +{ + Locker.Lock(); + uint64 result = BinaryAsset::GetMemoryUsage(); + result += sizeof(RawDataAsset) - sizeof(BinaryAsset); + result += Data.Count(); + Locker.Unlock(); + return result; +} + Asset::LoadResult RawDataAsset::load() { auto chunk0 = GetChunk(0); diff --git a/Source/Engine/Content/Assets/RawDataAsset.h b/Source/Engine/Content/Assets/RawDataAsset.h index 2558426e9..65aa37eb1 100644 --- a/Source/Engine/Content/Assets/RawDataAsset.h +++ b/Source/Engine/Content/Assets/RawDataAsset.h @@ -28,6 +28,10 @@ public: #endif +public: + // [BinaryAsset] + uint64 GetMemoryUsage() const override; + protected: // [BinaryAsset] LoadResult load() override; diff --git a/Source/Engine/Content/BinaryAsset.cpp b/Source/Engine/Content/BinaryAsset.cpp index 3b268f72e..99c91cc4a 100644 --- a/Source/Engine/Content/BinaryAsset.cpp +++ b/Source/Engine/Content/BinaryAsset.cpp @@ -452,6 +452,22 @@ const String& BinaryAsset::GetPath() const #endif } +uint64 BinaryAsset::GetMemoryUsage() const +{ + Locker.Lock(); + uint64 result = Asset::GetMemoryUsage(); + result += sizeof(BinaryAsset) - sizeof(Asset); + result += _dependantAssets.Capacity() * sizeof(BinaryAsset*); + for (int32 i = 0; i < ASSET_FILE_DATA_CHUNKS; i++) + { + auto chunk = _header.Chunks[i]; + if (chunk != nullptr && chunk->IsLoaded()) + result += chunk->Size(); + } + Locker.Unlock(); + return result; +} + /// /// Helper task used to initialize binary asset and upgrade it if need to in background. /// diff --git a/Source/Engine/Content/BinaryAsset.h b/Source/Engine/Content/BinaryAsset.h index e98c645fe..fb96db6f6 100644 --- a/Source/Engine/Content/BinaryAsset.h +++ b/Source/Engine/Content/BinaryAsset.h @@ -41,7 +41,6 @@ public: FlaxStorage* Storage; #if USE_EDITOR - /// /// The asset metadata information. Stored in a Json format. /// @@ -51,14 +50,12 @@ public: /// Asset dependencies list used by the asset for tracking (eg. material functions used by material asset). The pair of asset ID and cached file edit time (for tracking modification). /// Array> Dependencies; - #endif public: /// /// Gets the asset serialized version. /// - /// Version number. virtual uint32 GetSerializedVersion() const = 0; /// @@ -84,14 +81,11 @@ public: public: #if USE_EDITOR - #if COMPILE_WITH_ASSETS_IMPORTER - /// /// Reimports asset from the source file. /// API_FUNCTION() void Reimport() const; - #endif /// @@ -130,7 +124,6 @@ protected: virtual void OnDependencyModified(BinaryAsset* asset) { } - #endif protected: @@ -255,7 +248,6 @@ public: bool LoadChunks(AssetChunksFlag chunks); #if USE_EDITOR - /// /// Saves this asset to the storage container. /// @@ -281,7 +273,6 @@ public: /// In silent mode don't reload opened storage container that is using target file. /// True if failed, otherwise false. static bool SaveToAsset(const StringView& path, AssetInitData& data, bool silentMode = false); - #endif protected: @@ -302,6 +293,7 @@ public: void OnDeleteObject() override; #endif const String& GetPath() const final override; + uint64 GetMemoryUsage() const override; protected: // [Asset] diff --git a/Source/Engine/Content/JsonAsset.cpp b/Source/Engine/Content/JsonAsset.cpp index 4725f1ce9..9928f00e4 100644 --- a/Source/Engine/Content/JsonAsset.cpp +++ b/Source/Engine/Content/JsonAsset.cpp @@ -93,6 +93,17 @@ const String& JsonAssetBase::GetPath() const #endif } +uint64 JsonAssetBase::GetMemoryUsage() const +{ + Locker.Lock(); + uint64 result = Asset::GetMemoryUsage(); + result += sizeof(JsonAssetBase) - sizeof(Asset); + if (Data) + result += Document.GetAllocator().Capacity(); + Locker.Unlock(); + return result; +} + #if USE_EDITOR void FindIds(ISerializable::DeserializeStream& node, Array& output) @@ -248,6 +259,17 @@ JsonAsset::JsonAsset(const SpawnParams& params, const AssetInfo* info) { } +uint64 JsonAsset::GetMemoryUsage() const +{ + Locker.Lock(); + uint64 result = JsonAssetBase::GetMemoryUsage(); + result += sizeof(JsonAsset) - sizeof(JsonAssetBase); + if (Instance && InstanceType) + result += InstanceType.GetType().Size; + Locker.Unlock(); + return result; +} + Asset::LoadResult JsonAsset::loadAsset() { const auto result = JsonAssetBase::loadAsset(); diff --git a/Source/Engine/Content/JsonAsset.h b/Source/Engine/Content/JsonAsset.h index 5f2862abc..b8f4a9b50 100644 --- a/Source/Engine/Content/JsonAsset.h +++ b/Source/Engine/Content/JsonAsset.h @@ -77,6 +77,7 @@ public: public: // [Asset] const String& GetPath() const override; + uint64 GetMemoryUsage() const override; #if USE_EDITOR void GetReferences(Array& output) const override; #endif @@ -122,6 +123,10 @@ public: return Instance && InstanceType.IsAssignableFrom(T::TypeInitializer) ? (T*)Instance : nullptr; } +public: + // [JsonAssetBase] + uint64 GetMemoryUsage() const override; + protected: // [JsonAssetBase] LoadResult loadAsset() override; diff --git a/Source/Engine/Graphics/Textures/TextureBase.cpp b/Source/Engine/Graphics/Textures/TextureBase.cpp index fbd85830e..a4d458730 100644 --- a/Source/Engine/Graphics/Textures/TextureBase.cpp +++ b/Source/Engine/Graphics/Textures/TextureBase.cpp @@ -636,6 +636,21 @@ bool TextureBase::Init(void* ptr) return Init(initData); } +uint64 TextureBase::GetMemoryUsage() const +{ + Locker.Lock(); + uint64 result = BinaryAsset::GetMemoryUsage(); + result += sizeof(TextureBase) - sizeof(BinaryAsset); + if (_customData) + { + result += sizeof(InitData); + for (auto& mip : _customData->Mips) + result += mip.Data.Length(); + } + Locker.Unlock(); + return result; +} + void TextureBase::CancelStreaming() { _texture.CancelStreamingTasks(); diff --git a/Source/Engine/Graphics/Textures/TextureBase.h b/Source/Engine/Graphics/Textures/TextureBase.h index 857d03085..cc0e4b548 100644 --- a/Source/Engine/Graphics/Textures/TextureBase.h +++ b/Source/Engine/Graphics/Textures/TextureBase.h @@ -221,6 +221,7 @@ private: public: // [BinaryAsset] + uint64 GetMemoryUsage() const override; void CancelStreaming() override; // [ITextureOwner] diff --git a/Source/ThirdParty/rapidjson/document.h b/Source/ThirdParty/rapidjson/document.h index f52e969ab..f09f11d40 100644 --- a/Source/ThirdParty/rapidjson/document.h +++ b/Source/ThirdParty/rapidjson/document.h @@ -2304,6 +2304,12 @@ public: return *allocator_; } + //! Get the allocator of this document. + const Allocator& GetAllocator() const { + RAPIDJSON_ASSERT(allocator_); + return *allocator_; + } + //! Get the capacity of stack in bytes. size_t GetStackCapacity() const { return stack_.GetCapacity(); } From 359e7d68d4a77b9235164d3388a537a5eb9f738e Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Mon, 12 Dec 2022 11:22:15 +0100 Subject: [PATCH 71/83] Add simplified collider for in-built primitive meshes --- .../SceneGraph/Actors/StaticModelNode.cs | 52 ++++++++++++++++++- Source/Editor/Windows/ToolboxWindow.cs | 5 -- 2 files changed, 51 insertions(+), 6 deletions(-) diff --git a/Source/Editor/SceneGraph/Actors/StaticModelNode.cs b/Source/Editor/SceneGraph/Actors/StaticModelNode.cs index 1c76d966c..97415a3e8 100644 --- a/Source/Editor/SceneGraph/Actors/StaticModelNode.cs +++ b/Source/Editor/SceneGraph/Actors/StaticModelNode.cs @@ -25,7 +25,7 @@ namespace FlaxEditor.SceneGraph.Actors { base.OnContextMenu(contextMenu); - contextMenu.AddButton("Add mesh collider", OnAddMeshCollider).Enabled = ((StaticModel)Actor).Model != null; + contextMenu.AddButton("Add collider", OnAddMeshCollider).Enabled = ((StaticModel)Actor).Model != null; } private void OnAddMeshCollider() @@ -33,6 +33,56 @@ namespace FlaxEditor.SceneGraph.Actors var model = ((StaticModel)Actor).Model; if (!model) return; + + // Special case for in-built Editor models that can use analytical collision + var modelPath = model.Path; + if (modelPath.EndsWith("/Primitives/Cube.flax", StringComparison.Ordinal)) + { + var actor = new BoxCollider + { + StaticFlags = Actor.StaticFlags, + Transform = Actor.Transform, + }; + Editor.Instance.SceneEditing.Spawn(actor, Actor); + return; + } + if (modelPath.EndsWith("/Primitives/Sphere.flax", StringComparison.Ordinal)) + { + var actor = new SphereCollider + { + StaticFlags = Actor.StaticFlags, + Transform = Actor.Transform, + }; + Editor.Instance.SceneEditing.Spawn(actor, Actor); + return; + } + if (modelPath.EndsWith("/Primitives/Plane.flax", StringComparison.Ordinal)) + { + var actor = new BoxCollider + { + StaticFlags = Actor.StaticFlags, + Transform = Actor.Transform, + Size = new Float3(100.0f, 100.0f, 1.0f), + }; + Editor.Instance.SceneEditing.Spawn(actor, Actor); + return; + } + if (modelPath.EndsWith("/Primitives/Capsule.flax", StringComparison.Ordinal)) + { + var actor = new CapsuleCollider + { + StaticFlags = Actor.StaticFlags, + Transform = Actor.Transform, + Radius = 25.0f, + Height = 50.0f, + }; + Editor.Instance.SceneEditing.Spawn(actor, Actor); + actor.LocalPosition = new Vector3(0, 50.0f, 0); + actor.LocalOrientation = Quaternion.Euler(0, 0, 90.0f); + return; + } + + // Create collision data (or reuse) and add collision actor Action created = collisionData => { var actor = new MeshCollider diff --git a/Source/Editor/Windows/ToolboxWindow.cs b/Source/Editor/Windows/ToolboxWindow.cs index ff03d8e0d..99490ec07 100644 --- a/Source/Editor/Windows/ToolboxWindow.cs +++ b/Source/Editor/Windows/ToolboxWindow.cs @@ -290,11 +290,6 @@ namespace FlaxEditor.Windows return new Item(name, GUI.Drag.DragItems.GetDragData(path)); } - private Item CreateActorItem(string name, Type type) - { - return CreateActorItem(name, new ScriptType(type)); - } - private Item CreateActorItem(string name, ScriptType type) { return new ScriptTypeItem(name, type, GUI.Drag.DragActorType.GetDragData(type)); From 516e3fbc65af43ab98fe26127ee6345516d72717 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Mon, 12 Dec 2022 12:17:30 +0100 Subject: [PATCH 72/83] Fix Visject surface input box color for missing connection type but with type hint --- Source/Editor/Surface/SurfaceStyle.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/Source/Editor/Surface/SurfaceStyle.cs b/Source/Editor/Surface/SurfaceStyle.cs index a39980b66..44701d94a 100644 --- a/Source/Editor/Surface/SurfaceStyle.cs +++ b/Source/Editor/Surface/SurfaceStyle.cs @@ -148,7 +148,16 @@ namespace FlaxEditor.Surface public void GetConnectionColor(ScriptType type, ConnectionsHint hint, out Color color) { if (type == ScriptType.Null) - color = Colors.Default; + { + if (hint == ConnectionsHint.Vector) + color = Colors.Vector; + else if (hint == ConnectionsHint.Scalar) + color = Colors.Float; + else if (hint == ConnectionsHint.Enum) + color = Colors.Enum; + else + color = Colors.Default; + } else if (type.IsPointer || type.IsReference) { // Find underlying type without `*` or `&` From 48b88af88a67b641eb5253af8b2c4c06bc38ba31 Mon Sep 17 00:00:00 2001 From: Wojtek Figat Date: Mon, 12 Dec 2022 20:16:03 +0100 Subject: [PATCH 73/83] Fix deadlock in GPUDevice caused by f2c594569d37aac0bf729626ebffa0bed731dfd8 --- Source/Engine/Graphics/GPUDevice.cpp | 22 ++++++++++++---------- Source/Engine/Graphics/GPUDevice.h | 1 + 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/Source/Engine/Graphics/GPUDevice.cpp b/Source/Engine/Graphics/GPUDevice.cpp index d82900c1b..432acc548 100644 --- a/Source/Engine/Graphics/GPUDevice.cpp +++ b/Source/Engine/Graphics/GPUDevice.cpp @@ -374,24 +374,24 @@ bool GPUDevice::CanDraw() void GPUDevice::AddResource(GPUResource* resource) { - Locker.Lock(); + _resourcesLock.Lock(); ASSERT(resource && !_resources.Contains(resource)); _resources.Add(resource); - Locker.Unlock(); + _resourcesLock.Unlock(); } void GPUDevice::RemoveResource(GPUResource* resource) { - Locker.Lock(); + _resourcesLock.Lock(); ASSERT(resource && _resources.Contains(resource)); _resources.Remove(resource); - Locker.Unlock(); + _resourcesLock.Unlock(); } void GPUDevice::DumpResourcesToLog() const { StringBuilder output; - Locker.Lock(); + _resourcesLock.Lock(); output.AppendFormat(TEXT("GPU Resources dump. Count: {0}, total GPU memory used: {1}"), _resources.Count(), Utilities::BytesToText(GetMemoryUsage())); output.AppendLine(); @@ -428,7 +428,7 @@ void GPUDevice::DumpResourcesToLog() const output.AppendLine(); } - Locker.Unlock(); + _resourcesLock.Unlock(); LOG_STR(Info, output.ToStringView()); } @@ -449,11 +449,13 @@ void GPUDevice::preDispose() // Release GPU resources memory and unlink from device // Note: after that no GPU resources should be used/created, only deleted + _resourcesLock.Lock(); for (int32 i = _resources.Count() - 1; i >= 0 && i < _resources.Count(); i--) { _resources[i]->OnDeviceDispose(); } _resources.Clear(); + _resourcesLock.Unlock(); Locker.Unlock(); } @@ -592,18 +594,18 @@ void GPUDevice::Dispose() uint64 GPUDevice::GetMemoryUsage() const { uint64 result = 0; - Locker.Lock(); + _resourcesLock.Lock(); for (int32 i = 0; i < _resources.Count(); i++) result += _resources[i]->GetMemoryUsage(); - Locker.Unlock(); + _resourcesLock.Unlock(); return result; } Array GPUDevice::GetResources() const { - Locker.Lock(); + _resourcesLock.Lock(); Array result = _resources; - Locker.Unlock(); + _resourcesLock.Unlock(); return result; } diff --git a/Source/Engine/Graphics/GPUDevice.h b/Source/Engine/Graphics/GPUDevice.h index ca63d233a..0f28033af 100644 --- a/Source/Engine/Graphics/GPUDevice.h +++ b/Source/Engine/Graphics/GPUDevice.h @@ -94,6 +94,7 @@ protected: struct PrivateData; PrivateData* _res; Array _resources; + CriticalSection _resourcesLock; protected: /// From ee019510ca7ccc8be739502a1ad4fcf6a3ebd544 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Mon, 12 Dec 2022 14:58:16 +0100 Subject: [PATCH 74/83] Remove old `RT1_FloatRGB` and `RT2_FloatRGB` in favor pooled render targets --- Source/Engine/Graphics/RenderBuffers.cpp | 22 +------------------ Source/Engine/Graphics/RenderBuffers.h | 3 --- .../Renderer/GI/GlobalSurfaceAtlasPass.cpp | 3 ++- Source/Engine/Renderer/Renderer.cpp | 18 +++++++++++---- 4 files changed, 17 insertions(+), 29 deletions(-) diff --git a/Source/Engine/Graphics/RenderBuffers.cpp b/Source/Engine/Graphics/RenderBuffers.cpp index 345b666cf..f46da5f60 100644 --- a/Source/Engine/Graphics/RenderBuffers.cpp +++ b/Source/Engine/Graphics/RenderBuffers.cpp @@ -20,8 +20,6 @@ RenderBuffers::RenderBuffers(const SpawnParams& params) CREATE_TEXTURE(GBuffer1); CREATE_TEXTURE(GBuffer2); CREATE_TEXTURE(GBuffer3); - CREATE_TEXTURE(RT1_FloatRGB); - CREATE_TEXTURE(RT2_FloatRGB); #undef CREATE_TEXTURE } @@ -125,19 +123,7 @@ bool RenderBuffers::GetUseAlpha() const void RenderBuffers::SetUseAlpha(bool value) { - if (_useAlpha != value) - { - _useAlpha = value; - - // Reallocate buffers - if (_width != 0) - { - auto desc = GPUTextureDescription::New2D(_width, _height, GetOutputFormat(), GPUTextureFlags::ShaderResource | GPUTextureFlags::RenderTarget); - desc.DefaultClearColor = Color::Transparent; - RT1_FloatRGB->Init(desc); - RT2_FloatRGB->Init(desc); - } - } + _useAlpha = value; } const RenderBuffers::CustomBuffer* RenderBuffers::FindCustomBuffer(const StringView& name) const @@ -197,12 +183,6 @@ bool RenderBuffers::Init(int32 width, int32 height) desc.DefaultClearColor = Color::Transparent; result |= GBuffer3->Init(desc); - // Helper HDR buffers - desc.Format = GetOutputFormat(); - desc.DefaultClearColor = Color::Transparent; - result |= RT1_FloatRGB->Init(desc); - result |= RT2_FloatRGB->Init(desc); - // Cache data _width = width; _height = height; diff --git a/Source/Engine/Graphics/RenderBuffers.h b/Source/Engine/Graphics/RenderBuffers.h index d5f56119d..ed38d078e 100644 --- a/Source/Engine/Graphics/RenderBuffers.h +++ b/Source/Engine/Graphics/RenderBuffers.h @@ -54,9 +54,6 @@ public: GPUTexture* GBuffer[4]; }; - GPUTexture* RT1_FloatRGB; - GPUTexture* RT2_FloatRGB; - // Helper target for the eye adaptation float LastEyeAdaptationTime = 0.0f; GPUTexture* LuminanceMap = nullptr; diff --git a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp index 68c9878e5..d4760ba4e 100644 --- a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp +++ b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp @@ -1126,7 +1126,8 @@ void GlobalSurfaceAtlasPass::RenderDebug(RenderContext& renderContext, GPUContex Float2 outputSizeThird = outputSize * 0.333f; Float2 outputSizeTwoThird = outputSize * 0.666f; - GPUTexture* tempBuffer = renderContext.Buffers->RT2_FloatRGB; + auto tempBuffer = RenderTargetPool::Get(output->GetDescription()); + RENDER_TARGET_POOL_SET_NAME(tempBuffer, "GlobalSurfaceAtlas.TempBuffer"); context->Clear(tempBuffer->View(), Color::Black); context->SetRenderTarget(tempBuffer->View()); diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp index 34c32479e..1eb2c3a10 100644 --- a/Source/Engine/Renderer/Renderer.cpp +++ b/Source/Engine/Renderer/Renderer.cpp @@ -388,7 +388,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont auto outputFormat = renderContext.Buffers->GetOutputFormat(); auto tempDesc = GPUTextureDescription::New2D(renderContext.Buffers->GetWidth(), renderContext.Buffers->GetHeight(), outputFormat); auto lightBuffer = RenderTargetPool::Get(tempDesc); - RENDER_TARGET_POOL_SET_NAME(lightBuffer, "Lighting"); + RENDER_TARGET_POOL_SET_NAME(lightBuffer, "LightBuffer"); #if USE_EDITOR if (renderContext.View.Mode == ViewMode::QuadOverdraw) @@ -471,7 +471,8 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont if (renderContext.View.Mode == ViewMode::LightBuffer) { auto colorGradingLUT = ColorGradingPass::Instance()->RenderLUT(renderContext); - GPUTexture* tempBuffer = renderContext.Buffers->RT2_FloatRGB; + auto tempBuffer = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(tempBuffer, "TempBuffer"); EyeAdaptationPass::Instance()->Render(renderContext, lightBuffer); PostProcessingPass::Instance()->Render(renderContext, lightBuffer, tempBuffer, colorGradingLUT); RenderTargetPool::Release(colorGradingLUT); @@ -480,6 +481,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont context->SetRenderTarget(task->GetOutputView()); context->SetViewportAndScissors(task->GetOutputViewport()); context->Draw(tempBuffer); + RenderTargetPool::Release(tempBuffer); return; } @@ -519,8 +521,8 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont } // Run forward pass - GPUTexture* frameBuffer = renderContext.Buffers->RT1_FloatRGB; - GPUTexture* tempBuffer = renderContext.Buffers->RT2_FloatRGB; + auto frameBuffer = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(frameBuffer, "FrameBuffer"); ForwardPass::Instance()->Render(renderContext, lightBuffer, frameBuffer); // Cleanup @@ -535,10 +537,13 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont context->SetRenderTarget(task->GetOutputView()); context->SetViewportAndScissors(task->GetOutputViewport()); context->Draw(frameBuffer); + RenderTargetPool::Release(frameBuffer); return; } // Material and Custom PostFx + auto tempBuffer = RenderTargetPool::Get(tempDesc); + RENDER_TARGET_POOL_SET_NAME(tempBuffer, "TempBuffer"); renderContext.List->RunMaterialPostFxPass(context, renderContext, MaterialPostFxLocation::BeforePostProcessingPass, frameBuffer, tempBuffer); renderContext.List->RunCustomPostFxPass(context, renderContext, PostProcessEffectLocation::BeforePostProcessingPass, frameBuffer, tempBuffer); @@ -588,6 +593,8 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont context->SetRenderTarget(task->GetOutputView()); context->SetViewportAndScissors(task->GetOutputViewport()); MotionBlurPass::Instance()->RenderDebug(renderContext, frameBuffer->View()); + RenderTargetPool::Release(tempBuffer); + RenderTargetPool::Release(frameBuffer); return; } @@ -623,4 +630,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont MultiScaler::Instance()->Upscale(context, task->GetOutputViewport(), frameBuffer, task->GetOutputView()); } } + + RenderTargetPool::Release(tempBuffer); + RenderTargetPool::Release(frameBuffer); } From c17477abffabc2699b7d1719ba42c171f277e8e4 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Tue, 13 Dec 2022 11:51:31 +0100 Subject: [PATCH 75/83] Add `RenderingUpscaleLocation` for customizing upscaler location in render pipeline --- .../Editor/Windows/GraphicsQualityWindow.cs | 11 +++ Source/Engine/Graphics/RenderTask.h | 21 ++++++ Source/Engine/Renderer/ColorGradingPass.cpp | 5 -- Source/Engine/Renderer/MotionBlurPass.cpp | 4 +- Source/Engine/Renderer/PostProcessingPass.cpp | 3 +- Source/Engine/Renderer/Renderer.cpp | 70 +++++++++++++++---- 6 files changed, 91 insertions(+), 23 deletions(-) diff --git a/Source/Editor/Windows/GraphicsQualityWindow.cs b/Source/Editor/Windows/GraphicsQualityWindow.cs index 957d1af1a..932d8e6d7 100644 --- a/Source/Editor/Windows/GraphicsQualityWindow.cs +++ b/Source/Editor/Windows/GraphicsQualityWindow.cs @@ -113,6 +113,17 @@ namespace FlaxEditor.Windows set => MainRenderTask.Instance.RenderingPercentage = value; } + [NoSerialize, DefaultValue(RenderingUpscaleLocation.AfterAntiAliasingPass), VisibleIf(nameof(UpscaleLocation_Visible))] + [EditorOrder(1401), EditorDisplay("Quality")] + [Tooltip("The image resolution upscale location within rendering pipeline.")] + public RenderingUpscaleLocation UpscaleLocation + { + get => MainRenderTask.Instance.UpscaleLocation; + set => MainRenderTask.Instance.UpscaleLocation = value; + } + + private bool UpscaleLocation_Visible => MainRenderTask.Instance.RenderingPercentage < 1.0f; + [NoSerialize, DefaultValue(1.0f), Limit(0, 1)] [EditorOrder(1500), EditorDisplay("Quality"), Tooltip("The global density scale for all foliage instances. The default value is 1. Use values from range 0-1. Lower values decrease amount of foliage instances in-game. Use it to tweak game performance for slower devices.")] public float FoliageDensityScale diff --git a/Source/Engine/Graphics/RenderTask.h b/Source/Engine/Graphics/RenderTask.h index 92a48cf76..4df61c9d0 100644 --- a/Source/Engine/Graphics/RenderTask.h +++ b/Source/Engine/Graphics/RenderTask.h @@ -182,6 +182,22 @@ API_ENUM(Attributes="Flags") enum class ActorsSources DECLARE_ENUM_OPERATORS(ActorsSources); +/// +/// The Post Process effect rendering location within the rendering pipeline. +/// +API_ENUM() enum class RenderingUpscaleLocation +{ + /// + /// The up-scaling happens directly to the output buffer (backbuffer) after post processing and anti-aliasing. + /// + AfterAntiAliasingPass = 0, + + /// + /// The up-scaling happens before the post processing after scene rendering (after geometry, lighting, volumetrics, transparency and SSR/SSAO). + /// + BeforePostProcessingPass = 1, +}; + /// /// Render task which draws scene actors into the output buffer. /// @@ -244,6 +260,11 @@ public: /// API_FIELD() float RenderingPercentage = 1.0f; + /// + /// The image resolution upscale location within rendering pipeline. Unused if RenderingPercentage is 1. + /// + API_FIELD() RenderingUpscaleLocation UpscaleLocation = RenderingUpscaleLocation::AfterAntiAliasingPass; + public: /// /// The custom set of actors to render. diff --git a/Source/Engine/Renderer/ColorGradingPass.cpp b/Source/Engine/Renderer/ColorGradingPass.cpp index d9fb645de..0bbc4cce3 100644 --- a/Source/Engine/Renderer/ColorGradingPass.cpp +++ b/Source/Engine/Renderer/ColorGradingPass.cpp @@ -205,11 +205,6 @@ GPUTexture* ColorGradingPass::RenderLUT(RenderContext& renderContext) context->SetRenderTarget(lut->View()); context->DrawFullscreenTriangle(); } - - // TODO: this could run in async during scene rendering or sth - - const Viewport viewport = renderContext.Task->GetViewport(); - context->SetViewportAndScissors(viewport); context->UnBindSR(0); return lut; diff --git a/Source/Engine/Renderer/MotionBlurPass.cpp b/Source/Engine/Renderer/MotionBlurPass.cpp index 301d0a3eb..f47132794 100644 --- a/Source/Engine/Renderer/MotionBlurPass.cpp +++ b/Source/Engine/Renderer/MotionBlurPass.cpp @@ -265,8 +265,8 @@ void MotionBlurPass::Render(RenderContext& renderContext, GPUTexture*& input, GP ASSERT(motionVectors); auto context = GPUDevice::Instance->GetMainContext(); MotionBlurSettings& settings = renderContext.List->Settings.MotionBlur; - const int32 screenWidth = renderContext.Buffers->GetWidth(); - const int32 screenHeight = renderContext.Buffers->GetHeight(); + const int32 screenWidth = input->Width(); + const int32 screenHeight = input->Height(); const int32 motionVectorsWidth = screenWidth / static_cast(settings.MotionVectorsResolution); const int32 motionVectorsHeight = screenHeight / static_cast(settings.MotionVectorsResolution); if ((renderContext.View.Flags & ViewFlags::MotionBlur) == 0 || diff --git a/Source/Engine/Renderer/PostProcessingPass.cpp b/Source/Engine/Renderer/PostProcessingPass.cpp index 4e75e21fd..7a31c53bb 100644 --- a/Source/Engine/Renderer/PostProcessingPass.cpp +++ b/Source/Engine/Renderer/PostProcessingPass.cpp @@ -482,8 +482,7 @@ void PostProcessingPass::Render(RenderContext& renderContext, GPUTexture* input, context->BindSR(7, colorGradingLutView); // Composite final frame during single pass (done in full resolution) - auto viewport = renderContext.Task->GetViewport(); - context->SetViewportAndScissors(viewport); + context->SetViewportAndScissors((float)output->Width(), (float)output->Height()); context->SetRenderTarget(*output); context->SetState(_psComposite.Get(compositePermutationIndex)); context->DrawFullscreenTriangle(); diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp index 1eb2c3a10..9396069f7 100644 --- a/Source/Engine/Renderer/Renderer.cpp +++ b/Source/Engine/Renderer/Renderer.cpp @@ -122,12 +122,10 @@ void RendererService::Dispose() SAFE_DELETE_GPU_RESOURCE(IMaterial::BindParameters::PerViewConstants); } -void RenderAntiAliasingPass(RenderContext& renderContext, GPUTexture* input, GPUTextureView* output) +void RenderAntiAliasingPass(RenderContext& renderContext, GPUTexture* input, GPUTextureView* output, const Viewport& outputViewport) { auto context = GPUDevice::Instance->GetMainContext(); - auto screenSize = renderContext.View.ScreenSize; - context->SetViewportAndScissors(screenSize.X, screenSize.Y); - + context->SetViewportAndScissors(outputViewport); const auto aaMode = renderContext.List->Settings.AntiAliasing.Mode; if (aaMode == AntialiasingMode::FastApproximateAntialiasing) { @@ -554,6 +552,27 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont Swap(frameBuffer, tempBuffer); } + // Upscaling after scene rendering but before post processing + bool useUpscaling = task->RenderingPercentage < 1.0f; + const Viewport outputViewport = task->GetOutputViewport(); + if (useUpscaling && task->UpscaleLocation == RenderingUpscaleLocation::BeforePostProcessingPass) + { + useUpscaling = false; + RenderTargetPool::Release(tempBuffer); + tempDesc.Width = (int32)outputViewport.Width; + tempDesc.Height = (int32)outputViewport.Height; + tempBuffer = RenderTargetPool::Get(tempDesc); + context->ResetSR(); + if (renderContext.List->HasAnyPostFx(renderContext, PostProcessEffectLocation::CustomUpscale)) + renderContext.List->RunCustomPostFxPass(context, renderContext, PostProcessEffectLocation::CustomUpscale, frameBuffer, tempBuffer); + else + MultiScaler::Instance()->Upscale(context, outputViewport, frameBuffer, tempBuffer->View()); + if (tempBuffer->Width() == tempDesc.Width) + Swap(frameBuffer, tempBuffer); + RenderTargetPool::Release(tempBuffer); + tempBuffer = RenderTargetPool::Get(tempDesc); + } + // Depth of Field auto dofTemporary = DepthOfFieldPass::Instance()->Render(renderContext, frameBuffer); frameBuffer = dofTemporary ? dofTemporary : frameBuffer; @@ -591,7 +610,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont { context->ResetRenderTarget(); context->SetRenderTarget(task->GetOutputView()); - context->SetViewportAndScissors(task->GetOutputViewport()); + context->SetViewportAndScissors(outputViewport); MotionBlurPass::Instance()->RenderDebug(renderContext, frameBuffer->View()); RenderTargetPool::Release(tempBuffer); RenderTargetPool::Release(frameBuffer); @@ -599,35 +618,58 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont } // Anti Aliasing - if (!renderContext.List->HasAnyPostFx(renderContext, PostProcessEffectLocation::AfterAntiAliasingPass, MaterialPostFxLocation::AfterAntiAliasingPass) && Math::IsOne(task->RenderingPercentage)) + GPUTextureView* outputView = task->GetOutputView(); + if (!renderContext.List->HasAnyPostFx(renderContext, PostProcessEffectLocation::AfterAntiAliasingPass, MaterialPostFxLocation::AfterAntiAliasingPass) && !useUpscaling) { // AA -> Back Buffer - RenderAntiAliasingPass(renderContext, frameBuffer, task->GetOutputView()); + RenderAntiAliasingPass(renderContext, frameBuffer, outputView, outputViewport); } else { // AA -> PostFx - RenderAntiAliasingPass(renderContext, frameBuffer, *tempBuffer); + RenderAntiAliasingPass(renderContext, frameBuffer, *tempBuffer, Viewport(Float2(renderContext.View.ScreenSize))); context->ResetRenderTarget(); Swap(frameBuffer, tempBuffer); renderContext.List->RunCustomPostFxPass(context, renderContext, PostProcessEffectLocation::AfterAntiAliasingPass, frameBuffer, tempBuffer); renderContext.List->RunMaterialPostFxPass(context, renderContext, MaterialPostFxLocation::AfterAntiAliasingPass, frameBuffer, tempBuffer); // PostFx -> (up-scaling) -> Back Buffer - if (task->RenderingPercentage >= 1.0f) + if (!useUpscaling) { PROFILE_GPU("Copy frame"); - context->SetRenderTarget(task->GetOutputView()); - context->SetViewportAndScissors(task->GetOutputViewport()); + context->SetRenderTarget(outputView); + context->SetViewportAndScissors(outputViewport); context->Draw(frameBuffer); } - else if (renderContext.List->HasAnyPostFx(renderContext, PostProcessEffectLocation::CustomUpscale, MaterialPostFxLocation::MAX)) + else if (renderContext.List->HasAnyPostFx(renderContext, PostProcessEffectLocation::CustomUpscale)) { - renderContext.List->RunCustomPostFxPass(context, renderContext, PostProcessEffectLocation::CustomUpscale, frameBuffer, frameBuffer); + if (outputView->GetParent()->Is()) + { + // Upscale directly to the output texture + auto outputTexture = (GPUTexture*)outputView->GetParent(); + renderContext.List->RunCustomPostFxPass(context, renderContext, PostProcessEffectLocation::CustomUpscale, frameBuffer, outputTexture); + if (frameBuffer == (GPUTexture*)outputView->GetParent()) + Swap(frameBuffer, outputTexture); + } + else + { + // Use temporary buffer for upscaled frame if GetOutputView is owned by GPUSwapChain + RenderTargetPool::Release(tempBuffer); + tempDesc.Width = (int32)outputViewport.Width; + tempDesc.Height = (int32)outputViewport.Height; + tempBuffer = RenderTargetPool::Get(tempDesc); + renderContext.List->RunCustomPostFxPass(context, renderContext, PostProcessEffectLocation::CustomUpscale, frameBuffer, tempBuffer); + { + PROFILE_GPU("Copy frame"); + context->SetRenderTarget(outputView); + context->SetViewportAndScissors(outputViewport); + context->Draw(frameBuffer); + } + } } else { - MultiScaler::Instance()->Upscale(context, task->GetOutputViewport(), frameBuffer, task->GetOutputView()); + MultiScaler::Instance()->Upscale(context, outputViewport, frameBuffer, outputView); } } From 188428a7a9a089cb817bec3917e5d8ac8216b8fa Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 14 Dec 2022 14:03:59 +0100 Subject: [PATCH 76/83] Add `RenderSetup` and allow customizing it by gameplay and postfx --- Source/Engine/Graphics/PostProcessEffect.h | 7 +++ Source/Engine/Graphics/RenderTask.h | 5 ++ Source/Engine/Graphics/RenderView.cpp | 2 +- Source/Engine/Renderer/AntiAliasing/TAA.cpp | 5 -- Source/Engine/Renderer/AntiAliasing/TAA.h | 8 --- .../GI/DynamicDiffuseGlobalIllumination.cpp | 2 +- Source/Engine/Renderer/MotionBlurPass.cpp | 2 +- Source/Engine/Renderer/RenderList.h | 6 +++ Source/Engine/Renderer/RenderSetup.h | 15 ++++++ Source/Engine/Renderer/Renderer.cpp | 51 ++++++++++++------- Source/Engine/Renderer/Renderer.h | 7 --- .../Renderer/ScreenSpaceReflectionsPass.cpp | 6 --- .../Renderer/ScreenSpaceReflectionsPass.h | 7 --- 13 files changed, 68 insertions(+), 55 deletions(-) create mode 100644 Source/Engine/Renderer/RenderSetup.h diff --git a/Source/Engine/Graphics/PostProcessEffect.h b/Source/Engine/Graphics/PostProcessEffect.h index c02e428f6..7e5ce96d2 100644 --- a/Source/Engine/Graphics/PostProcessEffect.h +++ b/Source/Engine/Graphics/PostProcessEffect.h @@ -44,6 +44,13 @@ public: return GetEnabled(); } + /// + /// Pre-rendering event called before scene rendering begin. Can be used to perform custom rendering or customize render view/setup. + /// + virtual void PreRender(GPUContext* context, RenderContext& renderContext) + { + } + /// /// Performs custom postFx rendering. /// diff --git a/Source/Engine/Graphics/RenderTask.h b/Source/Engine/Graphics/RenderTask.h index 4df61c9d0..3596f9f7e 100644 --- a/Source/Engine/Graphics/RenderTask.h +++ b/Source/Engine/Graphics/RenderTask.h @@ -371,6 +371,11 @@ public: /// The rendering context. virtual void OnPostRender(GPUContext* context, RenderContext& renderContext); + /// + /// The action called before any rendering to override/customize setup RenderSetup inside RenderList. Can be used to enable eg. Motion Vectors rendering. + /// + Delegate SetupRender; + public: /// /// Gets the rendering render task viewport (before upsampling). diff --git a/Source/Engine/Graphics/RenderView.cpp b/Source/Engine/Graphics/RenderView.cpp index 777b7595d..9776608ed 100644 --- a/Source/Engine/Graphics/RenderView.cpp +++ b/Source/Engine/Graphics/RenderView.cpp @@ -18,7 +18,7 @@ void RenderView::Prepare(RenderContext& renderContext) // Check if use TAA (need to modify the projection matrix) Float2 taaJitter; NonJitteredProjection = Projection; - if (renderContext.List->Settings.AntiAliasing.Mode == AntialiasingMode::TemporalAntialiasing) + if (renderContext.List->Setup.UseTemporalAAJitter) { // Move to the next frame const int MaxSampleCount = 8; diff --git a/Source/Engine/Renderer/AntiAliasing/TAA.cpp b/Source/Engine/Renderer/AntiAliasing/TAA.cpp index 63038ae27..c8730220a 100644 --- a/Source/Engine/Renderer/AntiAliasing/TAA.cpp +++ b/Source/Engine/Renderer/AntiAliasing/TAA.cpp @@ -63,11 +63,6 @@ void TAA::Dispose() _shader = nullptr; } -bool TAA::NeedMotionVectors(const RenderContext& renderContext) -{ - return renderContext.List->Settings.AntiAliasing.Mode == AntialiasingMode::TemporalAntialiasing; -} - void TAA::Render(const RenderContext& renderContext, GPUTexture* input, GPUTextureView* output) { auto context = GPUDevice::Instance->GetMainContext(); diff --git a/Source/Engine/Renderer/AntiAliasing/TAA.h b/Source/Engine/Renderer/AntiAliasing/TAA.h index 06951a638..e6bfe9f44 100644 --- a/Source/Engine/Renderer/AntiAliasing/TAA.h +++ b/Source/Engine/Renderer/AntiAliasing/TAA.h @@ -16,14 +16,6 @@ private: GPUPipelineState* _psTAA; public: - - /// - /// Determinates whenever this pass requires motion vectors rendering. - /// - /// The rendering context. - /// True if need to render motion vectors, otherwise false. - static bool NeedMotionVectors(const RenderContext& renderContext); - /// /// Performs AA pass rendering for the input task. /// diff --git a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp index 25c98678d..2414ddeca 100644 --- a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp +++ b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp @@ -480,7 +480,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont auto& cascade = ddgiData.Cascades[cascadeIndex]; data.ProbeScrollClears[cascadeIndex] = Int4(cascade.ProbeScrollClears, 0); } - if (renderContext.List->Settings.AntiAliasing.Mode == AntialiasingMode::TemporalAntialiasing) + if (renderContext.List->Setup.UseTemporalAAJitter) { // Use temporal offset in the dithering factor (gets cleaned out by TAA) const float time = Time::Draw.UnscaledTime.GetTotalSeconds(); diff --git a/Source/Engine/Renderer/MotionBlurPass.cpp b/Source/Engine/Renderer/MotionBlurPass.cpp index f47132794..ba7b20569 100644 --- a/Source/Engine/Renderer/MotionBlurPass.cpp +++ b/Source/Engine/Renderer/MotionBlurPass.cpp @@ -162,7 +162,7 @@ void MotionBlurPass::RenderMotionVectors(RenderContext& renderContext) const int32 motionVectorsHeight = screenHeight / static_cast(settings.MotionVectorsResolution); // Ensure to have valid data - if (!Renderer::NeedMotionVectors(renderContext) || checkIfSkipPass()) + if (!renderContext.List->Setup.UseMotionVectors || checkIfSkipPass()) { // Skip pass (just clear motion vectors if texture is allocated) if (motionVectors->IsAllocated()) diff --git a/Source/Engine/Renderer/RenderList.h b/Source/Engine/Renderer/RenderList.h index 421f17dea..592d0d5ce 100644 --- a/Source/Engine/Renderer/RenderList.h +++ b/Source/Engine/Renderer/RenderList.h @@ -10,6 +10,7 @@ #include "DrawCall.h" #include "RenderListBuffer.h" #include "RendererAllocation.h" +#include "RenderSetup.h" enum class StaticFlags; class RenderBuffers; @@ -363,6 +364,11 @@ public: /// Array PostFx; + /// + /// The renderer setup for the frame drawing. + /// + RenderSetup Setup; + /// /// The post process settings. /// diff --git a/Source/Engine/Renderer/RenderSetup.h b/Source/Engine/Renderer/RenderSetup.h new file mode 100644 index 000000000..343f9dee0 --- /dev/null +++ b/Source/Engine/Renderer/RenderSetup.h @@ -0,0 +1,15 @@ +// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. + +#pragma once + +#include "Engine/Graphics/RenderTask.h" + +/// +/// The utility container for rendering setup configuration. Allows to properly decide about using certain render features (eg. motion vectors, TAA jitter) before rendering happens. +/// +struct FLAXENGINE_API RenderSetup +{ + RenderingUpscaleLocation UpscaleLocation = RenderingUpscaleLocation::AfterAntiAliasingPass; + bool UseMotionVectors = false; + bool UseTemporalAAJitter = false; +}; diff --git a/Source/Engine/Renderer/Renderer.cpp b/Source/Engine/Renderer/Renderer.cpp index 9396069f7..0ab25f6e5 100644 --- a/Source/Engine/Renderer/Renderer.cpp +++ b/Source/Engine/Renderer/Renderer.cpp @@ -5,6 +5,7 @@ #include "Engine/Graphics/RenderTargetPool.h" #include "Engine/Graphics/RenderBuffers.h" #include "Engine/Graphics/RenderTask.h" +#include "Engine/Graphics/PostProcessEffect.h" #include "Engine/Engine/EngineService.h" #include "GBufferPass.h" #include "ForwardPass.h" @@ -224,19 +225,6 @@ void Renderer::Render(SceneRenderTask* task) RenderList::ReturnToPool(e.List); } -bool Renderer::NeedMotionVectors(const RenderContext& renderContext) -{ - const int32 screenWidth = renderContext.Buffers->GetWidth(); - const int32 screenHeight = renderContext.Buffers->GetHeight(); - if (screenWidth < 16 || screenHeight < 16 || renderContext.Task->IsCameraCut) - return false; - MotionBlurSettings& motionBlurSettings = renderContext.List->Settings.MotionBlur; - return ((renderContext.View.Flags & ViewFlags::MotionBlur) != 0 && motionBlurSettings.Enabled && motionBlurSettings.Scale > ZeroTolerance) || - renderContext.View.Mode == ViewMode::MotionVectors || - ScreenSpaceReflectionsPass::NeedMotionVectors(renderContext) || - TAA::NeedMotionVectors(renderContext); -} - void Renderer::DrawSceneDepth(GPUContext* context, SceneRenderTask* task, GPUTexture* output, const Array& customActors) { CHECK(context && task && output && output->IsDepthStencil()); @@ -314,20 +302,45 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont aaMode = AntialiasingMode::None; // TODO: support TAA in ortho projection (see RenderView::Prepare to jitter projection matrix better) renderContext.List->Settings.AntiAliasing.Mode = aaMode; + // Initialize setup + RenderSetup& setup = renderContext.List->Setup; + { + PROFILE_CPU_NAMED("Setup"); + if (renderContext.View.Origin != renderContext.View.PrevOrigin) + renderContext.Task->CameraCut(); // Cut any temporal effects on rendering origin change + const int32 screenWidth = renderContext.Buffers->GetWidth(); + const int32 screenHeight = renderContext.Buffers->GetHeight(); + setup.UpscaleLocation = renderContext.Task->UpscaleLocation; + if (screenWidth < 16 || screenHeight < 16 || renderContext.Task->IsCameraCut) + setup.UseMotionVectors = false; + else + { + const MotionBlurSettings& motionBlurSettings = renderContext.List->Settings.MotionBlur; + const ScreenSpaceReflectionsSettings ssrSettings = renderContext.List->Settings.ScreenSpaceReflections; + setup.UseMotionVectors = ((renderContext.View.Flags & ViewFlags::MotionBlur) != 0 && motionBlurSettings.Enabled && motionBlurSettings.Scale > ZeroTolerance) || + renderContext.View.Mode == ViewMode::MotionVectors || + (ssrSettings.TemporalEffect && renderContext.View.Flags & ViewFlags::SSR) || + renderContext.List->Settings.AntiAliasing.Mode == AntialiasingMode::TemporalAntialiasing; + } + setup.UseTemporalAAJitter = aaMode == AntialiasingMode::TemporalAntialiasing; + + // Customize setup (by postfx or custom gameplay effects) + renderContext.Task->SetupRender(renderContext); + for (PostProcessEffect* e : renderContext.List->PostFx) + e->PreRender(context, renderContext); + } + // Prepare renderContext.View.Prepare(renderContext); - if (renderContext.View.Origin != renderContext.View.PrevOrigin) - renderContext.Task->CameraCut(); // Cut any temporal effects on rendering origin change renderContext.Buffers->Prepare(); // Build batch of render contexts (main view and shadow projections) const bool isGBufferDebug = GBufferPass::IsDebugView(renderContext.View.Mode); - const bool needMotionVectors = Renderer::NeedMotionVectors(renderContext); { PROFILE_CPU_NAMED("Collect Draw Calls"); view.Pass = DrawPass::GBuffer | DrawPass::Forward | DrawPass::Distortion; - if (needMotionVectors) + if (setup.UseMotionVectors) view.Pass |= DrawPass::MotionVectors; renderContextBatch.GetMainContext() = renderContext; // Sync render context in batch with the current value @@ -372,7 +385,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont renderContext.List->SortDrawCalls(renderContext, false, DrawCallsListType::GBufferNoDecals); renderContext.List->SortDrawCalls(renderContext, true, DrawCallsListType::Forward); renderContext.List->SortDrawCalls(renderContext, false, DrawCallsListType::Distortion); - if (needMotionVectors) + if (setup.UseMotionVectors) renderContext.List->SortDrawCalls(renderContext, false, DrawCallsListType::MotionVectors); for (int32 i = 1; i < renderContextBatch.Contexts.Count(); i++) { @@ -555,7 +568,7 @@ void RenderInner(SceneRenderTask* task, RenderContext& renderContext, RenderCont // Upscaling after scene rendering but before post processing bool useUpscaling = task->RenderingPercentage < 1.0f; const Viewport outputViewport = task->GetOutputViewport(); - if (useUpscaling && task->UpscaleLocation == RenderingUpscaleLocation::BeforePostProcessingPass) + if (useUpscaling && setup.UpscaleLocation == RenderingUpscaleLocation::BeforePostProcessingPass) { useUpscaling = false; RenderTargetPool::Release(tempBuffer); diff --git a/Source/Engine/Renderer/Renderer.h b/Source/Engine/Renderer/Renderer.h index 8f98f5335..7f470407e 100644 --- a/Source/Engine/Renderer/Renderer.h +++ b/Source/Engine/Renderer/Renderer.h @@ -33,13 +33,6 @@ public: /// The scene rendering task. static void Render(SceneRenderTask* task); - /// - /// Determinates whenever any pass requires motion vectors rendering. - /// - /// The rendering context. - /// True if need to render motion vectors, otherwise false. - static bool NeedMotionVectors(const RenderContext& renderContext); - public: /// diff --git a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp index ce7e6e3f3..2614d9f63 100644 --- a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp +++ b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.cpp @@ -55,12 +55,6 @@ PACK_STRUCT(struct Data GlobalSurfaceAtlasPass::ConstantsData GlobalSurfaceAtlas; }); -bool ScreenSpaceReflectionsPass::NeedMotionVectors(const RenderContext& renderContext) -{ - auto& settings = renderContext.List->Settings.ScreenSpaceReflections; - return settings.TemporalEffect && renderContext.View.Flags & ViewFlags::SSR; -} - String ScreenSpaceReflectionsPass::ToString() const { return TEXT("ScreenSpaceReflectionsPass"); diff --git a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.h b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.h index 8d38fd40d..84bdc8f42 100644 --- a/Source/Engine/Renderer/ScreenSpaceReflectionsPass.h +++ b/Source/Engine/Renderer/ScreenSpaceReflectionsPass.h @@ -36,13 +36,6 @@ private: AssetReference _preIntegratedGF; public: - /// - /// Determinates whenever this pass requires motion vectors rendering. - /// - /// The rendering context. - /// True if need to render motion vectors, otherwise false. - static bool NeedMotionVectors(const RenderContext& renderContext); - /// /// Perform SSR rendering for the input task (blends reflections to given texture using alpha blending). /// From c38eda579961f0c6961055cc139df0ef98484ae1 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 14 Dec 2022 14:04:14 +0100 Subject: [PATCH 77/83] Fixes for compilation --- Source/Engine/Content/AssetInfo.h | 5 +---- Source/Engine/Content/Content.cpp | 5 +++++ Source/Engine/Engine/Base/GameBase.h | 2 ++ Source/Engine/Render2D/FontTextureAtlas.cpp | 1 + Source/Engine/Renderer/Utils/MultiScaler.h | 1 + 5 files changed, 10 insertions(+), 4 deletions(-) diff --git a/Source/Engine/Content/AssetInfo.h b/Source/Engine/Content/AssetInfo.h index 7cb44b0f8..169352e62 100644 --- a/Source/Engine/Content/AssetInfo.h +++ b/Source/Engine/Content/AssetInfo.h @@ -54,8 +54,5 @@ public: /// Gets the string. /// /// The string. - String ToString() const - { - return String::Format(TEXT("ID: {0}, TypeName: {1}, Path: \'{2}\'"), ID, TypeName, Path); - } + String ToString() const; }; diff --git a/Source/Engine/Content/Content.cpp b/Source/Engine/Content/Content.cpp index e0910f48f..1e1f81e09 100644 --- a/Source/Engine/Content/Content.cpp +++ b/Source/Engine/Content/Content.cpp @@ -34,6 +34,11 @@ TimeSpan Content::AssetsUnloadInterval = TimeSpan::FromSeconds(10); Delegate Content::AssetDisposing; Delegate Content::AssetReloading; +String AssetInfo::ToString() const +{ + return String::Format(TEXT("ID: {0}, TypeName: {1}, Path: \'{2}\'"), ID, TypeName, Path); +} + namespace { // Assets diff --git a/Source/Engine/Engine/Base/GameBase.h b/Source/Engine/Engine/Base/GameBase.h index 31396490b..b883d76d6 100644 --- a/Source/Engine/Engine/Base/GameBase.h +++ b/Source/Engine/Engine/Base/GameBase.h @@ -2,6 +2,8 @@ #pragma once +#include "Engine/Core/Types/BaseTypes.h" + /// /// Build game header flags. /// diff --git a/Source/Engine/Render2D/FontTextureAtlas.cpp b/Source/Engine/Render2D/FontTextureAtlas.cpp index 75e63dda0..84d3efd16 100644 --- a/Source/Engine/Render2D/FontTextureAtlas.cpp +++ b/Source/Engine/Render2D/FontTextureAtlas.cpp @@ -1,6 +1,7 @@ // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. #include "FontTextureAtlas.h" +#include "Engine/Core/Log.h" #include "Engine/Core/Types/DataContainer.h" #include "Engine/Content/Factories/BinaryAssetFactory.h" #include "Engine/Graphics/PixelFormat.h" diff --git a/Source/Engine/Renderer/Utils/MultiScaler.h b/Source/Engine/Renderer/Utils/MultiScaler.h index 2e9fe2a26..9b2031c73 100644 --- a/Source/Engine/Renderer/Utils/MultiScaler.h +++ b/Source/Engine/Renderer/Utils/MultiScaler.h @@ -3,6 +3,7 @@ #pragma once #include "../RendererPass.h" +#include "Engine/Graphics/GPUContext.h" #include "Engine/Graphics/GPUPipelineStatePermutations.h" /// From 713aa3e0f9cb3adcd1b14e0dacd8d076ce10d706 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 14 Dec 2022 16:16:02 +0100 Subject: [PATCH 78/83] Add `SetResourceState` and `ForceRebindDescriptors` to `GPUContext` for integration with external rendering libraries --- Source/Engine/Graphics/GPUContext.cpp | 8 +++++ Source/Engine/Graphics/GPUContext.h | 10 +++++++ .../DirectX/DX12/GPUContextDX12.cpp | 29 +++++++++++++------ .../DirectX/DX12/GPUContextDX12.h | 2 ++ 4 files changed, 40 insertions(+), 9 deletions(-) diff --git a/Source/Engine/Graphics/GPUContext.cpp b/Source/Engine/Graphics/GPUContext.cpp index 2583d4885..2a8df73fc 100644 --- a/Source/Engine/Graphics/GPUContext.cpp +++ b/Source/Engine/Graphics/GPUContext.cpp @@ -63,3 +63,11 @@ void GPUContext::Draw(GPUTextureView* rt) SetState(_device->GetCopyLinearPS()); DrawFullscreenTriangle(); } + +void GPUContext::SetResourceState(GPUResource* resource, uint64 state, int32 subresource) +{ +} + +void GPUContext::ForceRebindDescriptors() +{ +} diff --git a/Source/Engine/Graphics/GPUContext.h b/Source/Engine/Graphics/GPUContext.h index 7c8b90a71..0a3e66051 100644 --- a/Source/Engine/Graphics/GPUContext.h +++ b/Source/Engine/Graphics/GPUContext.h @@ -596,4 +596,14 @@ public: /// Flushes the command buffer (calls GPU execution). /// API_FUNCTION() virtual void Flush() = 0; + + /// + /// Sets the state of the resource (or subresource). + /// + virtual void SetResourceState(GPUResource* resource, uint64 state, int32 subresource = -1); + + /// + /// Forces graphics backend to rebind descriptors after command list was used by external graphics library. + /// + virtual void ForceRebindDescriptors(); }; diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp index 9cad9a636..34dec929f 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.cpp @@ -236,13 +236,7 @@ void GPUContextDX12::Reset() Platform::MemoryClear(&_samplers, sizeof(_samplers)); _swapChainsUsed = 0; - // Bind Root Signature - _commandList->SetGraphicsRootSignature(_device->GetRootSignature()); - _commandList->SetComputeRootSignature(_device->GetRootSignature()); - - // Bind heaps - ID3D12DescriptorHeap* ppHeaps[] = { _device->RingHeap_CBV_SRV_UAV.GetHeap(), _device->RingHeap_Sampler.GetHeap() }; - _commandList->SetDescriptorHeaps(ARRAY_COUNT(ppHeaps), ppHeaps); + ForceRebindDescriptors(); } uint64 GPUContextDX12::Execute(bool waitForCompletion) @@ -1392,11 +1386,11 @@ void GPUContextDX12::CopySubresource(GPUResource* dstResource, uint32 dstSubreso auto srcBufferDX12 = dynamic_cast(srcResource); auto dstTextureDX12 = dynamic_cast(dstResource); auto srcTextureDX12 = dynamic_cast(srcResource); - + SetResourceState(dstResourceDX12, D3D12_RESOURCE_STATE_COPY_DEST); SetResourceState(srcResourceDX12, D3D12_RESOURCE_STATE_COPY_SOURCE); flushRBs(); - + // Buffer -> Buffer if (srcBufferDX12 && dstBufferDX12) { @@ -1430,4 +1424,21 @@ void GPUContextDX12::CopySubresource(GPUResource* dstResource, uint32 dstSubreso } } +void GPUContextDX12::SetResourceState(GPUResource* resource, uint64 state, int32 subresource) +{ + auto resourceDX12 = dynamic_cast(resource); + SetResourceState(resourceDX12, (D3D12_RESOURCE_STATES)state, subresource); +} + +void GPUContextDX12::ForceRebindDescriptors() +{ + // Bind Root Signature + _commandList->SetGraphicsRootSignature(_device->GetRootSignature()); + _commandList->SetComputeRootSignature(_device->GetRootSignature()); + + // Bind heaps + ID3D12DescriptorHeap* ppHeaps[] = {_device->RingHeap_CBV_SRV_UAV.GetHeap(), _device->RingHeap_Sampler.GetHeap()}; + _commandList->SetDescriptorHeaps(ARRAY_COUNT(ppHeaps), ppHeaps); +} + #endif diff --git a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.h b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.h index 47a331192..5e358d616 100644 --- a/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.h +++ b/Source/Engine/GraphicsDevice/DirectX/DX12/GPUContextDX12.h @@ -198,6 +198,8 @@ public: void CopyCounter(GPUBuffer* dstBuffer, uint32 dstOffset, GPUBuffer* srcBuffer) override; void CopyResource(GPUResource* dstResource, GPUResource* srcResource) override; void CopySubresource(GPUResource* dstResource, uint32 dstSubresource, GPUResource* srcResource, uint32 srcSubresource) override; + void SetResourceState(GPUResource* resource, uint64 state, int32 subresource) override; + void ForceRebindDescriptors() override; }; #endif From 79f4dfcaabda95732b442548c4935728315c98dd Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 14 Dec 2022 16:16:25 +0100 Subject: [PATCH 79/83] Add `GetNativePtr` to `GPUAdapter` --- Source/Engine/Graphics/GPUAdapter.h | 5 +++++ Source/Engine/GraphicsDevice/DirectX/GPUAdapterDX.h | 6 ++++-- Source/Engine/GraphicsDevice/Null/GPUAdapterNull.h | 7 ++++--- Source/Engine/GraphicsDevice/Vulkan/GPUAdapterVulkan.h | 4 ++++ 4 files changed, 17 insertions(+), 5 deletions(-) diff --git a/Source/Engine/Graphics/GPUAdapter.h b/Source/Engine/Graphics/GPUAdapter.h index e385c5836..1afe1127f 100644 --- a/Source/Engine/Graphics/GPUAdapter.h +++ b/Source/Engine/Graphics/GPUAdapter.h @@ -41,6 +41,11 @@ public: /// True if valid, otherwise false. virtual bool IsValid() const = 0; + /// + /// Gets the native pointer to the underlying graphics device adapter. It's a low-level platform-specific handle. + /// + API_PROPERTY() virtual void* GetNativePtr() const = 0; + /// /// Gets the GPU vendor identifier. /// diff --git a/Source/Engine/GraphicsDevice/DirectX/GPUAdapterDX.h b/Source/Engine/GraphicsDevice/DirectX/GPUAdapterDX.h index aea242972..48097b290 100644 --- a/Source/Engine/GraphicsDevice/DirectX/GPUAdapterDX.h +++ b/Source/Engine/GraphicsDevice/DirectX/GPUAdapterDX.h @@ -38,12 +38,14 @@ public: { return Index != INVALID_INDEX && MaxFeatureLevel != static_cast(0); } - + void* GetNativePtr() const override + { + return (void*)(intptr)Index; + } uint32 GetVendorId() const override { return (uint32)Description.VendorId; } - String GetDescription() const override { return Description.Description; diff --git a/Source/Engine/GraphicsDevice/Null/GPUAdapterNull.h b/Source/Engine/GraphicsDevice/Null/GPUAdapterNull.h index 84f05b16f..2fa5f0b27 100644 --- a/Source/Engine/GraphicsDevice/Null/GPUAdapterNull.h +++ b/Source/Engine/GraphicsDevice/Null/GPUAdapterNull.h @@ -12,18 +12,19 @@ class GPUAdapterNull : public GPUAdapter { public: - // [GPUAdapter] bool IsValid() const override { return true; } - + void* GetNativePtr() const override + { + return nullptr; + } uint32 GetVendorId() const override { return 0; } - String GetDescription() const override { return TEXT("Null"); diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUAdapterVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUAdapterVulkan.h index 781e3e73a..f3ddc5406 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUAdapterVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUAdapterVulkan.h @@ -61,6 +61,10 @@ public: { return Gpu != VK_NULL_HANDLE; } + void* GetNativePtr() const override + { + return (void*)Gpu; + } uint32 GetVendorId() const override { return GpuProps.vendorID; From 63e7fb85ec521cb7bf65dacf1897ca77bdbcb795 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Wed, 14 Dec 2022 16:16:43 +0100 Subject: [PATCH 80/83] Fix `GetNativePtr` on Vulkan --- Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp | 2 +- Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp | 5 ++++- Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h | 1 + Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.h | 1 - 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp index 546f3d59e..24621a560 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUContextVulkan.cpp @@ -783,7 +783,7 @@ void GPUContextVulkan::EventEnd() void* GPUContextVulkan::GetNativePtr() const { const auto cmdBuffer = _cmdBufferManager->GetCmdBuffer(); - return (void*)cmdBuffer; + return (void*)cmdBuffer->GetHandle(); } bool GPUContextVulkan::IsDepthBufferBinded() diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp index 470469aa1..90059c281 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.cpp @@ -1486,7 +1486,10 @@ GPUAdapter* GPUDeviceVulkan::GetAdapter() const void* GPUDeviceVulkan::GetNativePtr() const { - return static_cast(Device); + // Return both Instance and Device as pointer to void*[2] + _nativePtr[0] = (void*)Instance; + _nativePtr[1] = (void*)Device; + return _nativePtr; } static int32 GetMaxSampleCount(VkSampleCountFlags counts) diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h index b4fec211e..88b9d3d8d 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUDeviceVulkan.h @@ -459,6 +459,7 @@ class GPUDeviceVulkan : public GPUDevice private: CriticalSection _fenceLock; + mutable void* _nativePtr[2]; Dictionary _renderPasses; Dictionary _framebuffers; diff --git a/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.h b/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.h index fcbbd2c01..bd1294a87 100644 --- a/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.h +++ b/Source/Engine/GraphicsDevice/Vulkan/GPUTextureVulkan.h @@ -111,7 +111,6 @@ public: /// /// Gets the Vulkan image handle. /// - /// The image handle. FORCE_INLINE VkImage GetHandle() const { return _image; From b9244df8f7d8f2c6ad3017a87ac8929a9a4fbf74 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Thu, 15 Dec 2022 12:40:21 +0100 Subject: [PATCH 81/83] Fix temporal anti-aliasing to provide better quality output --- Content/Shaders/TAA.flax | 4 ++-- Source/Engine/Graphics/PostProcessSettings.h | 2 +- Source/Engine/Graphics/RenderView.cpp | 6 +++--- Source/Shaders/TAA.shader | 9 ++++----- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/Content/Shaders/TAA.flax b/Content/Shaders/TAA.flax index 768ffd750..6f30a121b 100644 --- a/Content/Shaders/TAA.flax +++ b/Content/Shaders/TAA.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e15b9c0eed4678e45c681a789159fff3ff13d5f0cbd0a4880df1f6c6f68d9812 -size 3371 +oid sha256:382c4754367afadc761e6ea3c3d61ad5be249cd4b55e959382f0476259e68367 +size 3343 diff --git a/Source/Engine/Graphics/PostProcessSettings.h b/Source/Engine/Graphics/PostProcessSettings.h index ed8a6dba2..7a8645721 100644 --- a/Source/Engine/Graphics/PostProcessSettings.h +++ b/Source/Engine/Graphics/PostProcessSettings.h @@ -1906,7 +1906,7 @@ API_STRUCT() struct FLAXENGINE_API AntiAliasingSettings : ISerializable /// The blending coefficient for moving fragments. Controls the percentage of history sample blended into the final color for fragments with significant active motion. /// API_FIELD(Attributes="Limit(0, 0.99f, 0.001f), EditorOrder(4), PostProcessSetting((int)AntiAliasingSettingsOverride.TAA_MotionBlending), EditorDisplay(null, \"TAA Motion Blending\")") - float TAA_MotionBlending = 0.4f; + float TAA_MotionBlending = 0.7f; public: /// diff --git a/Source/Engine/Graphics/RenderView.cpp b/Source/Engine/Graphics/RenderView.cpp index 9776608ed..fc0cead10 100644 --- a/Source/Engine/Graphics/RenderView.cpp +++ b/Source/Engine/Graphics/RenderView.cpp @@ -26,9 +26,9 @@ void RenderView::Prepare(RenderContext& renderContext) TaaFrameIndex = 0; // Calculate jitter - const float jitterSpread = renderContext.List->Settings.AntiAliasing.TAA_JitterSpread; - const float jitterX = RendererUtils::TemporalHalton(TaaFrameIndex + 1, 2) * jitterSpread; - const float jitterY = RendererUtils::TemporalHalton(TaaFrameIndex + 1, 3) * jitterSpread; + const float jitterSpread = renderContext.List->Settings.AntiAliasing.TAA_JitterSpread / 0.75f; + const float jitterX = (RendererUtils::TemporalHalton(TaaFrameIndex + 1, 2) - 0.5f) * jitterSpread; + const float jitterY = (RendererUtils::TemporalHalton(TaaFrameIndex + 1, 3) - 0.5f) * jitterSpread; taaJitter = Float2(jitterX * 2.0f / width, jitterY * 2.0f / height); // Modify projection matrix diff --git a/Source/Shaders/TAA.shader b/Source/Shaders/TAA.shader index f5f01ee19..cb64b5434 100644 --- a/Source/Shaders/TAA.shader +++ b/Source/Shaders/TAA.shader @@ -61,13 +61,13 @@ float4 PS(Quad_VS2PS input) : SV_Target0 } float2 velocity = SAMPLE_RT_LINEAR(MotionVectors, bestUV).xy; float velocityLength = length(velocity); - float2 prevUV = input.TexCoord + velocity; + float2 prevUV = input.TexCoord - velocity; // Apply sharpening float4 neighborhoodAvg = neighborhoodSum / 9.0; current += (current - neighborhoodAvg) * Sharpness; - // Sample history by clamp it to the nearby colros range to reduce artifacts + // Sample history by clamp it to the nearby colors range to reduce artifacts float4 history = SAMPLE_RT_LINEAR(InputHistory, prevUV); float lumaOffset = abs(Luminance(neighborhoodAvg) - Luminance(current)); float aabbMargin = lerp(4.0, 0.25, saturate(velocityLength * 100.0)) * lumaOffset; @@ -75,9 +75,8 @@ float4 PS(Quad_VS2PS input) : SV_Target0 //history = clamp(history, neighborhoodMin, neighborhoodMax); // Calculate history blending factor - float motion = saturate(velocityLength * 600.0f); - float blendfactor = lerp(StationaryBlending, MotionBlending, motion); - blendfactor = any(abs(prevUV * 2 - 1) >= 1.0f) ? 0.0f : blendfactor; + float motion = saturate(velocityLength * 1000.0f); + float blendfactor = any(abs(prevUV * 2 - 1) >= 1.0f) ? 0.0f : lerp(StationaryBlending, MotionBlending, motion); // Perform linear accumulation of the previous samples with a current one float4 color = lerp(current, history, blendfactor); From 3fcbcacd43f54f6101bcf8419a741fb4705f5039 Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Thu, 15 Dec 2022 17:33:14 +0100 Subject: [PATCH 82/83] Fix empty draw call submitting --- Source/Engine/Graphics/Models/Mesh.cpp | 3 ++- Source/Engine/Graphics/Models/SkinnedMesh.cpp | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Source/Engine/Graphics/Models/Mesh.cpp b/Source/Engine/Graphics/Models/Mesh.cpp index b75db1949..a115ddec7 100644 --- a/Source/Engine/Graphics/Models/Mesh.cpp +++ b/Source/Engine/Graphics/Models/Mesh.cpp @@ -574,7 +574,8 @@ void Mesh::Draw(const RenderContextBatch& renderContextBatch, const DrawInfo& in // Push draw call to the render lists const auto shadowsMode = (ShadowsCastingMode)(entry.ShadowsMode & slot.ShadowsMode); const DrawPass drawModes = (DrawPass)(info.DrawModes & material->GetDrawModes()); - renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, drawModes, info.Flags, shadowsMode, info.Bounds, drawCall, entry.ReceiveDecals); + if (drawModes != DrawPass::None) + renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, drawModes, info.Flags, shadowsMode, info.Bounds, drawCall, entry.ReceiveDecals); } bool Mesh::DownloadDataGPU(MeshBufferType type, BytesContainer& result) const diff --git a/Source/Engine/Graphics/Models/SkinnedMesh.cpp b/Source/Engine/Graphics/Models/SkinnedMesh.cpp index 17c63ac8e..3a4c2cc68 100644 --- a/Source/Engine/Graphics/Models/SkinnedMesh.cpp +++ b/Source/Engine/Graphics/Models/SkinnedMesh.cpp @@ -278,7 +278,8 @@ void SkinnedMesh::Draw(const RenderContextBatch& renderContextBatch, const DrawI // Push draw call to the render lists const auto shadowsMode = (ShadowsCastingMode)(entry.ShadowsMode & slot.ShadowsMode); const DrawPass drawModes = (DrawPass)(info.DrawModes & material->GetDrawModes()); - renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, drawModes, StaticFlags::None, shadowsMode, info.Bounds, drawCall, entry.ReceiveDecals); + if (drawModes != DrawPass::None) + renderContextBatch.GetMainContext().List->AddDrawCall(renderContextBatch, drawModes, StaticFlags::None, shadowsMode, info.Bounds, drawCall, entry.ReceiveDecals); } bool SkinnedMesh::DownloadDataGPU(MeshBufferType type, BytesContainer& result) const From 1cf6c5233ea56eaeabe282d8827d244f3d38e8ef Mon Sep 17 00:00:00 2001 From: Wojciech Figat Date: Thu, 15 Dec 2022 17:33:44 +0100 Subject: [PATCH 83/83] Refactor DDGI probes to use variable ray count depending on the probe location relative to the view frustum --- .../DebugMaterials/DDGIDebugProbes.flax | 4 +- Content/Shaders/GI/DDGI.flax | 4 +- Content/Shaders/GI/GlobalSurfaceAtlas.flax | 4 +- Content/Shaders/VolumetricFog.flax | 4 +- .../Materials/MaterialShaderFeatures.cpp | 2 +- .../GI/DynamicDiffuseGlobalIllumination.cpp | 20 ++--- .../GI/DynamicDiffuseGlobalIllumination.h | 2 +- .../Renderer/GI/GlobalSurfaceAtlasPass.cpp | 2 +- Source/Engine/Renderer/VolumetricFogPass.cpp | 2 +- Source/Shaders/GI/DDGI.hlsl | 59 +++++++------ Source/Shaders/GI/DDGI.shader | 84 ++++++++++--------- Source/Shaders/GI/GlobalSurfaceAtlas.shader | 4 +- Source/Shaders/VolumetricFog.shader | 4 +- 13 files changed, 106 insertions(+), 89 deletions(-) diff --git a/Content/Editor/DebugMaterials/DDGIDebugProbes.flax b/Content/Editor/DebugMaterials/DDGIDebugProbes.flax index fd74958c4..68f46f7d4 100644 --- a/Content/Editor/DebugMaterials/DDGIDebugProbes.flax +++ b/Content/Editor/DebugMaterials/DDGIDebugProbes.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:2405a01ca57fed4112695e699036aa63a77e5140dadd7de957a353992ada02ca -size 41461 +oid sha256:a34e48c787818a3a22072142c6a51aa8dd37ae03a1f96526f6021302c6f6508a +size 41832 diff --git a/Content/Shaders/GI/DDGI.flax b/Content/Shaders/GI/DDGI.flax index 9e45adb50..5e5b5c8be 100644 --- a/Content/Shaders/GI/DDGI.flax +++ b/Content/Shaders/GI/DDGI.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:f3816b8fdd088656e385f46832c2719c77d386d12ec14ac3d0ac6df017b2c7e4 -size 23668 +oid sha256:a5e9fd224618c4b2b6850a843bf9452d49099bfc44549662c1544cf40510294c +size 24284 diff --git a/Content/Shaders/GI/GlobalSurfaceAtlas.flax b/Content/Shaders/GI/GlobalSurfaceAtlas.flax index 3450fa8c6..baf00844c 100644 --- a/Content/Shaders/GI/GlobalSurfaceAtlas.flax +++ b/Content/Shaders/GI/GlobalSurfaceAtlas.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:c342070b981a0dbf335276434ce59f345861e8f9e7d4f2cf07ae2016542642e8 -size 12954 +oid sha256:3e56bf2cd056460a987fb98529e9a78ffa0bd7326ad9cae82145aa169c2dae4f +size 12952 diff --git a/Content/Shaders/VolumetricFog.flax b/Content/Shaders/VolumetricFog.flax index 997b1ab8f..f4990d1cc 100644 --- a/Content/Shaders/VolumetricFog.flax +++ b/Content/Shaders/VolumetricFog.flax @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:7fd020a2c82854ed852a2bb7682dc69b7abe31f139ecff485082d21d9188993d -size 14257 +oid sha256:1a3f3207746368c6d516d51e1053c08cbd4beea71703fa540b4229aa836cff14 +size 14255 diff --git a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp index f2e9ffa8a..a1bf52c9d 100644 --- a/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp +++ b/Source/Engine/Graphics/Materials/MaterialShaderFeatures.cpp @@ -170,7 +170,7 @@ bool GlobalIlluminationFeature::Bind(MaterialShader::BindParameters& params, Spa // Bind DDGI data data.DDGI = bindingDataDDGI.Constants; - params.GPUContext->BindSR(srv + 0, bindingDataDDGI.ProbesState); + params.GPUContext->BindSR(srv + 0, bindingDataDDGI.ProbesData); params.GPUContext->BindSR(srv + 1, bindingDataDDGI.ProbesDistance); params.GPUContext->BindSR(srv + 2, bindingDataDDGI.ProbesIrradiance); } diff --git a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp index 2414ddeca..9db25159f 100644 --- a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp +++ b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.cpp @@ -87,7 +87,7 @@ public: int32 ProbesCountTotal = 0; Int3 ProbeCounts = Int3::Zero; GPUTexture* ProbesTrace = nullptr; // Probes ray tracing: (RGB: hit radiance, A: hit distance) - GPUTexture* ProbesState = nullptr; // Probes state: (RGB: world-space offset, A: state) + GPUTexture* ProbesData = nullptr; // Probes data: (RGB: world-space offset, A: state/data) GPUTexture* ProbesIrradiance = nullptr; // Probes irradiance (RGB: sRGB color) GPUTexture* ProbesDistance = nullptr; // Probes distance (R: mean distance, G: mean distance^2) GPUBuffer* ActiveProbes = nullptr; // List with indices of the active probes (built during probes classification to use indirect dispatches for probes updating), counter at 0 @@ -97,7 +97,7 @@ public: FORCE_INLINE void Release() { RenderTargetPool::Release(ProbesTrace); - RenderTargetPool::Release(ProbesState); + RenderTargetPool::Release(ProbesData); RenderTargetPool::Release(ProbesIrradiance); RenderTargetPool::Release(ProbesDistance); SAFE_DELETE_GPU_RESOURCE(ActiveProbes); @@ -373,7 +373,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont #define INIT_TEXTURE(texture, format, width, height) desc.Format = format; desc.Width = width; desc.Height = height; ddgiData.texture = RenderTargetPool::Get(desc); if (!ddgiData.texture) return true; memUsage += ddgiData.texture->GetMemoryUsage(); RENDER_TARGET_POOL_SET_NAME(ddgiData.texture, "DDGI." #texture) desc.Flags = GPUTextureFlags::ShaderResource | GPUTextureFlags::UnorderedAccess; INIT_TEXTURE(ProbesTrace, PixelFormat::R16G16B16A16_Float, probeRaysCount, Math::Min(probesCountCascade, DDGI_TRACE_RAYS_PROBES_COUNT_LIMIT)); - INIT_TEXTURE(ProbesState, PixelFormat::R8G8B8A8_SNorm, probesCountTotalX, probesCountTotalY); + INIT_TEXTURE(ProbesData, PixelFormat::R8G8B8A8_SNorm, probesCountTotalX, probesCountTotalY); INIT_TEXTURE(ProbesIrradiance, PixelFormat::R11G11B10_Float, probesCountTotalX * (DDGI_PROBE_RESOLUTION_IRRADIANCE + 2), probesCountTotalY * (DDGI_PROBE_RESOLUTION_IRRADIANCE + 2)); INIT_TEXTURE(ProbesDistance, PixelFormat::R16G16_Float, probesCountTotalX * (DDGI_PROBE_RESOLUTION_DISTANCE + 2), probesCountTotalY * (DDGI_PROBE_RESOLUTION_DISTANCE + 2)); #undef INIT_TEXTURE @@ -393,7 +393,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont { // Clear probes PROFILE_GPU("Clear"); - context->ClearUA(ddgiData.ProbesState, Float4::Zero); + context->ClearUA(ddgiData.ProbesData, Float4::Zero); context->ClearUA(ddgiData.ProbesIrradiance, Float4::Zero); context->ClearUA(ddgiData.ProbesDistance, Float4::Zero); } @@ -458,7 +458,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont ddgiData.Result.Constants.IrradianceGamma = 1.5f; ddgiData.Result.Constants.IndirectLightingIntensity = indirectLightingIntensity; ddgiData.Result.Constants.FallbackIrradiance = fallbackIrradiance.ToFloat3() * fallbackIrradiance.A; - ddgiData.Result.ProbesState = ddgiData.ProbesState->View(); + ddgiData.Result.ProbesData = ddgiData.ProbesData->View(); ddgiData.Result.ProbesDistance = ddgiData.ProbesDistance->View(); ddgiData.Result.ProbesIrradiance = ddgiData.ProbesIrradiance->View(); @@ -516,7 +516,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont threadGroupsX = Math::DivideAndRoundUp(probesCountCascade, DDGI_PROBE_CLASSIFY_GROUP_SIZE); context->BindSR(0, bindingDataSDF.Texture ? bindingDataSDF.Texture->ViewVolume() : nullptr); context->BindSR(1, bindingDataSDF.TextureMip ? bindingDataSDF.TextureMip->ViewVolume() : nullptr); - context->BindUA(0, ddgiData.Result.ProbesState); + context->BindUA(0, ddgiData.Result.ProbesData); context->BindUA(1, ddgiData.ActiveProbes->View()); Data1 data; data.CascadeIndex = cascadeIndex; @@ -558,7 +558,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont context->BindSR(4, bindingDataSurfaceAtlas.Objects ? bindingDataSurfaceAtlas.Objects->View() : nullptr); context->BindSR(5, bindingDataSurfaceAtlas.AtlasDepth->View()); context->BindSR(6, bindingDataSurfaceAtlas.AtlasLighting->View()); - context->BindSR(7, ddgiData.Result.ProbesState); + context->BindSR(7, ddgiData.Result.ProbesData); context->BindSR(8, skybox); context->BindSR(9, ddgiData.ActiveProbes->View()); context->BindUA(0, ddgiData.ProbesTrace->View()); @@ -570,7 +570,7 @@ bool DynamicDiffuseGlobalIlluminationPass::RenderInner(RenderContext& renderCont // Update probes irradiance and distance textures (one thread-group per probe) { PROFILE_GPU_CPU_NAMED("Update Probes"); - context->BindSR(0, ddgiData.Result.ProbesState); + context->BindSR(0, ddgiData.Result.ProbesData); context->BindSR(1, ddgiData.ProbesTrace->View()); context->BindSR(2, ddgiData.ActiveProbes->View()); context->BindUA(0, ddgiData.Result.ProbesIrradiance); @@ -682,7 +682,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext, context->BindSR(1, renderContext.Buffers->GBuffer1->View()); context->BindSR(2, renderContext.Buffers->GBuffer2->View()); context->BindSR(3, renderContext.Buffers->DepthBuffer->View()); - context->BindSR(4, ddgiData.Result.ProbesState); + context->BindSR(4, ddgiData.Result.ProbesData); context->BindSR(5, ddgiData.Result.ProbesDistance); context->BindSR(6, ddgiData.Result.ProbesIrradiance); context->SetViewportAndScissors(renderContext.View.ScreenSize.X, renderContext.View.ScreenSize.Y); @@ -724,7 +724,7 @@ bool DynamicDiffuseGlobalIlluminationPass::Render(RenderContext& renderContext, context->SetRenderTarget(*renderContext.Buffers->DepthBuffer, ToSpan(targetBuffers, ARRAY_COUNT(targetBuffers))); { // Pass DDGI data to the material - _debugMaterial->SetParameterValue(TEXT("ProbesState"), Variant(ddgiData.ProbesState)); + _debugMaterial->SetParameterValue(TEXT("ProbesData"), Variant(ddgiData.ProbesData)); _debugMaterial->SetParameterValue(TEXT("ProbesIrradiance"), Variant(ddgiData.ProbesIrradiance)); _debugMaterial->SetParameterValue(TEXT("ProbesDistance"), Variant(ddgiData.ProbesDistance)); auto cb = _debugMaterial->GetShader()->GetCB(3); diff --git a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h index a6bdc9e9e..75a45061d 100644 --- a/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h +++ b/Source/Engine/Renderer/GI/DynamicDiffuseGlobalIllumination.h @@ -34,7 +34,7 @@ public: struct BindingData { ConstantsData Constants; - GPUTextureView* ProbesState; + GPUTextureView* ProbesData; GPUTextureView* ProbesDistance; GPUTextureView* ProbesIrradiance; }; diff --git a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp index d4760ba4e..e67ba36b2 100644 --- a/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp +++ b/Source/Engine/Renderer/GI/GlobalSurfaceAtlasPass.cpp @@ -1056,7 +1056,7 @@ bool GlobalSurfaceAtlasPass::Render(RenderContext& renderContext, GPUContext* co PROFILE_GPU_CPU_NAMED("DDGI"); data.DDGI = bindingDataDDGI.Constants; data.Light.Radius = giSettings.BounceIntensity / bindingDataDDGI.Constants.IndirectLightingIntensity; // Reuse for smaller CB - context->BindSR(5, bindingDataDDGI.ProbesState); + context->BindSR(5, bindingDataDDGI.ProbesData); context->BindSR(6, bindingDataDDGI.ProbesDistance); context->BindSR(7, bindingDataDDGI.ProbesIrradiance); context->UpdateCB(_cb0, &data); diff --git a/Source/Engine/Renderer/VolumetricFogPass.cpp b/Source/Engine/Renderer/VolumetricFogPass.cpp index 44cad992b..72cd2bb00 100644 --- a/Source/Engine/Renderer/VolumetricFogPass.cpp +++ b/Source/Engine/Renderer/VolumetricFogPass.cpp @@ -671,7 +671,7 @@ void VolumetricFogPass::Render(RenderContext& renderContext) int32 csIndex; if (useDDGI) { - context->BindSR(5, bindingDataDDGI.ProbesState); + context->BindSR(5, bindingDataDDGI.ProbesData); context->BindSR(6, bindingDataDDGI.ProbesDistance); context->BindSR(7, bindingDataDDGI.ProbesIrradiance); csIndex = 1; diff --git a/Source/Shaders/GI/DDGI.hlsl b/Source/Shaders/GI/DDGI.hlsl index 8ae91b3a6..498475561 100644 --- a/Source/Shaders/GI/DDGI.hlsl +++ b/Source/Shaders/GI/DDGI.hlsl @@ -13,9 +13,9 @@ #include "./Flax/Math.hlsl" #include "./Flax/Octahedral.hlsl" -#define DDGI_PROBE_STATE_INACTIVE 0.0f -#define DDGI_PROBE_STATE_ACTIVATED 0.2f -#define DDGI_PROBE_STATE_ACTIVE 1.0f +#define DDGI_PROBE_STATE_INACTIVE 0 +#define DDGI_PROBE_STATE_ACTIVATED 1 +#define DDGI_PROBE_STATE_ACTIVE 2 #define DDGI_PROBE_RESOLUTION_IRRADIANCE 6 // Resolution (in texels) for probe irradiance data (excluding 1px padding on each side) #define DDGI_PROBE_RESOLUTION_DISTANCE 14 // Resolution (in texels) for probe distance data (excluding 1px padding on each side) #define DDGI_SRGB_BLENDING 1 // Enables blending in sRGB color space, otherwise irradiance blending is done in linear space @@ -89,22 +89,32 @@ float3 GetDDGIProbeWorldPosition(DDGIData data, uint cascadeIndex, uint3 probeCo return probesOrigin + probePosition - probeGridOffset + (data.ProbesScrollOffsets[cascadeIndex].xyz * probesSpacing); } -// Loads probe probe state -float LoadDDGIProbeState(DDGIData data, Texture2D probesState, uint cascadeIndex, uint probeIndex) +// Loads probe probe data (encoded) +float4 LoadDDGIProbeData(DDGIData data, Texture2D probesData, uint cascadeIndex, uint probeIndex) { int2 probeDataCoords = GetDDGIProbeTexelCoords(data, cascadeIndex, probeIndex); - float4 probeState = probesState.Load(int3(probeDataCoords, 0)); - return probeState.w; + return probesData.Load(int3(probeDataCoords, 0)); } -// Loads probe world-space position (XYZ) and probe state (W) -float4 LoadDDGIProbePositionAndState(DDGIData data, Texture2D probesState, uint cascadeIndex, uint probeIndex, uint3 probeCoords) +// Encodes probe probe data +float4 EncodeDDGIProbeData(float3 probeOffset, uint probeState) { - int2 probeDataCoords = GetDDGIProbeTexelCoords(data, cascadeIndex, probeIndex); - float4 probeState = probesState.Load(int3(probeDataCoords, 0)); - probeState.xyz *= data.ProbesOriginAndSpacing[cascadeIndex].w; // Probe offset is [-1;1] within probes spacing - probeState.xyz += GetDDGIProbeWorldPosition(data, cascadeIndex, probeCoords); // Place probe on a grid - return probeState; + return float4(probeOffset, (float)probeState * (1.0f / 8.0f)); +} + +// Decodes probe state from the encoded state +uint DecodeDDGIProbeState(float4 probeData) +{ + return (uint)(probeData.w * 8.0f); +} + +// Decodes probe world-space position (XYZ) from the encoded state +float3 DecodeDDGIProbePosition(DDGIData data, float4 probeData, uint cascadeIndex, uint probeIndex, uint3 probeCoords) +{ + float3 probePosition = probeData.xyz; + probePosition *= data.ProbesOriginAndSpacing[cascadeIndex].w; // Probe offset is [-1;1] within probes spacing + probePosition += GetDDGIProbeWorldPosition(data, cascadeIndex, probeCoords); // Place probe on a grid + return probePosition; } // Calculates texture UVs for sampling probes atlas texture (irradiance or distance) @@ -122,11 +132,11 @@ float2 GetDDGIProbeUV(DDGIData data, uint cascadeIndex, uint probeIndex, float2 // Samples DDGI probes volume at the given world-space position and returns the irradiance. // bias - scales the bias vector to the initial sample point to reduce self-shading artifacts // dither - randomized per-pixel value in range 0-1, used to smooth dithering for cascades blending -float3 SampleDDGIIrradiance(DDGIData data, Texture2D probesState, Texture2D probesDistance, Texture2D probesIrradiance, float3 worldPosition, float3 worldNormal, float bias = 0.2f, float dither = 0.0f) +float3 SampleDDGIIrradiance(DDGIData data, Texture2D probesData, Texture2D probesDistance, Texture2D probesIrradiance, float3 worldPosition, float3 worldNormal, float bias = 0.2f, float dither = 0.0f) { // Select the highest cascade that contains the sample location uint cascadeIndex = 0; - float4 probeStates[8]; + float4 probesDatas[8]; for (; cascadeIndex < data.CascadesCount; cascadeIndex++) { float probesSpacing = data.ProbesOriginAndSpacing[cascadeIndex].w; @@ -145,9 +155,10 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D probesState, uint3 probeCoordsOffset = uint3(i, i >> 1, i >> 2) & 1; uint3 probeCoords = clamp(baseProbeCoords + probeCoordsOffset, uint3(0, 0, 0), data.ProbesCounts - uint3(1, 1, 1)); uint probeIndex = GetDDGIScrollingProbeIndex(data, cascadeIndex, probeCoords); - float4 probeState = probesState.Load(int3(GetDDGIProbeTexelCoords(data, cascadeIndex, probeIndex), 0)); - probeStates[i] = probeState; - if (probeState.w != DDGI_PROBE_STATE_INACTIVE) + float4 probeData = LoadDDGIProbeData(data, probesData, cascadeIndex, probeIndex); + probesDatas[i] = probeData; + uint probeState = DecodeDDGIProbeState(probeData); + if (probeState != DDGI_PROBE_STATE_INACTIVE) activeCount++; } @@ -182,12 +193,12 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D probesState, uint probeIndex = GetDDGIScrollingProbeIndex(data, cascadeIndex, probeCoords); // Load probe position and state - float4 probeState = probeStates[i]; - if (probeState.w == DDGI_PROBE_STATE_INACTIVE) + float4 probeData = probesDatas[i]; + uint probeState = DecodeDDGIProbeState(probeData); + if (probeState == DDGI_PROBE_STATE_INACTIVE) continue; - probeState.xyz *= probesSpacing; // Probe offset is [-1;1] within probes spacing float3 probeBasePosition = baseProbeWorldPosition + ((probeCoords - baseProbeCoords) * probesSpacing); - float3 probePosition = probeBasePosition + probeState.xyz; + float3 probePosition = probeBasePosition + probeData.xyz * probesSpacing; // Probe offset is [-1;1] within probes spacing // Calculate the distance and direction from the (biased and non-biased) shading point and the probe float3 worldPosToProbe = normalize(probePosition - worldPosition); @@ -233,7 +244,7 @@ float3 SampleDDGIIrradiance(DDGIData data, Texture2D probesState, #endif // Debug probe offset visualization - //probeIrradiance = float3(max(frac(probeState.xyz) * 2, 0.1f)); + //probeIrradiance = float3(max(frac(probeData.xyz) * 2, 0.1f)); // Accumulate weighted irradiance irradiance += float4(probeIrradiance * weight, weight); diff --git a/Source/Shaders/GI/DDGI.shader b/Source/Shaders/GI/DDGI.shader index 4ecd185ec..5feb04557 100644 --- a/Source/Shaders/GI/DDGI.shader +++ b/Source/Shaders/GI/DDGI.shader @@ -58,17 +58,18 @@ float3 GetProbeRayDirection(DDGIData data, uint rayIndex) return normalize(QuaternionRotate(data.RaysRotation, direction)); } -// Checks if the probe states are equal -bool GetProbeState(float a, float b) +// Calculates amount of rays to allocate for a probe +uint GetProbeRaysCount(DDGIData data, uint probeState) { - return abs(a - b) < 0.05f; + // TODO: implement variable ray count based on probe location relative to the view frustum (use probe state for storage) + return data.RaysCount; } #ifdef _CS_Classify #define DDGI_PROBE_RELOCATE_ITERATIVE 0 // If true, probes relocation algorithm tries to move them in additive way, otherwise all nearby locations are checked to find the best position -RWTexture2D RWProbesState : register(u0); +RWTexture2D RWProbesData : register(u0); RWByteAddressBuffer RWActiveProbes : register(u1); Texture3D GlobalSDFTex : register(t0); @@ -79,7 +80,7 @@ float3 Remap(float3 value, float3 fromMin, float3 fromMax, float3 toMin, float3 return (value - fromMin) / (fromMax - fromMin) * (toMax - toMin) + toMin; } -// Compute shader for updating probes state between active and inactive. +// Compute shader for updating probes state between active and inactive and performing probes relocation. META_CS(true, FEATURE_LEVEL_SM5) [numthreads(DDGI_PROBE_CLASSIFY_GROUP_SIZE, 1, 1)] void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID) @@ -94,14 +95,15 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID) float probesSpacing = DDGI.ProbesOriginAndSpacing[CascadeIndex].w; // Load probe state and position - float4 probeState = RWProbesState[probeDataCoords]; - probeState.xyz *= probesSpacing; // Probe offset is [-1;1] within probes spacing + float4 probeData = RWProbesData[probeDataCoords]; + uint probeState = DecodeDDGIProbeState(probeData); + float3 probeOffset = probeData.xyz * probesSpacing; // Probe offset is [-1;1] within probes spacing + float3 probeOffsetOld = probeOffset; float3 probeBasePosition = GetDDGIProbeWorldPosition(DDGI, CascadeIndex, probeCoords); float3 probePosition = probeBasePosition; #if DDGI_PROBE_RELOCATE_ITERATIVE - probePosition += probeState.xyz; + probePosition += probeOffset; #endif - float4 probeStateOld = probeState; // Use Global SDF to quickly get distance and direction to the scene geometry #if DDGI_PROBE_RELOCATE_ITERATIVE @@ -117,7 +119,8 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID) if (sdfDst > distanceLimit) // Probe is too far from geometry { // Disable it - probeState = float4(0, 0, 0, DDGI_PROBE_STATE_INACTIVE); + probeOffset = float3(0, 0, 0); + probeState = DDGI_PROBE_STATE_INACTIVE; } else { @@ -127,22 +130,22 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID) if (sdfDst < relocateLimit) { float3 offsetToAdd = sdfNormal * (sdf + threshold); - if (distance(probeState.xyz, offsetToAdd) < relocateLimit) + if (distance(probeOffset, offsetToAdd) < relocateLimit) { // Relocate it - probeState.xyz += offsetToAdd; + probeOffset += offsetToAdd; } } else { // Reset relocation - probeState.xyz = float3(0, 0, 0); + probeOffset = float3(0, 0, 0); } } else if (sdf > threshold * 4.0f) // Probe is far enough from any geometry { // Reset relocation - probeState.xyz = float3(0, 0, 0); + probeOffset = float3(0, 0, 0); } // Check if probe is relocated but the base location is fine @@ -150,7 +153,7 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID) if (sdf > threshold) { // Reset relocation - probeState.xyz = float3(0, 0, 0); + probeOffset = float3(0, 0, 0); } #else // Sample Global SDF around the probe location @@ -177,7 +180,7 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID) // Relocate the probe to the best found location (or zero if nothing good found) if (bestOffset.w <= threshold) bestOffset.xyz = float3(0, 0, 0); - probeState.xyz = bestOffset.xyz; + probeOffset = bestOffset.xyz; #endif // Check if probe was scrolled @@ -189,23 +192,21 @@ void CS_Classify(uint3 DispatchThreadId : SV_DispatchThreadID) int probeCount = (int)DDGI.ProbesCounts[planeIndex]; int newCord = (int)probeCoords[planeIndex] + probeScrollClears[planeIndex]; if (newCord < 0 || newCord >= probeCount) - { wasScrolled = true; - } } // If probe was in different location or was inactive last frame then mark it as activated - bool wasInactive = probeStateOld.w == DDGI_PROBE_STATE_INACTIVE; - bool wasRelocated = distance(probeState.xyz, probeStateOld.xyz) > 2.0f; - probeState.w = wasInactive || wasScrolled || wasRelocated ? DDGI_PROBE_STATE_ACTIVATED : DDGI_PROBE_STATE_ACTIVE; + bool wasInactive = probeState == DDGI_PROBE_STATE_INACTIVE; + bool wasRelocated = distance(probeOffset, probeOffsetOld) > 2.0f; + probeState = wasInactive || wasScrolled || wasRelocated ? DDGI_PROBE_STATE_ACTIVATED : DDGI_PROBE_STATE_ACTIVE; } // Save probe state - probeState.xyz /= probesSpacing; - RWProbesState[probeDataCoords] = probeState; + probeOffset /= probesSpacing; // Move offset back to [-1;1] space + RWProbesData[probeDataCoords] = EncodeDDGIProbeData(probeOffset, probeState); // Collect active probes - if (probeState.w != DDGI_PROBE_STATE_INACTIVE) + if (probeState != DDGI_PROBE_STATE_INACTIVE) { uint activeProbeIndex; RWActiveProbes.InterlockedAdd(0, 1, activeProbeIndex); // Counter at 0 @@ -250,7 +251,7 @@ ByteAddressBuffer RWGlobalSurfaceAtlasCulledObjects : register(t3); Buffer GlobalSurfaceAtlasObjects : register(t4); Texture2D GlobalSurfaceAtlasDepth : register(t5); Texture2D GlobalSurfaceAtlasTex : register(t6); -Texture2D ProbesState : register(t7); +Texture2D ProbesData : register(t7); TextureCube Skybox : register(t8); ByteAddressBuffer ActiveProbes : register(t9); @@ -269,14 +270,17 @@ void CS_TraceRays(uint3 DispatchThreadId : SV_DispatchThreadID) probeIndex = GetDDGIScrollingProbeIndex(DDGI, CascadeIndex, probeCoords); // Load current probe state and position - float4 probePositionAndState = LoadDDGIProbePositionAndState(DDGI, ProbesState, CascadeIndex, probeIndex, probeCoords); - if (probePositionAndState.w == DDGI_PROBE_STATE_INACTIVE) - return; // Skip disabled probes + float4 probeData = LoadDDGIProbeData(DDGI, ProbesData, CascadeIndex, probeIndex); + uint probeState = DecodeDDGIProbeState(probeData); + uint probeRaysCount = GetProbeRaysCount(DDGI, probeState); + if (probeState == DDGI_PROBE_STATE_INACTIVE || probeRaysCount < rayIndex) + return; // Skip disabled probes or if current thread's ray is unused + float3 probePosition = DecodeDDGIProbePosition(DDGI, probeData, CascadeIndex, probeIndex, probeCoords); float3 probeRayDirection = GetProbeRayDirection(DDGI, rayIndex); // Trace ray with Global SDF GlobalSDFTrace trace; - trace.Init(probePositionAndState.xyz, probeRayDirection, 0.0f, DDGI.RayMaxDistance); + trace.Init(probePosition, probeRayDirection, 0.0f, DDGI.RayMaxDistance); GlobalSDFHit hit = RayTraceGlobalSDF(GlobalSDF, GlobalSDFTex, GlobalSDFMip, trace); // Calculate radiance and distance @@ -328,7 +332,7 @@ groupshared float CachedProbesTraceDistance[DDGI_TRACE_RAYS_LIMIT]; groupshared float3 CachedProbesTraceDirection[DDGI_TRACE_RAYS_LIMIT]; RWTexture2D RWOutput : register(u0); -Texture2D ProbesState : register(t0); +Texture2D ProbesData : register(t0); Texture2D ProbesTrace : register(t1); ByteAddressBuffer ActiveProbes : register(t2); @@ -348,13 +352,15 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_ // Skip disabled probes bool skip = false; - float probeState = LoadDDGIProbeState(DDGI, ProbesState, CascadeIndex, probeIndex); + float4 probeData = LoadDDGIProbeData(DDGI, ProbesData, CascadeIndex, probeIndex); + uint probeState = DecodeDDGIProbeState(probeData); + uint probeRaysCount = GetProbeRaysCount(DDGI, probeState); if (probeState == DDGI_PROBE_STATE_INACTIVE) skip = true; #if DDGI_PROBE_UPDATE_MODE == 0 uint backfacesCount = 0; - uint backfacesLimit = uint(DDGI.RaysCount * 0.1f); + uint backfacesLimit = uint(probeRaysCount * 0.1f); #else float probesSpacing = DDGI.ProbesOriginAndSpacing[CascadeIndex].w; float distanceLimit = length(probesSpacing) * 1.5f; @@ -364,9 +370,9 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_ if (!skip) { // Load trace rays results into shared memory to reuse across whole thread group (raysCount per thread) - uint raysCount = (uint)(ceil((float)DDGI.RaysCount / (float)(DDGI_PROBE_RESOLUTION * DDGI_PROBE_RESOLUTION))); + uint raysCount = (uint)(ceil((float)probeRaysCount / (float)(DDGI_PROBE_RESOLUTION * DDGI_PROBE_RESOLUTION))); uint raysStart = GroupIndex * raysCount; - raysCount = max(min(raysStart + raysCount, DDGI.RaysCount), raysStart) - raysStart; + raysCount = max(min(raysStart + raysCount, probeRaysCount), raysStart) - raysStart; for (uint i = 0; i < raysCount; i++) { uint rayIndex = raysStart + i; @@ -392,7 +398,7 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_ // Loop over rays float4 result = float4(0, 0, 0, 0); LOOP - for (uint rayIndex = 0; rayIndex < DDGI.RaysCount; rayIndex++) + for (uint rayIndex = 0; rayIndex < probeRaysCount; rayIndex++) { float3 rayDirection = CachedProbesTraceDirection[rayIndex]; float rayWeight = max(dot(octahedralDirection, rayDirection), 0.0f); @@ -426,12 +432,12 @@ void CS_UpdateProbes(uint3 GroupThreadId : SV_GroupThreadID, uint3 GroupId : SV_ } // Normalize results - float epsilon = (float)DDGI.RaysCount * 1e-9f; + float epsilon = (float)probeRaysCount * 1e-9f; result.rgb *= 1.0f / (2.0f * max(result.a, epsilon)); // Load current probe value float3 previous = RWOutput[outputCoords].rgb; - bool wasActivated = GetProbeState(probeState, DDGI_PROBE_STATE_ACTIVATED); + bool wasActivated = probeState == DDGI_PROBE_STATE_ACTIVATED; if (ResetBlend || wasActivated) previous = float3(0, 0, 0); @@ -541,7 +547,7 @@ void CS_UpdateBorders(uint3 DispatchThreadId : SV_DispatchThreadID) #include "./Flax/Random.hlsl" #include "./Flax/LightingCommon.hlsl" -Texture2D ProbesState : register(t4); +Texture2D ProbesData : register(t4); Texture2D ProbesDistance : register(t5); Texture2D ProbesIrradiance : register(t6); @@ -565,7 +571,7 @@ void PS_IndirectLighting(Quad_VS2PS input, out float4 output : SV_Target0) // Sample irradiance float bias = 0.2f; float dither = RandN2(input.TexCoord + TemporalTime).x; - float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesState, ProbesDistance, ProbesIrradiance, gBuffer.WorldPos, gBuffer.Normal, bias, dither); + float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesData, ProbesDistance, ProbesIrradiance, gBuffer.WorldPos, gBuffer.Normal, bias, dither); // Calculate lighting float3 diffuseColor = GetDiffuseColor(gBuffer); diff --git a/Source/Shaders/GI/GlobalSurfaceAtlas.shader b/Source/Shaders/GI/GlobalSurfaceAtlas.shader index 70b5ee9dc..95607e4da 100644 --- a/Source/Shaders/GI/GlobalSurfaceAtlas.shader +++ b/Source/Shaders/GI/GlobalSurfaceAtlas.shader @@ -87,7 +87,7 @@ float4 PS_ClearLighting(AtlasVertexOutput input) : SV_Target // GBuffer+Depth at 0-3 slots Buffer GlobalSurfaceAtlasObjects : register(t4); #if INDIRECT_LIGHT -Texture2D ProbesState : register(t5); +Texture2D ProbesData : register(t5); Texture2D ProbesDistance : register(t6); Texture2D ProbesIrradiance : register(t7); #else @@ -134,7 +134,7 @@ float4 PS_Lighting(AtlasVertexOutput input) : SV_Target #if INDIRECT_LIGHT // Sample irradiance - float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesState, ProbesDistance, ProbesIrradiance, gBuffer.WorldPos, gBuffer.Normal); + float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesData, ProbesDistance, ProbesIrradiance, gBuffer.WorldPos, gBuffer.Normal); irradiance *= Light.Radius; // Cached BounceIntensity / IndirectLightingIntensity // Calculate lighting diff --git a/Source/Shaders/VolumetricFog.shader b/Source/Shaders/VolumetricFog.shader index 01756fe56..b24c2beae 100644 --- a/Source/Shaders/VolumetricFog.shader +++ b/Source/Shaders/VolumetricFog.shader @@ -286,7 +286,7 @@ Texture3D LightScatteringHistory : register(t2); Texture3D LocalShadowedLightScattering : register(t3); Texture2DArray ShadowMapCSM : register(t4); #if USE_DDGI -Texture2D ProbesState : register(t5); +Texture2D ProbesData : register(t5); Texture2D ProbesDistance : register(t6); Texture2D ProbesIrradiance : register(t7); #else @@ -337,7 +337,7 @@ void CS_LightScattering(uint3 GroupId : SV_GroupID, uint3 DispatchThreadId : SV_ #if USE_DDGI // Dynamic Diffuse Global Illumination - float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesState, ProbesDistance, ProbesIrradiance, positionWS, cameraVectorNormalized, 0.0f, cellOffset.x); + float3 irradiance = SampleDDGIIrradiance(DDGI, ProbesData, ProbesDistance, ProbesIrradiance, positionWS, cameraVectorNormalized, 0.0f, cellOffset.x); lightScattering += float4(irradiance, 1); #else // Sky light