Switched back to making MaterialAsset::GetPropertyValues automatically finalize the material asset. I realized that it's too burdensome to expect client code to call Finalize on the MaterialAsset; every code that calls GetPropertyValues would have to call Finalize(). Instead of using const_cast in GetPropertyValues like I was doing before, I just changed GetPropertyValues to be a non-const function. There were a few places in Decal code I had to update to pass non-const MaterialAsset pointers. This isn't ideal, but I think it's better than the alternatives.
Signed-off-by: santorac <55155825+santorac@users.noreply.github.com>
This commit is contained in:
@@ -49,7 +49,7 @@ namespace AZ
|
||||
}
|
||||
|
||||
// Extract exactly which texture asset we need to load from the given material and map type (diffuse, normal, etc).
|
||||
static AZ::Data::Asset<AZ::RPI::StreamingImageAsset> GetStreamingImageAsset(const AZ::RPI::MaterialAsset& materialAsset, const AZ::Name& propertyName)
|
||||
static AZ::Data::Asset<AZ::RPI::StreamingImageAsset> GetStreamingImageAsset(AZ::RPI::MaterialAsset& materialAsset, const AZ::Name& propertyName)
|
||||
{
|
||||
if (!materialAsset.IsReady())
|
||||
{
|
||||
@@ -84,7 +84,7 @@ namespace AZ
|
||||
static AZ::Data::Asset<AZ::RPI::StreamingImageAsset> GetStreamingImageAsset(const AZ::Data::Asset<Data::AssetData> materialAssetData, const AZ::Name& propertyName)
|
||||
{
|
||||
AZ_Assert(materialAssetData->IsReady(), "GetStreamingImageAsset() called with AssetData that is not ready.");
|
||||
const AZ::RPI::MaterialAsset* materialAsset = materialAssetData.GetAs<AZ::RPI::MaterialAsset>();
|
||||
AZ::RPI::MaterialAsset* materialAsset = materialAssetData.GetAs<AZ::RPI::MaterialAsset>();
|
||||
return GetStreamingImageAsset(*materialAsset, propertyName);
|
||||
}
|
||||
}
|
||||
@@ -141,7 +141,7 @@ namespace AZ
|
||||
return m_textureArrayPacked[mapType];
|
||||
}
|
||||
|
||||
bool DecalTextureArray::IsValidDecalMaterial(const AZ::RPI::MaterialAsset& materialAsset)
|
||||
bool DecalTextureArray::IsValidDecalMaterial(AZ::RPI::MaterialAsset& materialAsset)
|
||||
{
|
||||
return GetStreamingImageAsset(materialAsset, GetMapName(DecalMapType_Diffuse)).IsReady();
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace AZ
|
||||
// often different (BC5 for normals, BC7 for diffuse, etc)
|
||||
const Data::Instance<RPI::StreamingImage>& GetPackedTexture(const DecalMapType mapType) const;
|
||||
|
||||
static bool IsValidDecalMaterial(const RPI::MaterialAsset& materialAsset);
|
||||
static bool IsValidDecalMaterial(RPI::MaterialAsset& materialAsset);
|
||||
|
||||
private:
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ namespace AZ
|
||||
{
|
||||
namespace
|
||||
{
|
||||
static AZ::RHI::Size GetTextureSizeFromMaterialAsset(const AZ::RPI::MaterialAsset* materialAsset)
|
||||
static AZ::RHI::Size GetTextureSizeFromMaterialAsset(AZ::RPI::MaterialAsset* materialAsset)
|
||||
{
|
||||
for (const auto& elem : materialAsset->GetPropertyValues())
|
||||
{
|
||||
@@ -375,7 +375,7 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::optional<AZ::Render::DecalTextureArrayFeatureProcessor::DecalLocation> DecalTextureArrayFeatureProcessor::AddMaterialToTextureArrays(const AZ::RPI::MaterialAsset* materialAsset)
|
||||
AZStd::optional<AZ::Render::DecalTextureArrayFeatureProcessor::DecalLocation> DecalTextureArrayFeatureProcessor::AddMaterialToTextureArrays(AZ::RPI::MaterialAsset* materialAsset)
|
||||
{
|
||||
const RHI::Size textureSize = GetTextureSizeFromMaterialAsset(materialAsset);
|
||||
|
||||
@@ -410,7 +410,7 @@ namespace AZ
|
||||
AZ_PROFILE_SCOPE(AzRender, "DecalTextureArrayFeatureProcessor: OnAssetReady");
|
||||
const Data::AssetId& assetId = asset->GetId();
|
||||
|
||||
const RPI::MaterialAsset* materialAsset = asset.GetAs<AZ::RPI::MaterialAsset>();
|
||||
RPI::MaterialAsset* materialAsset = asset.GetAs<AZ::RPI::MaterialAsset>();
|
||||
const bool validDecalMaterial = materialAsset && DecalTextureArray::IsValidDecalMaterial(*materialAsset);
|
||||
if (validDecalMaterial)
|
||||
{
|
||||
|
||||
@@ -111,7 +111,7 @@ namespace AZ
|
||||
void CacheShaderIndices();
|
||||
|
||||
// This call could fail (returning nullopt) if we run out of texture arrays
|
||||
AZStd::optional<DecalLocation> AddMaterialToTextureArrays(const AZ::RPI::MaterialAsset* materialAsset);
|
||||
AZStd::optional<DecalLocation> AddMaterialToTextureArrays(AZ::RPI::MaterialAsset* materialAsset);
|
||||
|
||||
int FindTextureArrayWithSize(const RHI::Size& size) const;
|
||||
void RemoveMaterialFromDecal(const uint16_t decalIndex);
|
||||
|
||||
@@ -102,16 +102,6 @@ namespace AZ
|
||||
//! Returns a layout that includes a list of MaterialPropertyDescriptors for each material property.
|
||||
const MaterialPropertiesLayout* GetMaterialPropertiesLayout() const;
|
||||
|
||||
//! Returns whether the material's properties are fully processed or not.
|
||||
//! If true, property values can be accessed through GetPropertyValues().
|
||||
//! If false, property values can be accessed through GetRawPropertyValues().
|
||||
bool IsFinalized() const;
|
||||
|
||||
//! If the material asset is not finalized yet, this does the final processing of the raw property values to
|
||||
//! get the material asset ready to be used.
|
||||
//! Note the MaterialTypeAsset must be valid before this is called.
|
||||
void Finalize(AZStd::function<void(const char*)> reportWarning = nullptr, AZStd::function<void(const char*)> reportError = nullptr);
|
||||
|
||||
//! Returns the list of values for all properties in this material.
|
||||
//! The entries in this list align with the entries in the MaterialPropertiesLayout. Each AZStd::any is guaranteed
|
||||
//! to have a value of type that matches the corresponding MaterialPropertyDescriptor.
|
||||
@@ -122,19 +112,26 @@ namespace AZ
|
||||
//!
|
||||
//! Calling GetPropertyValues() will automatically finalize the material asset if it isn't finalized already. The
|
||||
//! MaterialTypeAsset must be loaded and ready.
|
||||
const AZStd::vector<MaterialPropertyValue>& GetPropertyValues() const;
|
||||
|
||||
const AZStd::vector<MaterialPropertyValue>& GetPropertyValues();
|
||||
|
||||
//! Returns true if material was created in a finalize state, as opposed to being finalized after loading from disk.
|
||||
bool WasPreFinalized() const;
|
||||
|
||||
//! Returns the list of raw values for all properties in this material, as listed in the source .material file(s), before the material asset was Finalized.
|
||||
//!
|
||||
//! The MaterialAsset can be created in a "half-baked" state (see MaterialUtils::BuildersShouldFinalizeMaterialAssets) where
|
||||
//! minimal processing has been done because it did not yet have access to the MaterialTypeAsset. In that case, the list will
|
||||
//! be populated with values copied from the source .material file with little or no validation or other processing. It includes
|
||||
//! all parent .material files, with properties listed in low-to-high priority order.
|
||||
//! This list will be empty however if the asset was finalized at build-time.
|
||||
//! This list will be empty however if the asset was finalized at build-time (i.e. WasPreFinalized() returns true).
|
||||
const AZStd::vector<AZStd::pair<Name, MaterialPropertyValue>>& GetRawPropertyValues() const;
|
||||
|
||||
private:
|
||||
bool PostLoadInit() override;
|
||||
|
||||
//! If the material asset is not finalized yet, this does the final processing of the raw property values to get the material asset ready to be used.
|
||||
//! MaterialTypeAsset must be valid before this is called.
|
||||
void Finalize(AZStd::function<void(const char*)> reportWarning = nullptr, AZStd::function<void(const char*)> reportError = nullptr);
|
||||
|
||||
//! Checks the material type version and potentially applies a series of property changes (most common are simple property renames)
|
||||
//! based on the MaterialTypeAsset's version update procedure.
|
||||
@@ -159,7 +156,7 @@ namespace AZ
|
||||
|
||||
//! Holds values for each material property, used to initialize Material instances.
|
||||
//! This is indexed by MaterialPropertyIndex and aligns with entries in m_materialPropertiesLayout.
|
||||
AZStd::vector<MaterialPropertyValue> m_propertyValues;
|
||||
mutable AZStd::vector<MaterialPropertyValue> m_propertyValues;
|
||||
|
||||
//! The MaterialAsset can be created in a "half-baked" state where minimal processing has been done because it does
|
||||
//! not yet have access to the MaterialTypeAsset. In that case, this list will be populated with values copied from
|
||||
@@ -175,10 +172,10 @@ namespace AZ
|
||||
AZStd::vector<AZStd::pair<Name, MaterialPropertyValue>> m_rawPropertyValues;
|
||||
|
||||
//! Tracks whether Finalize() has been called, meaning m_propertyValues is populated with data matching the material type's property layout.
|
||||
bool m_isFinalized = false;
|
||||
//! (This value is intentionally not serialized, it is set by the Finalize() function)
|
||||
mutable bool m_isFinalized = false;
|
||||
|
||||
//! Tracks whether the MaterialAsset was already in a finalized state when it was loaded.
|
||||
//! (This value is intentionally not serialized)
|
||||
bool m_wasPreFinalized = false;
|
||||
|
||||
//! The materialTypeVersion this materialAsset was based off. If the versions do not match at runtime when a
|
||||
|
||||
@@ -52,7 +52,7 @@ namespace AZ
|
||||
{
|
||||
AssetBuilderSDK::AssetBuilderDesc materialBuilderDescriptor;
|
||||
materialBuilderDescriptor.m_name = JobKey;
|
||||
materialBuilderDescriptor.m_version = 114; // material dependency improvements
|
||||
materialBuilderDescriptor.m_version = 115; // material dependency improvements updated
|
||||
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>();
|
||||
|
||||
@@ -128,7 +128,7 @@ namespace AZ
|
||||
if (auto* serialize = azrtti_cast<SerializeContext*>(context))
|
||||
{
|
||||
serialize->Class<MaterialAssetBuilderComponent, SceneAPI::SceneCore::ExportingComponent>()
|
||||
->Version(20); // material dependency improvements
|
||||
->Version(21); // material dependency improvements updated
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -62,8 +62,6 @@ namespace AZ
|
||||
|
||||
m_materialAsset = { &materialAsset, AZ::Data::AssetLoadBehavior::PreLoad };
|
||||
|
||||
m_materialAsset->Finalize();
|
||||
|
||||
// Cache off pointers to some key data structures from the material type...
|
||||
auto srgLayout = m_materialAsset->GetMaterialSrgLayout();
|
||||
if (srgLayout)
|
||||
|
||||
@@ -33,12 +33,12 @@ namespace AZ
|
||||
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<MaterialAsset, AZ::Data::AssetData>()
|
||||
->Version(13) // added m_rawPropertyValues
|
||||
->Version(14) // added m_rawPropertyValues
|
||||
->Field("materialTypeAsset", &MaterialAsset::m_materialTypeAsset)
|
||||
->Field("materialTypeVersion", &MaterialAsset::m_materialTypeVersion)
|
||||
->Field("propertyValues", &MaterialAsset::m_propertyValues)
|
||||
->Field("rawPropertyValues", &MaterialAsset::m_rawPropertyValues)
|
||||
->Field("isFinalized", &MaterialAsset::m_isFinalized)
|
||||
->Field("finalized", &MaterialAsset::m_wasPreFinalized)
|
||||
;
|
||||
}
|
||||
}
|
||||
@@ -104,19 +104,19 @@ namespace AZ
|
||||
return m_materialTypeAsset->GetMaterialPropertiesLayout();
|
||||
}
|
||||
|
||||
bool MaterialAsset::IsFinalized() const
|
||||
bool MaterialAsset::WasPreFinalized() const
|
||||
{
|
||||
if (m_isFinalized)
|
||||
{
|
||||
AZ_Assert(GetMaterialPropertiesLayout() && m_propertyValues.size() == GetMaterialPropertiesLayout()->GetPropertyCount(), "MaterialAsset is marked as Finalized but does not have the right number of property values.");
|
||||
}
|
||||
|
||||
return m_isFinalized;
|
||||
return m_wasPreFinalized;
|
||||
}
|
||||
|
||||
void MaterialAsset::Finalize(AZStd::function<void(const char*)> reportWarning, AZStd::function<void(const char*)> reportError)
|
||||
{
|
||||
if (IsFinalized())
|
||||
if (m_wasPreFinalized)
|
||||
{
|
||||
m_isFinalized = true;
|
||||
}
|
||||
|
||||
if (m_isFinalized)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -197,10 +197,18 @@ namespace AZ
|
||||
m_isFinalized = true;
|
||||
}
|
||||
|
||||
const AZStd::vector<MaterialPropertyValue>& MaterialAsset::GetPropertyValues() const
|
||||
const AZStd::vector<MaterialPropertyValue>& MaterialAsset::GetPropertyValues()
|
||||
{
|
||||
AZ_Error(s_debugTraceName, IsFinalized(), "MaterialAsset must be finalized before its property values can be accessed");
|
||||
// This can't be done in MaterialAssetHandler::LoadAssetData because the MaterialTypeAsset isn't necessarily loaded at that point.
|
||||
// And it can't be done in PostLoadInit() because that happens on the next frame which might be too late.
|
||||
// And overriding AssetHandler::InitAsset in MaterialAssetHandler didn't work, because there seems to be non-determinism on the order
|
||||
// of InitAsset calls when a ModelAsset references a MaterialAsset, the model gets initialized first and then fails to use the material.
|
||||
// So we finalize just-in-time when properties are accessed.
|
||||
// If we could solve the problem with InitAsset, that would be the ideal place to call Finalize() and we could make GetPropertyValues() const again.
|
||||
Finalize();
|
||||
|
||||
AZ_Assert(GetMaterialPropertiesLayout() && m_propertyValues.size() == GetMaterialPropertiesLayout()->GetPropertyCount(), "MaterialAsset should be finalized but does not have the right number of property values.");
|
||||
|
||||
return m_propertyValues;
|
||||
}
|
||||
|
||||
@@ -334,7 +342,6 @@ namespace AZ
|
||||
if (Base::LoadAssetData(asset, stream, assetLoadFilterCB) == Data::AssetHandler::LoadResult::LoadComplete)
|
||||
{
|
||||
asset.GetAs<MaterialAsset>()->AssetInitBus::Handler::BusConnect();
|
||||
asset.GetAs<MaterialAsset>()->m_wasPreFinalized = asset.GetAs<MaterialAsset>()->m_isFinalized;
|
||||
return Data::AssetHandler::LoadResult::LoadComplete;
|
||||
}
|
||||
|
||||
|
||||
@@ -49,6 +49,8 @@ namespace AZ
|
||||
[this](const char* message) { ReportWarning("%s", message); },
|
||||
[this](const char* message) { ReportError("%s", message); });
|
||||
|
||||
m_asset->m_wasPreFinalized = true;
|
||||
|
||||
// Finalize() doesn't clear the raw property data because that's the same function used at runtime, which does need to maintain the raw data
|
||||
// to support hot reload. But here we are pre-baking with the assumption that AP build dependencies will keep the material type
|
||||
// and material asset in sync, so we can discard the raw property data and just rely on the data in the material type asset.
|
||||
|
||||
@@ -111,6 +111,10 @@ namespace UnitTest
|
||||
|
||||
EXPECT_EQ(assetId, materialAsset->GetId());
|
||||
EXPECT_EQ(Data::AssetData::AssetStatus::Ready, materialAsset->GetStatus());
|
||||
|
||||
EXPECT_TRUE(materialAsset->WasPreFinalized());
|
||||
EXPECT_EQ(0, materialAsset->GetRawPropertyValues().size());
|
||||
|
||||
validate(materialAsset);
|
||||
|
||||
// Also test serialization...
|
||||
@@ -123,6 +127,57 @@ namespace UnitTest
|
||||
Data::Asset<RPI::MaterialAsset> serializedAsset = tester.SerializeIn(Data::AssetId(Uuid::CreateRandom()), noAssets);
|
||||
validate(serializedAsset);
|
||||
}
|
||||
|
||||
TEST_F(MaterialAssetTests, DeferredFinalize)
|
||||
{
|
||||
Data::AssetId assetId(Uuid::CreateRandom());
|
||||
|
||||
MaterialAssetCreator creator;
|
||||
bool shouldFinalize = false;
|
||||
creator.Begin(assetId, m_testMaterialTypeAsset, shouldFinalize);
|
||||
|
||||
creator.SetPropertyValue(Name{ "MyFloat2" }, Vector2{ 0.1f, 0.2f });
|
||||
creator.SetPropertyValue(Name{ "MyFloat3" }, Vector3{ 1.1f, 1.2f, 1.3f });
|
||||
creator.SetPropertyValue(Name{ "MyFloat4" }, Vector4{ 2.1f, 2.2f, 2.3f, 2.4f });
|
||||
creator.SetPropertyValue(Name{ "MyColor" }, Color{ 1.0f, 1.0f, 1.0f, 1.0f });
|
||||
creator.SetPropertyValue(Name{ "MyInt" }, -2);
|
||||
creator.SetPropertyValue(Name{ "MyUInt" }, 12u);
|
||||
creator.SetPropertyValue(Name{ "MyFloat" }, 1.5f);
|
||||
creator.SetPropertyValue(Name{ "MyBool" }, true);
|
||||
creator.SetPropertyValue(Name{ "MyImage" }, m_testImageAsset);
|
||||
creator.SetPropertyValue(Name{ "MyEnum" }, 1u);
|
||||
|
||||
Data::Asset<MaterialAsset> materialAsset;
|
||||
EXPECT_TRUE(creator.End(materialAsset));
|
||||
|
||||
EXPECT_FALSE(materialAsset->WasPreFinalized());
|
||||
EXPECT_EQ(10, materialAsset->GetRawPropertyValues().size());
|
||||
|
||||
// Also test serialization...
|
||||
|
||||
SerializeTester<RPI::MaterialAsset> tester(GetSerializeContext());
|
||||
tester.SerializeOut(materialAsset.Get());
|
||||
|
||||
// Using a filter that skips loading assets because we are using a dummy image asset
|
||||
ObjectStream::FilterDescriptor noAssets{ AZ::Data::AssetFilterNoAssetLoading };
|
||||
Data::Asset<RPI::MaterialAsset> serializedAsset = tester.SerializeIn(Data::AssetId(Uuid::CreateRandom()), noAssets);
|
||||
|
||||
EXPECT_FALSE(materialAsset->WasPreFinalized());
|
||||
EXPECT_EQ(10, materialAsset->GetRawPropertyValues().size());
|
||||
|
||||
// GetPropertyValues() will automatically finalize the material asset, so we can go ahead and check the property values.
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues().size(), 10);
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues()[0].GetValue<bool>(), true);
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues()[1].GetValue<int32_t>(), -2);
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues()[2].GetValue<uint32_t>(), 12);
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues()[3].GetValue<float>(), 1.5f);
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues()[4].GetValue<Vector2>(), Vector2(0.1f, 0.2f));
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues()[5].GetValue<Vector3>(), Vector3(1.1f, 1.2f, 1.3f));
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues()[6].GetValue<Vector4>(), Vector4(2.1f, 2.2f, 2.3f, 2.4f));
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues()[7].GetValue<Color>(), Color(1.0f, 1.0f, 1.0f, 1.0f));
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues()[8].GetValue<Data::Asset<ImageAsset>>(), m_testImageAsset);
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues()[9].GetValue<uint32_t>(), 1u);
|
||||
}
|
||||
|
||||
TEST_F(MaterialAssetTests, PropertyDefaultValuesComeFromParentMaterial)
|
||||
{
|
||||
@@ -267,15 +322,13 @@ namespace UnitTest
|
||||
warningFinder.AddExpectedErrorMessage("This material is based on version '1'");
|
||||
warningFinder.AddExpectedErrorMessage("material type is now at version '2'");
|
||||
|
||||
materialAsset->Finalize();
|
||||
|
||||
warningFinder.CheckExpectedErrorsFound();
|
||||
|
||||
// Even though this material was created using the old version of the material type, it's property values should get automatically
|
||||
// updated to align with the new property layout in the latest MaterialTypeAsset.
|
||||
MaterialPropertyIndex myIntIndex = materialAsset->GetMaterialPropertiesLayout()->FindPropertyIndex(Name{"MyIntRenamed"});
|
||||
EXPECT_EQ(2, myIntIndex.GetIndex());
|
||||
EXPECT_EQ(7, materialAsset->GetPropertyValues()[myIntIndex.GetIndex()].GetValue<int32_t>());
|
||||
|
||||
warningFinder.CheckExpectedErrorsFound();
|
||||
|
||||
// Since the MaterialAsset has already been updated, and the warning reported once, we should not see the "consider updating"
|
||||
// warning reported again on subsequent property accesses.
|
||||
|
||||
@@ -182,7 +182,7 @@ namespace UnitTest
|
||||
|
||||
Data::Asset<MaterialAsset> materialAsset = materialAssetOutcome.GetValue();
|
||||
|
||||
EXPECT_TRUE(materialAsset->IsFinalized());
|
||||
EXPECT_TRUE(materialAsset->WasPreFinalized());
|
||||
EXPECT_EQ(0, materialAsset->GetRawPropertyValues().size()); // A pre-baked material has no need for the original raw property names and values
|
||||
|
||||
// The order here is based on the order in the MaterialTypeSourceData, as added to the MaterialTypeAssetCreator.
|
||||
@@ -227,14 +227,10 @@ namespace UnitTest
|
||||
EXPECT_TRUE(materialAssetOutcome.IsSuccess());
|
||||
|
||||
Data::Asset<MaterialAsset> materialAsset = materialAssetOutcome.GetValue();
|
||||
|
||||
ErrorMessageFinder expectNotFinalizedError("MaterialAsset must be finalized");
|
||||
|
||||
EXPECT_FALSE(materialAsset->IsFinalized());
|
||||
EXPECT_FALSE(materialAsset->WasPreFinalized());
|
||||
|
||||
expectNotFinalizedError.ResetCounts();
|
||||
EXPECT_TRUE(materialAsset->GetPropertyValues().empty());
|
||||
expectNotFinalizedError.CheckExpectedErrorsFound();
|
||||
// Note we avoid calling GetPropertyValues() because that will auto-finalize the material. We want to check its raw property values first.
|
||||
|
||||
auto findRawPropertyValue = [materialAsset](const char* propertyId)
|
||||
{
|
||||
@@ -279,16 +275,10 @@ namespace UnitTest
|
||||
SerializeTester<RPI::MaterialAsset> tester(GetSerializeContext());
|
||||
tester.SerializeOut(materialAsset.Get());
|
||||
materialAsset = tester.SerializeIn(Uuid::CreateRandom(), ObjectStream::FilterDescriptor{AZ::Data::AssetFilterNoAssetLoading});
|
||||
|
||||
// We check that everything is still in the original un-finalized state after going through the serialization process.
|
||||
EXPECT_FALSE(materialAsset->IsFinalized());
|
||||
checkRawPropertyValues();
|
||||
expectNotFinalizedError.ResetCounts();
|
||||
EXPECT_TRUE(materialAsset->GetPropertyValues().empty());
|
||||
expectNotFinalizedError.CheckExpectedErrorsFound();
|
||||
|
||||
materialAsset->Finalize();
|
||||
EXPECT_TRUE(materialAsset->IsFinalized());
|
||||
// We check that the asset is still in the original un-finalized state after going through the serialization process.
|
||||
EXPECT_FALSE(materialAsset->WasPreFinalized());
|
||||
checkRawPropertyValues();
|
||||
|
||||
// Now all the property values should be available through the main GetPropertyValues() API.
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues()[0].GetValue<bool>(), true);
|
||||
@@ -301,8 +291,9 @@ namespace UnitTest
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues()[7].GetValue<Color>(), Color(0.1f, 0.2f, 0.3f, 0.4f));
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues()[8].GetValue<Data::Asset<ImageAsset>>(), m_testImageAsset);
|
||||
EXPECT_EQ(materialAsset->GetPropertyValues()[9].GetValue<uint32_t>(), 1u);
|
||||
|
||||
|
||||
// The raw property values are still available (because they are needed if a hot-reload of the MaterialTypeAsset occurs)
|
||||
EXPECT_FALSE(materialAsset->WasPreFinalized());
|
||||
checkRawPropertyValues();
|
||||
}
|
||||
|
||||
@@ -659,19 +650,19 @@ namespace UnitTest
|
||||
|
||||
auto materialAssetLevel1 = sourceDataLevel1.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true);
|
||||
EXPECT_TRUE(materialAssetLevel1.IsSuccess());
|
||||
EXPECT_TRUE(materialAssetLevel1.GetValue()->IsFinalized());
|
||||
EXPECT_TRUE(materialAssetLevel1.GetValue()->WasPreFinalized());
|
||||
|
||||
m_assetSystemStub.RegisterSourceInfo("level1.material", materialAssetLevel1.GetValue().GetId());
|
||||
|
||||
auto materialAssetLevel2 = sourceDataLevel2.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true);
|
||||
EXPECT_TRUE(materialAssetLevel2.IsSuccess());
|
||||
EXPECT_TRUE(materialAssetLevel2.GetValue()->IsFinalized());
|
||||
EXPECT_TRUE(materialAssetLevel2.GetValue()->WasPreFinalized());
|
||||
|
||||
m_assetSystemStub.RegisterSourceInfo("level2.material", materialAssetLevel2.GetValue().GetId());
|
||||
|
||||
auto materialAssetLevel3 = sourceDataLevel3.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::PreBake, true);
|
||||
EXPECT_TRUE(materialAssetLevel3.IsSuccess());
|
||||
EXPECT_TRUE(materialAssetLevel3.GetValue()->IsFinalized());
|
||||
EXPECT_TRUE(materialAssetLevel3.GetValue()->WasPreFinalized());
|
||||
|
||||
auto layout = m_testMaterialTypeAsset->GetMaterialPropertiesLayout();
|
||||
MaterialPropertyIndex myFloat = layout->FindPropertyIndex(Name("general.MyFloat"));
|
||||
@@ -731,21 +722,21 @@ namespace UnitTest
|
||||
auto materialAssetLevel1Result = sourceDataLevel1.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::DeferredBake, true);
|
||||
EXPECT_TRUE(materialAssetLevel1Result.IsSuccess());
|
||||
Data::Asset<MaterialAsset> materialAssetLevel1 = materialAssetLevel1Result.TakeValue();
|
||||
EXPECT_FALSE(materialAssetLevel1->IsFinalized());
|
||||
EXPECT_FALSE(materialAssetLevel1->WasPreFinalized());
|
||||
|
||||
m_assetSystemStub.RegisterSourceInfo("level1.material", materialAssetLevel1.GetId());
|
||||
|
||||
auto materialAssetLevel2Result = sourceDataLevel2.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::DeferredBake, true);
|
||||
EXPECT_TRUE(materialAssetLevel2Result.IsSuccess());
|
||||
Data::Asset<MaterialAsset> materialAssetLevel2 = materialAssetLevel2Result.TakeValue();
|
||||
EXPECT_FALSE(materialAssetLevel2->IsFinalized());
|
||||
EXPECT_FALSE(materialAssetLevel2->WasPreFinalized());
|
||||
|
||||
m_assetSystemStub.RegisterSourceInfo("level2.material", materialAssetLevel2.GetId());
|
||||
|
||||
auto materialAssetLevel3Result = sourceDataLevel3.CreateMaterialAsset(Uuid::CreateRandom(), "", MaterialAssetProcessingMode::DeferredBake, true);
|
||||
EXPECT_TRUE(materialAssetLevel3Result.IsSuccess());
|
||||
Data::Asset<MaterialAsset> materialAssetLevel3 = materialAssetLevel3Result.TakeValue();
|
||||
EXPECT_FALSE(materialAssetLevel3->IsFinalized());
|
||||
EXPECT_FALSE(materialAssetLevel3->WasPreFinalized());
|
||||
|
||||
// Now we'll create the material type asset in memory so the materials will have what they need to finalize.
|
||||
Data::Asset<MaterialTypeAsset> testMaterialTypeAsset = CreateTestMaterialTypeAsset(materialTypeAssetId);
|
||||
@@ -766,9 +757,7 @@ namespace UnitTest
|
||||
tester.SerializeOut(materialAssetLevel3.Get());
|
||||
materialAssetLevel3 = tester.SerializeIn(Uuid::CreateRandom(), ObjectStream::FilterDescriptor{AZ::Data::AssetFilterNoAssetLoading});
|
||||
|
||||
materialAssetLevel1->Finalize();
|
||||
materialAssetLevel2->Finalize();
|
||||
materialAssetLevel3->Finalize();
|
||||
// The properties will finalize automatically when we call GetPropertyValues()...
|
||||
|
||||
AZStd::array_view<MaterialPropertyValue> properties;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user