c9ee1f7871
The issue was because the preset reload was only happened in CreateJobs but not ProcessJobs. But these two functions might be called from different AssetBuilder. The fix is to add preset reload for Processjobs too. There was another change to add debug device name for streaming image. Signed-off-by: Qing Tao <55564570+VickyAtAZ@users.noreply.github.com>
351 lines
16 KiB
C++
351 lines
16 KiB
C++
/*
|
|
* 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 <BuilderSettings/TextureSettings.h>
|
|
#include <AzCore/RTTI/ReflectContext.h>
|
|
#include <AzCore/Serialization/EditContext.h>
|
|
#include <AzFramework/StringFunc/StringFunc.h>
|
|
#include <AzCore/IO/FileIO.h>
|
|
#include <AzCore/IO/SystemFile.h>
|
|
#include <AzCore/Serialization/Utils.h>
|
|
|
|
#include <BuilderSettings/BuilderSettingManager.h>
|
|
#include <ImageLoader/ImageLoaders.h>
|
|
|
|
|
|
namespace ImageProcessingAtom
|
|
{
|
|
const char* TextureSettings::ExtensionName = ".assetinfo";
|
|
|
|
TextureSettings::TextureSettings()
|
|
: m_presetId(0)
|
|
, m_sizeReduceLevel(0)
|
|
, m_suppressEngineReduce(false)
|
|
, m_enableMipmap(true)
|
|
, m_maintainAlphaCoverage(false)
|
|
, m_mipGenEval(MipGenEvalType::sum)
|
|
, m_mipGenType(MipGenType::blackmanHarris)
|
|
{
|
|
const int defaultMipMapValue = 50;
|
|
|
|
for (int i = 0; i < s_MaxMipMaps; ++i)
|
|
{
|
|
m_mipAlphaAdjust.push_back(defaultMipMapValue);
|
|
}
|
|
}
|
|
|
|
void TextureSettings::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context);
|
|
if (serialize)
|
|
{
|
|
serialize->Class<TextureSettings>()
|
|
->Version(2)
|
|
->Field("PresetID", &TextureSettings::m_presetId)
|
|
->Field("Preset", &TextureSettings::m_preset)
|
|
->Field("SizeReduceLevel", &TextureSettings::m_sizeReduceLevel)
|
|
->Field("EngineReduce", &TextureSettings::m_suppressEngineReduce)
|
|
->Field("EnableMipmap", &TextureSettings::m_enableMipmap)
|
|
->Field("MaintainAlphaCoverage", &TextureSettings::m_maintainAlphaCoverage)
|
|
->Field("MipMapAlphaAdjustments", &TextureSettings::m_mipAlphaAdjust)
|
|
->Field("MipMapGenEval", &TextureSettings::m_mipGenEval)
|
|
->Field("MipMapGenType", &TextureSettings::m_mipGenType)
|
|
->Field("PlatformSpecificOverrides", &TextureSettings::m_platfromOverrides)
|
|
->Field("OverridingPlatform", &TextureSettings::m_overridingPlatform);
|
|
|
|
AZ::EditContext* edit = serialize->GetEditContext();
|
|
if (edit)
|
|
{
|
|
edit->Class<TextureSettings>("Texture Setting", "")
|
|
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
|
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
|
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
|
|
->DataElement(AZ::Edit::UIHandlers::Default, &TextureSettings::m_mipAlphaAdjust, "Alpha Test Bias", "Multiplies the mipmap's alpha with a scale value that is based on alpha coverage. \
|
|
Set the mip 0 to mip 5 values to offset the alpha test values and ensure the mipmap's alpha coverage matches the original image. Specify a value from 0 to 100.")
|
|
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
|
->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, false)
|
|
->ElementAttribute(AZ::Edit::UIHandlers::Handler, AZ::Edit::UIHandlers::Slider)
|
|
->ElementAttribute(AZ::Edit::Attributes::Min, 0)
|
|
->ElementAttribute(AZ::Edit::Attributes::Max, 100)
|
|
->ElementAttribute(AZ::Edit::Attributes::Step, 1)
|
|
->DataElement(AZ::Edit::UIHandlers::ComboBox, &TextureSettings::m_mipGenType, "Filter Method", "")
|
|
->EnumAttribute(MipGenType::point, "Point")
|
|
->EnumAttribute(MipGenType::box, "Average")
|
|
->EnumAttribute(MipGenType::triangle, "Linear")
|
|
->EnumAttribute(MipGenType::quadratic, "Bilinear")
|
|
->EnumAttribute(MipGenType::gaussian, "Gaussian")
|
|
->EnumAttribute(MipGenType::blackmanHarris, "BlackmanHarris")
|
|
->EnumAttribute(MipGenType::kaiserSinc, "KaiserSinc")
|
|
->DataElement(AZ::Edit::UIHandlers::ComboBox, &TextureSettings::m_mipGenEval, "Pixel Sampling Type", "")
|
|
->EnumAttribute(MipGenEvalType::max, "Max")
|
|
->EnumAttribute(MipGenEvalType::min, "Min")
|
|
->EnumAttribute(MipGenEvalType::sum, "Sum")
|
|
->DataElement(AZ::Edit::UIHandlers::CheckBox, &TextureSettings::m_maintainAlphaCoverage, "Maintain Alpha Coverage", "Select this option to manually adjust Alpha channel mipmaps.")
|
|
;
|
|
}
|
|
}
|
|
}
|
|
|
|
bool TextureSettings::operator!=(const TextureSettings& other) const
|
|
{
|
|
return !(*this == other);
|
|
}
|
|
|
|
bool TextureSettings::operator==(const TextureSettings& other) const
|
|
{
|
|
/////////////////////////////
|
|
// Compare Alpha Adjust
|
|
/////////////////////////////
|
|
bool matchingAlphaTestAdjust = true;
|
|
for (AZ::u8 curIndex = 0; curIndex < s_MaxMipMaps; ++curIndex)
|
|
{
|
|
if (m_mipAlphaAdjust[curIndex] != other.m_mipAlphaAdjust[curIndex])
|
|
{
|
|
matchingAlphaTestAdjust = false;
|
|
break;
|
|
}
|
|
}
|
|
return
|
|
matchingAlphaTestAdjust &&
|
|
m_preset == other.m_preset &&
|
|
m_sizeReduceLevel == other.m_sizeReduceLevel &&
|
|
m_suppressEngineReduce == other.m_suppressEngineReduce &&
|
|
m_maintainAlphaCoverage == other.m_maintainAlphaCoverage &&
|
|
m_mipGenEval == other.m_mipGenEval &&
|
|
m_mipGenType == other.m_mipGenType;
|
|
}
|
|
|
|
bool TextureSettings::Equals(const TextureSettings& other, AZ::SerializeContext* serializeContext)
|
|
{
|
|
/////////////////////////////
|
|
// Compare Common Settings
|
|
/////////////////////////////
|
|
if (*this != other)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
/////////////////////////////
|
|
// Compare Overrides
|
|
/////////////////////////////
|
|
const MultiplatformTextureSettings selfOverrides = GetMultiplatformTextureSetting(*this, serializeContext);
|
|
const MultiplatformTextureSettings otherOverrides = GetMultiplatformTextureSetting(other, serializeContext);
|
|
auto selfOverridesIter = selfOverrides.begin();
|
|
auto otherOverridesIter = otherOverrides.begin();
|
|
|
|
while (selfOverridesIter != selfOverrides.end() && otherOverridesIter != otherOverrides.end())
|
|
{
|
|
if (selfOverridesIter->second != otherOverridesIter->second)
|
|
{
|
|
return false;
|
|
}
|
|
otherOverridesIter++;
|
|
selfOverridesIter++;
|
|
}
|
|
|
|
AZ_Assert(selfOverridesIter == selfOverrides.end() && otherOverridesIter == otherOverrides.end(), "Both iterators must be at the end by now.")
|
|
return true;
|
|
}
|
|
|
|
float TextureSettings::ComputeMIPAlphaOffset(AZ::u32 mip) const
|
|
{
|
|
if (mip / 2 + 1 >= s_MaxMipMaps)
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
float fVal = static_cast<float>(m_mipAlphaAdjust[s_MaxMipMaps - 1]);
|
|
if (mip / 2 + 1 < s_MaxMipMaps)
|
|
{
|
|
float fInterpolationSlider1 = static_cast<float>(m_mipAlphaAdjust[mip / 2]);
|
|
float fInterpolationSlider2 = static_cast<float>(m_mipAlphaAdjust[mip / 2 + 1]);
|
|
fVal = fInterpolationSlider1 + (fInterpolationSlider2 - fInterpolationSlider1) * (mip & 1) * 0.5f;
|
|
}
|
|
|
|
return 0.5f - fVal / 100.0f;
|
|
}
|
|
|
|
void TextureSettings::ApplyPreset(PresetName presetName)
|
|
{
|
|
const PresetSettings* presetSetting = BuilderSettingManager::Instance()->GetPreset(presetName);
|
|
if (presetSetting != nullptr)
|
|
{
|
|
m_sizeReduceLevel = presetSetting->m_sizeReduceLevel;
|
|
m_suppressEngineReduce = presetSetting->m_suppressEngineReduce;
|
|
if (presetSetting->m_mipmapSetting)
|
|
{
|
|
m_mipGenType = presetSetting->m_mipmapSetting->m_type;
|
|
}
|
|
|
|
m_preset = presetName;
|
|
}
|
|
else
|
|
{
|
|
AZ_Error("Image Processing", false, "Cannot set an invalid preset %s!", presetName.GetCStr());
|
|
}
|
|
}
|
|
|
|
StringOutcome TextureSettings::LoadTextureSetting(const AZStd::string& filepath, TextureSettings& textureSettingPtrOut, AZ::SerializeContext* serializeContext /*= nullptr*/)
|
|
{
|
|
auto loadedTextureSettingPtr = AZStd::unique_ptr<TextureSettings>(AZ::Utils::LoadObjectFromFile<TextureSettings>(filepath, serializeContext));
|
|
|
|
if (!loadedTextureSettingPtr)
|
|
{
|
|
return AZ::Failure(AZStd::string());
|
|
}
|
|
|
|
textureSettingPtrOut = *loadedTextureSettingPtr;
|
|
|
|
// In old format, the preset name doesn't exist. Using preset id to get preset name
|
|
// We can remove this when we fully deprecate the preset uuid
|
|
if (textureSettingPtrOut.m_preset.IsEmpty())
|
|
{
|
|
textureSettingPtrOut.m_preset = BuilderSettingManager::Instance()->GetPresetNameFromId(textureSettingPtrOut.m_presetId);
|
|
}
|
|
|
|
return AZ::Success(AZStd::string());
|
|
}
|
|
|
|
StringOutcome TextureSettings::WriteTextureSetting(const AZStd::string& filepath, TextureSettings& textureSetting, AZ::SerializeContext* serializeContext)
|
|
{
|
|
if (false == AZ::Utils::SaveObjectToFile<TextureSettings>(filepath, AZ::DataStream::StreamType::ST_XML, &textureSetting, serializeContext))
|
|
{
|
|
return STRING_OUTCOME_ERROR("Failed to write to file: " + filepath);
|
|
}
|
|
|
|
return STRING_OUTCOME_SUCCESS;
|
|
}
|
|
|
|
MultiplatformTextureSettings TextureSettings::GenerateDefaultMultiplatformTextureSettings(const AZStd::string& imageFilepath)
|
|
{
|
|
MultiplatformTextureSettings settings;
|
|
PlatformNameList platformsList = BuilderSettingManager::Instance()->GetPlatformList();
|
|
PresetName suggestedPreset = BuilderSettingManager::Instance()->GetSuggestedPreset(imageFilepath);
|
|
|
|
// If the suggested preset doesn't exist (or was failed to be loaded), return empty texture settings
|
|
if (BuilderSettingManager::Instance()->GetPreset(suggestedPreset) == nullptr)
|
|
{
|
|
AZ_Error("Image Processing", false, "Failed to find suggested preset [%s]", suggestedPreset.GetCStr());
|
|
return settings;
|
|
}
|
|
|
|
for (PlatformName& platform : platformsList)
|
|
{
|
|
TextureSettings textureSettings;
|
|
textureSettings.ApplyPreset(suggestedPreset);
|
|
settings.insert(AZStd::pair<PlatformName, TextureSettings>(platform, textureSettings));
|
|
}
|
|
return settings;
|
|
}
|
|
|
|
StringOutcome TextureSettings::GetPlatformSpecificTextureSetting(const PlatformName& platformName, const TextureSettings& baseTextureSettings,
|
|
TextureSettings& textureSettingsOut, AZ::SerializeContext* serializeContext)
|
|
{
|
|
// Obtain the DataPatch (if platform exists)
|
|
auto overrideIter = baseTextureSettings.m_platfromOverrides.find(platformName);
|
|
if (overrideIter == baseTextureSettings.m_platfromOverrides.end())
|
|
{
|
|
return STRING_OUTCOME_ERROR(AZStd::string::format("TextureSettings preset [%s] does not have override for platform [%s]",
|
|
baseTextureSettings.m_preset.GetCStr(), platformName.c_str()));
|
|
}
|
|
AZ::DataPatch& platformOverride = const_cast<AZ::DataPatch&>(overrideIter->second);
|
|
|
|
// Update settings instance with override values.
|
|
if (platformOverride.IsData())
|
|
{
|
|
// Apply the AZ::DataPatch to obtain a platform-overridden version of the TextureSettings.
|
|
AZStd::unique_ptr<TextureSettings> platformSpecificTextureSettings(platformOverride.Apply(&baseTextureSettings, serializeContext));
|
|
AZ_Assert(platformSpecificTextureSettings->m_mipAlphaAdjust.size() == s_MaxMipMaps, "Unexpected m_mipAlphaAdjust size.");
|
|
|
|
// Adjust overrides data to imply 'platformSpecificTextureSettings' *IS* the override.
|
|
platformSpecificTextureSettings->m_platfromOverrides.clear();
|
|
platformSpecificTextureSettings->m_overridingPlatform = platformName;
|
|
textureSettingsOut = *platformSpecificTextureSettings;
|
|
}
|
|
else
|
|
{
|
|
textureSettingsOut = baseTextureSettings;
|
|
}
|
|
|
|
return STRING_OUTCOME_SUCCESS;
|
|
}
|
|
|
|
const MultiplatformTextureSettings TextureSettings::GetMultiplatformTextureSetting(const TextureSettings& textureSettings, AZ::SerializeContext* serializeContext)
|
|
{
|
|
MultiplatformTextureSettings loadedSettingsReturn;
|
|
PlatformNameList platformsList = BuilderSettingManager::Instance()->GetPlatformList();
|
|
// Generate MultiplatformTextureSettings based on existing available overrides.
|
|
for (const PlatformName& curPlatformName : platformsList)
|
|
{
|
|
// Start with a copy of the base settings
|
|
TextureSettings curPlatformOverride = textureSettings;
|
|
if (!GetPlatformSpecificTextureSetting(curPlatformName, textureSettings, curPlatformOverride, serializeContext).IsSuccess())
|
|
{
|
|
// We have failed to obtain an override. Maintain base settings to indicate zero overrides.
|
|
// We still want to designate these TextureSettings as an (empty) override.
|
|
curPlatformOverride.m_platfromOverrides.clear();
|
|
curPlatformOverride.m_overridingPlatform = curPlatformName;
|
|
}
|
|
|
|
// Add as an entry to the multiplatform texture settings
|
|
loadedSettingsReturn.insert(AZStd::pair<PlatformName, TextureSettings>(curPlatformName, curPlatformOverride));
|
|
}
|
|
|
|
// return a copy of the results
|
|
return loadedSettingsReturn;
|
|
}
|
|
|
|
const MultiplatformTextureSettings TextureSettings::GetMultiplatformTextureSetting(const AZStd::string& imageFilepath, bool& canOverridePreset, AZ::SerializeContext* serializeContext)
|
|
{
|
|
TextureSettings loadedTextureSetting;
|
|
|
|
// Attempt to get metadata file path from image path.
|
|
AZStd::string metadataFilepath = imageFilepath + TextureSettings::ExtensionName;
|
|
bool hasMetafile = AZ::IO::SystemFile::Exists(metadataFilepath.c_str());
|
|
|
|
canOverridePreset = true;
|
|
|
|
// If the image has an accompanying metadata...
|
|
if(hasMetafile)
|
|
{
|
|
// Parse the metadata file.
|
|
if (LoadTextureSetting(metadataFilepath, loadedTextureSetting, serializeContext).IsSuccess())
|
|
{
|
|
canOverridePreset = false;
|
|
return GetMultiplatformTextureSetting(loadedTextureSetting, serializeContext);
|
|
}
|
|
else
|
|
{
|
|
AZ_Error("Image processing", false, "Failed to load the image's meta file %s", metadataFilepath.c_str());
|
|
}
|
|
}
|
|
|
|
return GenerateDefaultMultiplatformTextureSettings(imageFilepath);
|
|
}
|
|
|
|
StringOutcome TextureSettings::ApplySettings(const TextureSettings& settings, const PlatformName& overridePlatform, AZ::SerializeContext* serializeContext)
|
|
{
|
|
if (overridePlatform.empty())
|
|
{
|
|
*this = settings;
|
|
}
|
|
else
|
|
{
|
|
AZ::DataPatch newOverride;
|
|
if (false == newOverride.Create<TextureSettings, TextureSettings>(this, &settings, AZ::DataPatch::FlagsMap(), AZ::DataPatch::FlagsMap(), serializeContext))
|
|
{
|
|
return STRING_OUTCOME_ERROR("Failed to create TextureSettings platform override data. See AZ_Error log for details.");
|
|
}
|
|
|
|
m_platfromOverrides[overridePlatform] = newOverride;
|
|
}
|
|
|
|
return STRING_OUTCOME_SUCCESS;
|
|
}
|
|
}
|