Refactor Streaming with new settings and textures streaming configuration
This commit is contained in:
@@ -68,6 +68,11 @@ namespace FlaxEditor.Content.Create
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
InputSettings,
|
InputSettings,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The streaming settings.
|
||||||
|
/// </summary>
|
||||||
|
StreamingSettings,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The Windows settings.
|
/// The Windows settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -116,6 +121,7 @@ namespace FlaxEditor.Content.Create
|
|||||||
typeof(LocalizationSettings),
|
typeof(LocalizationSettings),
|
||||||
typeof(BuildSettings),
|
typeof(BuildSettings),
|
||||||
typeof(InputSettings),
|
typeof(InputSettings),
|
||||||
|
typeof(StreamingSettings),
|
||||||
typeof(WindowsPlatformSettings),
|
typeof(WindowsPlatformSettings),
|
||||||
typeof(UWPPlatformSettings),
|
typeof(UWPPlatformSettings),
|
||||||
typeof(LinuxPlatformSettings),
|
typeof(LinuxPlatformSettings),
|
||||||
|
|||||||
@@ -283,6 +283,12 @@ namespace FlaxEditor.Content.Import
|
|||||||
[EditorOrder(250), VisibleIf("PreserveAlphaCoverage"), DefaultValue(0.5f), Tooltip("The reference value for the alpha coverage preserving.")]
|
[EditorOrder(250), VisibleIf("PreserveAlphaCoverage"), DefaultValue(0.5f), Tooltip("The reference value for the alpha coverage preserving.")]
|
||||||
public float PreserveAlphaCoverageReference { get; set; } = 0.5f;
|
public float PreserveAlphaCoverageReference { get; set; } = 0.5f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Texture group for streaming (negative if unused). See Streaming Settings.
|
||||||
|
/// </summary>
|
||||||
|
[EditorOrder(300), Tooltip("Texture group for streaming (negative if unused). See Streaming Settings.")]
|
||||||
|
public int TextureGroup = -1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The sprites. Used to keep created sprites on sprite atlas reimport.
|
/// The sprites. Used to keep created sprites on sprite atlas reimport.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -305,6 +311,7 @@ namespace FlaxEditor.Content.Import
|
|||||||
public float PreserveAlphaCoverageReference;
|
public float PreserveAlphaCoverageReference;
|
||||||
public float Scale;
|
public float Scale;
|
||||||
public int MaxSize;
|
public int MaxSize;
|
||||||
|
public int TextureGroup;
|
||||||
public Int2 Size;
|
public Int2 Size;
|
||||||
public Rectangle[] SpriteAreas;
|
public Rectangle[] SpriteAreas;
|
||||||
public string[] SpriteNames;
|
public string[] SpriteNames;
|
||||||
@@ -327,7 +334,8 @@ namespace FlaxEditor.Content.Import
|
|||||||
PreserveAlphaCoverageReference = PreserveAlphaCoverageReference,
|
PreserveAlphaCoverageReference = PreserveAlphaCoverageReference,
|
||||||
Scale = Scale,
|
Scale = Scale,
|
||||||
Size = Size,
|
Size = Size,
|
||||||
MaxSize = (int)MaxSize
|
MaxSize = (int)MaxSize,
|
||||||
|
TextureGroup = TextureGroup,
|
||||||
};
|
};
|
||||||
if (Sprites != null && Sprites.Count > 0)
|
if (Sprites != null && Sprites.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -362,6 +370,7 @@ namespace FlaxEditor.Content.Import
|
|||||||
PreserveAlphaCoverageReference = options.PreserveAlphaCoverageReference;
|
PreserveAlphaCoverageReference = options.PreserveAlphaCoverageReference;
|
||||||
Scale = options.Scale;
|
Scale = options.Scale;
|
||||||
MaxSize = ConvertMaxSize(options.MaxSize);
|
MaxSize = ConvertMaxSize(options.MaxSize);
|
||||||
|
TextureGroup = options.TextureGroup;
|
||||||
Size = options.Size;
|
Size = options.Size;
|
||||||
if (options.SpriteAreas != null)
|
if (options.SpriteAreas != null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -241,16 +241,13 @@ CreateAssetResult PreviewsCache::create(CreateAssetContext& context)
|
|||||||
IMPORT_SETUP(PreviewsCache, 4);
|
IMPORT_SETUP(PreviewsCache, 4);
|
||||||
|
|
||||||
// Create texture header (custom data)
|
// Create texture header (custom data)
|
||||||
TextureHeader header;
|
TextureHeader textureHeader;
|
||||||
header.Width = ASSETS_ICONS_ATLAS_SIZE;
|
textureHeader.Width = ASSETS_ICONS_ATLAS_SIZE;
|
||||||
header.Height = ASSETS_ICONS_ATLAS_SIZE;
|
textureHeader.Height = ASSETS_ICONS_ATLAS_SIZE;
|
||||||
header.Format = ASSETS_ICONS_ATLAS_FORMAT;
|
textureHeader.Format = ASSETS_ICONS_ATLAS_FORMAT;
|
||||||
header.IsSRGB = false;
|
textureHeader.MipLevels = 1;
|
||||||
header.IsCubeMap = false;
|
textureHeader.NeverStream = true;
|
||||||
header.MipLevels = 1;
|
context.Data.CustomData.Copy(&textureHeader);
|
||||||
header.NeverStream = true;
|
|
||||||
header.Type = TextureFormatType::Unknown;
|
|
||||||
context.Data.CustomData.Copy(&header);
|
|
||||||
|
|
||||||
// Create blank image (chunk 0)
|
// Create blank image (chunk 0)
|
||||||
uint64 imageSize = CalculateTextureMemoryUsage(ASSETS_ICONS_ATLAS_FORMAT, ASSETS_ICONS_ATLAS_SIZE, ASSETS_ICONS_ATLAS_SIZE, 1);
|
uint64 imageSize = CalculateTextureMemoryUsage(ASSETS_ICONS_ATLAS_FORMAT, ASSETS_ICONS_ATLAS_SIZE, ASSETS_ICONS_ATLAS_SIZE, 1);
|
||||||
|
|||||||
@@ -66,6 +66,7 @@ struct InternalTextureOptions
|
|||||||
float PreserveAlphaCoverageReference;
|
float PreserveAlphaCoverageReference;
|
||||||
float Scale;
|
float Scale;
|
||||||
int32 MaxSize;
|
int32 MaxSize;
|
||||||
|
int32 TextureGroup;
|
||||||
int32 SizeX;
|
int32 SizeX;
|
||||||
int32 SizeY;
|
int32 SizeY;
|
||||||
MonoArray* SpriteAreas;
|
MonoArray* SpriteAreas;
|
||||||
@@ -86,6 +87,7 @@ struct InternalTextureOptions
|
|||||||
to->PreserveAlphaCoverage = from->PreserveAlphaCoverage;
|
to->PreserveAlphaCoverage = from->PreserveAlphaCoverage;
|
||||||
to->PreserveAlphaCoverageReference = from->PreserveAlphaCoverageReference;
|
to->PreserveAlphaCoverageReference = from->PreserveAlphaCoverageReference;
|
||||||
to->MaxSize = from->MaxSize;
|
to->MaxSize = from->MaxSize;
|
||||||
|
to->TextureGroup = from->TextureGroup;
|
||||||
to->SizeX = from->SizeX;
|
to->SizeX = from->SizeX;
|
||||||
to->SizeY = from->SizeY;
|
to->SizeY = from->SizeY;
|
||||||
to->Sprites.Clear();
|
to->Sprites.Clear();
|
||||||
@@ -118,6 +120,7 @@ struct InternalTextureOptions
|
|||||||
to->PreserveAlphaCoverageReference = from->PreserveAlphaCoverageReference;
|
to->PreserveAlphaCoverageReference = from->PreserveAlphaCoverageReference;
|
||||||
to->Scale = from->Scale;
|
to->Scale = from->Scale;
|
||||||
to->MaxSize = from->MaxSize;
|
to->MaxSize = from->MaxSize;
|
||||||
|
to->TextureGroup = from->TextureGroup;
|
||||||
to->SizeX = from->SizeX;
|
to->SizeX = from->SizeX;
|
||||||
to->SizeY = from->SizeY;
|
to->SizeY = from->SizeY;
|
||||||
if (from->Sprites.HasItems())
|
if (from->Sprites.HasItems())
|
||||||
|
|||||||
@@ -940,6 +940,7 @@ namespace FlaxEditor.Modules
|
|||||||
Proxy.Add(new SettingsProxy(typeof(AudioSettings), Editor.Instance.Icons.AudioSettings128));
|
Proxy.Add(new SettingsProxy(typeof(AudioSettings), Editor.Instance.Icons.AudioSettings128));
|
||||||
Proxy.Add(new SettingsProxy(typeof(BuildSettings), Editor.Instance.Icons.BuildSettings128));
|
Proxy.Add(new SettingsProxy(typeof(BuildSettings), Editor.Instance.Icons.BuildSettings128));
|
||||||
Proxy.Add(new SettingsProxy(typeof(InputSettings), Editor.Instance.Icons.InputSettings128));
|
Proxy.Add(new SettingsProxy(typeof(InputSettings), Editor.Instance.Icons.InputSettings128));
|
||||||
|
Proxy.Add(new SettingsProxy(typeof(StreamingSettings), Editor.Instance.Icons.BuildSettings128));
|
||||||
Proxy.Add(new SettingsProxy(typeof(WindowsPlatformSettings), Editor.Instance.Icons.WindowsSettings128));
|
Proxy.Add(new SettingsProxy(typeof(WindowsPlatformSettings), Editor.Instance.Icons.WindowsSettings128));
|
||||||
Proxy.Add(new SettingsProxy(typeof(UWPPlatformSettings), Editor.Instance.Icons.UWPSettings128));
|
Proxy.Add(new SettingsProxy(typeof(UWPPlatformSettings), Editor.Instance.Icons.UWPSettings128));
|
||||||
Proxy.Add(new SettingsProxy(typeof(LinuxPlatformSettings), Editor.Instance.Icons.LinuxSettings128));
|
Proxy.Add(new SettingsProxy(typeof(LinuxPlatformSettings), Editor.Instance.Icons.LinuxSettings128));
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "SceneAnimation.h"
|
#include "SceneAnimation.h"
|
||||||
|
#include "Engine/Core/Log.h"
|
||||||
#include "Engine/Content/Factories/BinaryAssetFactory.h"
|
#include "Engine/Content/Factories/BinaryAssetFactory.h"
|
||||||
#include "Engine/Content/Assets/MaterialBase.h"
|
#include "Engine/Content/Assets/MaterialBase.h"
|
||||||
#include "Engine/Content/Content.h"
|
#include "Engine/Content/Content.h"
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "MaterialBase.h"
|
#include "MaterialBase.h"
|
||||||
#include "MaterialInstance.h"
|
#include "MaterialInstance.h"
|
||||||
|
#include "Engine/Core/Log.h"
|
||||||
#include "Engine/Core/Types/Variant.h"
|
#include "Engine/Core/Types/Variant.h"
|
||||||
#include "Engine/Content/Content.h"
|
#include "Engine/Content/Content.h"
|
||||||
#include "Engine/Content/Factories/BinaryAssetFactory.h"
|
#include "Engine/Content/Factories/BinaryAssetFactory.h"
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "MaterialInstance.h"
|
#include "MaterialInstance.h"
|
||||||
|
#include "Engine/Core/Log.h"
|
||||||
#include "Engine/Core/Types/Variant.h"
|
#include "Engine/Core/Types/Variant.h"
|
||||||
#include "Engine/Content/Content.h"
|
#include "Engine/Content/Content.h"
|
||||||
#include "Engine/Content/Upgraders/MaterialInstanceUpgrader.h"
|
#include "Engine/Content/Upgraders/MaterialInstanceUpgrader.h"
|
||||||
|
|||||||
@@ -480,7 +480,6 @@ private:
|
|||||||
newHeader.IsSRGB = textureHeader.IsSRGB;
|
newHeader.IsSRGB = textureHeader.IsSRGB;
|
||||||
newHeader.NeverStream = textureHeader.NeverStream;
|
newHeader.NeverStream = textureHeader.NeverStream;
|
||||||
newHeader.Type = textureHeader.Type;
|
newHeader.Type = textureHeader.Type;
|
||||||
newHeader.IsCubeMap = false;
|
|
||||||
context.Output.CustomData.Copy(&newHeader);
|
context.Output.CustomData.Copy(&newHeader);
|
||||||
|
|
||||||
// Convert import options
|
// Convert import options
|
||||||
@@ -535,7 +534,6 @@ private:
|
|||||||
newHeader.MipLevels = textureHeader.MipLevels;
|
newHeader.MipLevels = textureHeader.MipLevels;
|
||||||
newHeader.Format = PixelFormatOldToNew(textureHeader.Format);
|
newHeader.Format = PixelFormatOldToNew(textureHeader.Format);
|
||||||
newHeader.IsSRGB = textureHeader.IsSRGB;
|
newHeader.IsSRGB = textureHeader.IsSRGB;
|
||||||
newHeader.NeverStream = false;
|
|
||||||
newHeader.Type = TextureFormatType::ColorRGB;
|
newHeader.Type = TextureFormatType::ColorRGB;
|
||||||
newHeader.IsCubeMap = true;
|
newHeader.IsCubeMap = true;
|
||||||
context.Output.CustomData.Copy(&newHeader);
|
context.Output.CustomData.Copy(&newHeader);
|
||||||
@@ -617,7 +615,6 @@ private:
|
|||||||
newHeader.IsSRGB = textureHeader.IsSRGB;
|
newHeader.IsSRGB = textureHeader.IsSRGB;
|
||||||
newHeader.NeverStream = textureHeader.NeverStream;
|
newHeader.NeverStream = textureHeader.NeverStream;
|
||||||
newHeader.Type = textureHeader.Type;
|
newHeader.Type = textureHeader.Type;
|
||||||
newHeader.IsCubeMap = false;
|
|
||||||
context.Output.CustomData.Copy(&newHeader);
|
context.Output.CustomData.Copy(&newHeader);
|
||||||
|
|
||||||
// Copy sprite atlas data from old header stream to chunk (chunk 15th)
|
// Copy sprite atlas data from old header stream to chunk (chunk 15th)
|
||||||
@@ -696,7 +693,6 @@ private:
|
|||||||
newHeader.IsSRGB = textureHeader.IsSRGB;
|
newHeader.IsSRGB = textureHeader.IsSRGB;
|
||||||
newHeader.NeverStream = textureHeader.NeverStream;
|
newHeader.NeverStream = textureHeader.NeverStream;
|
||||||
newHeader.Type = textureHeader.Type;
|
newHeader.Type = textureHeader.Type;
|
||||||
newHeader.IsCubeMap = false;
|
|
||||||
auto data = (IESProfile::CustomDataLayout*)newHeader.CustomData;
|
auto data = (IESProfile::CustomDataLayout*)newHeader.CustomData;
|
||||||
data->Brightness = brightness;
|
data->Brightness = brightness;
|
||||||
data->TextureMultiplier = multiplier;
|
data->TextureMultiplier = multiplier;
|
||||||
@@ -765,7 +761,6 @@ private:
|
|||||||
newHeader.IsSRGB = textureHeader.IsSRGB;
|
newHeader.IsSRGB = textureHeader.IsSRGB;
|
||||||
newHeader.NeverStream = textureHeader.NeverStream;
|
newHeader.NeverStream = textureHeader.NeverStream;
|
||||||
newHeader.Type = textureHeader.Type;
|
newHeader.Type = textureHeader.Type;
|
||||||
newHeader.IsCubeMap = false;
|
|
||||||
context.Output.CustomData.Copy(&newHeader);
|
context.Output.CustomData.Copy(&newHeader);
|
||||||
|
|
||||||
// Copy asset previews IDs mapping data from old chunk to new one
|
// Copy asset previews IDs mapping data from old chunk to new one
|
||||||
|
|||||||
@@ -168,6 +168,7 @@ CreateAssetResult ImportTexture::Create(CreateAssetContext& context, const Textu
|
|||||||
textureHeader.MipLevels = textureData.GetMipLevels();
|
textureHeader.MipLevels = textureData.GetMipLevels();
|
||||||
textureHeader.IsSRGB = PixelFormatExtensions::IsSRGB(textureHeader.Format);
|
textureHeader.IsSRGB = PixelFormatExtensions::IsSRGB(textureHeader.Format);
|
||||||
textureHeader.IsCubeMap = isCubeMap;
|
textureHeader.IsCubeMap = isCubeMap;
|
||||||
|
textureHeader.TextureGroup = options.TextureGroup;
|
||||||
ASSERT(textureHeader.MipLevels <= GPU_MAX_TEXTURE_MIP_LEVELS);
|
ASSERT(textureHeader.MipLevels <= GPU_MAX_TEXTURE_MIP_LEVELS);
|
||||||
|
|
||||||
// Save header
|
// Save header
|
||||||
@@ -306,6 +307,7 @@ CreateAssetResult ImportTexture::Create(CreateAssetContext& context, const Textu
|
|||||||
textureHeader.MipLevels = textureData.Mips.Count();
|
textureHeader.MipLevels = textureData.Mips.Count();
|
||||||
textureHeader.IsSRGB = PixelFormatExtensions::IsSRGB(textureHeader.Format);
|
textureHeader.IsSRGB = PixelFormatExtensions::IsSRGB(textureHeader.Format);
|
||||||
textureHeader.IsCubeMap = isCubeMap;
|
textureHeader.IsCubeMap = isCubeMap;
|
||||||
|
textureHeader.TextureGroup = options.TextureGroup;
|
||||||
ASSERT(textureHeader.MipLevels <= GPU_MAX_TEXTURE_MIP_LEVELS);
|
ASSERT(textureHeader.MipLevels <= GPU_MAX_TEXTURE_MIP_LEVELS);
|
||||||
|
|
||||||
// Save header
|
// Save header
|
||||||
@@ -542,12 +544,10 @@ CreateAssetResult ImportTexture::ImportIES(class CreateAssetContext& context)
|
|||||||
textureHeader.Width = loader.GetWidth();
|
textureHeader.Width = loader.GetWidth();
|
||||||
textureHeader.Height = loader.GetHeight();
|
textureHeader.Height = loader.GetHeight();
|
||||||
textureHeader.MipLevels = 1;
|
textureHeader.MipLevels = 1;
|
||||||
textureHeader.NeverStream = false;
|
|
||||||
textureHeader.Type = TextureFormatType::Unknown;
|
textureHeader.Type = TextureFormatType::Unknown;
|
||||||
textureHeader.Format = PixelFormat::R16_Float;
|
textureHeader.Format = PixelFormat::R16_Float;
|
||||||
textureHeader.IsSRGB = false;
|
|
||||||
textureHeader.IsCubeMap = false;
|
|
||||||
auto data = (IESProfile::CustomDataLayout*)textureHeader.CustomData;
|
auto data = (IESProfile::CustomDataLayout*)textureHeader.CustomData;
|
||||||
|
static_assert(sizeof(IESProfile::CustomDataLayout) <= sizeof(textureHeader.CustomData), "Invalid Custom Data size in Texture Header.");
|
||||||
data->Brightness = loader.GetBrightness();
|
data->Brightness = loader.GetBrightness();
|
||||||
data->TextureMultiplier = multiplier;
|
data->TextureMultiplier = multiplier;
|
||||||
ASSERT(textureHeader.MipLevels <= GPU_MAX_TEXTURE_MIP_LEVELS);
|
ASSERT(textureHeader.MipLevels <= GPU_MAX_TEXTURE_MIP_LEVELS);
|
||||||
|
|||||||
@@ -19,6 +19,7 @@
|
|||||||
#include "Engine/Content/AssetReference.h"
|
#include "Engine/Content/AssetReference.h"
|
||||||
#include "Engine/Engine/EngineService.h"
|
#include "Engine/Engine/EngineService.h"
|
||||||
#include "Engine/Engine/Globals.h"
|
#include "Engine/Engine/Globals.h"
|
||||||
|
#include "Engine/Streaming/StreamingSettings.h"
|
||||||
|
|
||||||
class GameSettingsService : public EngineService
|
class GameSettingsService : public EngineService
|
||||||
{
|
{
|
||||||
@@ -42,6 +43,7 @@ IMPLEMENT_SETTINGS_GETTER(TimeSettings, Time);
|
|||||||
IMPLEMENT_SETTINGS_GETTER(AudioSettings, Audio);
|
IMPLEMENT_SETTINGS_GETTER(AudioSettings, Audio);
|
||||||
IMPLEMENT_SETTINGS_GETTER(PhysicsSettings, Physics);
|
IMPLEMENT_SETTINGS_GETTER(PhysicsSettings, Physics);
|
||||||
IMPLEMENT_SETTINGS_GETTER(InputSettings, Input);
|
IMPLEMENT_SETTINGS_GETTER(InputSettings, Input);
|
||||||
|
IMPLEMENT_SETTINGS_GETTER(StreamingSettings, Streaming);
|
||||||
|
|
||||||
#if !USE_EDITOR
|
#if !USE_EDITOR
|
||||||
#if PLATFORM_WINDOWS
|
#if PLATFORM_WINDOWS
|
||||||
@@ -130,6 +132,7 @@ bool GameSettings::Load()
|
|||||||
PRELOAD_SETTINGS(Navigation);
|
PRELOAD_SETTINGS(Navigation);
|
||||||
PRELOAD_SETTINGS(Localization);
|
PRELOAD_SETTINGS(Localization);
|
||||||
PRELOAD_SETTINGS(GameCooking);
|
PRELOAD_SETTINGS(GameCooking);
|
||||||
|
PRELOAD_SETTINGS(Streaming);
|
||||||
#undef PRELOAD_SETTINGS
|
#undef PRELOAD_SETTINGS
|
||||||
|
|
||||||
// Apply the game settings to the engine
|
// Apply the game settings to the engine
|
||||||
@@ -157,6 +160,7 @@ void GameSettings::Apply()
|
|||||||
APPLY_SETTINGS(AudioSettings);
|
APPLY_SETTINGS(AudioSettings);
|
||||||
APPLY_SETTINGS(LayersAndTagsSettings);
|
APPLY_SETTINGS(LayersAndTagsSettings);
|
||||||
APPLY_SETTINGS(PhysicsSettings);
|
APPLY_SETTINGS(PhysicsSettings);
|
||||||
|
APPLY_SETTINGS(StreamingSettings);
|
||||||
APPLY_SETTINGS(InputSettings);
|
APPLY_SETTINGS(InputSettings);
|
||||||
APPLY_SETTINGS(GraphicsSettings);
|
APPLY_SETTINGS(GraphicsSettings);
|
||||||
APPLY_SETTINGS(NavigationSettings);
|
APPLY_SETTINGS(NavigationSettings);
|
||||||
@@ -202,6 +206,7 @@ void GameSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* mo
|
|||||||
DESERIALIZE(Navigation);
|
DESERIALIZE(Navigation);
|
||||||
DESERIALIZE(Localization);
|
DESERIALIZE(Localization);
|
||||||
DESERIALIZE(GameCooking);
|
DESERIALIZE(GameCooking);
|
||||||
|
DESERIALIZE(Streaming);
|
||||||
|
|
||||||
// Per-platform settings containers
|
// Per-platform settings containers
|
||||||
DESERIALIZE(WindowsPlatform);
|
DESERIALIZE(WindowsPlatform);
|
||||||
|
|||||||
@@ -91,6 +91,12 @@ namespace FlaxEditor.Content.Settings
|
|||||||
[EditorOrder(1050), EditorDisplay("Other Settings"), AssetReference(typeof(BuildSettings), true), Tooltip("Reference to Build Settings asset")]
|
[EditorOrder(1050), EditorDisplay("Other Settings"), AssetReference(typeof(BuildSettings), true), Tooltip("Reference to Build Settings asset")]
|
||||||
public JsonAsset GameCooking;
|
public JsonAsset GameCooking;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reference to <see cref="StreamingSettings"/> asset.
|
||||||
|
/// </summary>
|
||||||
|
[EditorOrder(1060), EditorDisplay("Other Settings"), AssetReference(typeof(StreamingSettings), true), Tooltip("Reference to Streaming Settings asset")]
|
||||||
|
public JsonAsset Streaming;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The custom settings to use with a game. Can be specified by the user to define game-specific options and be used by the external plugins (used as key-value pair).
|
/// The custom settings to use with a game. Can be specified by the user to define game-specific options and be used by the external plugins (used as key-value pair).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -229,6 +235,8 @@ namespace FlaxEditor.Content.Settings
|
|||||||
return LoadAsset<LocalizationSettings>(gameSettings.Localization) as T;
|
return LoadAsset<LocalizationSettings>(gameSettings.Localization) as T;
|
||||||
if (type == typeof(BuildSettings))
|
if (type == typeof(BuildSettings))
|
||||||
return LoadAsset<BuildSettings>(gameSettings.GameCooking) as T;
|
return LoadAsset<BuildSettings>(gameSettings.GameCooking) as T;
|
||||||
|
if (type == typeof(StreamingSettings))
|
||||||
|
return LoadAsset<StreamingSettings>(gameSettings.Streaming) as T;
|
||||||
if (type == typeof(InputSettings))
|
if (type == typeof(InputSettings))
|
||||||
return LoadAsset<InputSettings>(gameSettings.Input) as T;
|
return LoadAsset<InputSettings>(gameSettings.Input) as T;
|
||||||
if (type == typeof(AudioSettings))
|
if (type == typeof(AudioSettings))
|
||||||
@@ -333,6 +341,8 @@ namespace FlaxEditor.Content.Settings
|
|||||||
return SaveAsset(gameSettings, ref gameSettings.Localization, obj);
|
return SaveAsset(gameSettings, ref gameSettings.Localization, obj);
|
||||||
if (type == typeof(BuildSettings))
|
if (type == typeof(BuildSettings))
|
||||||
return SaveAsset(gameSettings, ref gameSettings.GameCooking, obj);
|
return SaveAsset(gameSettings, ref gameSettings.GameCooking, obj);
|
||||||
|
if (type == typeof(StreamingSettings))
|
||||||
|
return SaveAsset(gameSettings, ref gameSettings.Streaming, obj);
|
||||||
if (type == typeof(InputSettings))
|
if (type == typeof(InputSettings))
|
||||||
return SaveAsset(gameSettings, ref gameSettings.Input, obj);
|
return SaveAsset(gameSettings, ref gameSettings.Input, obj);
|
||||||
if (type == typeof(WindowsPlatformSettings))
|
if (type == typeof(WindowsPlatformSettings))
|
||||||
|
|||||||
@@ -70,6 +70,7 @@ public:
|
|||||||
Guid Navigation;
|
Guid Navigation;
|
||||||
Guid Localization;
|
Guid Localization;
|
||||||
Guid GameCooking;
|
Guid GameCooking;
|
||||||
|
Guid Streaming;
|
||||||
|
|
||||||
// Per-platform settings containers
|
// Per-platform settings containers
|
||||||
Guid WindowsPlatform;
|
Guid WindowsPlatform;
|
||||||
|
|||||||
@@ -17,6 +17,12 @@ protected:
|
|||||||
const T* _data;
|
const T* _data;
|
||||||
int32 _length;
|
int32 _length;
|
||||||
|
|
||||||
|
constexpr StringViewBase()
|
||||||
|
{
|
||||||
|
_data = nullptr;
|
||||||
|
_length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -189,8 +195,6 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
constexpr StringView()
|
constexpr StringView()
|
||||||
{
|
{
|
||||||
_data = nullptr;
|
|
||||||
_length = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -396,8 +400,6 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
constexpr StringAnsiView()
|
constexpr StringAnsiView()
|
||||||
{
|
{
|
||||||
_data = nullptr;
|
|
||||||
_length = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -9,6 +9,38 @@
|
|||||||
#include "Engine/Graphics/RenderTools.h"
|
#include "Engine/Graphics/RenderTools.h"
|
||||||
#include "Engine/Graphics/Async/Tasks/GPUUploadTextureMipTask.h"
|
#include "Engine/Graphics/Async/Tasks/GPUUploadTextureMipTask.h"
|
||||||
|
|
||||||
|
TextureHeader_Deprecated::TextureHeader_Deprecated()
|
||||||
|
{
|
||||||
|
Platform::MemoryClear(this, sizeof(*this));
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureHeader::TextureHeader()
|
||||||
|
{
|
||||||
|
Platform::MemoryClear(this, sizeof(*this));
|
||||||
|
TextureGroup = -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
TextureHeader::TextureHeader(TextureHeader_Deprecated& old)
|
||||||
|
{
|
||||||
|
Platform::MemoryClear(this, sizeof(*this));
|
||||||
|
Width = old.Width;;
|
||||||
|
Height = old.Height;
|
||||||
|
MipLevels = old.MipLevels;
|
||||||
|
Format = old.Format;
|
||||||
|
Type = old.Type;
|
||||||
|
if (old.IsCubeMap)
|
||||||
|
IsCubeMap = 1;
|
||||||
|
if (old.IsSRGB)
|
||||||
|
IsSRGB = 1;
|
||||||
|
if (old.NeverStream)
|
||||||
|
NeverStream = 1;
|
||||||
|
TextureGroup = -1;
|
||||||
|
Platform::MemoryCopy(CustomData, old.CustomData, sizeof(CustomData));
|
||||||
|
}
|
||||||
|
|
||||||
|
static_assert(sizeof(TextureHeader_Deprecated) == 10 * sizeof(int32), "Invalid TextureHeader size.");
|
||||||
|
static_assert(sizeof(TextureHeader) == 36, "Invalid TextureHeader size.");
|
||||||
|
|
||||||
StreamingTexture::StreamingTexture(ITextureOwner* parent, const String& name)
|
StreamingTexture::StreamingTexture(ITextureOwner* parent, const String& name)
|
||||||
: StreamableResource(StreamingGroups::Instance()->Textures())
|
: StreamableResource(StreamingGroups::Instance()->Textures())
|
||||||
, _owner(parent)
|
, _owner(parent)
|
||||||
@@ -112,6 +144,11 @@ String StreamingTexture::ToString() const
|
|||||||
return _texture->ToString();
|
return _texture->ToString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int32 StreamingTexture::GetMaxResidency() const
|
||||||
|
{
|
||||||
|
return _header.MipLevels;
|
||||||
|
}
|
||||||
|
|
||||||
int32 StreamingTexture::GetCurrentResidency() const
|
int32 StreamingTexture::GetCurrentResidency() const
|
||||||
{
|
{
|
||||||
return _texture->ResidentMipLevels();
|
return _texture->ResidentMipLevels();
|
||||||
|
|||||||
@@ -7,7 +7,7 @@
|
|||||||
#include "Types.h"
|
#include "Types.h"
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GPU texture object which can change it's resolution (quality) at runtime
|
/// GPU texture object which can change it's resolution (quality) at runtime.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class FLAXENGINE_API StreamingTexture : public Object, public StreamableResource
|
class FLAXENGINE_API StreamingTexture : public Object, public StreamableResource
|
||||||
{
|
{
|
||||||
@@ -180,10 +180,7 @@ public:
|
|||||||
String ToString() const override;
|
String ToString() const override;
|
||||||
|
|
||||||
// [StreamableResource]
|
// [StreamableResource]
|
||||||
int32 GetMaxResidency() const override
|
int32 GetMaxResidency() const override;
|
||||||
{
|
|
||||||
return _header.MipLevels;
|
|
||||||
}
|
|
||||||
int32 GetCurrentResidency() const override;
|
int32 GetCurrentResidency() const override;
|
||||||
int32 GetAllocatedResidency() const override;
|
int32 GetAllocatedResidency() const override;
|
||||||
bool CanBeUpdated() const override;
|
bool CanBeUpdated() const override;
|
||||||
|
|||||||
@@ -29,27 +29,27 @@ Vector2 TextureBase::Size() const
|
|||||||
|
|
||||||
int32 TextureBase::GetArraySize() const
|
int32 TextureBase::GetArraySize() const
|
||||||
{
|
{
|
||||||
return StreamingTexture()->TotalArraySize();
|
return _texture.TotalArraySize();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 TextureBase::GetMipLevels() const
|
int32 TextureBase::GetMipLevels() const
|
||||||
{
|
{
|
||||||
return StreamingTexture()->TotalMipLevels();
|
return _texture.TotalMipLevels();
|
||||||
}
|
}
|
||||||
|
|
||||||
int32 TextureBase::GetResidentMipLevels() const
|
int32 TextureBase::GetResidentMipLevels() const
|
||||||
{
|
{
|
||||||
return GetTexture()->ResidentMipLevels();
|
return _texture.GetTexture()->ResidentMipLevels();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 TextureBase::GetCurrentMemoryUsage() const
|
uint64 TextureBase::GetCurrentMemoryUsage() const
|
||||||
{
|
{
|
||||||
return GetTexture()->GetMemoryUsage();
|
return _texture.GetTexture()->GetMemoryUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64 TextureBase::GetTotalMemoryUsage() const
|
uint64 TextureBase::GetTotalMemoryUsage() const
|
||||||
{
|
{
|
||||||
return StreamingTexture()->GetTotalMemoryUsage();
|
return _texture.GetTotalMemoryUsage();
|
||||||
}
|
}
|
||||||
|
|
||||||
BytesContainer TextureBase::GetMipData(int32 mipIndex, int32& rowPitch, int32& slicePitch)
|
BytesContainer TextureBase::GetMipData(int32 mipIndex, int32& rowPitch, int32& slicePitch)
|
||||||
@@ -166,16 +166,15 @@ bool TextureBase::Init(InitData* initData)
|
|||||||
_customData = initData;
|
_customData = initData;
|
||||||
|
|
||||||
// Create texture
|
// Create texture
|
||||||
TextureHeader header;
|
TextureHeader textureHeader;
|
||||||
header.Format = initData->Format;
|
textureHeader.Format = initData->Format;
|
||||||
header.Width = initData->Width;
|
textureHeader.Width = initData->Width;
|
||||||
header.Height = initData->Height;
|
textureHeader.Height = initData->Height;
|
||||||
header.IsCubeMap = initData->ArraySize == 6;
|
textureHeader.IsCubeMap = initData->ArraySize == 6;
|
||||||
header.MipLevels = initData->Mips.Count();
|
textureHeader.MipLevels = initData->Mips.Count();
|
||||||
header.IsSRGB = false;
|
textureHeader.Type = TextureFormatType::ColorRGBA;
|
||||||
header.Type = TextureFormatType::ColorRGBA;
|
textureHeader.NeverStream = true;
|
||||||
header.NeverStream = true;
|
if (_texture.Create(textureHeader))
|
||||||
if (_texture.Create(header))
|
|
||||||
{
|
{
|
||||||
LOG(Warning, "Cannot initialize texture.");
|
LOG(Warning, "Cannot initialize texture.");
|
||||||
return true;
|
return true;
|
||||||
@@ -289,6 +288,41 @@ bool TextureBase::GetMipDataCustomPitch(int32 mipIndex, uint32& rowPitch, uint32
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TextureBase::init(AssetInitData& initData)
|
||||||
|
{
|
||||||
|
if (IsVirtual())
|
||||||
|
return false;
|
||||||
|
if (initData.SerializedVersion != TexturesSerializedVersion)
|
||||||
|
{
|
||||||
|
LOG(Error, "Invalid serialized texture version.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get texture header for asset custom data (fast access)
|
||||||
|
TextureHeader textureHeader;
|
||||||
|
if (initData.CustomData.Length() == sizeof(TextureHeader))
|
||||||
|
{
|
||||||
|
Platform::MemoryCopy(&textureHeader, initData.CustomData.Get(), sizeof(textureHeader));
|
||||||
|
}
|
||||||
|
else if (initData.CustomData.Length() == sizeof(TextureHeader_Deprecated))
|
||||||
|
{
|
||||||
|
textureHeader = TextureHeader(*(TextureHeader_Deprecated*)initData.CustomData.Get());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
LOG(Error, "Missing texture header.");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return _texture.Create(textureHeader);
|
||||||
|
}
|
||||||
|
|
||||||
|
Asset::LoadResult TextureBase::load()
|
||||||
|
{
|
||||||
|
// Loading textures is very fast xD
|
||||||
|
return LoadResult::Ok;
|
||||||
|
}
|
||||||
|
|
||||||
bool TextureBase::InitData::GenerateMip(int32 mipIndex, bool linear)
|
bool TextureBase::InitData::GenerateMip(int32 mipIndex, bool linear)
|
||||||
{
|
{
|
||||||
// Validate input
|
// Validate input
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "Engine/Content/BinaryAsset.h"
|
#include "Engine/Content/BinaryAsset.h"
|
||||||
#include "StreamingTexture.h"
|
#include "StreamingTexture.h"
|
||||||
#include "Engine/Core/Log.h"
|
|
||||||
|
|
||||||
class TextureData;
|
class TextureData;
|
||||||
|
|
||||||
@@ -15,12 +14,8 @@ class TextureData;
|
|||||||
API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API TextureBase : public BinaryAsset, public ITextureOwner
|
API_CLASS(Abstract, NoSpawn) class FLAXENGINE_API TextureBase : public BinaryAsset, public ITextureOwner
|
||||||
{
|
{
|
||||||
DECLARE_ASSET_HEADER(TextureBase);
|
DECLARE_ASSET_HEADER(TextureBase);
|
||||||
public:
|
|
||||||
|
|
||||||
static const uint32 TexturesSerializedVersion = 4;
|
static const uint32 TexturesSerializedVersion = 4;
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The texture init data (external source).
|
/// The texture init data (external source).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -180,43 +175,7 @@ public:
|
|||||||
protected:
|
protected:
|
||||||
|
|
||||||
// [BinaryAsset]
|
// [BinaryAsset]
|
||||||
bool init(AssetInitData& initData) override
|
bool init(AssetInitData& initData) override;
|
||||||
{
|
LoadResult load() override;
|
||||||
// Skip for virtual assets
|
|
||||||
if (IsVirtual())
|
|
||||||
return false;
|
|
||||||
|
|
||||||
// Validate
|
|
||||||
if (initData.SerializedVersion != 4)
|
|
||||||
{
|
|
||||||
LOG(Error, "Invalid serialized texture version.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
if (initData.CustomData.Length() != sizeof(TextureHeader))
|
|
||||||
{
|
|
||||||
LOG(Error, "Missing texture header.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Load header
|
|
||||||
TextureHeader header;
|
|
||||||
Platform::MemoryCopy(&header, initData.CustomData.Get(), sizeof(TextureHeader));
|
|
||||||
|
|
||||||
// Create texture
|
|
||||||
if (_texture.Create(header))
|
|
||||||
{
|
|
||||||
LOG(Error, "Cannot initialize texture.");
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
LoadResult load() override
|
|
||||||
{
|
|
||||||
// Loading textures is very fast xD
|
|
||||||
return LoadResult::Ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
void unload(bool isReloading) override;
|
void unload(bool isReloading) override;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -12,25 +12,53 @@
|
|||||||
DECLARE_ENUM_EX_7(TextureFormatType, byte, 0, Unknown, ColorRGB, ColorRGBA, NormalMap, GrayScale, HdrRGBA, HdrRGB);
|
DECLARE_ENUM_EX_7(TextureFormatType, byte, 0, Unknown, ColorRGB, ColorRGBA, NormalMap, GrayScale, HdrRGBA, HdrRGB);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Texture header structure
|
/// Old texture header structure (was not fully initialized to zero).
|
||||||
|
/// </summary>
|
||||||
|
struct TextureHeader_Deprecated
|
||||||
|
{
|
||||||
|
int32 Width;
|
||||||
|
int32 Height;
|
||||||
|
int32 MipLevels;
|
||||||
|
PixelFormat Format;
|
||||||
|
TextureFormatType Type;
|
||||||
|
bool IsCubeMap;
|
||||||
|
bool NeverStream;
|
||||||
|
bool IsSRGB;
|
||||||
|
byte CustomData[17];
|
||||||
|
|
||||||
|
TextureHeader_Deprecated();
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Texture header structure.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
struct FLAXENGINE_API TextureHeader
|
struct FLAXENGINE_API TextureHeader
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Top mip width in pixels
|
/// Width in pixels
|
||||||
/// </summary>
|
/// </summary>
|
||||||
int32 Width;
|
int32 Width;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Top mip height in pixels
|
/// Height in pixels
|
||||||
/// </summary>
|
/// </summary>
|
||||||
int32 Height;
|
int32 Height;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Depth in pixels
|
||||||
|
/// </summary>
|
||||||
|
int32 Depth;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Amount of mip levels
|
/// Amount of mip levels
|
||||||
/// </summary>
|
/// </summary>
|
||||||
int32 MipLevels;
|
int32 MipLevels;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Texture group for streaming (negative if unused).
|
||||||
|
/// </summary>
|
||||||
|
int32 TextureGroup;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Texture pixels format
|
/// Texture pixels format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -44,22 +72,23 @@ struct FLAXENGINE_API TextureHeader
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if texture is a cubemap (has 6 array slices per mip).
|
/// True if texture is a cubemap (has 6 array slices per mip).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsCubeMap;
|
byte IsCubeMap : 1;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// True if disable dynamic texture streaming
|
|
||||||
/// </summary>
|
|
||||||
bool NeverStream;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// True if texture contains sRGB colors data
|
/// True if texture contains sRGB colors data
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool IsSRGB;
|
byte IsSRGB : 1;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// True if disable dynamic texture streaming
|
||||||
|
/// </summary>
|
||||||
|
byte NeverStream : 1;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The custom data to be used per texture storage layer (faster access).
|
/// The custom data to be used per texture storage layer (faster access).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
byte CustomData[17];
|
byte CustomData[10];
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(TextureHeader) == 10 * sizeof(int32), "Invalid TextureHeader size.");
|
TextureHeader();
|
||||||
|
TextureHeader(TextureHeader_Deprecated& old);
|
||||||
|
};
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "CollisionData.h"
|
#include "CollisionData.h"
|
||||||
|
#include "Engine/Core/Log.h"
|
||||||
#include "Engine/Content/Content.h"
|
#include "Engine/Content/Content.h"
|
||||||
#include "Engine/Content/Assets/Model.h"
|
#include "Engine/Content/Assets/Model.h"
|
||||||
#include "Engine/Content/Factories/BinaryAssetFactory.h"
|
#include "Engine/Content/Factories/BinaryAssetFactory.h"
|
||||||
|
|||||||
@@ -1,16 +0,0 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
// Resources streaming types
|
|
||||||
typedef float StreamingQuality;
|
|
||||||
|
|
||||||
#define MIN_STREAMING_QUALITY 0.0f
|
|
||||||
#define MAX_STREAMING_QUALITY 1.0f
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Enables/disables dynamic resources streaming feature
|
|
||||||
/// </summary>
|
|
||||||
#define ENABLE_RESOURCES_DYNAMIC_STREAMING 1
|
|
||||||
|
|
||||||
class StreamableResource;
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#include "AudioStreamingHandler.h"
|
|
||||||
#include "Engine/Audio/AudioClip.h"
|
|
||||||
#include "Engine/Audio/Audio.h"
|
|
||||||
#include "Engine/Audio/AudioSource.h"
|
|
||||||
|
|
||||||
StreamingQuality AudioStreamingHandler::CalculateTargetQuality(StreamableResource* resource, DateTime now)
|
|
||||||
{
|
|
||||||
// Audio clips don't use quality but only residency
|
|
||||||
return MAX_STREAMING_QUALITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 AudioStreamingHandler::CalculateResidency(StreamableResource* resource, StreamingQuality quality)
|
|
||||||
{
|
|
||||||
ASSERT(resource);
|
|
||||||
auto clip = static_cast<AudioClip*>(resource);
|
|
||||||
const int32 chunksCount = clip->Buffers.Count();
|
|
||||||
bool chunksMask[ASSET_FILE_DATA_CHUNKS];
|
|
||||||
Platform::MemoryClear(chunksMask, sizeof(chunksMask));
|
|
||||||
|
|
||||||
// Find audio chunks required for streaming
|
|
||||||
clip->StreamingQueue.Clear();
|
|
||||||
for (int32 sourceIndex = 0; sourceIndex < Audio::Sources.Count(); sourceIndex++)
|
|
||||||
{
|
|
||||||
// TODO: collect refs to audio clip from sources and use faster iteration (but do it thread-safe)
|
|
||||||
|
|
||||||
const auto src = Audio::Sources[sourceIndex];
|
|
||||||
if (src->Clip == clip && src->GetState() == AudioSource::States::Playing)
|
|
||||||
{
|
|
||||||
// Stream the current and the next chunk if could be used in a while
|
|
||||||
const int32 chunk = src->_streamingFirstChunk;
|
|
||||||
ASSERT(Math::IsInRange(chunk, 0, chunksCount));
|
|
||||||
chunksMask[chunk] = true;
|
|
||||||
|
|
||||||
const float StreamingDstSec = 2.0f;
|
|
||||||
if (chunk + 1 < chunksCount && src->GetTime() + StreamingDstSec >= clip->GetBufferStartTime(src->_streamingFirstChunk))
|
|
||||||
{
|
|
||||||
chunksMask[chunk + 1] = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Try to enqueue chunks to modify (load or unload)
|
|
||||||
for (int32 i = 0; i < chunksCount; i++)
|
|
||||||
{
|
|
||||||
if (chunksMask[i] != (clip->Buffers[i] != 0))
|
|
||||||
{
|
|
||||||
clip->StreamingQueue.Add(i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return clip->StreamingQueue.Count();
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 AudioStreamingHandler::CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency)
|
|
||||||
{
|
|
||||||
// No smoothing or slowdown in residency change
|
|
||||||
return targetResidency;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool AudioStreamingHandler::RequiresStreaming(StreamableResource* resource, int32 currentResidency, int32 targetResidency)
|
|
||||||
{
|
|
||||||
// Audio clips use streaming queue buffer to detect streaming request start
|
|
||||||
const auto clip = static_cast<AudioClip*>(resource);
|
|
||||||
return clip->StreamingQueue.HasItems();
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Engine/Streaming/IStreamingHandler.h"
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Implementation of IStreamingHandler for audio resources.
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="IStreamingHandler" />
|
|
||||||
class FLAXENGINE_API AudioStreamingHandler : public IStreamingHandler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
// [IStreamingHandler]
|
|
||||||
StreamingQuality CalculateTargetQuality(StreamableResource* resource, DateTime now) override;
|
|
||||||
int32 CalculateResidency(StreamableResource* resource, StreamingQuality quality) override;
|
|
||||||
int32 CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency) override;
|
|
||||||
bool RequiresStreaming(StreamableResource* resource, int32 currentResidency, int32 targetResidency) override;
|
|
||||||
};
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#include "ModelsStreamingHandler.h"
|
|
||||||
#include "Engine/Content/Assets/Model.h"
|
|
||||||
|
|
||||||
StreamingQuality ModelsStreamingHandler::CalculateTargetQuality(StreamableResource* resource, DateTime now)
|
|
||||||
{
|
|
||||||
ASSERT(resource);
|
|
||||||
|
|
||||||
// TODO: calculate a proper quality levels for models based on render time and streaming enable/disable options
|
|
||||||
|
|
||||||
return MAX_STREAMING_QUALITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 ModelsStreamingHandler::CalculateResidency(StreamableResource* resource, StreamingQuality quality)
|
|
||||||
{
|
|
||||||
ASSERT(resource);
|
|
||||||
auto& model = *(Model*)resource;
|
|
||||||
auto lodCount = model.GetLODsCount();
|
|
||||||
|
|
||||||
if (quality < ZeroTolerance)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
int32 lods = Math::CeilToInt(quality * (StreamingQuality)lodCount);
|
|
||||||
|
|
||||||
ASSERT(model.IsValidLODIndex(lods - 1));
|
|
||||||
return lods;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 ModelsStreamingHandler::CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency)
|
|
||||||
{
|
|
||||||
ASSERT(resource);
|
|
||||||
auto& model = *(Model*)resource;
|
|
||||||
|
|
||||||
// Always load only single LOD at once
|
|
||||||
int32 residency = targetResidency;
|
|
||||||
int32 currentResidency = model.GetCurrentResidency();
|
|
||||||
if (currentResidency < targetResidency)
|
|
||||||
{
|
|
||||||
// Up
|
|
||||||
residency = currentResidency + 1;
|
|
||||||
}
|
|
||||||
else if (currentResidency > targetResidency)
|
|
||||||
{
|
|
||||||
// Down
|
|
||||||
residency = currentResidency - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return residency;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Engine/Streaming/IStreamingHandler.h"
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Implementation of IStreamingHandler for streamable models.
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="IStreamingHandler" />
|
|
||||||
class FLAXENGINE_API ModelsStreamingHandler : public IStreamingHandler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
// [IStreamingHandler]
|
|
||||||
StreamingQuality CalculateTargetQuality(StreamableResource* resource, DateTime now) override;
|
|
||||||
int32 CalculateResidency(StreamableResource* resource, StreamingQuality quality) override;
|
|
||||||
int32 CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency) override;
|
|
||||||
};
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#include "SkinnedModelsStreamingHandler.h"
|
|
||||||
#include "Engine/Content/Assets/SkinnedModel.h"
|
|
||||||
|
|
||||||
StreamingQuality SkinnedModelsStreamingHandler::CalculateTargetQuality(StreamableResource* resource, DateTime now)
|
|
||||||
{
|
|
||||||
ASSERT(resource);
|
|
||||||
|
|
||||||
// TODO: calculate a proper quality levels for models based on render time and streaming enable/disable options
|
|
||||||
|
|
||||||
return MAX_STREAMING_QUALITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 SkinnedModelsStreamingHandler::CalculateResidency(StreamableResource* resource, StreamingQuality quality)
|
|
||||||
{
|
|
||||||
ASSERT(resource);
|
|
||||||
auto& model = *(SkinnedModel*)resource;
|
|
||||||
auto lodCount = model.GetLODsCount();
|
|
||||||
|
|
||||||
if (quality < ZeroTolerance)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
int32 lods = Math::CeilToInt(quality * lodCount);
|
|
||||||
|
|
||||||
ASSERT(model.IsValidLODIndex(lods - 1));
|
|
||||||
return lods;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 SkinnedModelsStreamingHandler::CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency)
|
|
||||||
{
|
|
||||||
ASSERT(resource);
|
|
||||||
auto& model = *(SkinnedModel*)resource;
|
|
||||||
|
|
||||||
// Always load only single LOD at once
|
|
||||||
int32 residency = targetResidency;
|
|
||||||
int32 currentResidency = model.GetCurrentResidency();
|
|
||||||
if (currentResidency < targetResidency)
|
|
||||||
{
|
|
||||||
// Up
|
|
||||||
residency = currentResidency + 1;
|
|
||||||
}
|
|
||||||
else if (currentResidency > targetResidency)
|
|
||||||
{
|
|
||||||
// Down
|
|
||||||
residency = currentResidency - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return residency;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Engine/Streaming/IStreamingHandler.h"
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Implementation of IStreamingHandler for streamable skinned models.
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="IStreamingHandler" />
|
|
||||||
class FLAXENGINE_API SkinnedModelsStreamingHandler : public IStreamingHandler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
// [IStreamingHandler]
|
|
||||||
StreamingQuality CalculateTargetQuality(StreamableResource* resource, DateTime now) override;
|
|
||||||
int32 CalculateResidency(StreamableResource* resource, StreamingQuality quality) override;
|
|
||||||
int32 CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency) override;
|
|
||||||
};
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#include "TexturesStreamingHandler.h"
|
|
||||||
#include "Engine/Core/Math/Math.h"
|
|
||||||
#include "Engine/Graphics/Textures/StreamingTexture.h"
|
|
||||||
|
|
||||||
StreamingQuality TexturesStreamingHandler::CalculateTargetQuality(StreamableResource* resource, DateTime now)
|
|
||||||
{
|
|
||||||
ASSERT(resource);
|
|
||||||
auto& texture = *(StreamingTexture*)resource;
|
|
||||||
|
|
||||||
// TODO: calculate a proper quality levels for the textures
|
|
||||||
|
|
||||||
//return 0.5f;
|
|
||||||
|
|
||||||
return MAX_STREAMING_QUALITY;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 TexturesStreamingHandler::CalculateResidency(StreamableResource* resource, StreamingQuality quality)
|
|
||||||
{
|
|
||||||
ASSERT(resource);
|
|
||||||
auto& texture = *(StreamingTexture*)resource;
|
|
||||||
ASSERT(texture.IsInitialized());
|
|
||||||
const auto totalMipLevels = texture.TotalMipLevels();
|
|
||||||
|
|
||||||
if (quality < ZeroTolerance)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 mipLevels = Math::CeilToInt(quality * totalMipLevels);
|
|
||||||
if (mipLevels > 0 && mipLevels < 3 && totalMipLevels > 1 && texture.IsBlockCompressed())
|
|
||||||
{
|
|
||||||
// Block compressed textures require minimum size of 4 (3 mips or more)
|
|
||||||
mipLevels = 3;
|
|
||||||
}
|
|
||||||
|
|
||||||
ASSERT(Math::IsInRange(mipLevels, 0, totalMipLevels));
|
|
||||||
return mipLevels;
|
|
||||||
}
|
|
||||||
|
|
||||||
int32 TexturesStreamingHandler::CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency)
|
|
||||||
{
|
|
||||||
ASSERT(resource);
|
|
||||||
auto& texture = *(StreamingTexture*)resource;
|
|
||||||
ASSERT(texture.IsInitialized());
|
|
||||||
|
|
||||||
int32 residency = targetResidency;
|
|
||||||
int32 currentResidency = texture.GetCurrentResidency();
|
|
||||||
|
|
||||||
// Check if go up or down
|
|
||||||
if (currentResidency < targetResidency)
|
|
||||||
{
|
|
||||||
// Up
|
|
||||||
residency = Math::Min(currentResidency + 2, targetResidency);
|
|
||||||
|
|
||||||
// Stream first a few mips very fast (they are very small)
|
|
||||||
const int32 QuickStartMipsCount = 6;
|
|
||||||
if (currentResidency == 0)
|
|
||||||
{
|
|
||||||
residency = Math::Min(QuickStartMipsCount, targetResidency);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (currentResidency > targetResidency)
|
|
||||||
{
|
|
||||||
// Down at once
|
|
||||||
residency = targetResidency;
|
|
||||||
}
|
|
||||||
|
|
||||||
return residency;
|
|
||||||
}
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "Engine/Streaming/IStreamingHandler.h"
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Implementation of IStreamingHandler for streamable textures.
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="IStreamingHandler" />
|
|
||||||
class FLAXENGINE_API TexturesStreamingHandler : public IStreamingHandler
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
// [IStreamingHandler]
|
|
||||||
StreamingQuality CalculateTargetQuality(StreamableResource* resource, DateTime now) override;
|
|
||||||
int32 CalculateResidency(StreamableResource* resource, StreamingQuality quality) override;
|
|
||||||
int32 CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency) override;
|
|
||||||
};
|
|
||||||
@@ -2,13 +2,13 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Config.h"
|
#include "Engine/Core/Types/BaseTypes.h"
|
||||||
#include "Engine/Core/Types/DateTime.h"
|
|
||||||
|
|
||||||
class StreamingGroup;
|
class StreamingGroup;
|
||||||
|
class StreamableResource;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Base interface for all streamable resource handlers
|
/// Base interface for all streamable resource handlers that implement resource streaming policy.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
class FLAXENGINE_API IStreamingHandler
|
class FLAXENGINE_API IStreamingHandler
|
||||||
{
|
{
|
||||||
@@ -19,20 +19,20 @@ public:
|
|||||||
public:
|
public:
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates target quality level for the given resource.
|
/// Calculates target quality level (0-1) for the given resource.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="resource">The resource.</param>
|
/// <param name="resource">The resource.</param>
|
||||||
/// <param name="now">The current time.</param>
|
/// <param name="now">The current time.</param>
|
||||||
/// <returns>Target Quality</returns>
|
/// <returns>Target quality (0-1).</returns>
|
||||||
virtual StreamingQuality CalculateTargetQuality(StreamableResource* resource, DateTime now) = 0;
|
virtual float CalculateTargetQuality(StreamableResource* resource, DateTime now) = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates the residency level for a given resource and quality level.
|
/// Calculates the residency level for a given resource and quality level.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="resource">The resource.</param>
|
/// <param name="resource">The resource.</param>
|
||||||
/// <param name="quality">The quality level.</param>
|
/// <param name="quality">The quality level (0-1).</param>
|
||||||
/// <returns>Residency level</returns>
|
/// <returns>Residency level</returns>
|
||||||
virtual int32 CalculateResidency(StreamableResource* resource, StreamingQuality quality) = 0;
|
virtual int32 CalculateResidency(StreamableResource* resource, float quality) = 0;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Calculates the residency level to stream for a given resource and target residency.
|
/// Calculates the residency level to stream for a given resource and target residency.
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "StreamableResource.h"
|
#include "StreamableResource.h"
|
||||||
#include "StreamingManager.h"
|
#include "Streaming.h"
|
||||||
|
|
||||||
StreamableResource::StreamableResource(StreamingGroup* group)
|
StreamableResource::StreamableResource(StreamingGroup* group)
|
||||||
: _group(group)
|
: _group(group)
|
||||||
, _isDynamic(true)
|
, _isDynamic(true)
|
||||||
, _isStreaming(false)
|
, _isStreaming(false)
|
||||||
, _streamingQuality(MAX_STREAMING_QUALITY)
|
, _streamingQuality(1.0f)
|
||||||
{
|
{
|
||||||
ASSERT(_group != nullptr);
|
ASSERT(_group != nullptr);
|
||||||
}
|
}
|
||||||
@@ -23,7 +23,7 @@ void StreamableResource::startStreaming(bool isDynamic)
|
|||||||
|
|
||||||
if (_isStreaming == false)
|
if (_isStreaming == false)
|
||||||
{
|
{
|
||||||
StreamingManager::Resources.Add(this);
|
Streaming::Resources.Add(this);
|
||||||
_isStreaming = true;
|
_isStreaming = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -32,7 +32,7 @@ void StreamableResource::stopStreaming()
|
|||||||
{
|
{
|
||||||
if (_isStreaming == true)
|
if (_isStreaming == true)
|
||||||
{
|
{
|
||||||
StreamingManager::Resources.Remove(this);
|
Streaming::Resources.Remove(this);
|
||||||
Streaming = StreamingCache();
|
Streaming = StreamingCache();
|
||||||
_isStreaming = false;
|
_isStreaming = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@
|
|||||||
|
|
||||||
#include "Engine/Core/Types/DateTime.h"
|
#include "Engine/Core/Types/DateTime.h"
|
||||||
#include "Engine/Core/Collections/SamplesBuffer.h"
|
#include "Engine/Core/Collections/SamplesBuffer.h"
|
||||||
#include "Config.h"
|
|
||||||
|
|
||||||
class StreamingGroup;
|
class StreamingGroup;
|
||||||
class Task;
|
class Task;
|
||||||
@@ -18,7 +17,7 @@ protected:
|
|||||||
|
|
||||||
StreamingGroup* _group;
|
StreamingGroup* _group;
|
||||||
bool _isDynamic, _isStreaming;
|
bool _isDynamic, _isStreaming;
|
||||||
StreamingQuality _streamingQuality;
|
float _streamingQuality;
|
||||||
|
|
||||||
StreamableResource(StreamingGroup* group);
|
StreamableResource(StreamingGroup* group);
|
||||||
~StreamableResource();
|
~StreamableResource();
|
||||||
@@ -38,17 +37,13 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
FORCE_INLINE bool IsDynamic() const
|
FORCE_INLINE bool IsDynamic() const
|
||||||
{
|
{
|
||||||
#if ENABLE_RESOURCES_DYNAMIC_STREAMING
|
|
||||||
return _isDynamic;
|
return _isDynamic;
|
||||||
#else
|
|
||||||
return false;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets resource streaming quality level
|
/// Gets resource streaming quality level
|
||||||
/// </summary>
|
/// </summary>
|
||||||
FORCE_INLINE StreamingQuality GetStreamingQuality() const
|
FORCE_INLINE float GetStreamingQuality() const
|
||||||
{
|
{
|
||||||
return _streamingQuality;
|
return _streamingQuality;
|
||||||
}
|
}
|
||||||
@@ -114,7 +109,7 @@ public:
|
|||||||
DateTime LastUpdate = 0;
|
DateTime LastUpdate = 0;
|
||||||
int32 TargetResidency = 0;
|
int32 TargetResidency = 0;
|
||||||
DateTime TargetResidencyChange = 0;
|
DateTime TargetResidencyChange = 0;
|
||||||
SamplesBuffer<StreamingQuality, 5> QualitySamples;
|
SamplesBuffer<float, 5> QualitySamples;
|
||||||
};
|
};
|
||||||
|
|
||||||
StreamingCache Streaming;
|
StreamingCache Streaming;
|
||||||
|
|||||||
@@ -1,13 +1,15 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "StreamingManager.h"
|
#include "Streaming.h"
|
||||||
#include "StreamableResource.h"
|
#include "StreamableResource.h"
|
||||||
#include "StreamingGroup.h"
|
#include "StreamingGroup.h"
|
||||||
|
#include "StreamingSettings.h"
|
||||||
#include "Engine/Engine/EngineService.h"
|
#include "Engine/Engine/EngineService.h"
|
||||||
#include "Engine/Profiler/ProfilerCPU.h"
|
#include "Engine/Profiler/ProfilerCPU.h"
|
||||||
#include "Engine/Threading/Threading.h"
|
#include "Engine/Threading/Threading.h"
|
||||||
#include "Engine/Threading/Task.h"
|
#include "Engine/Threading/Task.h"
|
||||||
#include "Engine/Graphics/GPUDevice.h"
|
#include "Engine/Graphics/GPUDevice.h"
|
||||||
|
#include "Engine/Serialization/Serialization.h"
|
||||||
|
|
||||||
namespace StreamingManagerImpl
|
namespace StreamingManagerImpl
|
||||||
{
|
{
|
||||||
@@ -21,7 +23,6 @@ using namespace StreamingManagerImpl;
|
|||||||
class StreamingManagerService : public EngineService
|
class StreamingManagerService : public EngineService
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
StreamingManagerService()
|
StreamingManagerService()
|
||||||
: EngineService(TEXT("Streaming Manager"), 100)
|
: EngineService(TEXT("Streaming Manager"), 100)
|
||||||
{
|
{
|
||||||
@@ -32,7 +33,18 @@ public:
|
|||||||
|
|
||||||
StreamingManagerService StreamingManagerServiceInstance;
|
StreamingManagerService StreamingManagerServiceInstance;
|
||||||
|
|
||||||
StreamableResourcesCollection StreamingManager::Resources;
|
StreamableResourcesCollection Streaming::Resources;
|
||||||
|
Array<TextureGroup, InlinedAllocation<32>> Streaming::TextureGroups;
|
||||||
|
|
||||||
|
void StreamingSettings::Apply()
|
||||||
|
{
|
||||||
|
Streaming::TextureGroups = TextureGroups;
|
||||||
|
}
|
||||||
|
|
||||||
|
void StreamingSettings::Deserialize(DeserializeStream& stream, ISerializeModifier* modifier)
|
||||||
|
{
|
||||||
|
DESERIALIZE(TextureGroups);
|
||||||
|
}
|
||||||
|
|
||||||
void UpdateResource(StreamableResource* resource, DateTime now)
|
void UpdateResource(StreamableResource* resource, DateTime now)
|
||||||
{
|
{
|
||||||
@@ -43,18 +55,18 @@ void UpdateResource(StreamableResource* resource, DateTime now)
|
|||||||
auto handler = group->GetHandler();
|
auto handler = group->GetHandler();
|
||||||
|
|
||||||
// Calculate target quality for that asset
|
// Calculate target quality for that asset
|
||||||
StreamingQuality targetQuality = MAX_STREAMING_QUALITY;
|
float targetQuality = 1.0f;
|
||||||
if (resource->IsDynamic())
|
if (resource->IsDynamic())
|
||||||
{
|
{
|
||||||
targetQuality = handler->CalculateTargetQuality(resource, now);
|
targetQuality = handler->CalculateTargetQuality(resource, now);
|
||||||
// TODO: here we should apply resources group master scale (based on game settings quality level and memory level)
|
// TODO: here we should apply resources group master scale (based on game settings quality level and memory level)
|
||||||
targetQuality = Math::Clamp<StreamingQuality>(targetQuality, MIN_STREAMING_QUALITY, MAX_STREAMING_QUALITY);
|
targetQuality = Math::Saturate(targetQuality);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update quality smoothing
|
// Update quality smoothing
|
||||||
resource->Streaming.QualitySamples.Add(targetQuality);
|
resource->Streaming.QualitySamples.Add(targetQuality);
|
||||||
targetQuality = resource->Streaming.QualitySamples.Maximum();
|
targetQuality = resource->Streaming.QualitySamples.Maximum();
|
||||||
targetQuality = Math::Clamp<StreamingQuality>(targetQuality, MIN_STREAMING_QUALITY, MAX_STREAMING_QUALITY);
|
targetQuality = Math::Saturate(targetQuality);
|
||||||
|
|
||||||
// Calculate target residency level (discrete value)
|
// Calculate target residency level (discrete value)
|
||||||
auto maxResidency = resource->GetMaxResidency();
|
auto maxResidency = resource->GetMaxResidency();
|
||||||
@@ -132,7 +144,7 @@ void StreamingManagerService::Update()
|
|||||||
// Check if skip update
|
// Check if skip update
|
||||||
auto now = DateTime::NowUTC();
|
auto now = DateTime::NowUTC();
|
||||||
auto delta = now - LastUpdateTime;
|
auto delta = now - LastUpdateTime;
|
||||||
int32 resourcesCount = StreamingManager::Resources.ResourcesCount();
|
int32 resourcesCount = Streaming::Resources.ResourcesCount();
|
||||||
if (resourcesCount == 0 || delta < ManagerUpdatesInterval || GPUDevice::Instance->GetState() != GPUDevice::DeviceState::Ready)
|
if (resourcesCount == 0 || delta < ManagerUpdatesInterval || GPUDevice::Instance->GetState() != GPUDevice::DeviceState::Ready)
|
||||||
return;
|
return;
|
||||||
LastUpdateTime = now;
|
LastUpdateTime = now;
|
||||||
@@ -154,7 +166,7 @@ void StreamingManagerService::Update()
|
|||||||
LastUpdateResourcesIndex = 0;
|
LastUpdateResourcesIndex = 0;
|
||||||
|
|
||||||
// Peek resource
|
// Peek resource
|
||||||
const auto resource = StreamingManager::Resources[LastUpdateResourcesIndex];
|
const auto resource = Streaming::Resources[LastUpdateResourcesIndex];
|
||||||
|
|
||||||
// Try to update it
|
// Try to update it
|
||||||
if (now - resource->Streaming.LastUpdate >= ResourceUpdatesInterval && resource->CanBeUpdated())
|
if (now - resource->Streaming.LastUpdate >= ResourceUpdatesInterval && resource->CanBeUpdated())
|
||||||
25
Source/Engine/Streaming/Streaming.h
Normal file
25
Source/Engine/Streaming/Streaming.h
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Engine/Scripting/ScriptingType.h"
|
||||||
|
#include "TextureGroup.h"
|
||||||
|
#include "StreamableResourcesCollection.h"
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The content streaming service.
|
||||||
|
/// </summary>
|
||||||
|
API_CLASS(Static) class FLAXENGINE_API Streaming
|
||||||
|
{
|
||||||
|
DECLARE_SCRIPTING_TYPE_NO_SPAWN(Streaming);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List with all resources
|
||||||
|
/// </summary>
|
||||||
|
static StreamableResourcesCollection Resources;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Textures streaming configuration (per-group).
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD() static Array<TextureGroup, InlinedAllocation<32>> TextureGroups;
|
||||||
|
};
|
||||||
@@ -1,10 +1,7 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
#include "StreamingGroup.h"
|
#include "StreamingGroup.h"
|
||||||
#include "Handlers/TexturesStreamingHandler.h"
|
#include "StreamingHandlers.h"
|
||||||
#include "Handlers/ModelsStreamingHandler.h"
|
|
||||||
#include "Handlers/SkinnedModelsStreamingHandler.h"
|
|
||||||
#include "Handlers/AudioStreamingHandler.h"
|
|
||||||
|
|
||||||
StreamingGroup::StreamingGroup(Type type, IStreamingHandler* handler)
|
StreamingGroup::StreamingGroup(Type type, IStreamingHandler* handler)
|
||||||
: _type(type)
|
: _type(type)
|
||||||
|
|||||||
230
Source/Engine/Streaming/StreamingHandlers.cpp
Normal file
230
Source/Engine/Streaming/StreamingHandlers.cpp
Normal file
@@ -0,0 +1,230 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#include "StreamingHandlers.h"
|
||||||
|
#include "Streaming.h"
|
||||||
|
#include "Engine/Core/Math/Math.h"
|
||||||
|
#include "Engine/Graphics/Textures/StreamingTexture.h"
|
||||||
|
#include "Engine/Content/Assets/Model.h"
|
||||||
|
#include "Engine/Content/Assets/SkinnedModel.h"
|
||||||
|
#include "Engine/Audio/AudioClip.h"
|
||||||
|
#include "Engine/Audio/Audio.h"
|
||||||
|
#include "Engine/Audio/AudioSource.h"
|
||||||
|
|
||||||
|
float TexturesStreamingHandler::CalculateTargetQuality(StreamableResource* resource, DateTime now)
|
||||||
|
{
|
||||||
|
ASSERT(resource);
|
||||||
|
auto& texture = *(StreamingTexture*)resource;
|
||||||
|
const TextureHeader& header = *texture.GetHeader();
|
||||||
|
if (header.TextureGroup < 0 || header.TextureGroup >= Streaming::TextureGroups.Count())
|
||||||
|
{
|
||||||
|
// Full texture load by default
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Quality based on texture group settings
|
||||||
|
const TextureGroup& group = Streaming::TextureGroups[header.TextureGroup];
|
||||||
|
return group.QualityScale;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 TexturesStreamingHandler::CalculateResidency(StreamableResource* resource, float quality)
|
||||||
|
{
|
||||||
|
if (quality < ZeroTolerance)
|
||||||
|
return 0;
|
||||||
|
ASSERT(resource);
|
||||||
|
auto& texture = *(StreamingTexture*)resource;
|
||||||
|
ASSERT(texture.IsInitialized());
|
||||||
|
const TextureHeader& header = *texture.GetHeader();
|
||||||
|
|
||||||
|
const int32 totalMipLevels = texture.TotalMipLevels();
|
||||||
|
int32 mipLevels = Math::CeilToInt(quality * (float)totalMipLevels);
|
||||||
|
|
||||||
|
if (header.TextureGroup >= 0 && header.TextureGroup < Streaming::TextureGroups.Count())
|
||||||
|
{
|
||||||
|
const TextureGroup& group = Streaming::TextureGroups[header.TextureGroup];
|
||||||
|
mipLevels = Math::Clamp(mipLevels + group.MipLevelsBias, group.MipLevelsMin, group.MipLevelsMax);
|
||||||
|
#if USE_EDITOR
|
||||||
|
// Simulate per-platform limit in Editor
|
||||||
|
int32 max;
|
||||||
|
if (group.MipLevelsMaxPerPlatform.TryGet(PLATFORM_TYPE, max))
|
||||||
|
mipLevels = Math::Min(mipLevels, max);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mipLevels > 0 && mipLevels < 3 && totalMipLevels > 1 && texture.IsBlockCompressed())
|
||||||
|
{
|
||||||
|
// Block compressed textures require minimum size of 4 (3 mips or more)
|
||||||
|
mipLevels = 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
return Math::Clamp(mipLevels, 0, totalMipLevels);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 TexturesStreamingHandler::CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency)
|
||||||
|
{
|
||||||
|
ASSERT(resource);
|
||||||
|
auto& texture = *(StreamingTexture*)resource;
|
||||||
|
ASSERT(texture.IsInitialized());
|
||||||
|
int32 residency = targetResidency;
|
||||||
|
int32 currentResidency = texture.GetCurrentResidency();
|
||||||
|
if (currentResidency < targetResidency)
|
||||||
|
{
|
||||||
|
// Up
|
||||||
|
residency = Math::Min(currentResidency + 2, targetResidency);
|
||||||
|
|
||||||
|
// Stream first a few mips very fast (they are very small)
|
||||||
|
const int32 QuickStartMipsCount = 6;
|
||||||
|
if (currentResidency == 0)
|
||||||
|
{
|
||||||
|
residency = Math::Min(QuickStartMipsCount, targetResidency);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (currentResidency > targetResidency)
|
||||||
|
{
|
||||||
|
// Down at once
|
||||||
|
residency = targetResidency;
|
||||||
|
}
|
||||||
|
return residency;
|
||||||
|
}
|
||||||
|
|
||||||
|
float ModelsStreamingHandler::CalculateTargetQuality(StreamableResource* resource, DateTime now)
|
||||||
|
{
|
||||||
|
// TODO: calculate a proper quality levels for models based on render time and streaming enable/disable options
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 ModelsStreamingHandler::CalculateResidency(StreamableResource* resource, float quality)
|
||||||
|
{
|
||||||
|
if (quality < ZeroTolerance)
|
||||||
|
return 0;
|
||||||
|
ASSERT(resource);
|
||||||
|
auto& model = *(Model*)resource;
|
||||||
|
|
||||||
|
const int32 lodCount = model.GetLODsCount();
|
||||||
|
int32 lods = Math::CeilToInt(quality * (float)lodCount);
|
||||||
|
ASSERT(model.IsValidLODIndex(lods - 1));
|
||||||
|
return lods;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 ModelsStreamingHandler::CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency)
|
||||||
|
{
|
||||||
|
ASSERT(resource);
|
||||||
|
auto& model = *(Model*)resource;
|
||||||
|
|
||||||
|
// Always load only single LOD at once
|
||||||
|
int32 residency = targetResidency;
|
||||||
|
int32 currentResidency = model.GetCurrentResidency();
|
||||||
|
if (currentResidency < targetResidency)
|
||||||
|
{
|
||||||
|
// Up
|
||||||
|
residency = currentResidency + 1;
|
||||||
|
}
|
||||||
|
else if (currentResidency > targetResidency)
|
||||||
|
{
|
||||||
|
// Down
|
||||||
|
residency = currentResidency - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return residency;
|
||||||
|
}
|
||||||
|
|
||||||
|
float SkinnedModelsStreamingHandler::CalculateTargetQuality(StreamableResource* resource, DateTime now)
|
||||||
|
{
|
||||||
|
// TODO: calculate a proper quality levels for models based on render time and streaming enable/disable options
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 SkinnedModelsStreamingHandler::CalculateResidency(StreamableResource* resource, float quality)
|
||||||
|
{
|
||||||
|
if (quality < ZeroTolerance)
|
||||||
|
return 0;
|
||||||
|
ASSERT(resource);
|
||||||
|
auto& model = *(SkinnedModel*)resource;
|
||||||
|
|
||||||
|
const int32 lodCount = model.GetLODsCount();
|
||||||
|
int32 lods = Math::CeilToInt(quality * (float)lodCount);
|
||||||
|
ASSERT(model.IsValidLODIndex(lods - 1));
|
||||||
|
return lods;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 SkinnedModelsStreamingHandler::CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency)
|
||||||
|
{
|
||||||
|
ASSERT(resource);
|
||||||
|
auto& model = *(SkinnedModel*)resource;
|
||||||
|
|
||||||
|
// Always load only single LOD at once
|
||||||
|
int32 residency = targetResidency;
|
||||||
|
int32 currentResidency = model.GetCurrentResidency();
|
||||||
|
if (currentResidency < targetResidency)
|
||||||
|
{
|
||||||
|
// Up
|
||||||
|
residency = currentResidency + 1;
|
||||||
|
}
|
||||||
|
else if (currentResidency > targetResidency)
|
||||||
|
{
|
||||||
|
// Down
|
||||||
|
residency = currentResidency - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return residency;
|
||||||
|
}
|
||||||
|
|
||||||
|
float AudioStreamingHandler::CalculateTargetQuality(StreamableResource* resource, DateTime now)
|
||||||
|
{
|
||||||
|
// Audio clips don't use quality but only residency
|
||||||
|
return 1.0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 AudioStreamingHandler::CalculateResidency(StreamableResource* resource, float quality)
|
||||||
|
{
|
||||||
|
ASSERT(resource);
|
||||||
|
auto clip = static_cast<AudioClip*>(resource);
|
||||||
|
const int32 chunksCount = clip->Buffers.Count();
|
||||||
|
bool chunksMask[ASSET_FILE_DATA_CHUNKS];
|
||||||
|
Platform::MemoryClear(chunksMask, sizeof(chunksMask));
|
||||||
|
|
||||||
|
// Find audio chunks required for streaming
|
||||||
|
clip->StreamingQueue.Clear();
|
||||||
|
for (int32 sourceIndex = 0; sourceIndex < Audio::Sources.Count(); sourceIndex++)
|
||||||
|
{
|
||||||
|
// TODO: collect refs to audio clip from sources and use faster iteration (but do it thread-safe)
|
||||||
|
|
||||||
|
const auto src = Audio::Sources[sourceIndex];
|
||||||
|
if (src->Clip == clip && src->GetState() == AudioSource::States::Playing)
|
||||||
|
{
|
||||||
|
// Stream the current and the next chunk if could be used in a while
|
||||||
|
const int32 chunk = src->_streamingFirstChunk;
|
||||||
|
ASSERT(Math::IsInRange(chunk, 0, chunksCount));
|
||||||
|
chunksMask[chunk] = true;
|
||||||
|
|
||||||
|
const float StreamingDstSec = 2.0f;
|
||||||
|
if (chunk + 1 < chunksCount && src->GetTime() + StreamingDstSec >= clip->GetBufferStartTime(src->_streamingFirstChunk))
|
||||||
|
{
|
||||||
|
chunksMask[chunk + 1] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to enqueue chunks to modify (load or unload)
|
||||||
|
for (int32 i = 0; i < chunksCount; i++)
|
||||||
|
{
|
||||||
|
if (chunksMask[i] != (clip->Buffers[i] != 0))
|
||||||
|
{
|
||||||
|
clip->StreamingQueue.Add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return clip->StreamingQueue.Count();
|
||||||
|
}
|
||||||
|
|
||||||
|
int32 AudioStreamingHandler::CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency)
|
||||||
|
{
|
||||||
|
// No smoothing or slowdown in residency change
|
||||||
|
return targetResidency;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AudioStreamingHandler::RequiresStreaming(StreamableResource* resource, int32 currentResidency, int32 targetResidency)
|
||||||
|
{
|
||||||
|
// Audio clips use streaming queue buffer to detect streaming request start
|
||||||
|
const auto clip = static_cast<AudioClip*>(resource);
|
||||||
|
return clip->StreamingQueue.HasItems();
|
||||||
|
}
|
||||||
54
Source/Engine/Streaming/StreamingHandlers.h
Normal file
54
Source/Engine/Streaming/StreamingHandlers.h
Normal file
@@ -0,0 +1,54 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Engine/Streaming/IStreamingHandler.h"
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation of IStreamingHandler for streamable textures.
|
||||||
|
/// </summary>
|
||||||
|
class FLAXENGINE_API TexturesStreamingHandler : public IStreamingHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// [IStreamingHandler]
|
||||||
|
float CalculateTargetQuality(StreamableResource* resource, DateTime now) override;
|
||||||
|
int32 CalculateResidency(StreamableResource* resource, float quality) override;
|
||||||
|
int32 CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation of IStreamingHandler for streamable models.
|
||||||
|
/// </summary>
|
||||||
|
class FLAXENGINE_API ModelsStreamingHandler : public IStreamingHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// [IStreamingHandler]
|
||||||
|
float CalculateTargetQuality(StreamableResource* resource, DateTime now) override;
|
||||||
|
int32 CalculateResidency(StreamableResource* resource, float quality) override;
|
||||||
|
int32 CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation of IStreamingHandler for streamable skinned models.
|
||||||
|
/// </summary>
|
||||||
|
class FLAXENGINE_API SkinnedModelsStreamingHandler : public IStreamingHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// [IStreamingHandler]
|
||||||
|
float CalculateTargetQuality(StreamableResource* resource, DateTime now) override;
|
||||||
|
int32 CalculateResidency(StreamableResource* resource, float quality) override;
|
||||||
|
int32 CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency) override;
|
||||||
|
};
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Implementation of IStreamingHandler for audio clips.
|
||||||
|
/// </summary>
|
||||||
|
class FLAXENGINE_API AudioStreamingHandler : public IStreamingHandler
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// [IStreamingHandler]
|
||||||
|
float CalculateTargetQuality(StreamableResource* resource, DateTime now) override;
|
||||||
|
int32 CalculateResidency(StreamableResource* resource, float quality) override;
|
||||||
|
int32 CalculateRequestedResidency(StreamableResource* resource, int32 targetResidency) override;
|
||||||
|
bool RequiresStreaming(StreamableResource* resource, int32 currentResidency, int32 targetResidency) override;
|
||||||
|
};
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "StreamableResourcesCollection.h"
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Main class for dynamic resources streaming service
|
|
||||||
/// </summary>
|
|
||||||
class FLAXENGINE_API StreamingManager
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// List with all resources
|
|
||||||
/// </summary>
|
|
||||||
static StreamableResourcesCollection Resources;
|
|
||||||
};
|
|
||||||
32
Source/Engine/Streaming/StreamingSettings.h
Normal file
32
Source/Engine/Streaming/StreamingSettings.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Engine/Core/Config/Settings.h"
|
||||||
|
#include "TextureGroup.h"
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Content streaming settings.
|
||||||
|
/// </summary>
|
||||||
|
API_CLASS(sealed, Namespace="FlaxEditor.Content.Settings", NoConstructor) class FLAXENGINE_API StreamingSettings : public SettingsBase
|
||||||
|
{
|
||||||
|
DECLARE_SCRIPTING_TYPE_MINIMAL(StreamingSettings);
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Textures streaming configuration (per-group).
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes="EditorOrder(100), EditorDisplay(\"Textures\")")
|
||||||
|
Array<TextureGroup, InlinedAllocation<32>> TextureGroups;
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the instance of the settings asset (default value if missing). Object returned by this method is always loaded with valid data to use.
|
||||||
|
/// </summary>
|
||||||
|
static StreamingSettings* Get();
|
||||||
|
|
||||||
|
// [SettingsBase]
|
||||||
|
void Apply() override;
|
||||||
|
void Deserialize(DeserializeStream& stream, ISerializeModifier* modifier) final override;
|
||||||
|
};
|
||||||
56
Source/Engine/Streaming/TextureGroup.h
Normal file
56
Source/Engine/Streaming/TextureGroup.h
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright (c) 2012-2021 Wojciech Figat. All rights reserved.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "Engine/Core/Types/String.h"
|
||||||
|
#include "Engine/Core/ISerializable.h"
|
||||||
|
#if USE_EDITOR
|
||||||
|
#include "Engine/Core/Collections/Dictionary.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Settings container for a group of textures. Defines the data streaming options and resource quality.
|
||||||
|
/// </summary>
|
||||||
|
API_STRUCT() struct TextureGroup : ISerializable
|
||||||
|
{
|
||||||
|
API_AUTO_SERIALIZATION();
|
||||||
|
DECLARE_SCRIPTING_TYPE_MINIMAL(TextureGroup);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the group.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes="EditorOrder(10)")
|
||||||
|
String Name;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The quality scale factor applied to textures in this group. Can be used to increase or decrease textures resolution. In range 0-1 where 0 means lowest quality, 1 means full quality.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes="EditorOrder(20), Limit(0, 1)")
|
||||||
|
float QualityScale = 1.0f;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The minimum amount of loaded mip levels for textures in this group. Defines the amount of the mips that should be always loaded. Higher values decrease streaming usage and keep more mips loaded.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes="EditorOrder(30), Limit(0, 14)")
|
||||||
|
int32 MipLevelsMin = 0;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The maximum amount of loaded mip levels for textures in this group. Defines the maximum amount of the mips that can be loaded. Overriden per-platform. Lower values reduce textures quality and improve performance.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes="EditorOrder(40), Limit(1, 14)")
|
||||||
|
int32 MipLevelsMax = 14;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The loaded mip levels bias for textures in this group. Can be used to increase or decrease quality of the streaming for textures in this group (eg. bump up the quality during cinematic sequence).
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes="EditorOrder(50), Limit(-14, 14)")
|
||||||
|
int32 MipLevelsBias = 0;
|
||||||
|
|
||||||
|
#if USE_EDITOR
|
||||||
|
/// <summary>
|
||||||
|
/// The per-platform maximum amount of mip levels for textures in this group. Can be used to strip textures quality when cooking game for a target platform.
|
||||||
|
/// </summary>
|
||||||
|
API_FIELD(Attributes="EditorOrder(50)")
|
||||||
|
Dictionary<PlatformType, int32> MipLevelsMaxPerPlatform;
|
||||||
|
#endif
|
||||||
|
};
|
||||||
@@ -35,6 +35,7 @@ TextureTool::Options::Options()
|
|||||||
Resize = false;
|
Resize = false;
|
||||||
PreserveAlphaCoverage = false;
|
PreserveAlphaCoverage = false;
|
||||||
PreserveAlphaCoverageReference = 0.5f;
|
PreserveAlphaCoverageReference = 0.5f;
|
||||||
|
TextureGroup = -1;
|
||||||
Scale = 1.0f;
|
Scale = 1.0f;
|
||||||
SizeX = 1024;
|
SizeX = 1024;
|
||||||
SizeY = 1024;
|
SizeY = 1024;
|
||||||
@@ -97,6 +98,9 @@ void TextureTool::Options::Serialize(SerializeStream& stream, const void* otherO
|
|||||||
stream.JKEY("PreserveAlphaCoverageReference");
|
stream.JKEY("PreserveAlphaCoverageReference");
|
||||||
stream.Float(PreserveAlphaCoverageReference);
|
stream.Float(PreserveAlphaCoverageReference);
|
||||||
|
|
||||||
|
stream.JKEY("TextureGroup");
|
||||||
|
stream.Int(TextureGroup);
|
||||||
|
|
||||||
stream.JKEY("Scale");
|
stream.JKEY("Scale");
|
||||||
stream.Float(Scale);
|
stream.Float(Scale);
|
||||||
|
|
||||||
@@ -145,6 +149,7 @@ void TextureTool::Options::Deserialize(DeserializeStream& stream, ISerializeModi
|
|||||||
Resize = JsonTools::GetBool(stream, "Resize", Resize);
|
Resize = JsonTools::GetBool(stream, "Resize", Resize);
|
||||||
PreserveAlphaCoverage = JsonTools::GetBool(stream, "PreserveAlphaCoverage", PreserveAlphaCoverage);
|
PreserveAlphaCoverage = JsonTools::GetBool(stream, "PreserveAlphaCoverage", PreserveAlphaCoverage);
|
||||||
PreserveAlphaCoverageReference = JsonTools::GetFloat(stream, "PreserveAlphaCoverageReference", PreserveAlphaCoverageReference);
|
PreserveAlphaCoverageReference = JsonTools::GetFloat(stream, "PreserveAlphaCoverageReference", PreserveAlphaCoverageReference);
|
||||||
|
TextureGroup = JsonTools::GetInt(stream, "TextureGroup", TextureGroup);
|
||||||
Scale = JsonTools::GetFloat(stream, "Scale", Scale);
|
Scale = JsonTools::GetFloat(stream, "Scale", Scale);
|
||||||
SizeX = JsonTools::GetInt(stream, "SizeX", SizeX);
|
SizeX = JsonTools::GetInt(stream, "SizeX", SizeX);
|
||||||
SizeY = JsonTools::GetInt(stream, "SizeY", SizeY);
|
SizeY = JsonTools::GetInt(stream, "SizeY", SizeY);
|
||||||
|
|||||||
@@ -78,6 +78,11 @@ public:
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
float PreserveAlphaCoverageReference;
|
float PreserveAlphaCoverageReference;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Texture group for streaming (negative if unused). See Streaming Settings.
|
||||||
|
/// </summary>
|
||||||
|
int32 TextureGroup;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The import texture scale.
|
/// The import texture scale.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
Reference in New Issue
Block a user