You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
o3de/Gems/Atom/RPI/Code/Source/RPI.Public/Shader/Metrics/ShaderMetricsSystem.cpp

150 lines
4.9 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <Atom/RPI.Public/Shader/Metrics/ShaderMetricsSystem.h>
#include <Atom/RPI.Public/Shader/Metrics/ShaderMetrics.h>
#include <Atom/RPI.Reflect/Shader/ShaderAsset.h>
#include <AzCore/Interface/Interface.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/Utils//Utils.h>
#include <AtomCore/Serialization/Json/JsonUtils.h>
#include <AzFramework/IO/LocalFileIO.h>
namespace AZ
{
namespace RPI
{
AZStd::string GetMetricsFilePath()
{
char shaderMetricPath[AZ_MAX_PATH_LEN];
AZ::Utils::GetExecutableDirectory(shaderMetricPath, AZ_MAX_PATH_LEN);
return AZStd::string(shaderMetricPath) + AZ_CORRECT_FILESYSTEM_SEPARATOR_STRING + "ShaderMetrics.json";
}
ShaderMetricsSystemInterface* ShaderMetricsSystemInterface::Get()
{
return Interface<ShaderMetricsSystemInterface>::Get();
}
void ShaderMetricsSystem::Reflect(ReflectContext* context)
{
ShaderVariantRequest::Reflect(context);
ShaderVariantMetrics::Reflect(context);
}
void ShaderMetricsSystem::Init()
{
// Register the system to the interface.
Interface<ShaderMetricsSystemInterface>::Register(this);
ReadLog();
}
void ShaderMetricsSystem::Shutdown()
{
WriteLog();
// Unregister the system to the interface.
Interface<ShaderMetricsSystemInterface>::Unregister(this);
}
void ShaderMetricsSystem::Reset()
{
m_metrics.m_requests.clear();
}
void ShaderMetricsSystem::ReadLog()
{
const AZStd::string metricsFilePath = GetMetricsFilePath();
if (AZ::IO::LocalFileIO::GetInstance()->Exists(metricsFilePath.c_str()))
{
auto loadResult = AZ::JsonSerializationUtils::LoadObjectFromFile<ShaderVariantMetrics>(m_metrics, metricsFilePath.c_str());
if (!loadResult.IsSuccess())
{
AZ_Error("ShaderMetrics", false, "Unable to read %s file", metricsFilePath.c_str());
return;
}
}
}
void ShaderMetricsSystem::WriteLog()
{
const AZStd::string metricsFilePath = GetMetricsFilePath();
auto saveResult = AZ::JsonSerializationUtils::SaveObjectToFile<ShaderVariantMetrics>(&m_metrics, metricsFilePath.c_str());
if (!saveResult.IsSuccess())
{
AZ_Error("ShaderMetrics", false, "Unable to write %s file", metricsFilePath.c_str());
return;
}
}
bool ShaderMetricsSystem::IsEnabled() const
{
return m_isEnabled;
}
void ShaderMetricsSystem::SetEnabled(bool value)
{
m_isEnabled = value;
}
const ShaderVariantMetrics& ShaderMetricsSystem::GetMetrics() const
{
return m_metrics;
}
void ShaderMetricsSystem::RequestShaderVariant(const ShaderAsset* shader, const ShaderVariantId& shaderVariantId, const ShaderVariantSearchResult& result)
{
if (!m_isEnabled)
{
return;
}
AZ_PROFILE_FUNCTION(Debug::ProfileCategory::AzRender);
AZStd::lock_guard<AZStd::mutex> lock(m_metricsMutex);
// Log a new request
ShaderVariantRequest newRequest;
newRequest.m_shaderId = shader->GetId();
newRequest.m_shaderName = shader->GetName();
newRequest.m_shaderVariantId = shaderVariantId;
newRequest.m_shaderVariantStableId = result.GetStableId();
newRequest.m_dynamicOptionCount = result.GetDynamicOptionCount();
newRequest.m_requestCount = 1;
// Check if the specific shader variant was already requested to increase its request count
for (auto request = m_metrics.m_requests.begin(); request != m_metrics.m_requests.end(); ++request)
{
if (request->m_shaderId == newRequest.m_shaderId &&
request->m_shaderVariantId == newRequest.m_shaderVariantId)
{
request->m_requestCount++;
return;
}
}
// Otherwise, add a new request
m_metrics.m_requests.push_back(newRequest);
}
}; // namespace RPI
}; // namespace AZ