diff --git a/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/DeserializingTextureInfo.cs b/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/DeserializingTextureInfo.cs index 0ce853544..b87439fb4 100644 --- a/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/DeserializingTextureInfo.cs +++ b/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/DeserializingTextureInfo.cs @@ -1,4 +1,5 @@ -using UnityEngine; +using Unity.Collections; +using UnityEngine; namespace UniGLTF { @@ -8,9 +9,11 @@ namespace UniGLTF public sealed class DeserializingTextureInfo { /// - /// Texture のバイト列 + /// Texture のバイト列。 + /// GltfData が保持する NativeArray をコピーせずそのまま参照するため、Dispose してはならない。 + /// 未設定の場合は IsCreated == false となる。 /// - public byte[] ImageData { get; } + public NativeArray ImageData { get; } /// /// Texture の mimeType @@ -44,7 +47,7 @@ namespace UniGLTF public TextureImportTypes ImportTypes { get; } - public DeserializingTextureInfo(byte[] imageData, string dataMimeType, ColorSpace colorSpace, bool useMipmap, FilterMode filterMode, TextureWrapMode wrapModeU, TextureWrapMode wrapModeV) + public DeserializingTextureInfo(NativeArray imageData, string dataMimeType, ColorSpace colorSpace, bool useMipmap, FilterMode filterMode, TextureWrapMode wrapModeU, TextureWrapMode wrapModeV) { ImageData = imageData; DataMimeType = dataMimeType; @@ -55,7 +58,7 @@ namespace UniGLTF WrapModeV = wrapModeV; } - public DeserializingTextureInfo(byte[] imageData, string dataMimeType, ColorSpace colorSpace, SamplerParam samplerParam, TextureImportTypes importTypes) + public DeserializingTextureInfo(NativeArray imageData, string dataMimeType, ColorSpace colorSpace, SamplerParam samplerParam, TextureImportTypes importTypes) { ImageData = imageData; DataMimeType = dataMimeType; diff --git a/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/GltfTextureImporter.cs b/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/GltfTextureImporter.cs index 2832ff02c..9d74d249c 100644 --- a/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/GltfTextureImporter.cs +++ b/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/GltfTextureImporter.cs @@ -23,11 +23,7 @@ namespace UniGLTF TextureImportTypes.sRGB, default, default, - () => - { - var imageBytes = data.GetBytesFromImage(imageIndex); - return Task.FromResult<(byte[], string)?>((ToArray(imageBytes?.binary ?? default), imageBytes?.mimeType)); - }, + () => Task.FromResult(GetImageBytesFromImageIndex(data, imageIndex)), default, default, default, default, default); return (texDesc.SubAssetKey, texDesc); } @@ -214,19 +210,10 @@ namespace UniGLTF return (offset, scale); } - private static (byte[] binary, string mimeType)? GetImageBytesFromImageIndex(GltfData data, int imageIndex) + private static (NativeArray binary, string mimeType)? GetImageBytesFromImageIndex(GltfData data, int imageIndex) { - if (imageIndex >= 0 && imageIndex < data.GLTF.images.Count) - { - var imageBytes = data.GetBytesFromImage(imageIndex); - if (imageBytes.HasValue) - { - - return (ToArray(imageBytes.Value.binary), imageBytes.Value.mimeType); - } - } - - return default; + // NOTE: GltfData が保持する NativeArray をコピーせずそのまま返す。 + return data.GetBytesFromImage(imageIndex); } private static int? GetImageIndexFromTextureIndex(GltfData data, int textureIndex) @@ -272,25 +259,5 @@ namespace UniGLTF } return true; } - - - private static byte[] ToArray(NativeArray bytes) - { - // if (bytes.Array == null) - // { - // return new byte[] { }; - // } - // else if (bytes.Offset == 0 && bytes.Count == bytes.Array.Length) - // { - // return bytes.Array; - // } - // else - // { - // var result = new byte[bytes.Count]; - // Buffer.BlockCopy(bytes.Array, bytes.Offset, result, 0, result.Length); - // return result; - // } - return bytes.ToArray(); - } } } diff --git a/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/KtxTextureDeserializer.cs b/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/KtxTextureDeserializer.cs index 0cd450d8c..7d368bc6c 100644 --- a/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/KtxTextureDeserializer.cs +++ b/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/KtxTextureDeserializer.cs @@ -15,15 +15,16 @@ namespace UniGLTF #pragma warning restore 1998 { #if USE_COM_UNITY_CLOUD_KTX - if (textureInfo.ImageData == null) return null; + if (!textureInfo.ImageData.IsCreated) return null; // NOTE: IAwaitCaller を無視するので、同期読み込みを期待する環境で同期読み込みができない try { var ktxTexture = new KtxTexture(); - using var nativeBytes = new NativeArray(textureInfo.ImageData, Allocator.Persistent); + // NOTE: GltfData が保持する NativeArray をそのまま渡す。 + // KtxUnity は Open() 内で同期的に読み取るだけで所有権を取らないため、コピー不要。 var result = await ktxTexture.LoadFromBytes( - nativeBytes, + textureInfo.ImageData, linear: textureInfo.ColorSpace == ColorSpace.Linear, mipChain: textureInfo.UseMipmap ); diff --git a/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/TextureDescriptor.cs b/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/TextureDescriptor.cs index bd71d3063..ba4d87ca7 100644 --- a/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/TextureDescriptor.cs +++ b/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/TextureDescriptor.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Unity.Collections; using UnityEngine; namespace UniGLTF @@ -11,9 +12,12 @@ namespace UniGLTF /// Texture2D.LoadImage /// extact: /// File.WriteAllBytes + /// + /// NOTE: binary は GltfData が保持する NativeArray をそのまま参照する。 + /// コピーを避けるため、呼び出し側で Dispose してはならない。 /// /// - public delegate Task<(byte[] binary, string mimeType)?> GetTextureBytesAsync(); + public delegate Task<(NativeArray binary, string mimeType)?> GetTextureBytesAsync(); /// /// 入力 glTF ファイルを Import した結果生成される、UnityEngine.Texture のアセット 1 つを確定させる Import 情報。 diff --git a/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/TextureFactory.cs b/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/TextureFactory.cs index 7de031287..f47ea2c53 100644 --- a/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/TextureFactory.cs +++ b/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/TextureFactory.cs @@ -84,7 +84,7 @@ namespace UniGLTF // https://docs.unity3d.com/2018.4/Documentation/Manual/StandardShaderMaterialParameterNormalMap.html var data0 = await texDesc.Index0(); var rawTexture = await TextureDeserializer.LoadTextureAsync( - new DeserializingTextureInfo(data0?.binary, data0?.mimeType, ColorSpace.Linear, texDesc.Sampler, texDesc.TextureType), + new DeserializingTextureInfo(data0?.binary ?? default, data0?.mimeType, ColorSpace.Linear, texDesc.Sampler, texDesc.TextureType), awaitCaller); rawTexture.name = subAssetKey.Name; _textureCache.Add(subAssetKey, rawTexture); @@ -100,14 +100,14 @@ namespace UniGLTF { var data0 = await texDesc.Index0(); metallicRoughnessTexture = await TextureDeserializer.LoadTextureAsync( - new DeserializingTextureInfo(data0?.binary, data0?.mimeType, ColorSpace.Linear, texDesc.Sampler, texDesc.TextureType), + new DeserializingTextureInfo(data0?.binary ?? default, data0?.mimeType, ColorSpace.Linear, texDesc.Sampler, texDesc.TextureType), awaitCaller); } if (texDesc.Index1 != null) { var data1 = await texDesc.Index1(); occlusionTexture = await TextureDeserializer.LoadTextureAsync( - new DeserializingTextureInfo(data1?.binary, data1?.mimeType, ColorSpace.Linear, texDesc.Sampler, texDesc.TextureType), + new DeserializingTextureInfo(data1?.binary ?? default, data1?.mimeType, ColorSpace.Linear, texDesc.Sampler, texDesc.TextureType), awaitCaller); } @@ -127,7 +127,7 @@ namespace UniGLTF { var data0 = await texDesc.Index0(); var rawTexture = await TextureDeserializer.LoadTextureAsync( - new DeserializingTextureInfo(data0?.binary, data0?.mimeType, ColorSpace.sRGB, texDesc.Sampler, texDesc.TextureType), + new DeserializingTextureInfo(data0?.binary ?? default, data0?.mimeType, ColorSpace.sRGB, texDesc.Sampler, texDesc.TextureType), awaitCaller); rawTexture.name = subAssetKey.Name; _textureCache.Add(subAssetKey, rawTexture); @@ -137,7 +137,7 @@ namespace UniGLTF { var data0 = await texDesc.Index0(); var rawTexture = await TextureDeserializer.LoadTextureAsync( - new DeserializingTextureInfo(data0?.binary, data0?.mimeType, ColorSpace.Linear, texDesc.Sampler, texDesc.TextureType), + new DeserializingTextureInfo(data0?.binary ?? default, data0?.mimeType, ColorSpace.Linear, texDesc.Sampler, texDesc.TextureType), awaitCaller); rawTexture.name = subAssetKey.Name; _textureCache.Add(subAssetKey, rawTexture); diff --git a/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/UnitySupportedImageTypeDeserializer.cs b/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/UnitySupportedImageTypeDeserializer.cs index ee9c052ea..033a7f981 100644 --- a/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/UnitySupportedImageTypeDeserializer.cs +++ b/Packages/UniGLTF/Runtime/UniGLTF/IO/TextureIO/Import/UnitySupportedImageTypeDeserializer.cs @@ -1,5 +1,6 @@ using System; using System.Threading.Tasks; +using Unity.Collections; using UnityEngine; namespace UniGLTF @@ -29,12 +30,17 @@ namespace UniGLTF public async Task LoadTextureAsync(DeserializingTextureInfo textureInfo, IAwaitCaller awaitCaller) { - if (textureInfo.ImageData == null) return null; + if (!textureInfo.ImageData.IsCreated) return null; try { var texture = new Texture2D(2, 2, TextureFormat.ARGB32, textureInfo.UseMipmap, textureInfo.ColorSpace == ColorSpace.Linear); - texture.LoadImage(textureInfo.ImageData, ImportedTexturesAccessibility.ToMarkNonReadable()); +#if UNITY_6000_0_OR_NEWER + // Unity 6000.0.42f1 以降は LoadImage が ReadOnlySpan を受け取れるため、NativeArray からのコピーを避ける。 + texture.LoadImage(textureInfo.ImageData.AsReadOnlySpan(), ImportedTexturesAccessibility.ToMarkNonReadable()); +#else + texture.LoadImage(textureInfo.ImageData.ToArray(), ImportedTexturesAccessibility.ToMarkNonReadable()); +#endif await awaitCaller.NextFrame(); texture.wrapModeU = textureInfo.WrapModeU;