Merge branch 'Atom/santorac/RemixableMaterialTypes' into Atom/santorac/RemixableMaterialTypes2

This commit is contained in:
santorac
2021-09-28 22:14:23 -07:00
860 changed files with 25089 additions and 12205 deletions
@@ -30,6 +30,7 @@
#include <AzCore/IO/IOUtils.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Settings/SettingsRegistry.h>
namespace AZ
{
@@ -46,7 +47,7 @@ namespace AZ
{
AssetBuilderSDK::AssetBuilderDesc materialBuilderDescriptor;
materialBuilderDescriptor.m_name = JobKey;
materialBuilderDescriptor.m_version = 108; // ATOM-5041
materialBuilderDescriptor.m_version = 109; // Changed "id" to "name" in serialization
materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.material", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
materialBuilderDescriptor.m_patterns.push_back(AssetBuilderSDK::AssetBuilderPattern("*.materialtype", AssetBuilderSDK::AssetBuilderPattern::PatternType::Wildcard));
materialBuilderDescriptor.m_busId = azrtti_typeid<MaterialBuilder>();
@@ -66,21 +67,19 @@ namespace AZ
//! Adds all relevant dependencies for a referenced source file, considering that the path might be relative to the original file location or a full asset path.
//! This will usually include multiple source dependencies and a single job dependency, but will include only source dependencies if the file is not found.
//! Note the AssetBuilderSDK::JobDependency::m_platformIdentifier will not be set by this function. The calling code must set this value before passing back
//! to the AssetBuilderSDK::CreateJobsResponse.
void AddPossibleDependencies(
AZStd::string_view currentFilePath, AZStd::string_view referencedParentPath,
AZStd::vector<AssetBuilderSDK::SourceFileDependency>& sourceFileDependencies,
const char* jobKey, AZStd::vector<AssetBuilderSDK::JobDependency>& jobDependencies)
//! to the AssetBuilderSDK::CreateJobsResponse. If isOrderedOnceForMaterialTypes is true and the dependency is a materialtype file, the job dependency type
//! will be set to JobDependencyType::OrderOnce.
void AddPossibleDependencies(AZStd::string_view currentFilePath,
AZStd::string_view referencedParentPath,
const char* jobKey,
AZStd::vector<AssetBuilderSDK::JobDependency>& jobDependencies,
bool isOrderedOnceForMaterialTypes = false)
{
bool dependencyFileFound = false;
AZStd::vector<AZStd::string> possibleDependencies = RPI::AssetUtils::GetPossibleDepenencyPaths(currentFilePath, referencedParentPath);
for (auto& file : possibleDependencies)
{
AssetBuilderSDK::SourceFileDependency sourceFileDependency;
sourceFileDependency.m_sourceFileDependencyPath = file;
sourceFileDependencies.push_back(sourceFileDependency);
// The first path found is the highest priority, and will have a job dependency, as this is the one
// the builder will actually use
if (!dependencyFileFound)
@@ -93,8 +92,11 @@ namespace AZ
{
AssetBuilderSDK::JobDependency jobDependency;
jobDependency.m_jobKey = jobKey;
jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order;
jobDependency.m_sourceFile.m_sourceFileDependencyPath = file;
const bool isMaterialTypeFile = AzFramework::StringFunc::Path::IsExtension(file.c_str(), MaterialTypeSourceData::Extension);
jobDependency.m_type = (isMaterialTypeFile && isOrderedOnceForMaterialTypes) ? AssetBuilderSDK::JobDependencyType::OrderOnce : AssetBuilderSDK::JobDependencyType::Order;
jobDependencies.push_back(jobDependency);
}
}
@@ -173,8 +175,9 @@ namespace AZ
for (auto& shader : materialTypeSourceData.GetValue().m_shaderCollection)
{
AddPossibleDependencies(request.m_sourceFile, shader.m_shaderFilePath,
response.m_sourceFileDependencyList, "Shader Asset",
AddPossibleDependencies(request.m_sourceFile,
shader.m_shaderFilePath,
"Shader Asset",
outputJobDescriptor.m_jobDependencyList);
}
@@ -184,9 +187,10 @@ namespace AZ
for (const MaterialFunctorSourceData::AssetDependency& dependency : dependencies)
{
AddPossibleDependencies(request.m_sourceFile, dependency.m_sourceFilePath,
response.m_sourceFileDependencyList,
dependency.m_jobKey.c_str(), outputJobDescriptor.m_jobDependencyList);
AddPossibleDependencies(request.m_sourceFile,
dependency.m_sourceFilePath,
dependency.m_jobKey.c_str(),
outputJobDescriptor.m_jobDependencyList);
}
}
}
@@ -219,11 +223,24 @@ namespace AZ
parentMaterialPath = materialTypePath;
}
// If includeMaterialPropertyNames is false, then a job dependency is needed so the material builder can validate MaterialAsset properties
// against the MaterialTypeAsset at asset build time.
// If includeMaterialPropertyNames is true, the material properties will be validated at runtime when the material is loaded, so the job dependency
// is needed only for first-time processing to set up the initial MaterialAsset. This speeds up AP processing time when a materialtype file
// is edited (e.g. 10s when editing StandardPBR.materialtype on AtomTest project from 45s).
bool includeMaterialPropertyNames = true;
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
settingsRegistry->Get(includeMaterialPropertyNames, "/O3DE/Atom/RPI/MaterialBuilder/IncludeMaterialPropertyNames");
}
// Register dependency on the parent material source file so we can load it and use it's data to build this variant material.
// Note, we don't need a direct dependency on the material type because the parent material will depend on it.
AddPossibleDependencies(request.m_sourceFile, parentMaterialPath,
response.m_sourceFileDependencyList,
JobKey, outputJobDescriptor.m_jobDependencyList);
AddPossibleDependencies(request.m_sourceFile,
parentMaterialPath,
JobKey,
outputJobDescriptor.m_jobDependencyList,
includeMaterialPropertyNames);
}
}
@@ -44,7 +44,7 @@ namespace AZ
if (auto* serialize = azrtti_cast<SerializeContext*>(context))
{
serialize->Class<MaterialAssetDependenciesComponent, Component>()
->Version(4)
->Version(5) // Set materialtype dependency to OrderOnce
->Attribute(Edit::Attributes::SystemComponentTags, AZStd::vector<Crc32>({ AssetBuilderSDK::ComponentTags::AssetBuilder }));
}
}
@@ -78,10 +78,7 @@ namespace AZ
AZStd::string materialTypePath;
RPI::MaterialConverterBus::BroadcastResult(materialTypePath, &RPI::MaterialConverterBus::Events::GetMaterialTypePath);
bool includeMaterialPropertyNames = true;
RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames);
// TODO: Use includeMaterialPropertyNames to break materialtype dependency on fbx files. Materialasset's dependency on materialtypeasset will need to be decoupled first
if (conversionEnabled && !materialTypePath.empty() /*&& !includeMaterialPropertyNames*/)
if (conversionEnabled && !materialTypePath.empty())
{
AssetBuilderSDK::SourceFileDependency materialTypeSource;
materialTypeSource.m_sourceFileDependencyPath = materialTypePath;
@@ -90,7 +87,15 @@ namespace AZ
jobDependency.m_jobKey = "Atom Material Builder";
jobDependency.m_sourceFile = materialTypeSource;
jobDependency.m_platformIdentifier = platformIdentifier;
jobDependency.m_type = AssetBuilderSDK::JobDependencyType::Order;
// If includeMaterialPropertyNames is false, then a job dependency is needed so the material builder can validate
// MaterialAsset properties against the MaterialTypeAsset at asset build time. If includeMaterialPropertyNames is true, the
// material properties will be validated at runtime when the material is loaded, so the job dependency is needed only for
// first-time processing to set up the initial MaterialAsset. This speeds up AP processing time when a materialtype file is
// edited (e.g. 10s when editing StandardPBR.materialtype on AtomTest project from 45s).
bool includeMaterialPropertyNames = true;
RPI::MaterialConverterBus::BroadcastResult(includeMaterialPropertyNames, &RPI::MaterialConverterBus::Events::ShouldIncludeMaterialPropertyNames);
jobDependency.m_type = includeMaterialPropertyNames ? AssetBuilderSDK::JobDependencyType::OrderOnce : AssetBuilderSDK::JobDependencyType::Order;
jobDependencyList.push_back(jobDependency);
}
@@ -0,0 +1,126 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Atom/RPI.Edit/Material/MaterialPropertyConnectionSerializer.h>
#include <Atom/RPI.Edit/Material/MaterialUtils.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/Json/StackedString.h>
namespace AZ
{
namespace RPI
{
namespace JsonMaterialPropertyConnectionSerializerInternal
{
namespace Field
{
static constexpr const char type[] = "type";
static constexpr const char name[] = "name";
static constexpr const char id[] = "id"; // For backward compatibility
static constexpr const char shaderIndex[] = "shaderIndex";
}
static const AZStd::string_view AcceptedFields[] =
{
Field::type,
Field::name,
Field::id,
Field::shaderIndex
};
}
AZ_CLASS_ALLOCATOR_IMPL(JsonMaterialPropertyConnectionSerializer, SystemAllocator, 0);
JsonSerializationResult::Result JsonMaterialPropertyConnectionSerializer::Load(void* outputValue, const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertyConnectionSerializerInternal;
AZ_Assert(azrtti_typeid<MaterialTypeSourceData::PropertyConnection>() == outputValueTypeId,
"Unable to deserialize material property connection to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
MaterialTypeSourceData::PropertyConnection* propertyConnection = reinterpret_cast<MaterialTypeSourceData::PropertyConnection*>(outputValue);
AZ_Assert(propertyConnection, "Output value for JsonMaterialPropertyConnectionSerializer can't be null.");
JSR::ResultCode result(JSR::Tasks::ReadField);
if (!inputValue.IsObject())
{
return context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Unsupported, "Property connection must be a JSON object.");
}
MaterialUtils::CheckForUnrecognizedJsonFields(AcceptedFields, AZ_ARRAY_SIZE(AcceptedFields), inputValue, context, result);
result.Combine(ContinueLoadingFromJsonObjectField(&propertyConnection->m_type, azrtti_typeid<MaterialPropertyOutputType>(), inputValue, Field::type, context));
JsonSerializationResult::ResultCode nameResult = ContinueLoadingFromJsonObjectField(&propertyConnection->m_fieldName, azrtti_typeid<AZStd::string>(), inputValue, Field::name, context);
if (nameResult.GetOutcome() == JsonSerializationResult::Outcomes::DefaultsUsed)
{
// This "id" key is for backward compatibility.
result.Combine(ContinueLoadingFromJsonObjectField(&propertyConnection->m_fieldName, azrtti_typeid<AZStd::string>(), inputValue, Field::id, context));
}
else
{
result.Combine(nameResult);
}
result.Combine(ContinueLoadingFromJsonObjectField(&propertyConnection->m_shaderIndex, azrtti_typeid<int32_t>(), inputValue, Field::shaderIndex, context));
if (result.GetProcessing() == JsonSerializationResult::Processing::Completed)
{
return context.Report(result, "Successfully loaded property connection.");
}
else
{
return context.Report(result, "Partially loaded property connection.");
}
}
JsonSerializationResult::Result JsonMaterialPropertyConnectionSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
[[maybe_unused]] const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertyConnectionSerializerInternal;
AZ_Assert(azrtti_typeid<MaterialTypeSourceData::PropertyConnection>() == valueTypeId,
"Unable to serialize material property connection to json because the provided type is %s",
valueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(valueTypeId);
const MaterialTypeSourceData::PropertyConnection* propertyConnection = reinterpret_cast<const MaterialTypeSourceData::PropertyConnection*>(inputValue);
AZ_Assert(propertyConnection, "Input value for JsonMaterialPropertyConnectionSerializer can't be null.");
JSR::ResultCode result(JSR::Tasks::WriteValue);
outputValue.SetObject();
MaterialTypeSourceData::PropertyConnection defaultConnection;
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::type, &propertyConnection->m_type, &defaultConnection.m_type, azrtti_typeid<MaterialPropertyOutputType>(), context));
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::name, &propertyConnection->m_fieldName, &defaultConnection.m_fieldName, azrtti_typeid<AZStd::string>(), context));
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::shaderIndex, &propertyConnection->m_shaderIndex, &defaultConnection.m_shaderIndex, azrtti_typeid<int32_t>(), context));
if (result.GetProcessing() == JsonSerializationResult::Processing::Completed)
{
return context.Report(result, "Successfully stored property connection.");
}
else
{
return context.Report(result, "Partially stored property connection.");
}
}
} // namespace RPI
} // namespace AZ
@@ -0,0 +1,125 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Atom/RPI.Edit/Material/MaterialPropertyGroupSerializer.h>
#include <Atom/RPI.Edit/Material/MaterialUtils.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
#include <AzCore/Serialization/Json/JsonSerialization.h>
#include <AzCore/Serialization/Json/StackedString.h>
namespace AZ
{
namespace RPI
{
namespace JsonMaterialPropertyGroupSerializerInternal
{
namespace Field
{
static constexpr const char name[] = "name";
static constexpr const char id[] = "id"; // For backward compatibility
static constexpr const char displayName[] = "displayName";
static constexpr const char description[] = "description";
}
static const AZStd::string_view AcceptedFields[] =
{
Field::name,
Field::id,
Field::displayName,
Field::description
};
}
AZ_CLASS_ALLOCATOR_IMPL(JsonMaterialPropertyGroupSerializer, SystemAllocator, 0);
JsonSerializationResult::Result JsonMaterialPropertyGroupSerializer::Load(void* outputValue, const Uuid& outputValueTypeId,
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertyGroupSerializerInternal;
AZ_Assert(azrtti_typeid<MaterialTypeSourceData::GroupDefinition>() == outputValueTypeId,
"Unable to deserialize material property group to json because the provided type is %s",
outputValueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(outputValueTypeId);
MaterialTypeSourceData::GroupDefinition* propertyGroup = reinterpret_cast<MaterialTypeSourceData::GroupDefinition*>(outputValue);
AZ_Assert(propertyGroup, "Output value for JsonMaterialPropertyGroupSerializer can't be null.");
JSR::ResultCode result(JSR::Tasks::ReadField);
if (!inputValue.IsObject())
{
return context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Unsupported, "Property group must be a JSON object.");
}
MaterialUtils::CheckForUnrecognizedJsonFields(AcceptedFields, AZ_ARRAY_SIZE(AcceptedFields), inputValue, context, result);
JsonSerializationResult::ResultCode nameResult = ContinueLoadingFromJsonObjectField(&propertyGroup->m_name, azrtti_typeid<AZStd::string>(), inputValue, Field::name, context);
if (nameResult.GetOutcome() == JsonSerializationResult::Outcomes::DefaultsUsed)
{
// This "id" key is for backward compatibility.
result.Combine(ContinueLoadingFromJsonObjectField(&propertyGroup->m_name, azrtti_typeid<AZStd::string>(), inputValue, Field::id, context));
}
else
{
result.Combine(nameResult);
}
result.Combine(ContinueLoadingFromJsonObjectField(&propertyGroup->m_displayName, azrtti_typeid<AZStd::string>(), inputValue, Field::displayName, context));
result.Combine(ContinueLoadingFromJsonObjectField(&propertyGroup->m_description, azrtti_typeid<AZStd::string>(), inputValue, Field::description, context));
if (result.GetProcessing() == JsonSerializationResult::Processing::Completed)
{
return context.Report(result, "Successfully loaded property group.");
}
else
{
return context.Report(result, "Partially loaded property group.");
}
}
JsonSerializationResult::Result JsonMaterialPropertyGroupSerializer::Store(rapidjson::Value& outputValue, const void* inputValue,
[[maybe_unused]] const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertyGroupSerializerInternal;
AZ_Assert(azrtti_typeid<MaterialTypeSourceData::GroupDefinition>() == valueTypeId,
"Unable to serialize material property group to json because the provided type is %s",
valueTypeId.ToString<AZStd::string>().c_str());
AZ_UNUSED(valueTypeId);
const MaterialTypeSourceData::GroupDefinition* propertyGroup = reinterpret_cast<const MaterialTypeSourceData::GroupDefinition*>(inputValue);
AZ_Assert(propertyGroup, "Input value for JsonMaterialPropertyGroupSerializer can't be null.");
JSR::ResultCode result(JSR::Tasks::WriteValue);
outputValue.SetObject();
AZStd::string defaultEmpty;
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::name, &propertyGroup->m_name, &defaultEmpty, azrtti_typeid<AZStd::string>(), context));
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::displayName, &propertyGroup->m_displayName, &defaultEmpty, azrtti_typeid<AZStd::string>(), context));
result.Combine(ContinueStoringToJsonObjectField(outputValue, Field::description, &propertyGroup->m_description, &defaultEmpty, azrtti_typeid<AZStd::string>(), context));
if (result.GetProcessing() == JsonSerializationResult::Processing::Completed)
{
return context.Report(result, "Successfully stored property group.");
}
else
{
return context.Report(result, "Partially stored property group.");
}
}
} // namespace RPI
} // namespace AZ
@@ -8,6 +8,7 @@
#include <Atom/RPI.Edit/Material/MaterialPropertySerializer.h>
#include <Atom/RPI.Edit/Material/MaterialPropertyId.h>
#include <Atom/RPI.Edit/Material/MaterialUtils.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
@@ -23,11 +24,12 @@ namespace AZ
{
namespace RPI
{
namespace // Avoid conflicts in uber builds
namespace JsonMaterialPropertySerializerInternal
{
namespace Field
{
static constexpr const char name[] = "name";
static constexpr const char id[] = "id"; // For backward compatibility
static constexpr const char displayName[] = "displayName";
static constexpr const char description[] = "description";
static constexpr const char type[] = "type";
@@ -47,6 +49,7 @@ namespace AZ
static const AZStd::string_view AcceptedFields[] =
{
Field::name,
Field::id,
Field::displayName,
Field::description,
Field::type,
@@ -103,6 +106,7 @@ namespace AZ
JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
JSR::ResultCode result(JSR::Tasks::ReadField);
@@ -160,6 +164,7 @@ namespace AZ
JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
JSR::ResultCode result(JSR::Tasks::ReadField);
@@ -181,6 +186,7 @@ namespace AZ
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
AZ_Assert(azrtti_typeid<MaterialTypeSourceData::PropertyDefinition>() == outputValueTypeId,
"Unable to deserialize material property to json because the provided type is %s",
@@ -197,28 +203,19 @@ namespace AZ
return context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Unsupported, "Property definition must be a JSON object.");
}
// First check for unexpected fields
for (auto iter = inputValue.MemberBegin(); iter != inputValue.MemberEnd(); ++iter)
MaterialUtils::CheckForUnrecognizedJsonFields(AcceptedFields, AZ_ARRAY_SIZE(AcceptedFields), inputValue, context, result);
JsonSerializationResult::ResultCode nameResult = ContinueLoadingFromJsonObjectField(&property->m_name, azrtti_typeid<AZStd::string>(), inputValue, Field::name, context);
if (nameResult.GetOutcome() == JsonSerializationResult::Outcomes::DefaultsUsed)
{
bool matched = false;
for (int i = 0; i < AZ_ARRAY_SIZE(AcceptedFields); ++i)
{
if (iter->name.GetString() == AcceptedFields[i])
{
matched = true;
break;
}
}
if (!matched)
{
ScopedContextPath subPath{context, iter->name.GetString()};
result.Combine(context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Skipped, "Skipping unrecognized field"));
}
// This "id" key is for backward compatibility.
result.Combine(ContinueLoadingFromJsonObjectField(&property->m_name, azrtti_typeid<AZStd::string>(), inputValue, Field::id, context));
}
else
{
result.Combine(nameResult);
}
result.Combine(ContinueLoadingFromJsonObjectField(&property->m_name, azrtti_typeid<AZStd::string>(), inputValue, Field::name, context));
result.Combine(ContinueLoadingFromJsonObjectField(&property->m_displayName, azrtti_typeid<AZStd::string>(), inputValue, Field::displayName, context));
result.Combine(ContinueLoadingFromJsonObjectField(&property->m_description, azrtti_typeid<AZStd::string>(), inputValue, Field::description, context));
result.Combine(ContinueLoadingFromJsonObjectField(&property->m_dataType, azrtti_typeid<MaterialPropertyDataType>(), inputValue, Field::type, context));
@@ -302,6 +299,8 @@ namespace AZ
JsonSerializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
JSR::ResultCode result(JSR::Tasks::WriteValue);
if (property->m_value.Is<T>())
@@ -345,6 +344,8 @@ namespace AZ
JsonSerializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
JsonSerializationResult::ResultCode result(JSR::Tasks::WriteValue);
if (property->m_value.Is<T>())
@@ -360,6 +361,7 @@ namespace AZ
[[maybe_unused]] const void* defaultValue, const Uuid& valueTypeId, JsonSerializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
AZ_Assert(azrtti_typeid<MaterialTypeSourceData::PropertyDefinition>() == valueTypeId,
"Unable to serialize material property to json because the provided type is %s",
@@ -452,6 +454,8 @@ namespace AZ
const rapidjson::Value& inputValue, JsonDeserializerContext& context)
{
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
JSR::ResultCode result(JSR::Tasks::ReadField);
if (inputValue.HasMember(Field::vectorLabels))
@@ -467,6 +471,8 @@ namespace AZ
{
AZStd::string emptyString;
namespace JSR = JsonSerializationResult;
using namespace JsonMaterialPropertySerializerInternal;
JsonSerializationResult::ResultCode result(JSR::Tasks::WriteValue);
if (!property->m_vectorLabels.empty())
@@ -9,6 +9,8 @@
#include <Atom/RPI.Edit/Material/MaterialTypeSourceData.h>
#include <Atom/RPI.Edit/Material/MaterialPropertySerializer.h>
#include <Atom/RPI.Edit/Material/MaterialFunctorSourceDataSerializer.h>
#include <Atom/RPI.Edit/Material/MaterialPropertyConnectionSerializer.h>
#include <Atom/RPI.Edit/Material/MaterialPropertyGroupSerializer.h>
#include <Atom/RPI.Edit/Material/MaterialUtils.h>
#include <Atom/RPI.Edit/Common/AssetUtils.h>
@@ -46,29 +48,17 @@ namespace AZ
if (JsonRegistrationContext* jsonContext = azrtti_cast<JsonRegistrationContext*>(context))
{
jsonContext->Serializer<JsonMaterialPropertySerializer>()->HandlesType<MaterialTypeSourceData::PropertyDefinition>();
jsonContext->Serializer<JsonMaterialPropertyConnectionSerializer>()->HandlesType<MaterialTypeSourceData::PropertyConnection>();
jsonContext->Serializer<JsonMaterialPropertyGroupSerializer>()->HandlesType<MaterialTypeSourceData::GroupDefinition>();
}
else if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
{
serializeContext->Class<PropertyConnection>()
->Version(2)
->Field("type", &PropertyConnection::m_type)
->Field("name", &PropertyConnection::m_fieldName)
->Field("shaderIndex", &PropertyConnection::m_shaderIndex)
;
serializeContext->Class<PropertyConnection>()->Version(3);
serializeContext->Class<GroupDefinition>()->Version(4);
serializeContext->Class<PropertyDefinition>()->Version(1);
serializeContext->RegisterGenericType<PropertyConnectionList>();
serializeContext->Class<GroupDefinition>()
->Version(2)
->Field("name", &GroupDefinition::m_name)
->Field("displayName", &GroupDefinition::m_displayName)
->Field("description", &GroupDefinition::m_description)
;
serializeContext->Class<PropertyDefinition>()
->Version(1)
;
serializeContext->Class<ShaderVariantReferenceData>()
->Version(2)
->Field("file", &ShaderVariantReferenceData::m_shaderFilePath)
@@ -17,6 +17,8 @@
#include <Atom/RPI.Edit/Common/JsonFileLoadContext.h>
#include <Atom/RPI.Edit/Common/JsonUtils.h>
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
#include <AzCore/std/string/string.h>
@@ -99,6 +101,29 @@ namespace AZ
return AZ::Success(AZStd::move(materialType));
}
}
void CheckForUnrecognizedJsonFields(const AZStd::string_view* acceptedFieldNames, uint32_t acceptedFieldNameCount, const rapidjson::Value& object, JsonDeserializerContext& context, JsonSerializationResult::ResultCode &result)
{
for (auto iter = object.MemberBegin(); iter != object.MemberEnd(); ++iter)
{
bool matched = false;
for (uint32_t i = 0; i < acceptedFieldNameCount; ++i)
{
if (iter->name.GetString() == acceptedFieldNames[i])
{
matched = true;
break;
}
}
if (!matched)
{
ScopedContextPath subPath{context, iter->name.GetString()};
result.Combine(context.Report(JsonSerializationResult::Tasks::ReadField, JsonSerializationResult::Outcomes::Skipped, "Skipping unrecognized field"));
}
}
}
}
}
}
@@ -14,8 +14,6 @@
#include <Atom/RPI.Public/Scene.h>
#include <Atom/RPI.Public/View.h>
#include <Atom/RHI/CpuProfiler.h>
#include <AzCore/Math/MatrixUtils.h>
#include <AzCore/Math/ShapeIntersection.h>
#include <AzCore/Casting/numeric_cast.h>
@@ -299,7 +297,7 @@ namespace AZ
//work function
void Process() override
{
AZ_PROFILE_FUNCTION(RPI);
AZ_PROFILE_SCOPE(RPI, "AddObjectsToViewJob: Process");
const View::UsageFlags viewFlags = m_jobData->m_view->GetUsageFlags();
const RHI::DrawListMask drawListMask = m_jobData->m_view->GetDrawListMask();
@@ -645,7 +643,7 @@ namespace AZ
uint32_t AddLodDataToView(const Vector3& pos, const Cullable::LodData& lodData, RPI::View& view)
{
#ifdef AZ_CULL_PROFILE_DETAILED
AZ_PROFILE_FUNCTION(RPI);
AZ_PROFILE_SCOPE(RPI, "AddLodDataToView");
#endif
const Matrix4x4& viewToClip = view.GetViewToClipMatrix();
@@ -725,17 +723,27 @@ namespace AZ
void CullingScene::BeginCulling(const AZStd::vector<ViewPtr>& views)
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "CullingScene: BeginCulling");
AZ_PROFILE_SCOPE(RPI, "CullingScene: BeginCulling");
m_cullDataConcurrencyCheck.soft_lock();
m_debugCtx.ResetCullStats();
m_debugCtx.m_numCullablesInScene = GetNumCullables();
AZ::JobCompletion beginCullingCompletion;
for (auto& view : views)
{
view->BeginCulling();
const auto cullingLambda = [&view]()
{
view->BeginCulling();
};
AZ::Job* cullingJob = AZ::CreateJobFunction(AZStd::move(cullingLambda), true, nullptr);
cullingJob->SetDependent(&beginCullingCompletion);
cullingJob->Start();
}
beginCullingCompletion.StartAndWaitForCompletion();
AuxGeomDrawPtr auxGeom;
if (m_debugCtx.m_debugDraw)
{
@@ -7,7 +7,6 @@
*/
#include <Atom/RHI/CommandList.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/Factory.h>
#include <Atom/RHI/FrameGraphInterface.h>
#include <Atom/RHI/RHISystemInterface.h>
@@ -75,7 +74,7 @@ namespace AZ
void GpuQuerySystem::Update()
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "GpuQuerySystem: Update");
AZ_PROFILE_SCOPE(RPI, "GpuQuerySystem: Update");
for (auto& queryPool : m_queryPoolArray)
{
if (queryPool)
@@ -23,7 +23,6 @@
#include <Atom/RHI.Reflect/ImagePoolDescriptor.h>
#include <Atom/RHI/ImagePool.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/RHISystemInterface.h>
#include <AtomCore/Instance/InstanceDatabase.h>
@@ -34,6 +33,8 @@
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/Math/Color.h>
AZ_DECLARE_BUDGET(RPI);
namespace AZ
{
namespace RPI
@@ -171,7 +172,7 @@ namespace AZ
void ImageSystem::Update()
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "ImageSystem: Update");
AZ_PROFILE_SCOPE(RPI, "ImageSystem: Update");
AZStd::lock_guard<AZStd::mutex> lock(m_activeStreamingPoolMutex);
for (StreamingImagePool* imagePool : m_activeStreamingPools)
@@ -42,7 +42,7 @@ namespace AZ
Data::Instance<Model> Model::CreateInternal(const Data::Asset<ModelAsset>& modelAsset)
{
AZ_PROFILE_FUNCTION(RPI);
AZ_PROFILE_SCOPE(RPI, "Model: CreateInternal");
Data::Instance<Model> model = aznew Model();
const RHI::ResultCode resultCode = model->Init(modelAsset);
@@ -56,7 +56,7 @@ namespace AZ
RHI::ResultCode Model::Init(const Data::Asset<ModelAsset>& modelAsset)
{
AZ_PROFILE_FUNCTION(RPI);
AZ_PROFILE_SCOPE(RPI, "Model: Init");
m_lods.resize(modelAsset->GetLodAssets().size());
@@ -128,7 +128,7 @@ namespace AZ
bool Model::LocalRayIntersection(const AZ::Vector3& rayStart, const AZ::Vector3& rayDir, float& distanceNormalized, AZ::Vector3& normal) const
{
AZ_PROFILE_FUNCTION(RPI);
AZ_PROFILE_SCOPE(RPI, "Model: LocalRayIntersection");
if (!GetModelAsset())
{
@@ -171,7 +171,7 @@ namespace AZ
float& distanceNormalized,
AZ::Vector3& normal) const
{
AZ_PROFILE_FUNCTION(RPI);
AZ_PROFILE_SCOPE(RPI, "Model: RayIntersection");
const AZ::Vector3 clampedScale = nonUniformScale.GetMax(AZ::Vector3(AZ::MinTransformScale));
const AZ::Transform inverseTM = modelTransform.GetInverse();
@@ -27,7 +27,7 @@ namespace AZ
ModelLodIndex SelectLod(const View* view, const Vector3& position, const Model& model, ModelLodIndex lodOverride)
{
AZ_PROFILE_FUNCTION(RPI);
AZ_PROFILE_SCOPE(RPI, "ModelLodUtils: SelectLod");
ModelLodIndex lodIndex;
if (model.GetLodCount() == 1)
{
@@ -19,7 +19,6 @@
#include <AzCore/Serialization/Json/JsonUtils.h>
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RHI/FrameGraphBuilder.h>
#include <Atom/RPI.Public/Pass/FullscreenTrianglePass.h>
@@ -169,7 +168,7 @@ namespace AZ
void PassSystem::RemovePasses()
{
m_state = PassSystemState::RemovingPasses;
AZ_ATOM_PROFILE_FUNCTION("RPI", "PassSystem: RemovePasses");
AZ_PROFILE_SCOPE(RPI, "PassSystem: RemovePasses");
if (!m_removePassList.empty())
{
@@ -189,8 +188,7 @@ namespace AZ
void PassSystem::BuildPasses()
{
m_state = PassSystemState::BuildingPasses;
AZ_PROFILE_FUNCTION(RPI);
AZ_ATOM_PROFILE_FUNCTION("RPI", "PassSystem: BuildPassAttachments");
AZ_PROFILE_SCOPE(RPI, "PassSystem: BuildPasses");
m_passHierarchyChanged = m_passHierarchyChanged || !m_buildPassList.empty();
@@ -239,8 +237,7 @@ namespace AZ
void PassSystem::InitializePasses()
{
m_state = PassSystemState::InitializingPasses;
AZ_PROFILE_FUNCTION(RPI);
AZ_ATOM_PROFILE_FUNCTION("RPI", "PassSystem: BuildPassAttachments");
AZ_PROFILE_SCOPE(RPI, "PassSystem: InitializePasses");
m_passHierarchyChanged = m_passHierarchyChanged || !m_initializePassList.empty();
@@ -277,7 +274,6 @@ namespace AZ
void PassSystem::Validate()
{
m_state = PassSystemState::ValidatingPasses;
AZ_ATOM_PROFILE_FUNCTION("RPI", "PassSystem: Validate");
if (PassValidation::IsEnabled())
{
@@ -286,7 +282,7 @@ namespace AZ
return;
}
AZ_PROFILE_FUNCTION(RPI);
AZ_PROFILE_SCOPE(RPI, "PassSystem: Validate");
PassValidationResults validationResults;
m_rootPass->Validate(validationResults);
@@ -298,7 +294,7 @@ namespace AZ
void PassSystem::ProcessQueuedChanges()
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "PassSystem: ProcessQueuedChanges");
AZ_PROFILE_SCOPE(RPI, "PassSystem: ProcessQueuedChanges");
RemovePasses();
BuildPasses();
InitializePasses();
@@ -307,8 +303,7 @@ namespace AZ
void PassSystem::FrameUpdate(RHI::FrameGraphBuilder& frameGraphBuilder)
{
AZ_PROFILE_FUNCTION(RPI);
AZ_ATOM_PROFILE_FUNCTION("RPI", "PassSystem: FrameUpdate");
AZ_PROFILE_SCOPE(RPI, "PassSystem: FrameUpdate");
ResetFrameStatistics();
ProcessQueuedChanges();
@@ -317,14 +312,14 @@ namespace AZ
Pass::FramePrepareParams params{ &frameGraphBuilder };
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Pass: FrameBegin");
AZ_PROFILE_SCOPE(RPI, "Pass: FrameBegin");
m_rootPass->FrameBegin(params);
}
}
void PassSystem::FrameEnd()
{
AZ_ATOM_PROFILE_FUNCTION("RHI", "PassSystem: FrameEnd");
AZ_PROFILE_SCOPE(RHI, "PassSystem: FrameEnd");
m_state = PassSystemState::FrameEnd;
@@ -216,7 +216,7 @@ namespace AZ
void RasterPass::CompileResources(const RHI::FrameGraphCompileContext& context)
{
AZ_PROFILE_FUNCTION(RPI);
AZ_PROFILE_SCOPE(RPI, "RasterPass: CompileResources");
if (m_shaderResourceGroup == nullptr)
{
@@ -233,7 +233,7 @@ namespace AZ
void RPISystem::OnSystemTick()
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "RPISystem: OnSystemTick");
AZ_PROFILE_SCOPE(RPI, "RPISystem: OnSystemTick");
// Image system update is using system tick but not game tick so it can stream images in background even game is pausing
m_imageSystem.Update();
@@ -245,7 +245,7 @@ namespace AZ
{
return;
}
AZ_ATOM_PROFILE_FUNCTION("RPI", "RPISystem: SimulationTick");
AZ_PROFILE_SCOPE(RPI, "RPISystem: SimulationTick");
AssetInitBus::Broadcast(&AssetInitBus::Events::PostLoadInit);
@@ -273,8 +273,7 @@ namespace AZ
return;
}
AZ_PROFILE_FUNCTION(RPI);
AZ_ATOM_PROFILE_FUNCTION("RPI", "RPISystem: RenderTick");
AZ_PROFILE_SCOPE(RPI, "RPISystem: RenderTick");
// Query system update is to increment the frame count
m_querySystem.Update();
@@ -301,7 +300,7 @@ namespace AZ
});
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "RPISystem: FrameEnd");
AZ_PROFILE_SCOPE(RPI, "RPISystem: FrameEnd");
m_dynamicDraw.FrameEnd();
m_passSystem.FrameEnd();
@@ -397,7 +397,7 @@ namespace AZ
void RenderPipeline::OnStartFrame()
{
AZ_PROFILE_FUNCTION(RPI);
AZ_PROFILE_SCOPE(RPI, "RenderPipeline: OnStartFrame");
m_lastRenderStartTime = m_lastRenderRequestTime;
+11 -16
View File
@@ -6,8 +6,6 @@
*
*/
#include <Atom/RHI/CpuProfiler.h>
#include <Atom/RPI.Public/Culling.h>
#include <Atom/RPI.Public/DynamicDraw/DynamicDrawSystem.h>
#include <Atom/RPI.Public/FeatureProcessorFactory.h>
@@ -350,7 +348,7 @@ namespace AZ
void Scene::Simulate([[maybe_unused]] const TickTimeInfo& tickInfo, RHI::JobPolicy jobPolicy)
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: Simulate");
AZ_PROFILE_SCOPE(RPI, "Scene: Simulate");
m_simulationTime = tickInfo.m_currentGameTime;
@@ -389,7 +387,7 @@ namespace AZ
{
if (completionJob)
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: WaitAndCleanCompletionJob");
AZ_PROFILE_SCOPE(RPI, "Scene: WaitAndCleanCompletionJob");
//[GFX TODO]: the completion job should start earlier and wait for completion here
completionJob->StartAndWaitForCompletion();
delete completionJob;
@@ -422,11 +420,10 @@ namespace AZ
void Scene::PrepareRender([[maybe_unused]]const TickTimeInfo& tickInfo, RHI::JobPolicy jobPolicy)
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: PrepareRender");
AZ_PROFILE_SCOPE(RPI, "Scene: PrepareRender");
{
AZ_PROFILE_SCOPE(RPI, "WaitForSimulationCompletion");
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "WaitForSimulationCompletion");
WaitAndCleanCompletionJob(m_simulationCompletion);
}
@@ -435,7 +432,7 @@ namespace AZ
// Get active pipelines which need to be rendered and notify them of an impending frame.
AZStd::vector<RenderPipelinePtr> activePipelines;
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Scene: OnPrepareFrame");
AZ_PROFILE_SCOPE(RPI, "Scene: OnPrepareFrame");
for (auto& pipeline : m_pipelines)
{
pipeline->OnPrepareFrame();
@@ -449,7 +446,7 @@ namespace AZ
// Get active pipelines which need to be rendered and notify them frame started
for (const auto& pipeline : activePipelines)
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Scene: OnStartFrame");
AZ_PROFILE_SCOPE(RPI, "Scene: OnStartFrame");
pipeline->OnStartFrame();
}
@@ -468,7 +465,7 @@ namespace AZ
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Setup Views");
AZ_PROFILE_SCOPE(RPI, "Setup Views");
// Collect persistent views from all pipelines to be rendered
AZStd::map<ViewPtr, RHI::DrawListMask> persistentViews;
@@ -506,8 +503,7 @@ namespace AZ
}
{
AZ_PROFILE_SCOPE(RPI, "CollectDrawPackets");
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "CollectDrawPackets");
AZ_PROFILE_SCOPE(RPI, "CollectDrawPackets");
AZ::JobCompletion* collectDrawPacketsCompletion = aznew AZ::JobCompletion();
// Launch FeatureProcessor::Render() jobs
@@ -550,14 +546,13 @@ namespace AZ
// Add dynamic draw data for all the views
if (m_dynamicDrawSystem)
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "DynamicDraw SubmitDrawData");
AZ_PROFILE_SCOPE(RPI, "DynamicDraw SubmitDrawData");
m_dynamicDrawSystem->SubmitDrawData(this, m_renderPacket.m_views);
}
}
{
AZ_PROFILE_BEGIN(RPI, "FinalizeDrawLists");
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "FinalizeDrawLists");
if (jobPolicy == RHI::JobPolicy::Serial)
{
for (auto& view : m_renderPacket.m_views)
@@ -586,14 +581,14 @@ namespace AZ
}
{
AZ_ATOM_PROFILE_TIME_GROUP_REGION("RPI", "Scene OnEndPrepareRender");
AZ_PROFILE_SCOPE(RPI, "Scene OnEndPrepareRender");
SceneNotificationBus::Event(GetId(), &SceneNotification::OnEndPrepareRender);
}
}
void Scene::OnFrameEnd()
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: OnFrameEnd");
AZ_PROFILE_SCOPE(RPI, "Scene: OnFrameEnd");
bool didRender = false;
for (auto& pipeline : m_pipelines)
{
@@ -730,7 +725,7 @@ namespace AZ
void Scene::RebuildPipelineStatesLookup()
{
AZ_ATOM_PROFILE_FUNCTION("RPI", "Scene: RebuildPipelineStatesLookup");
AZ_PROFILE_SCOPE(RPI, "Scene: RebuildPipelineStatesLookup");
m_pipelineStatesLookup.clear();
AZStd::queue<ParentPass*> parents;
@@ -113,7 +113,7 @@ namespace AZ
return;
}
AZ_PROFILE_FUNCTION(RPI);
AZ_PROFILE_SCOPE(RPI, "ShaderMetricsSystem: RequestShaderVariant");
AZStd::lock_guard<AZStd::mutex> lock(m_metricsMutex);
@@ -239,7 +239,7 @@ namespace AZ
void View::FinalizeDrawLists()
{
AZ_PROFILE_FUNCTION(RPI);
AZ_PROFILE_SCOPE(RPI, "View: FinalizeDrawLists");
m_drawListContext.FinalizeLists();
if (m_passesByDrawList)
{
@@ -57,7 +57,7 @@ namespace AZ
// Only allocate buffer if initial data is not empty
if (initialData != nullptr && initialDataSize > 0)
{
bufferAsset->m_buffer.resize(descriptor.m_byteCount);
bufferAsset->m_buffer.resize_no_construct(descriptor.m_byteCount);
memcpy(bufferAsset->m_buffer.data(), initialData, initialDataSize);
}