Add **GPU Memory profiler** to Editor

This commit is contained in:
Wojciech Figat
2022-12-08 16:30:37 +01:00
parent f2c594569d
commit df82a0f5d0
47 changed files with 548 additions and 195 deletions

View File

@@ -1,5 +1,6 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
using System;
using FlaxEngine; using FlaxEngine;
using FlaxEngine.GUI; using FlaxEngine.GUI;
@@ -192,4 +193,74 @@ namespace FlaxEditor.GUI
} }
} }
} }
/// <summary>
/// The table row that contains events for mouse interaction.
/// </summary>
[HideInEditor]
public class ClickableRow : Row
{
private bool _leftClick;
private bool _isRightDown;
/// <summary>
/// The double click event.
/// </summary>
public Action DoubleClick;
/// <summary>
/// The left mouse button click event.
/// </summary>
public Action LeftClick;
/// <summary>
/// The right mouse button click event.
/// </summary>
public Action RightClick;
/// <inheritdoc />
public override bool OnMouseDoubleClick(Float2 location, MouseButton button)
{
DoubleClick?.Invoke();
return base.OnMouseDoubleClick(location, button);
}
/// <inheritdoc />
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);
}
/// <inheritdoc />
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);
}
/// <inheritdoc />
public override void OnMouseLeave()
{
_leftClick = false;
_isRightDown = false;
base.OnMouseLeave();
}
}
} }

View File

@@ -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
{
/// <summary>
/// The GPU Memory profiling mode.
/// </summary>
/// <seealso cref="FlaxEditor.Windows.Profiler.ProfilerMode" />
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<Resource[]> _resources;
private List<ClickableRow> _tableRowsCache;
private string[] _resourceTypesNames;
private Dictionary<string, Guid> _assetPathToId;
private Dictionary<Guid, Resource> _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,
};
}
/// <inheritdoc />
public override void Clear()
{
_memoryUsageChart.Clear();
_resources?.Clear();
_assetPathToId?.Clear();
_resourceCache?.Clear();
}
/// <inheritdoc />
public override void Update(ref SharedUpdateData sharedData)
{
_memoryUsageChart.AddSample(sharedData.Stats.MemoryGPU.Used);
if (_resourceCache == null)
_resourceCache = new Dictionary<Guid, Resource>();
if (_assetPathToId == null)
_assetPathToId = new Dictionary<string, Guid>();
// 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<Resource[]>();
_resources.Add(resources);
}
/// <inheritdoc />
public override void UpdateView(int selectedFrame, bool showOnlyLastUpdateEvents)
{
_memoryUsageChart.SelectedSampleIndex = selectedFrame;
if (_resources == null)
return;
if (_tableRowsCache == null)
_tableRowsCache = new List<ClickableRow>();
if (_resourceTypesNames == null)
_resourceTypesNames = new string[(int)GPUResourceType.MAX]
{
"Render Target",
"Texture",
"Cube Texture",
"Volume Texture",
"Buffer",
"Shader",
"Pipeline State",
"Descriptor",
"Query",
"Sampler",
};
UpdateTable();
}
/// <inheritdoc />
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;
}
}
}
}

View File

@@ -181,6 +181,7 @@ namespace FlaxEditor.Windows.Profiler
AddMode(new Overall()); AddMode(new Overall());
AddMode(new CPU()); AddMode(new CPU());
AddMode(new GPU()); AddMode(new GPU());
AddMode(new MemoryGPU());
AddMode(new Memory()); AddMode(new Memory());
AddMode(new Network()); AddMode(new Network());

View File

@@ -3,7 +3,6 @@
#pragma once #pragma once
#include "Engine/Threading/Task.h" #include "Engine/Threading/Task.h"
#include "Engine/Core/Types/String.h"
class Asset; class Asset;
class LoadingThread; class LoadingThread;
@@ -46,7 +45,6 @@ public:
/// <summary> /// <summary>
/// Gets a task type. /// Gets a task type.
/// </summary> /// </summary>
/// <returns>The type.</returns>
FORCE_INLINE Type GetType() const FORCE_INLINE Type GetType() const
{ {
return _type; return _type;
@@ -68,13 +66,7 @@ protected:
public: public:
// [Task] // [Task]
String ToString() const override String ToString() const override;
{
return String::Format(TEXT("Content Load Task {0} ({1})"),
ToString(GetType()),
::ToString(GetState())
);
}
protected: protected:
// [Task] // [Task]

View File

@@ -211,6 +211,11 @@ void ContentLoadingManagerService::Dispose()
Tasks.CancelAll(); Tasks.CancelAll();
} }
String ContentLoadTask::ToString() const
{
return String::Format(TEXT("Content Load Task {0} ({1})"), ToString(GetType()), (int32)GetState());
}
void ContentLoadTask::Enqueue() void ContentLoadTask::Enqueue()
{ {
Tasks.Add(this); Tasks.Add(this);

View File

@@ -2,8 +2,6 @@
#pragma once #pragma once
#include "Engine/Core/Enums.h"
/// <summary> /// <summary>
/// Build game header flags. /// Build game header flags.
/// </summary> /// </summary>

View File

@@ -4,7 +4,6 @@
#include "Engine/Threading/Task.h" #include "Engine/Threading/Task.h"
#include "Engine/Platform/Platform.h" #include "Engine/Platform/Platform.h"
#include "Engine/Core/Log.h"
#include "GPUTasksContext.h" #include "GPUTasksContext.h"
class GPUResource; class GPUResource;
@@ -89,32 +88,7 @@ public:
/// Executes this task. /// Executes this task.
/// </summary> /// </summary>
/// <param name="context">The context.</param> /// <param name="context">The context.</param>
void Execute(GPUTasksContext* 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;
}
}
/// <summary> /// <summary>
/// Action fired when asynchronous operation has been synchronized with a GPU /// Action fired when asynchronous operation has been synchronized with a GPU
@@ -154,10 +128,7 @@ protected:
public: public:
// [Task] // [Task]
String ToString() const override String ToString() const override;
{
return String::Format(TEXT("GPU Async Task {0} ({1})"), ToString(GetType()), ::ToString(GetState()));
}
protected: protected:
// [Task] // [Task]

View File

@@ -2,6 +2,7 @@
#include "GPUTasksContext.h" #include "GPUTasksContext.h"
#include "GPUTask.h" #include "GPUTask.h"
#include "Engine/Core/Log.h"
#include "Engine/Graphics/GPUDevice.h" #include "Engine/Graphics/GPUDevice.h"
#include "Engine/Threading/Threading.h" #include "Engine/Threading/Threading.h"

View File

@@ -3,8 +3,42 @@
#include "GPUTasksManager.h" #include "GPUTasksManager.h"
#include "GPUTask.h" #include "GPUTask.h"
#include "GPUTasksExecutor.h" #include "GPUTasksExecutor.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Types/String.h"
#include "Engine/Graphics/GPUDevice.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() void GPUTask::Enqueue()
{ {
GPUDevice::Instance->GetTasksManager()->_tasks.Add(this); GPUDevice::Instance->GetTasksManager()->_tasks.Add(this);

View File

@@ -395,14 +395,9 @@ String GPUBuffer::ToString() const
#endif #endif
} }
GPUResource::ResourceType GPUBuffer::GetResourceType() const GPUResourceType GPUBuffer::GetResourceType() const
{ {
return ResourceType::Buffer; return GPUResourceType::Buffer;
}
GPUResource::ObjectType GPUBuffer::GetObjectType() const
{
return ObjectType::Buffer;
} }
void GPUBuffer::OnReleaseGPU() void GPUBuffer::OnReleaseGPU()

View File

@@ -205,8 +205,7 @@ protected:
public: public:
// [GPUResource] // [GPUResource]
String ToString() const override; String ToString() const override;
ResourceType GetResourceType() const final override; GPUResourceType GetResourceType() const final override;
ObjectType GetObjectType() const final override;
protected: protected:
// [GPUResource] // [GPUResource]

View File

@@ -23,6 +23,7 @@
#include "Engine/Engine/EngineService.h" #include "Engine/Engine/EngineService.h"
#include "Engine/Profiler/Profiler.h" #include "Engine/Profiler/Profiler.h"
#include "Engine/Renderer/RenderList.h" #include "Engine/Renderer/RenderList.h"
#include "Engine/Scripting/Enums.h"
GPUPipelineState* GPUPipelineState::Spawn(const SpawnParams& params) GPUPipelineState* GPUPipelineState::Spawn(const SpawnParams& params)
{ {
@@ -79,9 +80,9 @@ bool GPUPipelineState::Init(const Description& desc)
return false; return false;
} }
GPUResource::ResourceType GPUPipelineState::GetResourceType() const GPUResourceType GPUPipelineState::GetResourceType() const
{ {
return ResourceType::PipelineState; return GPUResourceType::PipelineState;
} }
GPUPipelineState::Description GPUPipelineState::Description::Default = GPUPipelineState::Description GPUPipelineState::Description::Default =
@@ -193,16 +194,13 @@ GPUResource::~GPUResource()
#endif #endif
} }
GPUResource::ObjectType GPUResource::GetObjectType() const
{
return ObjectType::Other;
}
uint64 GPUResource::GetMemoryUsage() const uint64 GPUResource::GetMemoryUsage() const
{ {
return _memoryUsage; 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 #if GPU_ENABLE_RESOURCE_NAMING
String GPUResource::GetName() const String GPUResource::GetName() const
@@ -394,11 +392,11 @@ void GPUDevice::DumpResourcesToLog() const
output.AppendLine(); output.AppendLine();
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<GPUResource::ResourceType>(typeIndex); const auto type = static_cast<GPUResourceType>(typeIndex);
output.AppendFormat(TEXT("Group: {0}s"), GPUResource::ToString(type)); output.AppendFormat(TEXT("Group: {0}s"), ScriptingEnum::ToString(type));
output.AppendLine(); output.AppendLine();
int32 count = 0; int32 count = 0;

View File

@@ -4,7 +4,6 @@
#include "Engine/Platform/Platform.h" #include "Engine/Platform/Platform.h"
#include "Engine/Platform/CriticalSection.h" #include "Engine/Platform/CriticalSection.h"
#include "Engine/Core/Enums.h"
#include "Engine/Core/NonCopyable.h" #include "Engine/Core/NonCopyable.h"
#include "Engine/Core/Collections/Array.h" #include "Engine/Core/Collections/Array.h"
#include "Engine/Scripting/ScriptingObject.h" #include "Engine/Scripting/ScriptingObject.h"
@@ -43,7 +42,15 @@ public:
/// <summary> /// <summary>
/// Graphics Device states that describe its lifetime. /// Graphics Device states that describe its lifetime.
/// </summary> /// </summary>
DECLARE_ENUM_6(DeviceState, Missing, Created, Ready, Removed, Disposing, Disposed); enum class DeviceState
{
Missing = 0,
Created,
Ready,
Removed,
Disposing,
Disposed
};
/// <summary> /// <summary>
/// Describes a video output display mode. /// Describes a video output display mode.

View File

@@ -160,5 +160,5 @@ public:
public: public:
// [GPUResource] // [GPUResource]
ResourceType GetResourceType() const final override; GPUResourceType GetResourceType() const final override;
}; };

View File

@@ -2,7 +2,6 @@
#pragma once #pragma once
#include "Engine/Core/Enums.h"
#include "Engine/Scripting/ScriptingObject.h" #include "Engine/Scripting/ScriptingObject.h"
#include "Config.h" #include "Config.h"
@@ -12,23 +11,41 @@
#define SAFE_DELETE_GPU_RESOURCE(x) if (x) { (x)->DeleteObjectNow(); (x) = nullptr; } #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; } #define SAFE_DELETE_GPU_RESOURCES(x) for (auto& e : (x)) if (e) { e->DeleteObjectNow(); e = nullptr; }
/// <summary>
/// GPU resources types.
/// </summary>
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
};
/// <summary> /// <summary>
/// The base class for all GPU resources. /// The base class for all GPU resources.
/// </summary> /// </summary>
API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API GPUResource : public ScriptingObject API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API GPUResource : public ScriptingObject
{ {
DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUResource); DECLARE_SCRIPTING_TYPE_NO_SPAWN(GPUResource);
public:
/// <summary>
/// GPU Resources types.
/// </summary>
DECLARE_ENUM_10(ResourceType, RenderTarget, Texture, CubeTexture, VolumeTexture, Buffer, Shader, PipelineState, Descriptor, Query, Sampler);
/// <summary>
/// GPU Resources object types. Used to detect Texture objects from subset of Types: RenderTarget, Texture, CubeTexture, VolumeTexture which use the same API object.
/// </summary>
DECLARE_ENUM_3(ObjectType, Texture, Buffer, Other);
protected: protected:
uint64 _memoryUsage = 0; uint64 _memoryUsage = 0;
#if GPU_ENABLE_RESOURCE_NAMING #if GPU_ENABLE_RESOURCE_NAMING
@@ -65,21 +82,16 @@ public:
public: public:
/// <summary> /// <summary>
/// Gets the resource type. /// Gets the GPU resource type.
/// </summary> /// </summary>
virtual ResourceType GetResourceType() const = 0; API_PROPERTY() virtual GPUResourceType GetResourceType() const = 0;
/// <summary>
/// Gets resource object type.
/// </summary>
virtual ObjectType GetObjectType() const;
/// <summary> /// <summary>
/// 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). /// 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).
/// </summary> /// </summary>
API_PROPERTY() uint64 GetMemoryUsage() const; API_PROPERTY() uint64 GetMemoryUsage() const;
#if GPU_ENABLE_RESOURCE_NAMING #if !BUILD_RELEASE
/// <summary> /// <summary>
/// Gets the resource name. /// Gets the resource name.
/// </summary> /// </summary>

View File

@@ -95,7 +95,7 @@ String GPUSwapChain::ToString() const
#endif #endif
} }
GPUResource::ResourceType GPUSwapChain::GetResourceType() const GPUResourceType GPUSwapChain::GetResourceType() const
{ {
return ResourceType::Texture; return GPUResourceType::Texture;
} }

View File

@@ -160,5 +160,5 @@ public:
public: public:
// [GPUResource] // [GPUResource]
String ToString() const override; String ToString() const override;
ResourceType GetResourceType() const final override; GPUResourceType GetResourceType() const final override;
}; };

View File

@@ -48,14 +48,8 @@ public:
{ {
return TEXT("TimerQuery"); return TEXT("TimerQuery");
} }
GPUResourceType GetResourceType() const final override
ResourceType GetResourceType() const final override
{ {
return ResourceType::Query; return GPUResourceType::Query;
}
ObjectType GetObjectType() const final override
{
return ObjectType::Other;
} }
}; };

View File

@@ -251,7 +251,7 @@ bool Mesh::Load(uint32 vertices, uint32 triangles, void* vb0, void* vb1, void* v
// Create GPU buffers // Create GPU buffers
#if GPU_ENABLE_RESOURCE_NAMING #if GPU_ENABLE_RESOURCE_NAMING
#define MESH_BUFFER_NAME(postfix) GetModel()->ToString() + TEXT(postfix) #define MESH_BUFFER_NAME(postfix) GetModel()->GetPath() + TEXT(postfix)
#else #else
#define MESH_BUFFER_NAME(postfix) String::Empty #define MESH_BUFFER_NAME(postfix) String::Empty
#endif #endif

View File

@@ -2,7 +2,6 @@
#pragma once #pragma once
#include "Engine/Core/Enums.h"
#include "Engine/Core/Math/Packed.h" #include "Engine/Core/Math/Packed.h"
#include "Engine/Core/Math/Vector2.h" #include "Engine/Core/Math/Vector2.h"
#include "Engine/Core/Math/Vector3.h" #include "Engine/Core/Math/Vector3.h"
@@ -23,7 +22,15 @@ struct RenderView;
/// <summary> /// <summary>
/// Importing model lightmap UVs source /// Importing model lightmap UVs source
/// </summary> /// </summary>
DECLARE_ENUM_6(ModelLightmapUVsSource, Disable, Generate, Channel0, Channel1, Channel2, Channel3); enum class ModelLightmapUVsSource
{
Disable = 0,
Generate,
Channel0,
Channel1,
Channel2,
Channel3
};
/// <summary> /// <summary>
/// The mesh buffer types. /// The mesh buffer types.

View File

@@ -3,7 +3,6 @@
#pragma once #pragma once
#include "Engine/Core/Types/BaseTypes.h" #include "Engine/Core/Types/BaseTypes.h"
#include "Engine/Core/Enums.h"
#include "Engine/Graphics/Config.h" #include "Engine/Graphics/Config.h"
#include "Engine/Graphics/Materials/MaterialInfo.h" #include "Engine/Graphics/Materials/MaterialInfo.h"
#include "../Config.h" #include "../Config.h"
@@ -31,7 +30,12 @@ public:
/// <summary> /// <summary>
/// Different shader cache storage modes (disabled, inside asset and in project cache) /// Different shader cache storage modes (disabled, inside asset and in project cache)
/// </summary> /// </summary>
DECLARE_ENUM_3(CachingMode, Disabled, AssetInternal, ProjectCache); enum class CachingMode
{
Disabled = 0,
AssetInternal,
ProjectCache
};
/// <summary> /// <summary>
/// Current shaders caching mode to use /// Current shaders caching mode to use

View File

@@ -23,8 +23,8 @@ public:
public: public:
// [GPUResource] // [GPUResource]
ResourceType GetResourceType() const override GPUResourceType GetResourceType() const override
{ {
return ResourceType::Buffer; return GPUResourceType::Buffer;
} }
}; };

View File

@@ -190,9 +190,9 @@ GPUShaderProgram* GPUShader::GetShader(ShaderStage stage, const StringAnsiView&
return shader; return shader;
} }
GPUResource::ResourceType GPUShader::GetResourceType() const GPUResourceType GPUShader::GetResourceType() const
{ {
return ResourceType::Shader; return GPUResourceType::Shader;
} }
void GPUShader::OnReleaseGPU() void GPUShader::OnReleaseGPU()

View File

@@ -182,7 +182,7 @@ protected:
public: public:
// [GPUResource] // [GPUResource]
ResourceType GetResourceType() const final override; GPUResourceType GetResourceType() const final override;
protected: protected:
// [GPUResource] // [GPUResource]

View File

@@ -101,14 +101,9 @@ String GPUSampler::ToString() const
#endif #endif
} }
GPUResource::ResourceType GPUSampler::GetResourceType() const GPUResourceType GPUSampler::GetResourceType() const
{ {
return ResourceType::Sampler; return GPUResourceType::Sampler;
}
GPUResource::ObjectType GPUSampler::GetObjectType() const
{
return ObjectType::Other;
} }
void GPUSampler::OnReleaseGPU() void GPUSampler::OnReleaseGPU()

View File

@@ -43,8 +43,7 @@ protected:
public: public:
// [GPUResource] // [GPUResource]
String ToString() const override; String ToString() const override;
ResourceType GetResourceType() const final override; GPUResourceType GetResourceType() const final override;
ObjectType GetObjectType() const final override;
protected: protected:
// [GPUResource] // [GPUResource]

View File

@@ -575,18 +575,13 @@ String GPUTexture::ToString() const
#endif #endif
} }
GPUResource::ResourceType GPUTexture::GetResourceType() const GPUResourceType GPUTexture::GetResourceType() const
{ {
if (IsVolume()) if (IsVolume())
return ResourceType::VolumeTexture; return GPUResourceType::VolumeTexture;
if (IsCubeMap()) if (IsCubeMap())
return ResourceType::CubeTexture; return GPUResourceType::CubeTexture;
return IsRegularTexture() ? ResourceType::Texture : ResourceType::RenderTarget; return IsRegularTexture() ? GPUResourceType::Texture : GPUResourceType::RenderTarget;
}
GPUResource::ObjectType GPUTexture::GetObjectType() const
{
return ObjectType::Texture;
} }
void GPUTexture::OnReleaseGPU() void GPUTexture::OnReleaseGPU()

View File

@@ -573,8 +573,7 @@ protected:
public: public:
// [GPUResource] // [GPUResource]
String ToString() const override; String ToString() const override;
ResourceType GetResourceType() const final override; GPUResourceType GetResourceType() const final override;
ObjectType GetObjectType() const final override;
protected: protected:
// [GPUResource] // [GPUResource]

View File

@@ -1,6 +1,7 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
#include "StreamingTexture.h" #include "StreamingTexture.h"
#include "Engine/Core/Log.h"
#include "Engine/Threading/Threading.h" #include "Engine/Threading/Threading.h"
#include "Engine/Streaming/StreamingGroup.h" #include "Engine/Streaming/StreamingGroup.h"
#include "Engine/Content/Loading/ContentLoadingManager.h" #include "Engine/Content/Loading/ContentLoadingManager.h"

View File

@@ -190,9 +190,9 @@ public:
public: public:
// [GPUResourceDX12] // [GPUResourceDX12]
ResourceType GetResourceType() const override GPUResourceType GetResourceType() const override
{ {
return ResourceType::Descriptor; return GPUResourceType::Descriptor;
} }
protected: protected:

View File

@@ -128,9 +128,9 @@ void DescriptorHeapWithSlotsDX12::ReleaseSlot(uint32 index)
value &= ~mask; 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) DescriptorHeapPoolDX12::DescriptorHeapPoolDX12(GPUDeviceDX12* device, D3D12_DESCRIPTOR_HEAP_TYPE type, uint32 descriptorsCountPerHeap, bool shaderVisible)

View File

@@ -87,7 +87,7 @@ public:
public: public:
// [GPUResourceDX12] // [GPUResourceDX12]
ResourceType GetResourceType() const final override; GPUResourceType GetResourceType() const final override;
protected: protected:
@@ -170,9 +170,9 @@ public:
public: public:
// [GPUResourceDX12] // [GPUResourceDX12]
ResourceType GetResourceType() const final override GPUResourceType GetResourceType() const final override
{ {
return ResourceType::Descriptor; return GPUResourceType::Descriptor;
} }
protected: protected:

View File

@@ -1299,25 +1299,23 @@ void GPUContextDX12::CopyResource(GPUResource* dstResource, GPUResource* srcReso
auto dstResourceDX12 = dynamic_cast<ResourceOwnerDX12*>(dstResource); auto dstResourceDX12 = dynamic_cast<ResourceOwnerDX12*>(dstResource);
auto srcResourceDX12 = dynamic_cast<ResourceOwnerDX12*>(srcResource); auto srcResourceDX12 = dynamic_cast<ResourceOwnerDX12*>(srcResource);
auto dstBufferDX12 = dynamic_cast<GPUBufferDX12*>(dstResource);
auto srcBufferDX12 = dynamic_cast<GPUBufferDX12*>(srcResource);
auto dstTextureDX12 = dynamic_cast<GPUTextureDX12*>(dstResource);
auto srcTextureDX12 = dynamic_cast<GPUTextureDX12*>(srcResource);
SetResourceState(dstResourceDX12, D3D12_RESOURCE_STATE_COPY_DEST); SetResourceState(dstResourceDX12, D3D12_RESOURCE_STATE_COPY_DEST);
SetResourceState(srcResourceDX12, D3D12_RESOURCE_STATE_COPY_SOURCE); SetResourceState(srcResourceDX12, D3D12_RESOURCE_STATE_COPY_SOURCE);
flushRBs(); flushRBs();
auto srcType = srcResource->GetObjectType();
auto dstType = dstResource->GetObjectType();
// Buffer -> Buffer // Buffer -> Buffer
if (srcType == GPUResource::ObjectType::Buffer && dstType == GPUResource::ObjectType::Buffer) if (srcBufferDX12 && dstBufferDX12)
{ {
_commandList->CopyResource(dstResourceDX12->GetResource(), srcResourceDX12->GetResource()); _commandList->CopyResource(dstResourceDX12->GetResource(), srcResourceDX12->GetResource());
} }
// Texture -> Texture // Texture -> Texture
else if (srcType == GPUResource::ObjectType::Texture && dstType == GPUResource::ObjectType::Texture) else if (srcTextureDX12 && dstTextureDX12)
{ {
auto dstTextureDX12 = static_cast<GPUTextureDX12*>(dstResource);
auto srcTextureDX12 = static_cast<GPUTextureDX12*>(srcResource);
if (dstTextureDX12->IsStaging()) if (dstTextureDX12->IsStaging())
{ {
// Staging Texture -> Staging Texture // Staging Texture -> Staging Texture
@@ -1388,32 +1386,26 @@ void GPUContextDX12::CopySubresource(GPUResource* dstResource, uint32 dstSubreso
{ {
ASSERT(dstResource && srcResource); ASSERT(dstResource && srcResource);
auto srcType = srcResource->GetObjectType(); auto dstResourceDX12 = dynamic_cast<ResourceOwnerDX12*>(dstResource);
auto dstType = dstResource->GetObjectType(); auto srcResourceDX12 = dynamic_cast<ResourceOwnerDX12*>(srcResource);
auto dstBufferDX12 = dynamic_cast<GPUBufferDX12*>(dstResource);
auto srcBufferDX12 = dynamic_cast<GPUBufferDX12*>(srcResource);
auto dstTextureDX12 = dynamic_cast<GPUTextureDX12*>(dstResource);
auto srcTextureDX12 = dynamic_cast<GPUTextureDX12*>(srcResource);
// Buffer -> Buffer SetResourceState(dstResourceDX12, D3D12_RESOURCE_STATE_COPY_DEST);
if (srcType == GPUResource::ObjectType::Buffer && dstType == GPUResource::ObjectType::Buffer) SetResourceState(srcResourceDX12, D3D12_RESOURCE_STATE_COPY_SOURCE);
{
auto dstBufferDX12 = dynamic_cast<ResourceOwnerDX12*>(dstResource);
auto srcBufferDX12 = dynamic_cast<ResourceOwnerDX12*>(srcResource);
SetResourceState(dstBufferDX12, D3D12_RESOURCE_STATE_COPY_DEST);
SetResourceState(srcBufferDX12, D3D12_RESOURCE_STATE_COPY_SOURCE);
flushRBs(); flushRBs();
// Buffer -> Buffer
if (srcBufferDX12 && dstBufferDX12)
{
uint64 bytesCount = srcResource->GetMemoryUsage(); uint64 bytesCount = srcResource->GetMemoryUsage();
_commandList->CopyBufferRegion(dstBufferDX12->GetResource(), 0, srcBufferDX12->GetResource(), 0, bytesCount); _commandList->CopyBufferRegion(dstBufferDX12->GetResource(), 0, srcBufferDX12->GetResource(), 0, bytesCount);
} }
// Texture -> Texture // Texture -> Texture
else if (srcType == GPUResource::ObjectType::Texture && dstType == GPUResource::ObjectType::Texture) else if (srcTextureDX12 && dstTextureDX12)
{ {
auto dstTextureDX12 = static_cast<GPUTextureDX12*>(dstResource);
auto srcTextureDX12 = static_cast<GPUTextureDX12*>(srcResource);
SetResourceState(dstTextureDX12, D3D12_RESOURCE_STATE_COPY_DEST);
SetResourceState(srcTextureDX12, D3D12_RESOURCE_STATE_COPY_SOURCE);
flushRBs();
if (srcTextureDX12->IsStaging() || dstTextureDX12->IsStaging()) if (srcTextureDX12->IsStaging() || dstTextureDX12->IsStaging())
{ {
Log::NotImplementedException(TEXT("Copy region of staging resources is not supported yet.")); Log::NotImplementedException(TEXT("Copy region of staging resources is not supported yet."));

View File

@@ -56,9 +56,9 @@ public:
public: public:
// [GPUResourceDX12] // [GPUResourceDX12]
ResourceType GetResourceType() const final override GPUResourceType GetResourceType() const final override
{ {
return ResourceType::Buffer; return GPUResourceType::Buffer;
} }
// [ResourceOwnerDX12] // [ResourceOwnerDX12]

View File

@@ -87,7 +87,7 @@ namespace DescriptorSet
return ShaderStage::Geometry; return ShaderStage::Geometry;
default: default:
CRASH; CRASH;
return static_cast<ShaderStage>(ShaderStage_Count); return (ShaderStage)ShaderStage_Count;
} }
} }

View File

@@ -5,6 +5,7 @@
#include "GPUBufferVulkan.h" #include "GPUBufferVulkan.h"
#include "GPUContextVulkan.h" #include "GPUContextVulkan.h"
#include "RenderToolsVulkan.h" #include "RenderToolsVulkan.h"
#include "Engine/Core/Log.h"
#include "Engine/Threading/Threading.h" #include "Engine/Threading/Threading.h"
#include "Engine/Graphics/Async/Tasks/GPUUploadBufferTask.h" #include "Engine/Graphics/Async/Tasks/GPUUploadBufferTask.h"

View File

@@ -1493,17 +1493,13 @@ void GPUContextVulkan::CopyResource(GPUResource* dstResource, GPUResource* srcRe
if (cmdBuffer->IsInsideRenderPass()) if (cmdBuffer->IsInsideRenderPass())
EndRenderPass(); EndRenderPass();
auto dstTextureVulkan = static_cast<GPUTextureVulkan*>(dstResource); auto dstTextureVulkan = dynamic_cast<GPUTextureVulkan*>(dstResource);
auto srcTextureVulkan = static_cast<GPUTextureVulkan*>(srcResource); auto srcTextureVulkan = dynamic_cast<GPUTextureVulkan*>(srcResource);
auto dstBufferVulkan = dynamic_cast<GPUBufferVulkan*>(dstResource);
auto dstBufferVulkan = static_cast<GPUBufferVulkan*>(dstResource); auto srcBufferVulkan = dynamic_cast<GPUBufferVulkan*>(srcResource);
auto srcBufferVulkan = static_cast<GPUBufferVulkan*>(srcResource);
const auto srcType = srcResource->GetObjectType();
const auto dstType = dstResource->GetObjectType();
// Buffer -> Buffer // Buffer -> Buffer
if (srcType == GPUResource::ObjectType::Buffer && dstType == GPUResource::ObjectType::Buffer) if (srcBufferVulkan && dstBufferVulkan)
{ {
// Transition resources // Transition resources
AddBufferBarrier(dstBufferVulkan, VK_ACCESS_TRANSFER_WRITE_BIT); 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); vkCmdCopyBuffer(cmdBuffer->GetHandle(), srcBufferVulkan->GetHandle(), dstBufferVulkan->GetHandle(), 1, &bufferCopy);
} }
// Texture -> Texture // Texture -> Texture
else if (srcType == GPUResource::ObjectType::Texture && dstType == GPUResource::ObjectType::Texture) else if (srcTextureVulkan && dstTextureVulkan)
{ {
if (dstTextureVulkan->IsStaging()) if (dstTextureVulkan->IsStaging())
{ {
@@ -1632,17 +1628,13 @@ void GPUContextVulkan::CopySubresource(GPUResource* dstResource, uint32 dstSubre
if (cmdBuffer->IsInsideRenderPass()) if (cmdBuffer->IsInsideRenderPass())
EndRenderPass(); EndRenderPass();
auto dstTextureVulkan = static_cast<GPUTextureVulkan*>(dstResource); auto dstTextureVulkan = dynamic_cast<GPUTextureVulkan*>(dstResource);
auto srcTextureVulkan = static_cast<GPUTextureVulkan*>(srcResource); auto srcTextureVulkan = dynamic_cast<GPUTextureVulkan*>(srcResource);
auto dstBufferVulkan = dynamic_cast<GPUBufferVulkan*>(dstResource);
auto dstBufferVulkan = static_cast<GPUBufferVulkan*>(dstResource); auto srcBufferVulkan = dynamic_cast<GPUBufferVulkan*>(srcResource);
auto srcBufferVulkan = static_cast<GPUBufferVulkan*>(srcResource);
auto srcType = srcResource->GetObjectType();
auto dstType = dstResource->GetObjectType();
// Buffer -> Buffer // Buffer -> Buffer
if (srcType == GPUResource::ObjectType::Buffer && dstType == GPUResource::ObjectType::Buffer) if (srcBufferVulkan && dstBufferVulkan)
{ {
ASSERT(dstSubresource == 0 && srcSubresource == 0); 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); vkCmdCopyBuffer(cmdBuffer->GetHandle(), srcBufferVulkan->GetHandle(), dstBufferVulkan->GetHandle(), 1, &bufferCopy);
} }
// Texture -> Texture // Texture -> Texture
else if (srcType == GPUResource::ObjectType::Texture && dstType == GPUResource::ObjectType::Texture) else if (srcTextureVulkan && dstTextureVulkan)
{ {
const int32 dstMipMaps = dstTextureVulkan->MipLevels(); const int32 dstMipMaps = dstTextureVulkan->MipLevels();
const int32 dstMipIndex = dstSubresource % dstMipMaps; const int32 dstMipIndex = dstSubresource % dstMipMaps;

View File

@@ -67,9 +67,9 @@ public:
public: public:
// [GPUResourceVulkan] // [GPUResourceVulkan]
ResourceType GetResourceType() const final override GPUResourceType GetResourceType() const final override
{ {
return ResourceType::Buffer; return GPUResourceType::Buffer;
} }
// [ResourceOwnerVulkan] // [ResourceOwnerVulkan]

View File

@@ -3,7 +3,7 @@
#pragma once #pragma once
#include "Engine/Core/Config.h" #include "Engine/Core/Config.h"
#include "Engine/Core/Enums.h" #include "Engine/Core/Types/BaseTypes.h"
// Level system types // Level system types
class SceneObject; class SceneObject;

View File

@@ -2,7 +2,6 @@
#pragma once #pragma once
#include "Engine/Core/Enums.h"
#include "Engine/Core/Config.h" #include "Engine/Core/Config.h"
#include "Engine/Core/Math/Vector2.h" #include "Engine/Core/Math/Vector2.h"
#include "Engine/Core/Math/Vector3.h" #include "Engine/Core/Math/Vector3.h"

View File

@@ -119,9 +119,8 @@ public:
public: public:
/// <summary> /// <summary>
/// Gets shader function meta stage type /// Gets shader function meta stage type.
/// </summary> /// </summary>
/// <returns>Shader Stage type</returns>
virtual ShaderStage GetStage() const = 0; virtual ShaderStage GetStage() const = 0;
}; };

View File

@@ -3,6 +3,7 @@
#include "TerrainPatch.h" #include "TerrainPatch.h"
#include "Terrain.h" #include "Terrain.h"
#include "Engine/Serialization/Serialization.h" #include "Engine/Serialization/Serialization.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Math/Color32.h" #include "Engine/Core/Math/Color32.h"
#include "Engine/Profiler/ProfilerCPU.h" #include "Engine/Profiler/ProfilerCPU.h"
#include "Engine/Physics/Physics.h" #include "Engine/Physics/Physics.h"

View File

@@ -35,7 +35,7 @@ void MainThreadTask::RunAll(float dt)
String MainThreadTask::ToString() const 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() void MainThreadTask::Enqueue()

View File

@@ -13,7 +13,15 @@
/// <summary> /// <summary>
/// Represents the current stage in the lifecycle of a Task. /// Represents the current stage in the lifecycle of a Task.
/// </summary> /// </summary>
DECLARE_ENUM_EX_6(TaskState, int64, 0, Created, Failed, Canceled, Queued, Running, Finished); enum class TaskState : int64
{
Created = 0,
Failed,
Canceled,
Queued,
Running,
Finished
};
/// <summary> /// <summary>
/// Represents an asynchronous operation. /// Represents an asynchronous operation.

View File

@@ -7,6 +7,7 @@
#include "ConcurrentTaskQueue.h" #include "ConcurrentTaskQueue.h"
#include "Engine/Core/Log.h" #include "Engine/Core/Log.h"
#include "Engine/Core/Math/Math.h" #include "Engine/Core/Math/Math.h"
#include "Engine/Core/Types/String.h"
#include "Engine/Engine/Globals.h" #include "Engine/Engine/Globals.h"
#include "Engine/Engine/EngineService.h" #include "Engine/Engine/EngineService.h"
#include "Engine/Platform/ConditionVariable.h" #include "Engine/Platform/ConditionVariable.h"
@@ -27,6 +28,11 @@ namespace ThreadPoolImpl
CriticalSection JobsMutex; CriticalSection JobsMutex;
} }
String ThreadPoolTask::ToString() const
{
return String::Format(TEXT("Thread Pool Task ({0})"), (int32)GetState());
}
void ThreadPoolTask::Enqueue() void ThreadPoolTask::Enqueue()
{ {
ThreadPoolImpl::Jobs.Add(this); ThreadPoolImpl::Jobs.Add(this);

View File

@@ -3,7 +3,6 @@
#pragma once #pragma once
#include "Task.h" #include "Task.h"
#include "Engine/Core/Types/String.h"
class ThreadPool; class ThreadPool;
@@ -28,10 +27,7 @@ protected:
public: public:
// [Task] // [Task]
String ToString() const override String ToString() const override;
{
return String::Format(TEXT("Thread Pool Task ({0})"), ::ToString(GetState()));
}
protected: protected:

View File

@@ -1,6 +1,7 @@
// Copyright (c) 2012-2022 Wojciech Figat. All rights reserved. // Copyright (c) 2012-2022 Wojciech Figat. All rights reserved.
#include "Screenshot.h" #include "Screenshot.h"
#include "Engine/Core/Log.h"
#include "Engine/Core/Math/Math.h" #include "Engine/Core/Math/Math.h"
#include "Engine/Graphics/RenderTask.h" #include "Engine/Graphics/RenderTask.h"
#include "Engine/Platform/FileSystem.h" #include "Engine/Platform/FileSystem.h"