mirror of
https://github.com/aharabada/glitchy-engine-beef.git
synced 2026-09-05 13:01:52 +00:00
Load pngs from cache
This commit is contained in:
@@ -230,4 +230,17 @@ class AssetCache
|
||||
|
||||
return .Ok;
|
||||
}
|
||||
|
||||
public Result<void> OpenFileStream(CachedAsset asset, FileStream fileStream)
|
||||
{
|
||||
if (asset == null)
|
||||
return .Err;
|
||||
|
||||
Try!(fileStream.Close());
|
||||
Try!(fileStream.Open(asset.FilePath, .Read, .Read));
|
||||
|
||||
fileStream.Position = asset.DataOffset;
|
||||
|
||||
return .Ok;
|
||||
}
|
||||
}
|
||||
@@ -27,3 +27,8 @@ interface IAssetExporter
|
||||
|
||||
Result<void> Export(Stream stream, ProcessedResource processedObject, AssetExporterConfig config);
|
||||
}
|
||||
|
||||
interface IProcessedAssetLoader
|
||||
{
|
||||
Result<Asset> Load(Stream stream);
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ using Bon;
|
||||
using GlitchyEngine.Content;
|
||||
using GlitchyEngine;
|
||||
using GlitchyEngine.Renderer;
|
||||
using GlitchyEngine.Math;
|
||||
using static GlitchyEditor.Assets.Importers.LoadedTextureInfo;
|
||||
|
||||
namespace GlitchyEditor.Assets.Importers;
|
||||
@@ -233,12 +234,21 @@ class TextureProcessorConfig : AssetProcessorConfig
|
||||
{
|
||||
[BonInclude]
|
||||
private GenerateMipMaps _generateMipMaps;
|
||||
|
||||
[BonInclude]
|
||||
private SamplerStateDescription _samplerStateDescription = .();
|
||||
|
||||
public GenerateMipMaps GenerateMipMaps
|
||||
{
|
||||
get => _generateMipMaps;
|
||||
set => SetIfChanged(ref _generateMipMaps, value);
|
||||
}
|
||||
|
||||
public SamplerStateDescription SamplerStateDescription
|
||||
{
|
||||
get => _samplerStateDescription;
|
||||
set => SetIfChanged(ref _samplerStateDescription, value);
|
||||
}
|
||||
}
|
||||
|
||||
abstract class ProcessedResource
|
||||
@@ -267,6 +277,8 @@ class ProcessedTexture : ProcessedResource
|
||||
public int Height = -1;
|
||||
public int Depth = -1;
|
||||
|
||||
public SamplerStateDescription SamplerStateDescription;
|
||||
|
||||
public override AssetType AssetType => .Texture;
|
||||
|
||||
public class TextureSurface
|
||||
@@ -277,9 +289,11 @@ class ProcessedTexture : ProcessedResource
|
||||
public int Depth;
|
||||
public int MipLevel;
|
||||
public int ArraySlice;
|
||||
public int LinePitch;
|
||||
public int SlicePitch;
|
||||
|
||||
[AllowAppend]
|
||||
public this(int width, int height, int depth, Span<uint8> data, int mipLevel, int arraySlice)
|
||||
public this(int width, int height, int depth, Span<uint8> data, int mipLevel, int arraySlice, int linePitch, int slicePitch)
|
||||
{
|
||||
uint8[] pixelData = append uint8[data.Length];
|
||||
data.CopyTo(pixelData);
|
||||
@@ -290,6 +304,8 @@ class ProcessedTexture : ProcessedResource
|
||||
Depth = depth;
|
||||
MipLevel = mipLevel;
|
||||
ArraySlice = arraySlice;
|
||||
LinePitch = linePitch;
|
||||
SlicePitch = slicePitch;
|
||||
}
|
||||
|
||||
public uint64 LoadRaw(int x, int y, int z, Format format, ComponentInfo component)
|
||||
@@ -389,13 +405,15 @@ class TextureProcessor : IAssetProcessor
|
||||
processedTexture.Width = importedTexture.TextureInfo.Width;
|
||||
processedTexture.Height = importedTexture.TextureInfo.Height;
|
||||
processedTexture.Depth = importedTexture.TextureInfo.Depth;
|
||||
|
||||
processedTexture.SamplerStateDescription = config.SamplerStateDescription;
|
||||
|
||||
processedTexture.SetSurfaceCount(importedTexture.TextureInfo.ArraySize, importedTexture.TextureInfo.MipMapCount);
|
||||
|
||||
for (LoadedSurface loadedSurface in importedTexture.Surfaces)
|
||||
{
|
||||
ProcessedTexture.TextureSurface surface = new .(loadedSurface.Width, loadedSurface.Height, loadedSurface.Depth,
|
||||
loadedSurface.Data, loadedSurface.MipLevel, loadedSurface.ArrayIndex);
|
||||
loadedSurface.Data, loadedSurface.MipLevel, loadedSurface.ArrayIndex, loadedSurface.Pitch, loadedSurface.SlicePitch);
|
||||
processedTexture.Surfaces[loadedSurface.ArrayIndex, loadedSurface.MipLevel] = surface;
|
||||
}
|
||||
|
||||
@@ -499,7 +517,9 @@ class TextureProcessor : IAssetProcessor
|
||||
|
||||
if (smallerLevel == null)
|
||||
{
|
||||
smallerLevel = new ProcessedTexture.TextureSurface(width, height, depth, new uint8[width * height * depth * pixelFormat.BitsPerPixel()], largerLevel.MipLevel + 1, largerLevel.ArraySlice);
|
||||
smallerLevel = new ProcessedTexture.TextureSurface(width, height, depth,
|
||||
new uint8[width * height * depth * pixelFormat.BitsPerPixel()], largerLevel.MipLevel + 1, largerLevel.ArraySlice,
|
||||
-1, -1); // TODO!
|
||||
}
|
||||
|
||||
// TODO: Kaiser mip maps?
|
||||
@@ -556,6 +576,8 @@ class TextureExporter : IAssetExporter
|
||||
Depth of larges mip-slice (4 bytes)
|
||||
Array size (4 bytes)
|
||||
Mip map levels (4 bytes)
|
||||
Is Cubemap (1 byte)
|
||||
Data Byte count (8 bytes)
|
||||
Pixeldata
|
||||
{
|
||||
Array[0]: Mip[0] Mip[1] ... Mip[M]
|
||||
@@ -573,6 +595,9 @@ class TextureExporter : IAssetExporter
|
||||
Try!(stream.Write((uint32)processedTexture.Depth));
|
||||
Try!(stream.Write((uint32)processedTexture.ArraySize));
|
||||
Try!(stream.Write((uint32)processedTexture.MipMapCount));
|
||||
Try!(stream.Write(processedTexture.IsCubeMap));
|
||||
|
||||
Try!(WriteSamplerStateDescription(stream, processedTexture.SamplerStateDescription));
|
||||
|
||||
for (int arraySlice < processedTexture.ArraySize)
|
||||
{
|
||||
@@ -599,29 +624,122 @@ class TextureExporter : IAssetExporter
|
||||
|
||||
if (validateDepth < 1)
|
||||
validateDepth = 1;
|
||||
|
||||
|
||||
Try!(stream.Write((uint32)slice.LinePitch));
|
||||
Try!(stream.Write((uint32)slice.SlicePitch));
|
||||
Try!(stream.Write((uint64)slice.PixelData.Count));
|
||||
Try!(stream.TryWrite(slice.PixelData));
|
||||
}
|
||||
}
|
||||
|
||||
return .Ok;
|
||||
}
|
||||
}
|
||||
|
||||
class TextureLoader
|
||||
{
|
||||
public Result<Asset> Load(Stream data, AssetIdentifier assetIdentifier)
|
||||
private Result<void> WriteSamplerStateDescription(Stream stream, SamplerStateDescription sampler)
|
||||
{
|
||||
Dimension dimension = Try!(data.Read<Dimension>());
|
||||
Format pixelFormat = Try!(data.Read<Format>());
|
||||
uint32 width = Try!(data.Read<uint32>());
|
||||
uint32 height = Try!(data.Read<uint32>());
|
||||
uint32 depth = Try!(data.Read<uint32>());
|
||||
uint32 arraySize = Try!(data.Read<uint32>());
|
||||
uint32 mipMapCount = Try!(data.Read<uint32>());
|
||||
Try!(stream.Write(sampler.MinFilter));
|
||||
Try!(stream.Write(sampler.MagFilter));
|
||||
Try!(stream.Write(sampler.MipFilter));
|
||||
Try!(stream.Write(sampler.FilterMode));
|
||||
Try!(stream.Write(sampler.ComparisonFunction));
|
||||
Try!(stream.Write(sampler.AddressModeU));
|
||||
Try!(stream.Write(sampler.AddressModeV));
|
||||
Try!(stream.Write(sampler.AddressModeW));
|
||||
Try!(stream.Write(sampler.MipLODBias));
|
||||
Try!(stream.Write(sampler.MipMinLOD));
|
||||
Try!(stream.Write(sampler.MipMaxLOD));
|
||||
Try!(stream.Write(sampler.MaxAnisotropy));
|
||||
Try!(stream.Write(sampler.BorderColor));
|
||||
|
||||
return .Ok;
|
||||
}
|
||||
}
|
||||
|
||||
class TextureLoader : IProcessedAssetLoader
|
||||
{
|
||||
public Result<Asset> Load(Stream dataStream)
|
||||
{
|
||||
Dimension dimension = Try!(dataStream.Read<Dimension>());
|
||||
Format pixelFormat = Try!(dataStream.Read<Format>());
|
||||
uint32 width = Try!(dataStream.Read<uint32>());
|
||||
uint32 height = Try!(dataStream.Read<uint32>());
|
||||
uint32 depth = Try!(dataStream.Read<uint32>());
|
||||
uint32 arraySize = Try!(dataStream.Read<uint32>());
|
||||
uint32 mipMapCount = Try!(dataStream.Read<uint32>());
|
||||
bool isCubemap = Try!(dataStream.Read<bool>());
|
||||
|
||||
return .Ok(null);
|
||||
SamplerStateDescription sampler = Try!(ReadSampler(dataStream));
|
||||
|
||||
List<uint8[]> surfaceDatas = scope .(mipMapCount * arraySize);
|
||||
defer { ClearAndDeleteItems!(surfaceDatas); }
|
||||
|
||||
TextureSliceData[] slices = scope TextureSliceData[mipMapCount * arraySize];
|
||||
|
||||
int index = 0;
|
||||
for (int arraySlice < arraySize)
|
||||
{
|
||||
for (int mipSlice < mipMapCount)
|
||||
{
|
||||
uint32 linePitch = Try!(dataStream.Read<uint32>());
|
||||
uint32 slicePitch = Try!(dataStream.Read<uint32>());
|
||||
uint64 byteCount = Try!(dataStream.Read<uint64>());
|
||||
|
||||
uint8[] surfaceData = new uint8[byteCount];
|
||||
Try!(dataStream.TryRead(surfaceData));
|
||||
slices[index] = .(surfaceData.Ptr, linePitch, slicePitch);
|
||||
|
||||
index++;
|
||||
|
||||
surfaceDatas.Add(surfaceData);
|
||||
}
|
||||
}
|
||||
|
||||
Texture result = null;
|
||||
|
||||
switch (dimension)
|
||||
{
|
||||
case .Texture2D:
|
||||
if (isCubemap)
|
||||
{
|
||||
Runtime.NotImplemented();
|
||||
}
|
||||
else
|
||||
{
|
||||
Texture2DDesc desc = .(width, height, pixelFormat, arraySize, mipMapCount, .Immutable, .None);
|
||||
|
||||
Texture2D texture = new Texture2D(desc);
|
||||
|
||||
texture.SetData(slices);
|
||||
|
||||
result = texture;
|
||||
}
|
||||
default:
|
||||
Runtime.NotImplemented();
|
||||
}
|
||||
|
||||
result.SamplerState = SamplerStateManager.GetSampler(sampler);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Result<SamplerStateDescription> ReadSampler(Stream dataStream)
|
||||
{
|
||||
SamplerStateDescription sampler;
|
||||
|
||||
sampler.MinFilter = Try!(dataStream.Read<FilterFunction>());
|
||||
sampler.MagFilter = Try!(dataStream.Read<FilterFunction>());
|
||||
sampler.MipFilter = Try!(dataStream.Read<FilterFunction>());
|
||||
sampler.FilterMode = Try!(dataStream.Read<FilterMode>());
|
||||
sampler.ComparisonFunction = Try!(dataStream.Read<ComparisonFunction>());
|
||||
sampler.AddressModeU = Try!(dataStream.Read<TextureAddressMode>());
|
||||
sampler.AddressModeV = Try!(dataStream.Read<TextureAddressMode>());
|
||||
sampler.AddressModeW = Try!(dataStream.Read<TextureAddressMode>());
|
||||
sampler.MipLODBias = Try!(dataStream.Read<float>());
|
||||
sampler.MipMinLOD = Try!(dataStream.Read<float>());
|
||||
sampler.MipMaxLOD = Try!(dataStream.Read<float>());
|
||||
sampler.MaxAnisotropy = Try!(dataStream.Read<uint8>());
|
||||
sampler.BorderColor = Try!(dataStream.Read<ColorRGBA>());
|
||||
|
||||
return sampler;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,70 +469,73 @@ class EditorContentManager : IContentManager
|
||||
Log.EngineLogger.Error($"Could not find asset with handle {handle}.");
|
||||
return .Invalid;
|
||||
}
|
||||
|
||||
AssetNode assetNode = resultNode->Value;
|
||||
AssetFile file = assetNode.AssetFile;
|
||||
|
||||
CachedAsset cacheEntry = _assetCache.GetCacheEntry(handle);
|
||||
|
||||
Asset loadedAsset;
|
||||
|
||||
// TODO: Remove this check once we no longer need the old stuff
|
||||
if (cacheEntry != null)
|
||||
{
|
||||
// TODO: Load asset with new loaders
|
||||
}
|
||||
|
||||
String filePath = scope String(resultNode->Value.Path);
|
||||
|
||||
AssetNode assetNode = resultNode->Value;
|
||||
AssetFile file = assetNode.AssetFile;
|
||||
|
||||
GetResourceAndSubassetName(assetNode.Identifier, let resourceName, let subassetName);
|
||||
|
||||
IAssetLoader assetLoader = GetAssetLoader(file);
|
||||
|
||||
//Log.EngineLogger.AssertDebug(assetLoader != null);
|
||||
if (assetLoader == null)
|
||||
{
|
||||
Log.EngineLogger.Error($"No asset loader registered for asset \"{resultNode->Value.Identifier}\" ({handle}).");
|
||||
return .Invalid;
|
||||
}
|
||||
|
||||
Asset loadedAsset;
|
||||
|
||||
// TODO: Support lazy loading for all asset types
|
||||
if (!(assetLoader is EditorTextureAssetLoader) || blocking)
|
||||
{
|
||||
Stream stream = OpenStream(filePath, true);
|
||||
|
||||
loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config, resourceName, subassetName, this);
|
||||
|
||||
delete stream;
|
||||
|
||||
if (loadedAsset == null)
|
||||
return .Invalid;
|
||||
loadedAsset = LoadFromCache(handle, blocking);
|
||||
}
|
||||
else
|
||||
{
|
||||
PlaceholderAsset placeholder = new PlaceholderAsset(file, assetLoader, .Loading);
|
||||
// else use the old mess...
|
||||
|
||||
String filePath = scope String(resultNode->Value.Path);
|
||||
|
||||
String filePath2 = new String(filePath);
|
||||
String newResourceName = new String(resourceName);
|
||||
String newSesourceName = subassetName == null ? null : new String(subassetName.Value);
|
||||
GetResourceAndSubassetName(assetNode.Identifier, let resourceName, let subassetName);
|
||||
|
||||
placeholder.LoadingTask = new Task(new () => {
|
||||
AsyncLoadAsset(placeholder, filePath2, assetLoader, file,
|
||||
newResourceName, newSesourceName);
|
||||
});
|
||||
IAssetLoader assetLoader = GetAssetLoader(file);
|
||||
|
||||
ThreadPool.QueueUserWorkItem(placeholder.LoadingTask);
|
||||
//Log.EngineLogger.AssertDebug(assetLoader != null);
|
||||
if (assetLoader == null)
|
||||
{
|
||||
Log.EngineLogger.Error($"No asset loader registered for asset \"{resultNode->Value.Identifier}\" ({handle}).");
|
||||
return .Invalid;
|
||||
}
|
||||
|
||||
loadedAsset = placeholder;
|
||||
// TODO: Support lazy loading for all asset types
|
||||
if (!(assetLoader is EditorTextureAssetLoader) || blocking)
|
||||
{
|
||||
Stream stream = OpenStream(filePath, true);
|
||||
|
||||
loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config, resourceName, subassetName, this);
|
||||
|
||||
delete stream;
|
||||
|
||||
if (loadedAsset == null)
|
||||
return .Invalid;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlaceholderAsset placeholder = new PlaceholderAsset(file, assetLoader, .Loading);
|
||||
|
||||
String filePath2 = new String(filePath);
|
||||
String newResourceName = new String(resourceName);
|
||||
String newSesourceName = subassetName == null ? null : new String(subassetName.Value);
|
||||
|
||||
placeholder.LoadingTask = new Task(new () => {
|
||||
AsyncLoadAsset(placeholder, filePath2, assetLoader, file,
|
||||
newResourceName, newSesourceName);
|
||||
});
|
||||
|
||||
ThreadPool.QueueUserWorkItem(placeholder.LoadingTask);
|
||||
|
||||
loadedAsset = placeholder;
|
||||
}
|
||||
}
|
||||
|
||||
loadedAsset.Identifier = assetNode.Identifier;
|
||||
|
||||
_handleToAsset.Add(handle, loadedAsset);
|
||||
|
||||
loadedAsset.[Friend]_contentManager = this;
|
||||
loadedAsset.[Friend]_handle = handle;
|
||||
|
||||
// Add to Identifier -> Handle map
|
||||
_handleToAsset.Add(handle, loadedAsset);
|
||||
_identiferToHandle.Add(loadedAsset.Identifier, handle);
|
||||
|
||||
file.[Friend]_loadedAsset = loadedAsset;
|
||||
@@ -567,99 +570,6 @@ class EditorContentManager : IContentManager
|
||||
|
||||
return .Invalid;
|
||||
}
|
||||
|
||||
//Result<TreeNode<AssetNode>> resultNode = AssetHierarchy.GetNodeFromIdentifier(fixedIdentifier);
|
||||
|
||||
//resultNode.
|
||||
|
||||
/*
|
||||
if (_identiferToHandle.TryGetValue(fixedIdentifier, let asset))
|
||||
return asset;
|
||||
|
||||
GetResourceAndSubassetName(fixedIdentifier, let resourceName, let subassetName);
|
||||
|
||||
Result<TreeNode<AssetNode>> resultNode = AssetHierarchy.GetNodeFromIdentifier(fixedIdentifier);
|
||||
|
||||
if (resultNode case .Err)
|
||||
{
|
||||
Log.EngineLogger.Error($"Could not find asset \"{fixedIdentifier}\".");
|
||||
return .Invalid;
|
||||
}
|
||||
|
||||
String filePath = scope String(resultNode->Value.Path);
|
||||
|
||||
AssetFile file = resultNode->Value.AssetFile;
|
||||
|
||||
IAssetLoader assetLoader = GetAssetLoader(file);
|
||||
|
||||
// TODO: what are we supposed to do if we don't find a loader? Surely not crash...
|
||||
//Log.EngineLogger.AssertDebug(assetLoader != null);
|
||||
if (assetLoader == null)
|
||||
{
|
||||
Log.EngineLogger.Error($"No asset loader registered for asset {identifier}.");
|
||||
return .Invalid;
|
||||
}
|
||||
|
||||
Asset loadedAsset;
|
||||
|
||||
// TODO: Support lazy loading for all asset types
|
||||
if (!(assetLoader is EditorTextureAssetLoader) || blocking)
|
||||
{
|
||||
Stream stream = OpenStream(filePath, true);
|
||||
|
||||
loadedAsset = assetLoader.LoadAsset(stream, file.AssetConfig.Config, resourceName, subassetName, this);
|
||||
|
||||
delete stream;
|
||||
|
||||
if (loadedAsset == null)
|
||||
return .Invalid;
|
||||
}
|
||||
else
|
||||
{
|
||||
PlaceholderAsset placeholder = new PlaceholderAsset(file, assetLoader, .Loading);
|
||||
|
||||
String filePath2 = new String(filePath);
|
||||
String newResourceName = new String(resourceName);
|
||||
String newSesourceName = subassetName == null ? null : new String(subassetName.Value);
|
||||
|
||||
placeholder.LoadingTask = new Task(new () => {
|
||||
AsyncLoadAsset(placeholder, filePath2, assetLoader, file,
|
||||
newResourceName, newSesourceName);
|
||||
});
|
||||
|
||||
ThreadPool.QueueUserWorkItem(placeholder.LoadingTask);
|
||||
|
||||
loadedAsset = placeholder;
|
||||
}
|
||||
|
||||
loadedAsset.Identifier = fixedIdentifier;
|
||||
|
||||
AssetHandle handle = .Invalid;
|
||||
|
||||
if (file.AssetConfig.AssetHandle == .Invalid)
|
||||
{
|
||||
handle = ManageAsset(loadedAsset);
|
||||
// TODO: Does this ever happen?
|
||||
file.AssetConfig.AssetHandle = handle;
|
||||
}
|
||||
else
|
||||
{
|
||||
handle = file.AssetConfig.AssetHandle;
|
||||
_handleToAsset.Add(handle, loadedAsset);
|
||||
|
||||
loadedAsset.[Friend]_contentManager = this;
|
||||
loadedAsset.[Friend]_handle = handle;
|
||||
}
|
||||
|
||||
// ManageAsset increases RefCount, but this scope also holds a reference.
|
||||
loadedAsset.ReleaseRef();
|
||||
|
||||
// Add to Identifier -> Handle map
|
||||
_identiferToHandle.Add(loadedAsset.Identifier, handle);
|
||||
|
||||
file.[Friend]_loadedAsset = loadedAsset;
|
||||
|
||||
return handle;*/
|
||||
}
|
||||
|
||||
private void AsyncLoadAsset(PlaceholderAsset placeholder, String filePath, IAssetLoader assetLoader, AssetFile file, String resourceName, String subassetName)
|
||||
@@ -998,4 +908,39 @@ class EditorContentManager : IContentManager
|
||||
//UnmanageAsset(asset);
|
||||
//ManageAsset(asset);
|
||||
}
|
||||
|
||||
// TODO: obviously use a map or something...
|
||||
TextureLoader textureLoader = new .();
|
||||
|
||||
private IProcessedAssetLoader GetLoader(AssetType assetType)
|
||||
{
|
||||
switch (assetType)
|
||||
{
|
||||
case .Texture:
|
||||
return textureLoader;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private Asset LoadFromCache(AssetHandle handle, bool isBlocking)
|
||||
{
|
||||
FileStream file = scope .();
|
||||
|
||||
CachedAsset asset = _assetCache.GetCacheEntry(handle);
|
||||
|
||||
// TODO: Actually return a placeholder, but they probably need rework too...
|
||||
if (_assetCache.OpenFileStream(asset, file) case .Err)
|
||||
return null;
|
||||
|
||||
IProcessedAssetLoader loader = GetLoader(asset.AssetType);
|
||||
|
||||
switch (loader.Load(file))
|
||||
{
|
||||
case .Ok(let loadedAsset):
|
||||
return loadedAsset;
|
||||
case .Err:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user