Exemplo n.º 1
0
        public static void Main(string[] args)
        {
            if (args.Length < 4)
            {
                Console.WriteLine("Format: {path} {width} {height} {blockXSize} {blockYSize}");
            }
            else
            {
                string path       = args[0];
                int    width      = int.Parse(args[1]);
                int    height     = int.Parse(args[2]);
                int    blockXSize = int.Parse(args[3]);
                int    blockYSize = int.Parse(args[4]);
                byte[] data       = File.ReadAllBytes(path);

                using (DirectBitmap bitmap = new DirectBitmap(width, height))
                {
                    AstcDecoder decoder = new AstcDecoder();
                    decoder.DecodeASTC(data, width, height, blockXSize, blockYSize, bitmap.Bits);

                    string dirPath = Path.GetDirectoryName(path);
                    string name    = Path.GetFileNameWithoutExtension(path);
                    string newPath = Path.Combine(dirPath, name + "_decoded.png");
                    bitmap.Bitmap.Save(newPath, ImageFormat.Png);
                }

                Console.WriteLine("Finished");
            }

            Console.ReadKey();
        }
        public static Bitmap GetBitmap(Texture texture, int ArrayLevel = 0, int MipLevel = 0, int DepthLevel = 0)
        {
            int width  = (int)Math.Max(1, texture.Width >> MipLevel);
            int height = (int)Math.Max(1, texture.Height >> MipLevel);
            TextureFormatInfo formatInfo = TextureFormatInfo.FormatTable[texture.Format];
            Memory <byte>     data       = GetImageData(texture, ArrayLevel, MipLevel, DepthLevel);

            if (AstcDecoder.CanHandle(texture))
            {
                if (AstcDecoder.TryDecodeToRgba8(data, (int)formatInfo.BlockWidth, (int)formatInfo.BlockHeight, width, height, 1, 1, out var decoded))
                {
                    return(GetBitmapFromBytes(ConvertBgraToRgba(decoded), width, height, PixelFormat.Format32bppArgb));
                }
            }
            else if (DDSDecoder.CanHandle(texture))
            {
                return(DDSDecoder.Decompress(data.Span, width, height, texture.Format));
            }
            else if (RgbaDecoder.CanHandle(texture))
            {
                return(RgbaDecoder.Decode(data.Span, width, height, texture.Format));
            }

            return(null);
        }
Exemplo n.º 3
0
        /// <summary>
        /// Converts texture data to a format and layout that is supported by the host GPU.
        /// </summary>
        /// <param name="data">Data to be converted</param>
        /// <returns>Converted data</returns>
        private ReadOnlySpan <byte> ConvertToHostCompatibleFormat(ReadOnlySpan <byte> data)
        {
            if (Info.IsLinear)
            {
                data = LayoutConverter.ConvertLinearStridedToLinear(
                    Info.Width,
                    Info.Height,
                    Info.FormatInfo.BlockWidth,
                    Info.FormatInfo.BlockHeight,
                    Info.Stride,
                    Info.FormatInfo.BytesPerPixel,
                    data);
            }
            else
            {
                data = LayoutConverter.ConvertBlockLinearToLinear(
                    Info.Width,
                    Info.Height,
                    _depth,
                    Info.Levels,
                    _layers,
                    Info.FormatInfo.BlockWidth,
                    Info.FormatInfo.BlockHeight,
                    Info.FormatInfo.BytesPerPixel,
                    Info.GobBlocksInY,
                    Info.GobBlocksInZ,
                    Info.GobBlocksInTileX,
                    _sizeInfo,
                    data);
            }

            if (!_context.Capabilities.SupportsAstcCompression && Info.FormatInfo.Format.IsAstc())
            {
                if (!AstcDecoder.TryDecodeToRgba8(
                        data.ToArray(),
                        Info.FormatInfo.BlockWidth,
                        Info.FormatInfo.BlockHeight,
                        Info.Width,
                        Info.Height,
                        _depth,
                        Info.Levels,
                        _layers,
                        out Span <byte> decoded))
                {
                    string texInfo = $"{Info.Target} {Info.FormatInfo.Format} {Info.Width}x{Info.Height}x{Info.DepthOrLayers} levels {Info.Levels}";

                    Logger.Debug?.Print(LogClass.Gpu, $"Invalid ASTC texture at 0x{Info.Address:X} ({texInfo}).");
                }

                data = decoded;
            }

            return(data);
        }
Exemplo n.º 4
0
        private static bool IsTextureDecodable(Texture texture)
        {
            if (AstcDecoder.CanHandle(texture))
            {
                return(true);
            }
            if (DDSDecoder.CanHandle(texture))
            {
                return(true);
            }
            if (RgbaDecoder.CanHandle(texture))
            {
                return(true);
            }

            return(false);
        }
Exemplo n.º 5
0
        public static DirectBitmap ASTCTextureToBitmap(Texture2D texture, byte[] data)
        {
            int          width     = texture.Width;
            int          height    = texture.Height;
            int          blockSize = texture.ASTCBlockSize();
            DirectBitmap bitmap    = new DirectBitmap(width, height);

            try
            {
                AstcDecoder.DecodeASTC(data, width, height, blockSize, blockSize, bitmap.Bits);
                return(bitmap);
            }
            catch
            {
                bitmap.Dispose();
                throw;
            }
        }
Exemplo n.º 6
0
        /// <summary>
        /// Converts texture data to a format and layout that is supported by the host GPU.
        /// </summary>
        /// <param name="data">Data to be converted</param>
        /// <returns>Converted data</returns>
        private ReadOnlySpan <byte> ConvertToHostCompatibleFormat(ReadOnlySpan <byte> data)
        {
            if (Info.IsLinear)
            {
                data = LayoutConverter.ConvertLinearStridedToLinear(
                    Info.Width,
                    Info.Height,
                    Info.FormatInfo.BlockWidth,
                    Info.FormatInfo.BlockHeight,
                    Info.Stride,
                    Info.FormatInfo.BytesPerPixel,
                    data);
            }
            else
            {
                data = LayoutConverter.ConvertBlockLinearToLinear(
                    Info.Width,
                    Info.Height,
                    _depth,
                    Info.Levels,
                    _layers,
                    Info.FormatInfo.BlockWidth,
                    Info.FormatInfo.BlockHeight,
                    Info.FormatInfo.BytesPerPixel,
                    Info.GobBlocksInY,
                    Info.GobBlocksInZ,
                    Info.GobBlocksInTileX,
                    _sizeInfo,
                    data);
            }

            // Handle compressed cases not supported by the host:
            // - ASTC is usually not supported on desktop cards.
            // - BC4/BC5 is not supported on 3D textures.
            if (!_context.Capabilities.SupportsAstcCompression && Info.FormatInfo.Format.IsAstc())
            {
                if (!AstcDecoder.TryDecodeToRgba8(
                        data.ToArray(),
                        Info.FormatInfo.BlockWidth,
                        Info.FormatInfo.BlockHeight,
                        Info.Width,
                        Info.Height,
                        _depth,
                        Info.Levels,
                        _layers,
                        out Span <byte> decoded))
                {
                    string texInfo = $"{Info.Target} {Info.FormatInfo.Format} {Info.Width}x{Info.Height}x{Info.DepthOrLayers} levels {Info.Levels}";

                    Logger.Debug?.Print(LogClass.Gpu, $"Invalid ASTC texture at 0x{Info.Address:X} ({texInfo}).");
                }

                data = decoded;
            }
            else if (Target == Target.Texture3D && Info.FormatInfo.Format.IsBc4())
            {
                data = BCnDecoder.DecodeBC4(data, Info.Width, Info.Height, _depth, Info.Levels, _layers, Info.FormatInfo.Format == Format.Bc4Snorm);
            }
            else if (Target == Target.Texture3D && Info.FormatInfo.Format.IsBc5())
            {
                data = BCnDecoder.DecodeBC5(data, Info.Width, Info.Height, _depth, Info.Levels, _layers, Info.FormatInfo.Format == Format.Bc5Snorm);
            }

            return(data);
        }
Exemplo n.º 7
0
        public void Create(long key, byte[] data, GalImage image)
        {
            int handle = GL.GenTexture();

            TextureTarget target = ImageUtils.GetTextureTarget(image.TextureTarget);

            GL.BindTexture(target, handle);

            const int level  = 0; //TODO: Support mipmap textures.
            const int border = 0;

            _textureCache.AddOrUpdate(key, new ImageHandler(handle, image), (uint)data.Length);

            if (ImageUtils.IsCompressed(image.Format) && !IsAstc(image.Format))
            {
                InternalFormat internalFmt = OglEnumConverter.GetCompressedImageFormat(image.Format);

                switch (target)
                {
                case TextureTarget.Texture1D:
                    GL.CompressedTexImage1D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        border,
                        data.Length,
                        data);
                    break;

                case TextureTarget.Texture2D:
                    GL.CompressedTexImage2D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        border,
                        data.Length,
                        data);
                    break;

                case TextureTarget.Texture3D:
                    GL.CompressedTexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.Depth,
                        border,
                        data.Length,
                        data);
                    break;

                // Cube map arrays are just 2D texture arrays with 6 entries
                // per cube map so we can handle them in the same way
                case TextureTarget.TextureCubeMapArray:
                case TextureTarget.Texture2DArray:
                    GL.CompressedTexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.LayerCount,
                        border,
                        data.Length,
                        data);
                    break;

                case TextureTarget.TextureCubeMap:
                    Span <byte> array = new Span <byte>(data);

                    int faceSize = ImageUtils.GetSize(image) / 6;

                    for (int Face = 0; Face < 6; Face++)
                    {
                        GL.CompressedTexImage2D(
                            TextureTarget.TextureCubeMapPositiveX + Face,
                            level,
                            internalFmt,
                            image.Width,
                            image.Height,
                            border,
                            faceSize,
                            array.Slice(Face * faceSize, faceSize).ToArray());
                    }
                    break;

                default:
                    throw new NotImplementedException($"Unsupported texture target type: {target}");
                }
            }
            else
            {
                //TODO: Use KHR_texture_compression_astc_hdr when available
                if (IsAstc(image.Format))
                {
                    int textureBlockWidth  = ImageUtils.GetBlockWidth(image.Format);
                    int textureBlockHeight = ImageUtils.GetBlockHeight(image.Format);
                    int textureBlockDepth  = ImageUtils.GetBlockDepth(image.Format);

                    data = AstcDecoder.DecodeToRgba8888(
                        data,
                        textureBlockWidth,
                        textureBlockHeight,
                        textureBlockDepth,
                        image.Width,
                        image.Height,
                        image.Depth);

                    image.Format = GalImageFormat.Rgba8 | (image.Format & GalImageFormat.TypeMask);
                }

                (PixelInternalFormat internalFmt,
                 PixelFormat format,
                 PixelType type) = OglEnumConverter.GetImageFormat(image.Format);


                switch (target)
                {
                case TextureTarget.Texture1D:
                    GL.TexImage1D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        border,
                        format,
                        type,
                        data);
                    break;

                case TextureTarget.Texture2D:
                    GL.TexImage2D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        border,
                        format,
                        type,
                        data);
                    break;

                case TextureTarget.Texture3D:
                    GL.TexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.Depth,
                        border,
                        format,
                        type,
                        data);
                    break;

                // Cube map arrays are just 2D texture arrays with 6 entries
                // per cube map so we can handle them in the same way
                case TextureTarget.TextureCubeMapArray:
                case TextureTarget.Texture2DArray:
                    GL.TexImage3D(
                        target,
                        level,
                        internalFmt,
                        image.Width,
                        image.Height,
                        image.LayerCount,
                        border,
                        format,
                        type,
                        data);
                    break;

                case TextureTarget.TextureCubeMap:
                    Span <byte> array = new Span <byte>(data);

                    int faceSize = ImageUtils.GetSize(image) / 6;

                    for (int face = 0; face < 6; face++)
                    {
                        GL.TexImage2D(
                            TextureTarget.TextureCubeMapPositiveX + face,
                            level,
                            internalFmt,
                            image.Width,
                            image.Height,
                            border,
                            format,
                            type,
                            array.Slice(face * faceSize, faceSize).ToArray());
                    }
                    break;

                default:
                    throw new NotImplementedException($"Unsupported texture target type: {target}");
                }
            }
        }
Exemplo n.º 8
0
        /// <summary>
        /// Synchronizes guest and host memory.
        /// This will overwrite the texture data with the texture data on the guest memory, if a CPU
        /// modification is detected.
        /// Be aware that this can cause texture data written by the GPU to be lost, this is just a
        /// one way copy (from CPU owned to GPU owned memory).
        /// </summary>
        public void SynchronizeMemory()
        {
            if (_sequenceNumber == _context.SequenceNumber && _hasData)
            {
                return;
            }

            _sequenceNumber = _context.SequenceNumber;

            bool modified = _context.PhysicalMemory.GetModifiedRanges(Address, Size, ResourceName.Texture).Length != 0;

            if (!modified && _hasData)
            {
                return;
            }

            ReadOnlySpan <byte> data = _context.PhysicalMemory.GetSpan(Address, Size);

            if (Info.IsLinear)
            {
                data = LayoutConverter.ConvertLinearStridedToLinear(
                    Info.Width,
                    Info.Height,
                    Info.FormatInfo.BlockWidth,
                    Info.FormatInfo.BlockHeight,
                    Info.Stride,
                    Info.FormatInfo.BytesPerPixel,
                    data);
            }
            else
            {
                data = LayoutConverter.ConvertBlockLinearToLinear(
                    Info.Width,
                    Info.Height,
                    _depth,
                    Info.Levels,
                    _layers,
                    Info.FormatInfo.BlockWidth,
                    Info.FormatInfo.BlockHeight,
                    Info.FormatInfo.BytesPerPixel,
                    Info.GobBlocksInY,
                    Info.GobBlocksInZ,
                    Info.GobBlocksInTileX,
                    _sizeInfo,
                    data);
            }

            if (!_context.Capabilities.SupportsAstcCompression && Info.FormatInfo.Format.IsAstc())
            {
                if (!AstcDecoder.TryDecodeToRgba8(
                        data.ToArray(),
                        Info.FormatInfo.BlockWidth,
                        Info.FormatInfo.BlockHeight,
                        Info.Width,
                        Info.Height,
                        _depth,
                        Info.Levels,
                        out Span <byte> decoded))
                {
                    string texInfo = $"{Info.Target} {Info.FormatInfo.Format} {Info.Width}x{Info.Height}x{Info.DepthOrLayers} levels {Info.Levels}";

                    Logger.PrintDebug(LogClass.Gpu, $"Invalid ASTC texture at 0x{Info.Address:X} ({texInfo}).");
                }

                data = decoded;
            }

            HostTexture.SetData(data);

            _hasData = true;
        }