Merge branch 'development' of https://github.com/aws-lumberyard-dev/o3de into mnaumov/2372_signOffFix

Signed-off-by: Mikhail Naumov <mnaumov@amazon.com>
This commit is contained in:
Mikhail Naumov
2021-08-17 14:14:56 -07:00
9 changed files with 271 additions and 136 deletions
@@ -219,42 +219,10 @@ namespace AzToolsFramework
bool PrefabEditorEntityOwnershipService::SaveToStream(AZ::IO::GenericStream& stream, AZStd::string_view filename)
{
AZ::IO::Path relativePath = m_loaderInterface->GenerateRelativePath(filename);
AzToolsFramework::Prefab::TemplateId templateId = m_prefabSystemComponent->GetTemplateIdFromFilePath(relativePath);
m_rootInstance->SetTemplateSourcePath(relativePath);
if (templateId == AzToolsFramework::Prefab::InvalidTemplateId)
{
m_rootInstance->m_containerEntity->AddComponent(aznew Prefab::EditorPrefabComponent());
HandleEntitiesAdded({ m_rootInstance->m_containerEntity.get() });
AzToolsFramework::Prefab::PrefabDom dom;
bool success = AzToolsFramework::Prefab::PrefabDomUtils::StoreInstanceInPrefabDom(*m_rootInstance, dom);
if (!success)
{
AZ_Error("Prefab", false, "Failed to convert current root instance into a DOM when saving file '%.*s'", AZ_STRING_ARG(filename));
return false;
}
templateId = m_prefabSystemComponent->AddTemplate(relativePath, AZStd::move(dom));
if (templateId == AzToolsFramework::Prefab::InvalidTemplateId)
{
AZ_Error("Prefab", false, "Couldn't add new template id '%i' when saving file '%.*s'", templateId, AZ_STRING_ARG(filename));
return false;
}
}
Prefab::TemplateId prevTemplateId = m_rootInstance->GetTemplateId();
m_rootInstance->SetTemplateId(templateId);
if (prevTemplateId != Prefab::InvalidTemplateId && templateId != prevTemplateId)
{
// Make sure we only have one level template loaded at a time
m_prefabSystemComponent->RemoveTemplate(prevTemplateId);
}
AZStd::string out;
if (!m_loaderInterface->SaveTemplateToString(m_rootInstance->GetTemplateId(), out))
{
return false;
@@ -266,7 +234,7 @@ namespace AzToolsFramework
{
return false;
}
m_prefabSystemComponent->SetTemplateDirtyFlag(templateId, false);
m_prefabSystemComponent->SetTemplateDirtyFlag(m_rootInstance->GetTemplateId(), false);
return true;
}
@@ -9,6 +9,7 @@
#include "ProfilingCaptureSystemComponent.h"
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/CpuProfilerImpl.h>
#include <Atom/RHI/RHIUtils.h>
#include <Atom/RHI/RHISystemInterface.h>
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
@@ -141,36 +142,6 @@ namespace AZ
AZStd::vector<PipelineStatisticsSerializerEntry> m_pipelineStatisticsEntries;
};
// Intermediate class to serialize Cpu TimedRegion data.
class CpuProfilingStatisticsSerializer
{
public:
class CpuProfilingStatisticsSerializerEntry
{
public:
AZ_TYPE_INFO(CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry, "{26B78F65-EB96-46E2-BE7E-A1233880B225}");
static void Reflect(AZ::ReflectContext* context);
CpuProfilingStatisticsSerializerEntry() = default;
CpuProfilingStatisticsSerializerEntry(const RHI::CachedTimeRegion& cachedTimeRegion);
private:
Name m_groupName;
Name m_regionName;
uint16_t m_stackDepth;
AZStd::sys_time_t m_startTick;
AZStd::sys_time_t m_endTick;
};
AZ_TYPE_INFO(CpuProfilingStatisticsSerializer, "{D5B02946-0D27-474F-9A44-364C2706DD41}");
static void Reflect(AZ::ReflectContext* context);
CpuProfilingStatisticsSerializer() = default;
CpuProfilingStatisticsSerializer(const AZStd::ring_buffer<RHI::CpuProfiler::TimeRegionMap>& continuousData);
AZStd::vector<CpuProfilingStatisticsSerializerEntry> m_cpuProfilingStatisticsSerializerEntries;
};
// Intermediate class to serialize benchmark metadata.
class BenchmarkMetadataSerializer
{
@@ -327,65 +298,6 @@ namespace AZ
}
}
// --- CpuProfilingStatisticsSerializer ---
CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializer(const AZStd::ring_buffer<RHI::CpuProfiler::TimeRegionMap>& continuousData)
{
// Create serializable entries
for (const auto& timeRegionMap : continuousData)
{
for (const auto& threadEntry : timeRegionMap)
{
for (const auto& cachedRegionEntry : threadEntry.second)
{
m_cpuProfilingStatisticsSerializerEntries.insert(
m_cpuProfilingStatisticsSerializerEntries.end(),
cachedRegionEntry.second.begin(),
cachedRegionEntry.second.end());
}
}
}
}
void CpuProfilingStatisticsSerializer::Reflect(AZ::ReflectContext* context)
{
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<CpuProfilingStatisticsSerializer>()
->Version(1)
->Field("cpuProfilingStatisticsSerializerEntry", &CpuProfilingStatisticsSerializer::m_cpuProfilingStatisticsSerializerEntries)
;
}
CpuProfilingStatisticsSerializerEntry::Reflect(context);
}
// --- CpuProfilingStatisticsSerializerEntry ---
CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::CpuProfilingStatisticsSerializerEntry(const RHI::CachedTimeRegion& cachedTimeRegion)
{
m_groupName = cachedTimeRegion.m_groupRegionName->m_groupName;
m_regionName = cachedTimeRegion.m_groupRegionName->m_regionName;
m_stackDepth = cachedTimeRegion.m_stackDepth;
m_startTick = cachedTimeRegion.m_startTick;
m_endTick = cachedTimeRegion.m_endTick;
}
void CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::Reflect(AZ::ReflectContext* context)
{
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<CpuProfilingStatisticsSerializerEntry>()
->Version(1)
->Field("groupName", &CpuProfilingStatisticsSerializerEntry::m_groupName)
->Field("regionName", &CpuProfilingStatisticsSerializerEntry::m_regionName)
->Field("stackDepth", &CpuProfilingStatisticsSerializerEntry::m_stackDepth)
->Field("startTick", &CpuProfilingStatisticsSerializerEntry::m_startTick)
->Field("endTick", &CpuProfilingStatisticsSerializerEntry::m_endTick)
;
}
}
// --- BenchmarkMetadataSerializer ---
BenchmarkMetadataSerializer::BenchmarkMetadataSerializer(const AZStd::string& benchmarkName, const RHI::PhysicalDeviceDescriptor& gpuDescriptor)
@@ -458,7 +370,7 @@ namespace AZ
TimestampSerializer::Reflect(context);
CpuFrameTimeSerializer::Reflect(context);
PipelineStatisticsSerializer::Reflect(context);
CpuProfilingStatisticsSerializer::Reflect(context);
RHI::CpuProfilingStatisticsSerializer::Reflect(context);
BenchmarkMetadataSerializer::Reflect(context);
}
@@ -651,10 +563,10 @@ namespace AZ
JsonSerializerSettings serializationSettings;
serializationSettings.m_keepDefaults = true;
CpuProfilingStatisticsSerializer serializer(data);
RHI::CpuProfilingStatisticsSerializer serializer(data);
const auto saveResult = JsonSerializationUtils::SaveObjectToFile(&serializer,
outputFilePath, (CpuProfilingStatisticsSerializer*)nullptr, &serializationSettings);
outputFilePath, (RHI::CpuProfilingStatisticsSerializer*)nullptr, &serializationSettings);
AZStd::string captureInfo = outputFilePath;
if (!saveResult.IsSuccess())
@@ -694,7 +606,7 @@ namespace AZ
const bool captureStarted = m_cpuProfilingStatisticsCapture.StartCapture([this, outputFilePath, wasEnabled]()
{
// Blocking call for a single frame of data, avoid thread overhead
AZStd::ring_buffer<RHI::CpuProfiler::TimeRegionMap> singleFrameData;
AZStd::ring_buffer<RHI::CpuProfiler::TimeRegionMap> singleFrameData(1);
singleFrameData.push_back(RHI::CpuProfiler::Get()->GetTimeRegionMap());
SerializeCpuProfilingData(singleFrameData, outputFilePath, wasEnabled);
});
@@ -12,6 +12,7 @@
#include <AzCore/Component/TickBus.h>
#include <AzCore/Memory/OSAllocator.h>
#include <AzCore/Name/Name.h>
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/unordered_set.h>
#include <AzCore/std/parallel/mutex.h>
@@ -161,5 +162,33 @@ namespace AZ
AZStd::ring_buffer<TimeRegionMap> m_continuousCaptureData;
};
}; // namespace RPI
// Intermediate class to serialize Cpu TimedRegion data.
class CpuProfilingStatisticsSerializer
{
public:
class CpuProfilingStatisticsSerializerEntry
{
public:
AZ_TYPE_INFO(CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry, "{26B78F65-EB96-46E2-BE7E-A1233880B225}");
static void Reflect(AZ::ReflectContext* context);
CpuProfilingStatisticsSerializerEntry() = default;
CpuProfilingStatisticsSerializerEntry(const RHI::CachedTimeRegion& cachedTimeRegion);
Name m_groupName;
Name m_regionName;
uint16_t m_stackDepth;
AZStd::sys_time_t m_startTick;
AZStd::sys_time_t m_endTick;
};
AZ_TYPE_INFO(CpuProfilingStatisticsSerializer, "{D5B02946-0D27-474F-9A44-364C2706DD41}");
static void Reflect(AZ::ReflectContext* context);
CpuProfilingStatisticsSerializer() = default;
CpuProfilingStatisticsSerializer(const AZStd::ring_buffer<RHI::CpuProfiler::TimeRegionMap>& continuousData);
AZStd::vector<CpuProfilingStatisticsSerializerEntry> m_cpuProfilingStatisticsSerializerEntries;
};
}; // namespace RHI
}; // namespace AZ
@@ -409,5 +409,64 @@ namespace AZ
m_cachedTimeRegionMutex.unlock();
}
}
}
}
// --- CpuProfilingStatisticsSerializer ---
CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializer(const AZStd::ring_buffer<RHI::CpuProfiler::TimeRegionMap>& continuousData)
{
// Create serializable entries
for (const auto& timeRegionMap : continuousData)
{
for (const auto& threadEntry : timeRegionMap)
{
for (const auto& cachedRegionEntry : threadEntry.second)
{
m_cpuProfilingStatisticsSerializerEntries.insert(
m_cpuProfilingStatisticsSerializerEntries.end(),
cachedRegionEntry.second.begin(),
cachedRegionEntry.second.end());
}
}
}
}
void CpuProfilingStatisticsSerializer::Reflect(AZ::ReflectContext* context)
{
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<CpuProfilingStatisticsSerializer>()
->Version(1)
->Field("cpuProfilingStatisticsSerializerEntries", &CpuProfilingStatisticsSerializer::m_cpuProfilingStatisticsSerializerEntries)
;
}
CpuProfilingStatisticsSerializerEntry::Reflect(context);
}
// --- CpuProfilingStatisticsSerializerEntry ---
CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::CpuProfilingStatisticsSerializerEntry(const RHI::CachedTimeRegion& cachedTimeRegion)
{
m_groupName = cachedTimeRegion.m_groupRegionName->m_groupName;
m_regionName = cachedTimeRegion.m_groupRegionName->m_regionName;
m_stackDepth = cachedTimeRegion.m_stackDepth;
m_startTick = cachedTimeRegion.m_startTick;
m_endTick = cachedTimeRegion.m_endTick;
}
void CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry::Reflect(AZ::ReflectContext* context)
{
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<CpuProfilingStatisticsSerializerEntry>()
->Version(1)
->Field("groupName", &CpuProfilingStatisticsSerializerEntry::m_groupName)
->Field("regionName", &CpuProfilingStatisticsSerializerEntry::m_regionName)
->Field("stackDepth", &CpuProfilingStatisticsSerializerEntry::m_stackDepth)
->Field("startTick", &CpuProfilingStatisticsSerializerEntry::m_startTick)
->Field("endTick", &CpuProfilingStatisticsSerializerEntry::m_endTick)
;
}
}
} // namespace RHI
} // namespace AZ
@@ -10,7 +10,9 @@
#include <AzCore/JSON/document.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AtomCore/Serialization/Json/JsonUtils.h>
#include <Atom/RPI.Edit/Common/JsonFileLoadContext.h>
#include <Atom/RPI.Edit/Common/JsonReportingHelper.h>
@@ -118,7 +120,6 @@ namespace AZ
AZ_Error("AZ::RPI::JsonUtils", false, "Failed to load object from json string: %s", loadResult.GetError().c_str());
return false;
}
} // namespace JsonUtils
} // namespace RPI
} // namespace AZ
@@ -40,29 +40,35 @@ namespace AtomToolsFramework
const AZStd::any& AtomToolsDocument::GetPropertyValue(const AZ::Name& propertyFullName) const
{
AZ_UNUSED(propertyFullName);
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return m_invalidValue;
}
const AtomToolsFramework::DynamicProperty& AtomToolsDocument::GetProperty(const AZ::Name& propertyFullName) const
{
AZ_UNUSED(propertyFullName);
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return m_invalidProperty;
}
bool AtomToolsDocument::IsPropertyGroupVisible(const AZ::Name& propertyGroupFullName) const
{
AZ_UNUSED(propertyGroupFullName);
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
void AtomToolsDocument::SetPropertyValue(const AZ::Name& propertyFullName, const AZStd::any& value)
{
AZ_UNUSED(propertyFullName);
AZ_UNUSED(value);
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
}
bool AtomToolsDocument::Open(AZStd::string_view loadPath)
{
AZ_UNUSED(loadPath);
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
@@ -81,6 +87,7 @@ namespace AtomToolsFramework
bool AtomToolsDocument::SaveAsCopy(AZStd::string_view savePath)
{
AZ_UNUSED(savePath);
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
@@ -88,6 +95,7 @@ namespace AtomToolsFramework
bool AtomToolsDocument::SaveAsChild(AZStd::string_view savePath)
{
AZ_UNUSED(savePath);
AZ_Error("AtomToolsDocument", false, "%s not implemented.", __FUNCTION__);
return false;
}
@@ -9,6 +9,7 @@
#pragma once
#include <AzCore/Component/TickBus.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Math/Random.h>
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
@@ -102,6 +103,12 @@ namespace AZ
//! Draws the statistical view of the CPU profiling data.
void DrawStatisticsView();
//! Callback invoked when the "Load File" button is pressed in the file picker.
void LoadFile();
//! Draws the file picker window.
void DrawFilePicker();
//! Draws the CPU profiling visualizer.
void DrawVisualizer();
@@ -198,6 +205,14 @@ namespace AZ
AZ::RHI::CpuTimingStatistics m_cpuTimingStatisticsWhenPause;
AZStd::string m_lastCapturedFilePath;
bool m_showFilePicker = false;
// Cached file paths to previous traces on disk, sorted with the most recent trace at the front.
AZStd::vector<IO::Path> m_cachedCapturePaths;
// Index into the file picker, used to determine which file to load when "Load File" is pressed.
int m_currentFileIndex = 0;
};
} // namespace Render
} // namespace AZ
@@ -9,9 +9,14 @@
#include <Atom/Feature/Utils/ProfilingCaptureBus.h>
#include <Atom/RHI.Reflect/CpuTimingStatistics.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/CpuProfilerImpl.h>
#include <Atom/RPI.Edit/Common/JsonUtils.h>
#include <Atom/RPI.Public/RPISystemInterface.h>
#include <AzCore/IO/Path/Path_fwd.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/JSON/filereadstream.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
#include <AzCore/std/containers/map.h>
#include <AzCore/std/containers/set.h>
#include <AzCore/std/limits.h>
@@ -45,6 +50,74 @@ namespace AZ
AZ_Assert(ticksPerSecond >= 1000, "Error in converting ticks to ms, expected ticksPerSecond >= 1000");
return static_cast<float>((ticks * 1000) / (ticksPerSecond / 1000)) / 1000.0f;
}
using DeserializedCpuData = AZStd::vector<RHI::CpuProfilingStatisticsSerializer::CpuProfilingStatisticsSerializerEntry>;
inline Outcome<DeserializedCpuData, AZStd::string> LoadSavedCpuProfilingStatistics(const AZStd::string& capturePath)
{
auto* base = IO::FileIOBase::GetInstance();
char resolvedPath[IO::MaxPathLength];
if (!base->ResolvePath(capturePath.c_str(), resolvedPath, IO::MaxPathLength))
{
return Failure(AZStd::string::format("Could not resolve the path to file %s, is the path correct?", resolvedPath));
}
u64 captureSizeBytes;
const IO::Result fileSizeResult = base->Size(resolvedPath, captureSizeBytes);
if (!fileSizeResult)
{
return Failure(AZStd::string::format("Could not read the size of file %s, is the path correct?", resolvedPath));
}
// NOTE: this uses raw file pointers over the abstractions and utility functions provided by AZ::JsonSerializationUtils because
// saved profiling captures can be upwards of 400 MB. This necessitates a buffered approach to avoid allocating huge chunks of memory.
FILE* fp = nullptr;
azfopen(&fp, resolvedPath, "rb");
if (!fp)
{
return Failure(AZStd::string::format("Could not fopen file %s, is the path correct?\n", resolvedPath));
}
constexpr AZStd::size_t MaxBufSize = 65536;
const AZStd::size_t bufSize = AZStd::min(MaxBufSize, aznumeric_cast<AZStd::size_t>(captureSizeBytes));
char* buf = reinterpret_cast<char*>(azmalloc(bufSize));
rapidjson::Document document;
rapidjson::FileReadStream inputStream(fp, buf, bufSize);
document.ParseStream(inputStream);
azfree(buf);
fclose(fp);
if (document.HasParseError())
{
const auto pe = document.GetParseError();
return Failure(AZStd::string::format(
"Rapidjson could not parse the document with ParseErrorCode %u. See 3rdParty/rapidjson/error.h for definitions.\n", pe));
}
if (!document.IsObject() || !document.HasMember("ClassData"))
{
return Failure(AZStd::string::format(
"Error in loading saved capture: top-level object does not have a ClassData field. Did the serialization format change recently?\n"));
}
AZ_TracePrintf("JsonUtils", "Successfully loaded JSON into memory.\n");
const auto& root = document["ClassData"];
RHI::CpuProfilingStatisticsSerializer serializer;
const JsonSerializationResult::ResultCode deserializationResult = JsonSerialization::Load(serializer, root);
if (deserializationResult.GetProcessing() == JsonSerializationResult::Processing::Halted
|| serializer.m_cpuProfilingStatisticsSerializerEntries.empty())
{
return Failure(AZStd::string::format("Error in deserializing document: %s\n", deserializationResult.ToString(capturePath.c_str()).c_str()));
}
AZ_TracePrintf("JsonUtils", "Successfully loaded CPU profiling data with %zu profiling entries.\n",
serializer.m_cpuProfilingStatisticsSerializerEntries.size());
return Success(AZStd::move(serializer.m_cpuProfilingStatisticsSerializerEntries));
}
} // namespace CpuProfilerImGuiHelper
inline void ImGuiCpuProfiler::Draw(bool& keepDrawing, const AZ::RHI::CpuTimingStatistics& currentCpuTimingStatistics)
@@ -80,6 +153,11 @@ namespace AZ
{
DrawStatisticsView();
}
if (m_showFilePicker)
{
DrawFilePicker();
}
}
ImGui::End();
@@ -110,6 +188,11 @@ namespace AZ
inline void ImGuiCpuProfiler::DrawCommonHeader()
{
if (!m_lastCapturedFilePath.empty())
{
ImGui::Text("Saved: %s", m_lastCapturedFilePath.c_str());
}
if (ImGui::Button(m_enableVisualizer ? "Swap to statistics" : "Swap to visualizer"))
{
m_enableVisualizer = !m_enableVisualizer;
@@ -157,10 +240,31 @@ namespace AZ
}
}
if (!m_lastCapturedFilePath.empty())
ImGui::SameLine();
if (ImGui::Button("Load file"))
{
ImGui::SameLine();
ImGui::Text("Saved: %s", m_lastCapturedFilePath.c_str());
m_showFilePicker = true;
// Only update the cached file list when opened so that we aren't making IO calls on every frame.
auto* base = AZ::IO::FileIOBase::GetInstance();
const AZStd::string defaultSavedCapturePath = "@user@/CpuProfiler";
m_cachedCapturePaths.clear();
base->FindFiles(
defaultSavedCapturePath.c_str(), "*.json",
[&paths = m_cachedCapturePaths](const char* path) -> bool
{
auto foundPath = IO::Path(path);
paths.push_back(foundPath);
return true;
});
// Sort by decreasing modification time (most recent at the top)
AZStd::sort(m_cachedCapturePaths.begin(), m_cachedCapturePaths.end(),
[&base](const IO::Path& lhs, const IO::Path& rhs)
{
return base->ModificationTime(lhs.c_str()) > base->ModificationTime(rhs.c_str());
});
}
}
@@ -313,6 +417,45 @@ namespace AZ
}
}
inline void ImGuiCpuProfiler::DrawFilePicker()
{
ImGui::SetNextWindowSize({ 500, 200 }, ImGuiCond_Once);
if (ImGui::Begin("File Picker", &m_showFilePicker))
{
if (ImGui::Button("Load selected"))
{
LoadFile();
}
auto getter = [](void* vectorPointer, int idx, const char** out_text) -> bool
{
const auto& pathVec = *static_cast<AZStd::vector<IO::Path>*>(vectorPointer);
if (idx < 0 || idx >= pathVec.size())
{
return false;
}
*out_text = pathVec[idx].c_str();
return true;
};
ImGui::SetNextItemWidth(ImGui::GetWindowContentRegionWidth());
ImGui::ListBox("", &m_currentFileIndex, getter, &m_cachedCapturePaths, aznumeric_cast<int>(m_cachedCapturePaths.size()));
}
ImGui::End();
}
inline void ImGuiCpuProfiler::LoadFile()
{
const IO::Path& pathToLoad = m_cachedCapturePaths[m_currentFileIndex];
auto res = CpuProfilerImGuiHelper::LoadSavedCpuProfilingStatistics(pathToLoad.String());
if (!res.IsSuccess())
{
AZ_TracePrintf("ImGuiCpuProfiler", "%s", res.GetError().c_str());
return;
}
// TODO ATOM-16022 Parse this data and display it in the visualizer widget.
}
// -- CPU Visualizer --
inline void ImGuiCpuProfiler::DrawVisualizer()
{
+1 -1
View File
@@ -6,7 +6,7 @@
#
#
set(LY_UNITY_BUILD OFF CACHE BOOL "UNITY builds")
set(LY_UNITY_BUILD ON CACHE BOOL "UNITY builds")
include(CMakeFindDependencyMacro)
include(cmake/LyAutoGen.cmake)