Ejemplo n.º 1
0
        public override void Serialize(ContentSerializerContext context, SerializationStream stream, Image textureData)
        {
            if (context.Mode == ArchiveMode.Deserialize)
            {
                var isStreamable = stream.ReadBoolean();
                if (!isStreamable)
                {
                    var image = Image.Load(stream.NativeStream);
                    textureData.InitializeFrom(image);
                }
                else
                {
                    // Read image header
                    var imageDescription = new ImageDescription();
                    ImageHelper.ImageDescriptionSerializer.Serialize(ref imageDescription, ArchiveMode.Deserialize, stream);

                    // Read content storage header
                    ContentStorageHeader storageHeader;
                    ContentStorageHeader.Read(stream, out storageHeader);

                    // Deserialize whole texture to image without streaming feature
                    var contentSerializerContext = stream.Context.Get(ContentSerializerContext.ContentSerializerContextProperty);
                    DeserializeImage(contentSerializerContext.ContentManager, textureData, ref imageDescription, ref storageHeader);
                }
            }
            else
            {
                textureData.Save(stream.NativeStream, ImageFileType.Xenko);
            }
        }
Ejemplo n.º 2
0
        internal static void Serialize(ArchiveMode mode, SerializationStream stream, Texture texture, bool allowContentStreaming)
        {
            if (mode == ArchiveMode.Deserialize)
            {
                var services = stream.Context.Tags.Get(ServiceRegistry.ServiceRegistryKey);
                var graphicsDeviceService     = services.GetSafeServiceAs <IGraphicsDeviceService>();
                var texturesStreamingProvider = services.GetService <ITexturesStreamingProvider>();

                var isStreamable = stream.ReadBoolean();
                if (!isStreamable)
                {
                    texturesStreamingProvider?.UnregisterTexture(texture);

                    // TODO: Error handling?
                    using (var textureData = Image.Load(stream.NativeStream))
                    {
                        if (texture.GraphicsDevice != null)
                        {
                            texture.OnDestroyed(); //Allows fast reloading todo review maybe?
                        }
                        texture.AttachToGraphicsDevice(graphicsDeviceService.GraphicsDevice);
                        texture.InitializeFrom(textureData.Description, new TextureViewDescription(), textureData.ToDataBox());

                        // Setup reload callback (reload from asset manager)
                        var contentSerializerContext = stream.Context.Get(ContentSerializerContext.ContentSerializerContextProperty);
                        if (contentSerializerContext != null)
                        {
                            var assetManager = contentSerializerContext.ContentManager;
                            var url          = contentSerializerContext.Url;

                            texture.Reload = (graphicsResource) =>
                            {
                                var textureDataReloaded = assetManager.Load <Image>(url);
                                ((Texture)graphicsResource).Recreate(textureDataReloaded.ToDataBox());
                                assetManager.Unload(textureDataReloaded);
                            };
                        }
                    }
                }
                else
                {
                    if (texture.GraphicsDevice != null)
                    {
                        texture.OnDestroyed();
                    }

                    texture.AttachToGraphicsDevice(graphicsDeviceService.GraphicsDevice);
                    texture.Reload = null;

                    // Read image header
                    var imageDescription = new ImageDescription();
                    ImageHelper.ImageDescriptionSerializer.Serialize(ref imageDescription, ArchiveMode.Deserialize, stream);

                    // Read content storage header
                    ContentStorageHeader storageHeader;
                    ContentStorageHeader.Read(stream, out storageHeader);

                    // Check if streaming service is available
                    if (texturesStreamingProvider != null)
                    {
                        // Load initial texture (with limited number of mipmaps)
                        if (storageHeader.InitialImage)
                        {
                            using (var textureData = Image.Load(stream.NativeStream))
                            {
                                if (texture.GraphicsDevice != null)
                                {
                                    texture.OnDestroyed(); //Allows fast reloading todo review maybe?
                                }
                                texture.InitializeFrom(textureData.Description, new TextureViewDescription(), textureData.ToDataBox());
                            }
                        }

                        if (allowContentStreaming)
                        {
                            // Register texture for streaming
                            // NOTE: Here we don't load texture data and don't allocate GPU memory
                            texturesStreamingProvider.RegisterTexture(texture, ref imageDescription, ref storageHeader);
                        }
                        else
                        {
                            // Request texture loading (should be fully loaded)
                            texturesStreamingProvider.FullyLoadTexture(texture, ref imageDescription, ref storageHeader);
                        }
                    }
                    else
                    {
                        // Load initial texture and discard it (we are going to load the full chunk texture right after)
                        if (storageHeader.InitialImage)
                        {
                            using (var textureData = Image.Load(stream.NativeStream)) { }
                        }

                        // Deserialize whole texture without streaming feature
                        var contentSerializerContext = stream.Context.Get(ContentSerializerContext.ContentSerializerContextProperty);
                        DeserializeTexture(contentSerializerContext.ContentManager, texture, ref imageDescription, ref storageHeader);
                    }
                }
            }
            else
            {
                var textureData = texture.GetSerializationData();
                if (textureData is null)
                {
                    throw new InvalidOperationException("Trying to serialize a Texture without CPU info.");
                }

                textureData.Write(stream);
            }
        }
Ejemplo n.º 3
0
        private static void DeserializeTexture(ContentManager contentManager, Texture texture, ref ImageDescription imageDescription, ref ContentStorageHeader storageHeader)
        {
            using (var content = new ContentStreamingService())
            {
                // Get content storage container
                var storage = content.GetStorage(ref storageHeader);
                if (storage is null)
                {
                    throw new ContentStreamingException("Missing content storage.");
                }
                storage.LockChunks();

                // Cache data
                var  fileProvider      = contentManager.FileProvider;
                var  format            = imageDescription.Format;
                bool isBlockCompressed =
                    (format >= PixelFormat.BC1_Typeless && format <= PixelFormat.BC5_SNorm) ||
                    (format >= PixelFormat.BC6H_Typeless && format <= PixelFormat.BC7_UNorm_SRgb);
                var dataBoxes    = new DataBox[imageDescription.MipLevels * imageDescription.ArraySize];
                int dataBoxIndex = 0;

                // Get data boxes data
                for (int arrayIndex = 0; arrayIndex < imageDescription.ArraySize; arrayIndex++)
                {
                    for (int mipIndex = 0; mipIndex < imageDescription.MipLevels; mipIndex++)
                    {
                        int mipWidth  = imageDescription.Width >> mipIndex;
                        int mipHeight = imageDescription.Height >> mipIndex;
                        if (isBlockCompressed && ((mipWidth % 4) != 0 || (mipHeight % 4) != 0))
                        {
                            mipWidth  = unchecked ((int)(((uint)(mipWidth + 3)) & ~3U));
                            mipHeight = unchecked ((int)(((uint)(mipHeight + 3)) & ~3U));
                        }

                        int rowPitch, slicePitch;
                        int widthPacked;
                        int heightPacked;
                        Image.ComputePitch(format, mipWidth, mipHeight, out rowPitch, out slicePitch, out widthPacked, out heightPacked);

                        var chunk = storage.GetChunk(mipIndex);
                        if (chunk == null || chunk.Size != slicePitch * imageDescription.ArraySize)
                        {
                            throw new ContentStreamingException("Data chunk is missing or has invalid size.", storage);
                        }
                        var data = chunk.GetData(fileProvider);
                        if (!chunk.IsLoaded)
                        {
                            throw new ContentStreamingException("Data chunk is not loaded.", storage);
                        }

                        dataBoxes[dataBoxIndex].DataPointer = data + slicePitch * arrayIndex;
                        dataBoxes[dataBoxIndex].RowPitch    = rowPitch;
                        dataBoxes[dataBoxIndex].SlicePitch  = slicePitch;
                        dataBoxIndex++;
                    }
                }

                // Initialize texture
                texture.InitializeFrom(imageDescription, new TextureViewDescription(), dataBoxes);

                storage.UnlockChunks();
            }
        }
Ejemplo n.º 4
0
 /// <inheritdoc />
 void ITexturesStreamingProvider.RegisterTexture(Texture obj, ref ImageDescription imageDescription, ref ContentStorageHeader storageHeader)
 {
     lock (resources)
     {
         CreateStreamingTexture(obj, ref imageDescription, ref storageHeader);
     }
 }
Ejemplo n.º 5
0
        /// <inheritdoc />
        void ITexturesStreamingProvider.FullyLoadTexture(Texture obj, ref ImageDescription imageDescription, ref ContentStorageHeader storageHeader)
        {
            lock (resources)
            {
                // Get streaming object
                var resource = CreateStreamingTexture(obj, ref imageDescription, ref storageHeader);

                // Stream resource to the maximum level
                FullyLoadResource(resource);

                // Release streaming object
                resource.Release();
            }
        }
Ejemplo n.º 6
0
        private StreamingTexture CreateStreamingTexture(Texture obj, ref ImageDescription imageDescription, ref ContentStorageHeader storageHeader)
        {
            // Get content storage container
            var storage = ContentStreaming.GetStorage(ref storageHeader);

            if (storage == null)
            {
                throw new ContentStreamingException("Missing content storage.");
            }

            // Find resource or create new
            var resource = Get(obj);

            if (resource == null)
            {
                resource = new StreamingTexture(this, obj);
                RegisterResource(resource);
            }

            // Update resource storage/description information (may be modified on asset rebuilding)
            resource.Init(storage, ref imageDescription);

            // Check if cannot use streaming
            if (!Enabled)
            {
                FullyLoadResource(resource);
            }

            return(resource);
        }
Ejemplo n.º 7
0
        private static void DeserializeImage(ContentManager contentManager, Image obj, ref ImageDescription imageDescription, ref ContentStorageHeader storageHeader)
        {
            using (var content = new ContentStreamingService())
            {
                // Get content storage container
                var storage = content.GetStorage(ref storageHeader);
                if (storage == null)
                {
                    throw new ContentStreamingException("Missing content storage.");
                }
                storage.LockChunks();

                // Cache data
                var  fileProvider      = contentManager.FileProvider;
                var  format            = imageDescription.Format;
                bool isBlockCompressed =
                    (format >= PixelFormat.BC1_Typeless && format <= PixelFormat.BC5_SNorm) ||
                    (format >= PixelFormat.BC6H_Typeless && format <= PixelFormat.BC7_UNorm_SRgb);

                // Calculate total size
                int size = 0;
                for (int mipIndex = 0; mipIndex < imageDescription.MipLevels; mipIndex++)
                {
                    int mipWidth  = Math.Max(1, imageDescription.Width >> mipIndex);
                    int mipHeight = Math.Max(1, imageDescription.Height >> mipIndex);
                    if (isBlockCompressed && ((mipWidth % 4) != 0 || (mipHeight % 4) != 0))
                    {
                        mipWidth  = unchecked ((int)(((uint)(mipWidth + 3)) & ~(uint)3));
                        mipHeight = unchecked ((int)(((uint)(mipHeight + 3)) & ~(uint)3));
                    }

                    int rowPitch, slicePitch;
                    int widthPacked;
                    int heightPacked;
                    Image.ComputePitch(format, mipWidth, mipHeight, out rowPitch, out slicePitch, out widthPacked, out heightPacked);

                    size += slicePitch;
                }
                size *= imageDescription.ArraySize;

                // Preload chunks
                for (int mipIndex = 0; mipIndex < imageDescription.MipLevels; mipIndex++)
                {
                    storage.GetChunk(mipIndex)?.GetData(fileProvider);
                }

                // Allocate buffer for image data
                var buffer = Utilities.AllocateMemory(size);

                try
                {
                    // Load image data to the buffer
                    var bufferPtr = buffer;
                    for (int arrayIndex = 0; arrayIndex < imageDescription.ArraySize; arrayIndex++)
                    {
                        for (int mipIndex = 0; mipIndex < imageDescription.MipLevels; mipIndex++)
                        {
                            int mipWidth  = Math.Max(1, imageDescription.Width >> mipIndex);
                            int mipHeight = Math.Max(1, imageDescription.Height >> mipIndex);
                            if (isBlockCompressed && ((mipWidth % 4) != 0 || (mipHeight % 4) != 0))
                            {
                                mipWidth  = unchecked ((int)(((uint)(mipWidth + 3)) & ~(uint)3));
                                mipHeight = unchecked ((int)(((uint)(mipHeight + 3)) & ~(uint)3));
                            }

                            int rowPitch, slicePitch;
                            int widthPacked;
                            int heightPacked;
                            Image.ComputePitch(format, mipWidth, mipHeight, out rowPitch, out slicePitch, out widthPacked, out heightPacked);
                            var chunk = storage.GetChunk(mipIndex);
                            if (chunk == null || chunk.Size != slicePitch * imageDescription.ArraySize)
                            {
                                throw new ContentStreamingException("Data chunk is missing or has invalid size.", storage);
                            }
                            var data = chunk.GetData(fileProvider);
                            if (!chunk.IsLoaded)
                            {
                                throw new ContentStreamingException("Data chunk is not loaded.", storage);
                            }

                            Utilities.CopyMemory(bufferPtr, data, chunk.Size);
                            bufferPtr += chunk.Size;
                        }
                    }

                    // Initialize image
                    var image = new Image(imageDescription, buffer, 0, null, true);
                    obj.InitializeFrom(image);
                }
                catch
                {
                    // Free memory in case of error
                    Utilities.FreeMemory(buffer);

                    throw;
                }

                storage.UnlockChunks();
            }
        }
Ejemplo n.º 8
0
 /// <summary>
 /// Initializes a new instance of the <see cref="TextureSerializationData"/> class.
 /// </summary>
 /// <param name="image">The image.</param>
 /// <param name="enableStreaming">Enables/disables texture streaming</param>
 /// <param name="storageHeader">Streaming storage data</param>
 public TextureSerializationData([NotNull] Image image, bool enableStreaming, ContentStorageHeader storageHeader)
 {
     Image           = image;
     EnableStreaming = enableStreaming;
     StorageHeader   = storageHeader;
 }
Ejemplo n.º 9
0
 /// <inheritdoc />
 void ITexturesStreamingProvider.RegisterTexture(Texture obj, ref ImageDescription imageDescription, ref ContentStorageHeader storageHeader)
 {
     using (resourceLocker.UpgradableReadLock())
     {
         CreateStreamingTexture(obj, ref imageDescription, ref storageHeader);
     }
 }