/// <summary>
        /// Create a new host shader cache file.
        /// </summary>
        /// <param name="programCode">The host shader program</param>
        /// <param name="codeHolders">The shaders code holder</param>
        /// <returns>Raw data of a new host shader cache file</returns>
        internal static byte[] Create(ReadOnlySpan <byte> programCode, ShaderCodeHolder[] codeHolders)
        {
            HostShaderCacheHeader header = new HostShaderCacheHeader((byte)codeHolders.Length, programCode.Length);

            HostShaderCacheEntry[] entries = new HostShaderCacheEntry[codeHolders.Length];

            for (int i = 0; i < codeHolders.Length; i++)
            {
                if (codeHolders[i] == null)
                {
                    entries[i] = new HostShaderCacheEntry();
                }
                else
                {
                    entries[i] = new HostShaderCacheEntry(codeHolders[i].Info);
                }
            }

            using (MemoryStream stream = new MemoryStream())
            {
                BinaryWriter writer = new BinaryWriter(stream);

                writer.WriteStruct(header);

                foreach (HostShaderCacheEntry entry in entries)
                {
                    writer.WriteStruct(entry.Header);
                }

                foreach (HostShaderCacheEntry entry in entries)
                {
                    foreach (BufferDescriptor cBuffer in entry.CBuffers)
                    {
                        writer.WriteStruct(cBuffer);
                    }

                    foreach (BufferDescriptor sBuffer in entry.SBuffers)
                    {
                        writer.WriteStruct(sBuffer);
                    }

                    foreach (TextureDescriptor texture in entry.Textures)
                    {
                        writer.WriteStruct(texture);
                    }

                    foreach (TextureDescriptor image in entry.Images)
                    {
                        writer.WriteStruct(image);
                    }
                }

                writer.Write(programCode);

                return(stream.ToArray());
            }
        }
        /// <summary>
        /// Parse a raw cached user shader program into an array of shader cache entry.
        /// </summary>
        /// <param name="data">The raw cached host shader</param>
        /// <param name="programCode">The host shader program</param>
        /// <returns>An array of shader cache entry</returns>
        internal static HostShaderCacheEntry[] Parse(ReadOnlySpan <byte> data, out ReadOnlySpan <byte> programCode)
        {
            HostShaderCacheHeader fileHeader = MemoryMarshal.Read <HostShaderCacheHeader>(data);

            data = data.Slice(Unsafe.SizeOf <HostShaderCacheHeader>());

            ReadOnlySpan <HostShaderCacheEntryHeader> entryHeaders = MemoryMarshal.Cast <byte, HostShaderCacheEntryHeader>(data.Slice(0, fileHeader.Count * Unsafe.SizeOf <HostShaderCacheEntryHeader>()));

            data = data.Slice(fileHeader.Count * Unsafe.SizeOf <HostShaderCacheEntryHeader>());

            HostShaderCacheEntry[] result = new HostShaderCacheEntry[fileHeader.Count];

            for (int i = 0; i < result.Length; i++)
            {
                HostShaderCacheEntryHeader header = entryHeaders[i];

                if (!header.InUse)
                {
                    continue;
                }

                int cBufferDescriptorsSize = header.CBuffersCount * Unsafe.SizeOf <BufferDescriptor>();
                int sBufferDescriptorsSize = header.SBuffersCount * Unsafe.SizeOf <BufferDescriptor>();
                int textureDescriptorsSize = header.TexturesCount * Unsafe.SizeOf <TextureDescriptor>();
                int imageDescriptorsSize   = header.ImagesCount * Unsafe.SizeOf <TextureDescriptor>();

                ReadOnlySpan <BufferDescriptor> cBuffers = MemoryMarshal.Cast <byte, BufferDescriptor>(data.Slice(0, cBufferDescriptorsSize));
                data = data.Slice(cBufferDescriptorsSize);

                ReadOnlySpan <BufferDescriptor> sBuffers = MemoryMarshal.Cast <byte, BufferDescriptor>(data.Slice(0, sBufferDescriptorsSize));
                data = data.Slice(sBufferDescriptorsSize);

                ReadOnlySpan <TextureDescriptor> textureDescriptors = MemoryMarshal.Cast <byte, TextureDescriptor>(data.Slice(0, textureDescriptorsSize));
                data = data.Slice(textureDescriptorsSize);

                ReadOnlySpan <TextureDescriptor> imageDescriptors = MemoryMarshal.Cast <byte, TextureDescriptor>(data.Slice(0, imageDescriptorsSize));
                data = data.Slice(imageDescriptorsSize);

                result[i] = new HostShaderCacheEntry(header, cBuffers.ToArray(), sBuffers.ToArray(), textureDescriptors.ToArray(), imageDescriptors.ToArray());
            }

            programCode = data.Slice(0, fileHeader.CodeSize);

            return(result);
        }