예제 #1
0
        public static int GetSize(GalImage image)
        {
            ImageDescriptor desc = GetImageDescriptor(image.Format);

            int componentCount = GetCoordsCountTextureTarget(image.TextureTarget);

            if (IsArray(image.TextureTarget))
            {
                componentCount--;
            }

            int width  = DivRoundUp(image.Width, desc.BlockWidth);
            int height = DivRoundUp(image.Height, desc.BlockHeight);
            int depth  = DivRoundUp(image.Depth, desc.BlockDepth);

            switch (componentCount)
            {
            case 1:
                return(desc.BytesPerPixel * width * image.LayerCount);

            case 2:
                return(desc.BytesPerPixel * width * height * image.LayerCount);

            case 3:
                return(desc.BytesPerPixel * width * height * depth * image.LayerCount);

            default:
                throw new InvalidOperationException($"Invalid component count: {componentCount}");
            }
        }
예제 #2
0
        private void SetZeta(NvGpuVmm Vmm)
        {
            long VA = MakeInt64From2xInt32(NvGpuEngine3dReg.ZetaAddress);

            int ZetaFormat = ReadRegister(NvGpuEngine3dReg.ZetaFormat);

            int BlockDim = ReadRegister(NvGpuEngine3dReg.ZetaBlockDimensions);

            int GobBlockHeight = 1 << ((BlockDim >> 4) & 7);

            GalMemoryLayout Layout = (GalMemoryLayout)((BlockDim >> 12) & 1); //?

            bool ZetaEnable = ReadRegisterBool(NvGpuEngine3dReg.ZetaEnable);

            if (VA == 0 || ZetaFormat == 0 || !ZetaEnable)
            {
                Gpu.Renderer.RenderTarget.UnbindZeta();

                return;
            }

            long Key = Vmm.GetPhysicalAddress(VA);

            int Width  = ReadRegister(NvGpuEngine3dReg.ZetaHoriz);
            int Height = ReadRegister(NvGpuEngine3dReg.ZetaVert);

            GalImageFormat Format = ImageUtils.ConvertZeta((GalZetaFormat)ZetaFormat);

            GalImage Image = new GalImage(Width, Height, 1, GobBlockHeight, Layout, Format);

            Gpu.ResourceManager.SendZetaBuffer(Vmm, Key, Image);
        }
예제 #3
0
        public void Create(long Key, int Size, GalImage Image)
        {
            int Handle = GL.GenTexture();

            GL.BindTexture(TextureTarget.Texture2D, Handle);

            const int Level  = 0; //TODO: Support mipmap textures.
            const int Border = 0;

            TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Size);

            if (ImageUtils.IsCompressed(Image.Format))
            {
                throw new InvalidOperationException("Surfaces with compressed formats are not supported!");
            }

            (PixelInternalFormat InternalFmt,
             PixelFormat Format,
             PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);

            GL.TexImage2D(
                TextureTarget.Texture2D,
                Level,
                InternalFmt,
                Image.Width,
                Image.Height,
                Border,
                Format,
                Type,
                IntPtr.Zero);
        }
예제 #4
0
        private void SetZeta(NvGpuVmm Vmm)
        {
            long ZA = MakeInt64From2xInt32(NvGpuEngine3dReg.ZetaAddress);

            int Format = ReadRegister(NvGpuEngine3dReg.ZetaFormat);

            bool ZetaEnable = (ReadRegister(NvGpuEngine3dReg.ZetaEnable) & 1) != 0;

            if (ZA == 0 || Format == 0 || !ZetaEnable)
            {
                Gpu.Renderer.FrameBuffer.UnbindZeta();

                return;
            }

            long Key = Vmm.GetPhysicalAddress(ZA);

            int Width  = ReadRegister(NvGpuEngine3dReg.ZetaHoriz);
            int Height = ReadRegister(NvGpuEngine3dReg.ZetaVert);

            GalImageFormat ImageFormat = ImageFormatConverter.ConvertZeta((GalZetaFormat)Format);

            GalImage Image = new GalImage(Width, Height, ImageFormat);

            long Size = TextureHelper.GetTextureSize(Image);

            Gpu.Renderer.Texture.CreateFb(Key, Size, Image);
            Gpu.Renderer.FrameBuffer.BindZeta(Key);
        }
예제 #5
0
        public static void WriteTexture(NvGpuVmm vmm, GalImage image, long position, byte[] data)
        {
            ISwizzle swizzle = TextureHelper.GetSwizzle(image);

            ImageDescriptor desc = GetImageDescriptor(image.Format);

            (int width, int height, int depth) = GetImageSizeInBlocks(image);

            int bytesPerPixel = desc.BytesPerPixel;

            int inOffs = 0;

            for (int z = 0; z < depth; z++)
            {
                for (int y = 0; y < height; y++)
                {
                    for (int x = 0; x < width; x++)
                    {
                        long offset = (uint)swizzle.GetSwizzleOffset(x, y, z);

                        vmm.Memory.WriteBytes(position + offset, data, inOffs, bytesPerPixel);

                        inOffs += bytesPerPixel;
                    }
                }
            }
        }
예제 #6
0
        public static (int Width, int Height) GetImageSizeInBlocks(GalImage Image)
        {
            ImageDescriptor Desc = GetImageDescriptor(Image.Format);

            return(DivRoundUp(Image.Width, Desc.BlockWidth),
                   DivRoundUp(Image.Height, Desc.BlockHeight));
        }
예제 #7
0
        private void PrepareSendTexture(NvGpuVmm Vmm, long Position, GalImage NewImage)
        {
            long Size = ImageUtils.GetSize(NewImage);

            bool SkipCheck = false;

            if (ImageTypes.TryGetValue(Position, out ImageType OldType))
            {
                if (OldType == ImageType.ColorBuffer || OldType == ImageType.ZetaBuffer)
                {
                    //Avoid data destruction
                    MemoryRegionModified(Vmm, Position, Size, NvGpuBufferType.Texture);

                    SkipCheck = true;
                }
            }

            if (SkipCheck || !MemoryRegionModified(Vmm, Position, Size, NvGpuBufferType.Texture))
            {
                if (TryReuse(Vmm, Position, NewImage))
                {
                    return;
                }
            }

            byte[] Data = ImageUtils.ReadTexture(Vmm, NewImage, Position);

            Gpu.Renderer.Texture.Create(Position, Data, NewImage);
        }
예제 #8
0
        public static ISwizzle GetSwizzle(GalImage image)
        {
            int blockWidth    = ImageUtils.GetBlockWidth(image.Format);
            int blockHeight   = ImageUtils.GetBlockHeight(image.Format);
            int blockDepth    = ImageUtils.GetBlockDepth(image.Format);
            int bytesPerPixel = ImageUtils.GetBytesPerPixel(image.Format);

            int width  = BitUtils.DivRoundUp(image.Width, blockWidth);
            int height = BitUtils.DivRoundUp(image.Height, blockHeight);
            int depth  = BitUtils.DivRoundUp(image.Depth, blockDepth);

            if (image.Layout == GalMemoryLayout.BlockLinear)
            {
                int alignMask = image.TileWidth * (64 / bytesPerPixel) - 1;

                width = (width + alignMask) & ~alignMask;

                return(new BlockLinearSwizzle(
                           width,
                           height,
                           depth,
                           image.GobBlockHeight,
                           image.GobBlockDepth,
                           bytesPerPixel));
            }
            else
            {
                return(new LinearSwizzle(image.Pitch, bytesPerPixel, width, height));
            }
        }
예제 #9
0
        private void PrepareSendTexture(NvGpuVmm vmm, long position, GalImage newImage)
        {
            long size = ImageUtils.GetSize(newImage);

            bool skipCheck = false;

            if (_imageTypes.TryGetValue(position, out ImageType oldType))
            {
                if (oldType == ImageType.ColorBuffer || oldType == ImageType.ZetaBuffer)
                {
                    //Avoid data destruction
                    MemoryRegionModified(vmm, position, size, NvGpuBufferType.Texture);

                    skipCheck = true;
                }
            }

            if (skipCheck || !MemoryRegionModified(vmm, position, size, NvGpuBufferType.Texture))
            {
                if (TryReuse(vmm, position, newImage))
                {
                    return;
                }
            }

            byte[] data = ImageUtils.ReadTexture(vmm, newImage, position);

            _gpu.Renderer.Texture.Create(position, data, newImage);
        }
예제 #10
0
        private void SetZeta(NvGpuVmm vmm)
        {
            long va = MakeInt64From2xInt32(NvGpuEngine3dReg.ZetaAddress);

            int zetaFormat = ReadRegister(NvGpuEngine3dReg.ZetaFormat);

            int blockDim = ReadRegister(NvGpuEngine3dReg.ZetaBlockDimensions);

            int gobBlockHeight = 1 << ((blockDim >> 4) & 7);

            GalMemoryLayout layout = (GalMemoryLayout)((blockDim >> 12) & 1); //?

            bool zetaEnable = ReadRegisterBool(NvGpuEngine3dReg.ZetaEnable);

            if (va == 0 || zetaFormat == 0 || !zetaEnable)
            {
                _gpu.Renderer.RenderTarget.UnbindZeta();

                return;
            }

            long key = vmm.GetPhysicalAddress(va);

            int width  = ReadRegister(NvGpuEngine3dReg.ZetaHoriz);
            int height = ReadRegister(NvGpuEngine3dReg.ZetaVert);

            GalImageFormat format = ImageUtils.ConvertZeta((GalZetaFormat)zetaFormat);

            // TODO: Support non 2D?
            GalImage image = new GalImage(width, height, 1, 1, 1, gobBlockHeight, 1, layout, format, GalTextureTarget.TwoD);

            _gpu.ResourceManager.SendZetaBuffer(vmm, key, image);
        }
예제 #11
0
        public void Create(long Key, byte[] Data, GalImage Image)
        {
            int Handle = GL.GenTexture();

            GL.BindTexture(TextureTarget.Texture2D, 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);

                GL.CompressedTexImage2D(
                    TextureTarget.Texture2D,
                    Level,
                    InternalFmt,
                    Image.Width,
                    Image.Height,
                    Border,
                    Data.Length,
                    Data);
            }
            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);

                    Data = ASTCDecoder.DecodeToRGBA8888(
                        Data,
                        TextureBlockWidth,
                        TextureBlockHeight, 1,
                        Image.Width,
                        Image.Height, 1);

                    Image.Format = GalImageFormat.RGBA8 | (Image.Format & GalImageFormat.TypeMask);
                }

                (PixelInternalFormat InternalFmt,
                 PixelFormat Format,
                 PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);

                GL.TexImage2D(
                    TextureTarget.Texture2D,
                    Level,
                    InternalFmt,
                    Image.Width,
                    Image.Height,
                    Border,
                    Format,
                    Type,
                    Data);
            }
        }
예제 #12
0
        public static (int Width, int Height, int Depth) GetImageSizeInBlocks(GalImage image)
        {
            ImageDescriptor desc = GetImageDescriptor(image.Format);

            return(DivRoundUp(image.Width, desc.BlockWidth),
                   DivRoundUp(image.Height, desc.BlockHeight),
                   DivRoundUp(image.Depth, desc.BlockDepth));
        }
예제 #13
0
        private void SetFrameBuffer(NvGpuVmm vmm, int fbIndex)
        {
            ProfileConfig profile = Profiles.GPU.Engine3d.SetFrameBuffer;

            profile.SessionItem = fbIndex.ToString();

            Profile.Begin(profile);

            long va = MakeInt64From2xInt32(NvGpuEngine3dReg.FrameBufferNAddress + fbIndex * 0x10);

            int surfFormat = ReadRegister(NvGpuEngine3dReg.FrameBufferNFormat + fbIndex * 0x10);

            if (va == 0 || surfFormat == 0)
            {
                _gpu.Renderer.RenderTarget.UnbindColor(fbIndex);

                Profile.End(profile);

                return;
            }

            long key = vmm.GetPhysicalAddress(va);

            int width  = ReadRegister(NvGpuEngine3dReg.FrameBufferNWidth + fbIndex * 0x10);
            int height = ReadRegister(NvGpuEngine3dReg.FrameBufferNHeight + fbIndex * 0x10);

            int arrayMode   = ReadRegister(NvGpuEngine3dReg.FrameBufferNArrayMode + fbIndex * 0x10);
            int layerCount  = arrayMode & 0xFFFF;
            int layerStride = ReadRegister(NvGpuEngine3dReg.FrameBufferNLayerStride + fbIndex * 0x10);
            int baseLayer   = ReadRegister(NvGpuEngine3dReg.FrameBufferNBaseLayer + fbIndex * 0x10);
            int blockDim    = ReadRegister(NvGpuEngine3dReg.FrameBufferNBlockDim + fbIndex * 0x10);

            int gobBlockHeight = 1 << ((blockDim >> 4) & 7);

            GalMemoryLayout layout = (GalMemoryLayout)((blockDim >> 12) & 1);

            float tx = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateX + fbIndex * 8);
            float ty = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateY + fbIndex * 8);

            float sx = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleX + fbIndex * 8);
            float sy = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleY + fbIndex * 8);

            _viewportX0 = (int)MathF.Max(0, tx - MathF.Abs(sx));
            _viewportY0 = (int)MathF.Max(0, ty - MathF.Abs(sy));

            _viewportX1 = (int)(tx + MathF.Abs(sx));
            _viewportY1 = (int)(ty + MathF.Abs(sy));

            GalImageFormat format = ImageUtils.ConvertSurface((GalSurfaceFormat)surfFormat);

            GalImage image = new GalImage(width, height, 1, 1, 1, gobBlockHeight, 1, layout, format, GalTextureTarget.TwoD);

            _gpu.ResourceManager.SendColorBuffer(vmm, key, fbIndex, image);

            _gpu.Renderer.RenderTarget.SetViewport(fbIndex, _viewportX0, _viewportY0, _viewportX1 - _viewportX0, _viewportY1 - _viewportY0);

            Profile.End(profile);
        }
예제 #14
0
        public static int GetLayerOffset(GalImage image, int mipLevel)
        {
            if (mipLevel <= 0)
            {
                mipLevel = 1;
            }

            return(TextureHelper.GetSwizzle(image).GetMipOffset(mipLevel));
        }
예제 #15
0
        public static int GetSize(GalImage Image)
        {
            ImageDescriptor Desc = GetImageDescriptor(Image.Format);

            int Width  = DivRoundUp(Image.Width, Desc.BlockWidth);
            int Height = DivRoundUp(Image.Height, Desc.BlockHeight);

            return(Desc.BytesPerPixel * Width * Height);
        }
예제 #16
0
        public void SendTexture(NvGpuVmm Vmm, long Position, GalImage NewImage, int TexIndex = -1)
        {
            PrepareSendTexture(Vmm, Position, NewImage);

            if (TexIndex >= 0)
            {
                Gpu.Renderer.Texture.Bind(Position, TexIndex, NewImage);
            }

            ImageTypes[Position] = ImageType.Texture;
        }
예제 #17
0
        public void Reinterpret(long key, GalImage newImage)
        {
            if (!_texture.TryGetImage(key, out GalImage oldImage))
            {
                return;
            }

            if (newImage.Format == oldImage.Format &&
                newImage.Width == oldImage.Width &&
                newImage.Height == oldImage.Height &&
                newImage.Depth == oldImage.Depth &&
                newImage.LayerCount == oldImage.LayerCount &&
                newImage.TextureTarget == oldImage.TextureTarget)
            {
                return;
            }

            if (_copyPbo == 0)
            {
                _copyPbo = GL.GenBuffer();
            }

            GL.BindBuffer(BufferTarget.PixelPackBuffer, _copyPbo);

            // The buffer should be large enough to hold the largest texture.
            int bufferSize = Math.Max(ImageUtils.GetSize(oldImage),
                                      ImageUtils.GetSize(newImage));

            GL.BufferData(BufferTarget.PixelPackBuffer, bufferSize, IntPtr.Zero, BufferUsageHint.StreamCopy);

            if (!_texture.TryGetImageHandler(key, out ImageHandler cachedImage))
            {
                throw new InvalidOperationException();
            }

            (_, PixelFormat format, PixelType type) = OglEnumConverter.GetImageFormat(cachedImage.Format);

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

            GL.BindTexture(target, cachedImage.Handle);

            GL.GetTexImage(target, 0, format, type, IntPtr.Zero);

            GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
            GL.BindBuffer(BufferTarget.PixelUnpackBuffer, _copyPbo);

            GL.PixelStore(PixelStoreParameter.UnpackRowLength, oldImage.Width);

            _texture.Create(key, ImageUtils.GetSize(newImage), newImage);

            GL.PixelStore(PixelStoreParameter.UnpackRowLength, 0);

            GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
        }
예제 #18
0
        public static byte[] ReadTexture(IMemory memory, GalImage image, long position)
        {
            MemoryManager cpuMemory;

            if (memory is NvGpuVmm vmm)
            {
                cpuMemory = vmm.Memory;
            }
            else
            {
                cpuMemory = (MemoryManager)memory;
            }

            ISwizzle swizzle = TextureHelper.GetSwizzle(image);

            ImageDescriptor desc = GetImageDescriptor(image.Format);

            (int width, int height, int depth) = GetImageSizeInBlocks(image);

            int bytesPerPixel = desc.BytesPerPixel;

            //Note: Each row of the texture needs to be aligned to 4 bytes.
            int pitch = (width * bytesPerPixel + 3) & ~3;


            int dataLayerSize = height * pitch * depth;

            byte[] data = new byte[dataLayerSize * image.LayerCount];

            int targetMipLevel = image.MaxMipmapLevel <= 1 ? 1 : image.MaxMipmapLevel - 1;
            int layerOffset    = GetLayerOffset(image, targetMipLevel);

            for (int layer = 0; layer < image.LayerCount; layer++)
            {
                for (int z = 0; z < depth; z++)
                {
                    for (int y = 0; y < height; y++)
                    {
                        int outOffs = (dataLayerSize * layer) + y * pitch + (z * width * height * bytesPerPixel);

                        for (int x = 0; x < width; x++)
                        {
                            long offset = (uint)swizzle.GetSwizzleOffset(x, y, z);

                            cpuMemory.ReadBytes(position + (layerOffset * layer) + offset, data, outOffs, bytesPerPixel);

                            outOffs += bytesPerPixel;
                        }
                    }
                }
            }

            return(data);
        }
예제 #19
0
        private bool TryReuse(NvGpuVmm vmm, long position, GalImage newImage)
        {
            if (_gpu.Renderer.Texture.TryGetImage(position, out GalImage cachedImage) && cachedImage.TextureTarget == newImage.TextureTarget && cachedImage.SizeMatches(newImage))
            {
                _gpu.Renderer.RenderTarget.Reinterpret(position, newImage);

                return(true);
            }

            return(false);
        }
예제 #20
0
        public void CreateFb(long Key, long Size, GalImage Image)
        {
            if (!TryGetImage(Key, out ImageHandler CachedImage))
            {
                CachedImage = new ImageHandler();

                TextureCache.AddOrUpdate(Key, CachedImage, Size);
            }

            CachedImage.EnsureSetup(Image);
        }
예제 #21
0
        private bool TryReuse(NvGpuVmm Vmm, long Position, GalImage NewImage)
        {
            if (Gpu.Renderer.Texture.TryGetImage(Position, out GalImage CachedImage) && CachedImage.SizeMatches(NewImage))
            {
                Gpu.Renderer.RenderTarget.Reinterpret(Position, NewImage);

                return(true);
            }

            return(false);
        }
예제 #22
0
        private (long, GalImage, GalTextureSampler) UploadTexture(NvGpuVmm vmm, int textureHandle)
        {
            if (textureHandle == 0)
            {
                // FIXME: Some games like puyo puyo will use handles with the value 0.
                // This is a bug, most likely caused by sync issues.
                return(0, default(GalImage), default(GalTextureSampler));
            }

            Profile.Begin(Profiles.GPU.Engine3d.UploadTexture);

            bool linkedTsc = ReadRegisterBool(NvGpuEngine3dReg.LinkedTsc);

            int ticIndex = (textureHandle >> 0) & 0xfffff;

            int tscIndex = linkedTsc ? ticIndex : (textureHandle >> 20) & 0xfff;

            long ticPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.TexHeaderPoolOffset);
            long tscPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.TexSamplerPoolOffset);

            ticPosition += ticIndex * 0x20;
            tscPosition += tscIndex * 0x20;

            GalImage image = TextureFactory.MakeTexture(vmm, ticPosition);

            GalTextureSampler sampler = TextureFactory.MakeSampler(_gpu, vmm, tscPosition);

            long key = vmm.ReadInt64(ticPosition + 4) & 0xffffffffffff;

            if (image.Layout == GalMemoryLayout.BlockLinear)
            {
                key &= ~0x1ffL;
            }
            else if (image.Layout == GalMemoryLayout.Pitch)
            {
                key &= ~0x1fL;
            }

            key = vmm.GetPhysicalAddress(key);

            if (key == -1)
            {
                Profile.End(Profiles.GPU.Engine3d.UploadTexture);

                // FIXME: Shouldn't ignore invalid addresses.
                return(0, default(GalImage), default(GalTextureSampler));
            }

            _gpu.ResourceManager.SendTexture(vmm, key, image);

            Profile.End(Profiles.GPU.Engine3d.UploadTexture);

            return(key, image, sampler);
        }
예제 #23
0
        public static GalImage MakeTexture(NvGpuVmm Vmm, long TicPosition)
        {
            int[] Tic = ReadWords(Vmm, TicPosition, 8);

            GalImageFormat Format = GetImageFormat(Tic);

            GalTextureSource XSource = (GalTextureSource)((Tic[0] >> 19) & 7);
            GalTextureSource YSource = (GalTextureSource)((Tic[0] >> 22) & 7);
            GalTextureSource ZSource = (GalTextureSource)((Tic[0] >> 25) & 7);
            GalTextureSource WSource = (GalTextureSource)((Tic[0] >> 28) & 7);

            TextureSwizzle Swizzle = (TextureSwizzle)((Tic[2] >> 21) & 7);

            GalMemoryLayout Layout;

            if (Swizzle == TextureSwizzle.BlockLinear ||
                Swizzle == TextureSwizzle.BlockLinearColorKey)
            {
                Layout = GalMemoryLayout.BlockLinear;
            }
            else
            {
                Layout = GalMemoryLayout.Pitch;
            }

            int BlockHeightLog2 = (Tic[3] >> 3) & 7;
            int TileWidthLog2   = (Tic[3] >> 10) & 7;

            int BlockHeight = 1 << BlockHeightLog2;
            int TileWidth   = 1 << TileWidthLog2;

            int Width  = (Tic[4] & 0xffff) + 1;
            int Height = (Tic[5] & 0xffff) + 1;

            GalImage Image = new GalImage(
                Width,
                Height,
                TileWidth,
                BlockHeight,
                Layout,
                Format,
                XSource,
                YSource,
                ZSource,
                WSource);

            if (Layout == GalMemoryLayout.Pitch)
            {
                Image.Pitch = (Tic[3] & 0xffff) << 5;
            }

            return(Image);
        }
예제 #24
0
        public void SendZetaBuffer(NvGpuVmm vmm, long position, GalImage newImage)
        {
            long size = (uint)ImageUtils.GetSize(newImage);

            _imageTypes[position] = ImageType.ZetaBuffer;

            if (!TryReuse(vmm, position, newImage))
            {
                _gpu.Renderer.Texture.Create(position, (int)size, newImage);
            }

            _gpu.Renderer.RenderTarget.BindZeta(position);
        }
예제 #25
0
        public bool TryGetImage(long Key, out GalImage Image)
        {
            if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
            {
                Image = CachedImage.Image;

                return(true);
            }

            Image = default(GalImage);

            return(false);
        }
예제 #26
0
        public bool TryGetImage(long key, out GalImage image)
        {
            if (_textureCache.TryGetValue(key, out ImageHandler cachedImage))
            {
                image = cachedImage.Image;

                return(true);
            }

            image = default(GalImage);

            return(false);
        }
예제 #27
0
        public void SendZetaBuffer(NvGpuVmm Vmm, long Position, GalImage NewImage)
        {
            long Size = (uint)ImageUtils.GetSize(NewImage);

            ImageTypes[Position] = ImageType.ZetaBuffer;

            if (!TryReuse(Vmm, Position, NewImage))
            {
                Gpu.Renderer.Texture.Create(Position, (int)Size, NewImage);
            }

            Gpu.Renderer.RenderTarget.BindZeta(Position);
        }
예제 #28
0
        public void Reinterpret(long Key, GalImage NewImage)
        {
            if (!Texture.TryGetImage(Key, out GalImage OldImage))
            {
                return;
            }

            if (NewImage.Format == OldImage.Format &&
                NewImage.Width == OldImage.Width &&
                NewImage.Height == OldImage.Height)
            {
                return;
            }

            if (CopyPBO == 0)
            {
                CopyPBO = GL.GenBuffer();
            }

            GL.BindBuffer(BufferTarget.PixelPackBuffer, CopyPBO);

            //The buffer should be large enough to hold the largest texture.
            int BufferSize = Math.Max(ImageUtils.GetSize(OldImage),
                                      ImageUtils.GetSize(NewImage));

            GL.BufferData(BufferTarget.PixelPackBuffer, BufferSize, IntPtr.Zero, BufferUsageHint.StreamCopy);

            if (!Texture.TryGetImageHandler(Key, out ImageHandler CachedImage))
            {
                throw new InvalidOperationException();
            }

            (_, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(CachedImage.Format);

            GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle);

            GL.GetTexImage(TextureTarget.Texture2D, 0, Format, Type, IntPtr.Zero);

            GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
            GL.BindBuffer(BufferTarget.PixelUnpackBuffer, CopyPBO);

            GL.PixelStore(PixelStoreParameter.UnpackRowLength, OldImage.Width);

            Texture.Create(Key, ImageUtils.GetSize(NewImage), NewImage);

            GL.PixelStore(PixelStoreParameter.UnpackRowLength, 0);

            GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
        }
예제 #29
0
        private (long, GalImage, GalTextureSampler) UploadTexture(NvGpuVmm Vmm, int TextureHandle)
        {
            if (TextureHandle == 0)
            {
                //FIXME: Some games like puyo puyo will use handles with the value 0.
                //This is a bug, most likely caused by sync issues.
                return(0, default(GalImage), default(GalTextureSampler));
            }

            bool LinkedTsc = ReadRegisterBool(NvGpuEngine3dReg.LinkedTsc);

            int TicIndex = (TextureHandle >> 0) & 0xfffff;

            int TscIndex = LinkedTsc ? TicIndex : (TextureHandle >> 20) & 0xfff;

            long TicPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.TexHeaderPoolOffset);
            long TscPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.TexSamplerPoolOffset);

            TicPosition += TicIndex * 0x20;
            TscPosition += TscIndex * 0x20;

            GalImage Image = TextureFactory.MakeTexture(Vmm, TicPosition);

            GalTextureSampler Sampler = TextureFactory.MakeSampler(Gpu, Vmm, TscPosition);

            long Key = Vmm.ReadInt64(TicPosition + 4) & 0xffffffffffff;

            if (Image.Layout == GalMemoryLayout.BlockLinear)
            {
                Key &= ~0x1ffL;
            }
            else if (Image.Layout == GalMemoryLayout.Pitch)
            {
                Key &= ~0x1fL;
            }

            Key = Vmm.GetPhysicalAddress(Key);

            if (Key == -1)
            {
                //FIXME: Shouldn't ignore invalid addresses.
                return(0, default(GalImage), default(GalTextureSampler));
            }

            Gpu.ResourceManager.SendTexture(Vmm, Key, Image);

            return(Key, Image, Sampler);
        }
예제 #30
0
        public bool TryGetCachedTexture(long Key, long DataSize, out GalImage Image)
        {
            if (TextureCache.TryGetSize(Key, out long Size) && Size == DataSize)
            {
                if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
                {
                    Image = CachedImage.Image;

                    return(true);
                }
            }

            Image = default(GalImage);

            return(false);
        }