Merge pull request #5752 from aws-lumberyard-dev/puvvadar/gitflow_211118_o3de

Merge stabilization/2110
This commit is contained in:
puvvadar
2021-11-19 15:46:16 -08:00
committed by GitHub
387 changed files with 6580 additions and 3688 deletions
@@ -63,11 +63,21 @@ namespace AZ
{
BusDisconnect();
}
bool MaterialBuilder::ReportMaterialAssetWarningsAsErrors() const
{
bool warningsAsErrors = false;
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
{
settingsRegistry->Get(warningsAsErrors, "/O3DE/Atom/RPI/MaterialBuilder/WarningsAsErrors");
}
return warningsAsErrors;
}
//! 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. If isOrderedOnceForMaterialTypes is true and the dependency is a materialtype file, the job dependency type
//! 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,
@@ -277,8 +287,8 @@ namespace AZ
return materialTypeAssetOutcome.GetValue();
}
AZ::Data::Asset<MaterialAsset> CreateMaterialAsset(AZStd::string_view materialSourceFilePath, const rapidjson::Value& json)
AZ::Data::Asset<MaterialAsset> MaterialBuilder::CreateMaterialAsset(AZStd::string_view materialSourceFilePath, const rapidjson::Value& json) const
{
auto material = LoadSourceData<MaterialSourceData>(json, materialSourceFilePath);
@@ -292,7 +302,7 @@ namespace AZ
return {};
}
auto materialAssetOutcome = material.GetValue().CreateMaterialAsset(Uuid::CreateRandom(), materialSourceFilePath, true);
auto materialAssetOutcome = material.GetValue().CreateMaterialAsset(Uuid::CreateRandom(), materialSourceFilePath, ReportMaterialAssetWarningsAsErrors());
if (!materialAssetOutcome.IsSuccess())
{
return {};
@@ -9,6 +9,8 @@
#pragma once
#include <AssetBuilderSDK/AssetBuilderBusses.h>
#include <Atom/RPI.Reflect/Material/MaterialAsset.h>
#include <AzCore/JSON/document.h>
namespace AZ
{
@@ -37,6 +39,9 @@ namespace AZ
private:
AZ::Data::Asset<MaterialAsset> CreateMaterialAsset(AZStd::string_view materialSourceFilePath, const rapidjson::Value& json) const;
bool ReportMaterialAssetWarningsAsErrors() const;
bool m_isShuttingDown = false;
};
@@ -10,6 +10,7 @@
#include <AzFramework/StringFunc/StringFunc.h>
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
#include <AzCore/IO/IOUtils.h>
#include <AzCore/IO/Path/Path.h>
namespace AZ
{
@@ -46,6 +47,12 @@ namespace AZ
AZStd::string ResolvePathReference(const AZStd::string& originatingSourceFilePath, const AZStd::string& referencedSourceFilePath)
{
// The IsAbsolute part prevents "second join parameter is an absolute path" warnings in StringFunc::Path::Join below
if (referencedSourceFilePath.empty() || AZ::IO::PathView{referencedSourceFilePath}.IsAbsolute())
{
return referencedSourceFilePath;
}
AZStd::string normalizedReferencedPath = referencedSourceFilePath;
AzFramework::StringFunc::Path::Normalize(normalizedReferencedPath);
@@ -113,7 +120,7 @@ namespace AZ
return results;
}
Outcome<Data::AssetId> MakeAssetId(const AZStd::string& sourcePath, uint32_t productSubId)
Outcome<Data::AssetId> MakeAssetId(const AZStd::string& sourcePath, uint32_t productSubId, TraceLevel reporting)
{
bool assetFound = false;
AZ::Data::AssetInfo sourceInfo;
@@ -122,7 +129,7 @@ namespace AZ
if (!assetFound)
{
AZ_Error("AssetUtils", false, "Could not find asset [%s]", sourcePath.c_str());
AssetUtilsInternal::ReportIssue(reporting, AZStd::string::format("Could not find asset [%s]", sourcePath.c_str()).c_str());
return AZ::Failure();
}
else
@@ -131,10 +138,10 @@ namespace AZ
}
}
Outcome<Data::AssetId> MakeAssetId(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId)
Outcome<Data::AssetId> MakeAssetId(const AZStd::string& originatingSourcePath, const AZStd::string& referencedSourceFilePath, uint32_t productSubId, TraceLevel reporting)
{
AZStd::string resolvedPath = ResolvePathReference(originatingSourcePath, referencedSourceFilePath);
return MakeAssetId(resolvedPath, productSubId);
return MakeAssetId(resolvedPath, productSubId, reporting);
}
} // namespace AssetUtils
} // namespace RPI
@@ -304,7 +304,7 @@ namespace AZ
MaterialPropertyId propertyId{ group.first, property.first };
if (!property.second.m_value.IsValid())
{
AZ_Warning("Material source data", false, "Source data for material property value is invalid.");
materialAssetCreator.ReportWarning("Source data for material property value is invalid.");
}
else
{
@@ -318,22 +318,20 @@ namespace AZ
{
case MaterialPropertyDataType::Image:
{
Outcome<Data::Asset<ImageAsset>> imageAssetResult = MaterialUtils::GetImageAssetReference(
materialSourceFilePath, property.second.m_value.GetValue<AZStd::string>());
Data::Asset<ImageAsset> imageAsset;
if (imageAssetResult.IsSuccess())
MaterialUtils::GetImageAssetResult result = MaterialUtils::GetImageAssetReference(
imageAsset, materialSourceFilePath, property.second.m_value.GetValue<AZStd::string>());
if (result == MaterialUtils::GetImageAssetResult::Missing)
{
auto& imageAsset = imageAssetResult.GetValue();
// Load referenced images when load material
imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad);
materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset);
}
else
{
materialAssetCreator.ReportError(
materialAssetCreator.ReportWarning(
"Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(),
property.second.m_value.GetValue<AZStd::string>().data());
}
imageAsset.SetAutoLoadBehavior(Data::AssetLoadBehavior::PreLoad);
materialAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset);
}
break;
case MaterialPropertyDataType::Enum:
@@ -451,20 +451,21 @@ namespace AZ
{
case MaterialPropertyDataType::Image:
{
auto imageAssetResult = MaterialUtils::GetImageAssetReference(
materialTypeSourceFilePath, property.m_value.GetValue<AZStd::string>());
Data::Asset<ImageAsset> imageAsset;
if (imageAssetResult)
{
auto imageAsset = imageAssetResult.GetValue();
materialTypeAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset);
}
else
MaterialUtils::GetImageAssetResult result = MaterialUtils::GetImageAssetReference(
imageAsset, materialTypeSourceFilePath, property.m_value.GetValue<AZStd::string>());
if (result == MaterialUtils::GetImageAssetResult::Missing)
{
materialTypeAssetCreator.ReportError(
"Material property '%s': Could not find the image '%s'", propertyId.GetFullName().GetCStr(),
property.m_value.GetValue<AZStd::string>().data());
}
else
{
materialTypeAssetCreator.SetPropertyValue(propertyId.GetFullName(), imageAsset);
}
}
break;
case MaterialPropertyDataType::Enum:
@@ -28,25 +28,36 @@ namespace AZ
{
namespace MaterialUtils
{
Outcome<Data::Asset<ImageAsset>> GetImageAssetReference(AZStd::string_view materialSourceFilePath, const AZStd::string imageFilePath)
GetImageAssetResult GetImageAssetReference(Data::Asset<ImageAsset>& imageAsset, AZStd::string_view materialSourceFilePath, const AZStd::string imageFilePath)
{
imageAsset = {};
if (imageFilePath.empty())
{
// The image value was present but specified an empty string, meaning the texture asset should be explicitly cleared.
return AZ::Success(Data::Asset<ImageAsset>());
return GetImageAssetResult::Empty;
}
else
{
Outcome<Data::AssetId> imageAssetId = AssetUtils::MakeAssetId(materialSourceFilePath, imageFilePath, StreamingImageAsset::GetImageAssetSubId());
// We use TraceLevel::None because fallback textures are available and we'll return GetImageAssetResult::Missing below in that case.
// Callers of GetImageAssetReference will be responsible for logging warnings or errors as needed.
Outcome<Data::AssetId> imageAssetId = AssetUtils::MakeAssetId(materialSourceFilePath, imageFilePath, StreamingImageAsset::GetImageAssetSubId(), AssetUtils::TraceLevel::None);
if (!imageAssetId.IsSuccess())
{
return AZ::Failure();
}
else
{
Data::Asset<ImageAsset> unloadedImageAssetReference(imageAssetId.GetValue(), azrtti_typeid<StreamingImageAsset>(), imageFilePath);
return AZ::Success(unloadedImageAssetReference);
// When the AssetId cannot be found, we don't want to outright fail, because the runtime has mechanisms for displaying fallback textures which gives the
// user a better recovery workflow. On the other hand we can't just provide an empty/invalid Asset<ImageAsset> because that would be interpreted as simply
// no value was present and result in using no texture, and this would amount to a silent failure.
// So we use a randomly generated (well except for the "BADA55E7" bit ;) UUID which the runtime and tools will interpret as a missing asset and represent
// it as such.
static const Uuid InvalidAssetPlaceholderId = "{BADA55E7-1A1D-4940-B655-9D08679BD62F}";
imageAsset = Data::Asset<ImageAsset>{InvalidAssetPlaceholderId, azrtti_typeid<StreamingImageAsset>(), imageFilePath};
return GetImageAssetResult::Missing;
}
imageAsset = Data::Asset<ImageAsset>{imageAssetId.GetValue(), azrtti_typeid<StreamingImageAsset>(), imageFilePath};
return GetImageAssetResult::Found;
}
}
@@ -178,6 +178,10 @@ namespace AZ
pipelineViews.m_views.resize(1);
}
ViewPtr previousView = pipelineViews.m_views[0];
if (view)
{
view->OnAddToRenderPipeline();
}
pipelineViews.m_views[0] = view;
if (previousView)
@@ -238,6 +242,7 @@ namespace AZ
pipelineViews.m_type = PipelineViewType::Transient;
}
view->SetPassesByDrawList(&pipelineViews.m_passesByDrawList);
view->OnAddToRenderPipeline();
pipelineViews.m_views.push_back(view);
}
}
+64 -26
View File
@@ -47,18 +47,14 @@ namespace AZ
{
AZ_Assert(!name.IsEmpty(), "invalid name");
// Set default matrixes.
// Set default matrices
SetWorldToViewMatrix(AZ::Matrix4x4::CreateIdentity());
AZ::Matrix4x4 viewToClipMatrix;
AZ::MakePerspectiveFovMatrixRH(viewToClipMatrix, AZ::Constants::HalfPi, 1, 0.1f, 1000.f, true);
SetViewToClipMatrix(viewToClipMatrix);
Data::Asset<ShaderAsset> viewSrgShaderAsset = RPISystemInterface::Get()->GetCommonShaderAssetForSrgs();
TryCreateShaderResourceGroup();
if (viewSrgShaderAsset.IsReady())
{
m_shaderResourceGroup = ShaderResourceGroup::Create(viewSrgShaderAsset, RPISystemInterface::Get()->GetViewSrgLayout()->GetName());
}
#if AZ_TRAIT_MASKED_OCCLUSION_CULLING_SUPPORTED
m_maskedOcclusionCulling = MaskedOcclusionCulling::Create();
m_maskedOcclusionCulling->SetResolution(MaskedSoftwareOcclusionCullingWidth, MaskedSoftwareOcclusionCullingHeight);
@@ -125,6 +121,7 @@ namespace AZ
m_worldToViewMatrix = worldToView;
m_worldToClipMatrix = m_viewToClipMatrix * m_worldToViewMatrix;
m_clipToWorldMatrix = m_worldToClipMatrix.GetInverseFull();
m_onWorldToViewMatrixChange.Signal(m_worldToViewMatrix);
m_onWorldToClipMatrixChange.Signal(m_worldToClipMatrix);
@@ -162,6 +159,7 @@ namespace AZ
m_worldToViewMatrix = m_viewToWorldMatrix.GetInverseFast();
m_worldToClipMatrix = m_viewToClipMatrix * m_worldToViewMatrix;
m_clipToWorldMatrix = m_worldToClipMatrix.GetInverseFull();
// Only signal an update when there is a change, otherwise this might block
// user input from changing the value.
@@ -177,6 +175,7 @@ namespace AZ
m_viewToClipMatrix = viewToClip;
m_worldToClipMatrix = m_viewToClipMatrix * m_worldToViewMatrix;
m_clipToWorldMatrix = m_worldToClipMatrix.GetInverseFull();
// Update z depth constant simultaneously
// zNear -> n, zFar -> f
@@ -227,6 +226,11 @@ namespace AZ
return m_worldToClipMatrix;
}
const AZ::Matrix4x4& View::GetClipToWorldMatrix() const
{
return m_clipToWorldMatrix;
}
bool View::HasDrawListTag(RHI::DrawListTag drawListTag)
{
return drawListTag.IsValid() && m_drawListMask[drawListTag.GetIndex()];
@@ -361,16 +365,19 @@ namespace AZ
{
if (m_clipSpaceOffset.IsZero())
{
Matrix4x4 worldToClipPrevMatrix = m_viewToClipPrevMatrix * m_worldToViewPrevMatrix;
m_shaderResourceGroup->SetConstant(m_worldToClipPrevMatrixConstantIndex, worldToClipPrevMatrix);
m_shaderResourceGroup->SetConstant(m_viewProjectionMatrixConstantIndex, m_worldToClipMatrix);
m_shaderResourceGroup->SetConstant(m_projectionMatrixConstantIndex, m_viewToClipMatrix);
m_shaderResourceGroup->SetConstant(m_clipToWorldMatrixConstantIndex, m_clipToWorldMatrix);
m_shaderResourceGroup->SetConstant(m_projectionMatrixInverseConstantIndex, m_viewToClipMatrix.GetInverseFull());
if (m_shaderResourceGroup)
{
Matrix4x4 worldToClipPrevMatrix = m_viewToClipPrevMatrix * m_worldToViewPrevMatrix;
m_shaderResourceGroup->SetConstant(m_worldToClipPrevMatrixConstantIndex, worldToClipPrevMatrix);
m_shaderResourceGroup->SetConstant(m_viewProjectionMatrixConstantIndex, m_worldToClipMatrix);
m_shaderResourceGroup->SetConstant(m_projectionMatrixConstantIndex, m_viewToClipMatrix);
m_shaderResourceGroup->SetConstant(m_clipToWorldMatrixConstantIndex, m_clipToWorldMatrix);
m_shaderResourceGroup->SetConstant(m_projectionMatrixInverseConstantIndex, m_viewToClipMatrix.GetInverseFull());
}
}
else
{
// Offset the current and previous frame clip matricies
// Offset the current and previous frame clip matrices
Matrix4x4 offsetViewToClipMatrix = m_viewToClipMatrix;
offsetViewToClipMatrix.SetElement(0, 2, m_clipSpaceOffset.GetX());
offsetViewToClipMatrix.SetElement(1, 2, m_clipSpaceOffset.GetY());
@@ -379,27 +386,33 @@ namespace AZ
offsetViewToClipPrevMatrix.SetElement(0, 2, m_clipSpaceOffset.GetX());
offsetViewToClipPrevMatrix.SetElement(1, 2, m_clipSpaceOffset.GetY());
// Build other matricies dependent on the view to clip matricies
// Build other matrices dependent on the view to clip matrices
Matrix4x4 offsetWorldToClipMatrix = offsetViewToClipMatrix * m_worldToViewMatrix;
Matrix4x4 offsetWorldToClipPrevMatrix = offsetViewToClipPrevMatrix * m_worldToViewPrevMatrix;
Matrix4x4 offsetClipToViewMatrix = offsetViewToClipMatrix.GetInverseFull();
Matrix4x4 offsetClipToWorldMatrix = m_viewToWorldMatrix * offsetClipToViewMatrix;
m_shaderResourceGroup->SetConstant(m_worldToClipPrevMatrixConstantIndex, offsetWorldToClipPrevMatrix);
m_shaderResourceGroup->SetConstant(m_viewProjectionMatrixConstantIndex, offsetWorldToClipMatrix);
m_shaderResourceGroup->SetConstant(m_projectionMatrixConstantIndex, offsetViewToClipMatrix);
m_shaderResourceGroup->SetConstant(m_clipToWorldMatrixConstantIndex, offsetClipToWorldMatrix);
m_shaderResourceGroup->SetConstant(m_projectionMatrixInverseConstantIndex, offsetViewToClipMatrix.GetInverseFull());
if (m_shaderResourceGroup)
{
m_shaderResourceGroup->SetConstant(m_worldToClipPrevMatrixConstantIndex, offsetWorldToClipPrevMatrix);
m_shaderResourceGroup->SetConstant(m_viewProjectionMatrixConstantIndex, offsetWorldToClipMatrix);
m_shaderResourceGroup->SetConstant(m_projectionMatrixConstantIndex, offsetViewToClipMatrix);
m_shaderResourceGroup->SetConstant(m_clipToWorldMatrixConstantIndex, offsetClipToWorldMatrix);
m_shaderResourceGroup->SetConstant(m_projectionMatrixInverseConstantIndex, offsetViewToClipMatrix.GetInverseFull());
}
}
m_shaderResourceGroup->SetConstant(m_worldPositionConstantIndex, m_position);
m_shaderResourceGroup->SetConstant(m_viewMatrixConstantIndex, m_worldToViewMatrix);
m_shaderResourceGroup->SetConstant(m_viewMatrixInverseConstantIndex, m_worldToViewMatrix.GetInverseFull());
m_shaderResourceGroup->SetConstant(m_zConstantsConstantIndex, m_nearZ_farZ_farZTimesNearZ_farZMinusNearZ);
m_shaderResourceGroup->SetConstant(m_unprojectionConstantsIndex, m_unprojectionConstants);
if (m_shaderResourceGroup)
{
m_shaderResourceGroup->SetConstant(m_worldPositionConstantIndex, m_position);
m_shaderResourceGroup->SetConstant(m_viewMatrixConstantIndex, m_worldToViewMatrix);
m_shaderResourceGroup->SetConstant(m_viewMatrixInverseConstantIndex, m_worldToViewMatrix.GetInverseFull());
m_shaderResourceGroup->SetConstant(m_zConstantsConstantIndex, m_nearZ_farZ_farZTimesNearZ_farZMinusNearZ);
m_shaderResourceGroup->SetConstant(m_unprojectionConstantsIndex, m_unprojectionConstants);
m_shaderResourceGroup->Compile();
m_shaderResourceGroup->Compile();
}
m_viewToClipPrevMatrix = m_viewToClipMatrix;
m_worldToViewPrevMatrix = m_worldToViewMatrix;
@@ -418,5 +431,30 @@ namespace AZ
{
return m_maskedOcclusionCulling;
}
void View::TryCreateShaderResourceGroup()
{
if (!m_shaderResourceGroup)
{
if (auto rpiSystemInterface = RPISystemInterface::Get())
{
if (Data::Asset<ShaderAsset> viewSrgShaderAsset = rpiSystemInterface->GetCommonShaderAssetForSrgs();
viewSrgShaderAsset.IsReady())
{
m_shaderResourceGroup =
ShaderResourceGroup::Create(viewSrgShaderAsset, rpiSystemInterface->GetViewSrgLayout()->GetName());
}
}
}
}
void View::OnAddToRenderPipeline()
{
TryCreateShaderResourceGroup();
if (!m_shaderResourceGroup)
{
AZ_Warning("RPI::View", false, "Shader Resource Group failed to initialize");
}
}
} // namespace RPI
} // namespace AZ
@@ -7,6 +7,7 @@
*/
#include <Atom/RPI.Reflect/Image/StreamingImageAssetHandler.h>
#include <Atom/RPI.Public/Image/ImageSystemInterface.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <AzFramework/Asset/AssetSystemBus.h>
@@ -52,7 +53,7 @@ namespace AZ
missingAssetStatus, &AzFramework::AssetSystem::AssetSystemRequests::GetAssetStatusById, asset.GetId().m_guid);
// Determine which fallback image to use
const char* relativePath = "textures/defaults/defaultfallback.png.streamingimage";
const char* relativePath = DefaultImageAssetPaths::DefaultFallback;
bool useDebugFallbackImages = true;
if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr)
@@ -66,15 +67,15 @@ namespace AZ
{
case AzFramework::AssetSystem::AssetStatus::AssetStatus_Queued:
case AzFramework::AssetSystem::AssetStatus::AssetStatus_Compiling:
relativePath = "textures/defaults/processing.png.streamingimage";
relativePath = DefaultImageAssetPaths::Processing;
break;
case AzFramework::AssetSystem::AssetStatus::AssetStatus_Failed:
relativePath = "textures/defaults/processingfailed.png.streamingimage";
relativePath = DefaultImageAssetPaths::ProcessingFailed;
break;
case AzFramework::AssetSystem::AssetStatus::AssetStatus_Missing:
case AzFramework::AssetSystem::AssetStatus::AssetStatus_Unknown:
case AzFramework::AssetSystem::AssetStatus::AssetStatus_Compiled:
relativePath = "textures/defaults/missing.png.streamingimage";
relativePath = DefaultImageAssetPaths::Missing;
break;
}
}
@@ -118,12 +118,16 @@ namespace AZ
else if (value.is<Data::Asset<Data::AssetData>>())
{
result.m_value = Data::Asset<RPI::ImageAsset>(
AZStd::any_cast<Data::Asset<Data::AssetData>>(value).GetId(), azrtti_typeid<RPI::StreamingImageAsset>());
AZStd::any_cast<Data::Asset<Data::AssetData>>(value).GetId(),
azrtti_typeid<RPI::StreamingImageAsset>(),
AZStd::any_cast<Data::Asset<Data::AssetData>>(value).GetHint());
}
else if (value.is<Data::Asset<StreamingImageAsset>>())
{
result.m_value = Data::Asset<RPI::ImageAsset>(
AZStd::any_cast<Data::Asset<StreamingImageAsset>>(value).GetId(), azrtti_typeid<RPI::StreamingImageAsset>());
AZStd::any_cast<Data::Asset<StreamingImageAsset>>(value).GetId(),
azrtti_typeid<RPI::StreamingImageAsset>(),
AZStd::any_cast<Data::Asset<StreamingImageAsset>>(value).GetHint());
}
else if (value.is<Data::Asset<ImageAsset>>())
{