Share images between framebuffers and textures

This commit is contained in:
ReinUsesLisp 2018-08-11 01:44:25 -03:00
commit 5ea1382aff
9 changed files with 211 additions and 146 deletions

View file

@ -4,14 +4,10 @@ namespace Ryujinx.Graphics.Gal
{ {
public interface IGalFrameBuffer public interface IGalFrameBuffer
{ {
void CreateColor(long Key, int Width, int Height, GalFrameBufferFormat Format);
void BindColor(long Key, int Attachment); void BindColor(long Key, int Attachment);
void UnbindColor(int Attachment); void UnbindColor(int Attachment);
void CreateZeta(long Key, int Width, int Height, GalZetaFormat Format);
void BindZeta(long Key); void BindZeta(long Key);
void UnbindZeta(); void UnbindZeta();

View file

@ -7,6 +7,8 @@ namespace Ryujinx.Graphics.Gal
void Create(long Key, byte[] Data, GalImage Image); void Create(long Key, byte[] Data, GalImage Image);
void CreateFb(long Key, long Size, GalImage Image);
bool TryGetCachedTexture(long Key, long DataSize, out GalImage Image); bool TryGetCachedTexture(long Key, long DataSize, out GalImage Image);
void Bind(long Key, int Index); void Bind(long Key, int Index);

View file

@ -50,12 +50,22 @@ namespace Ryujinx.Graphics.Gal
public static GalImageFormat ConvertFrameBuffer(GalFrameBufferFormat Format) public static GalImageFormat ConvertFrameBuffer(GalFrameBufferFormat Format)
{ {
switch (Format)
{
case GalFrameBufferFormat.R32Float: return GalImageFormat.R32;
}
//Stubbed. //Stubbed.
return GalImageFormat.A8B8G8R8; return GalImageFormat.A8B8G8R8;
} }
public static GalImageFormat ConvertZeta(GalZetaFormat Format) public static GalImageFormat ConvertZeta(GalZetaFormat Format)
{ {
switch (Format)
{
case GalZetaFormat.Z32Float: return GalImageFormat.ZF32;
}
//Stubbed. //Stubbed.
return GalImageFormat.Z24S8; return GalImageFormat.Z24S8;
} }

View file

@ -5,7 +5,7 @@ using System.Collections.Generic;
namespace Ryujinx.Graphics.Gal.OpenGL namespace Ryujinx.Graphics.Gal.OpenGL
{ {
public class OGLFrameBuffer : IGalFrameBuffer class OGLFrameBuffer : IGalFrameBuffer
{ {
private struct Rect private struct Rect
{ {
@ -23,8 +23,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
} }
} }
private static readonly DrawBuffersEnum[] DrawBuffers = new DrawBuffersEnum[] private static readonly DrawBuffersEnum[] DrawBuffers = new DrawBuffersEnum[]
{ {
DrawBuffersEnum.ColorAttachment0, DrawBuffersEnum.ColorAttachment0,
@ -42,8 +40,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private const GalImageFormat RawFormat = GalImageFormat.A8B8G8R8; private const GalImageFormat RawFormat = GalImageFormat.A8B8G8R8;
private Dictionary<long, TCE> ColorTextures; private OGLTexture Texture;
private Dictionary<long, TCE> ZetaTextures;
private TCE RawTex; private TCE RawTex;
private TCE ReadTex; private TCE ReadTex;
@ -64,35 +61,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private int SrcFb; private int SrcFb;
private int DstFb; private int DstFb;
public OGLFrameBuffer() public OGLFrameBuffer(OGLTexture Texture)
{ {
ColorTextures = new Dictionary<long, TCE>(); this.Texture = Texture;
ZetaTextures = new Dictionary<long, TCE>();
}
public void CreateColor(long Key, int Width, int Height, GalFrameBufferFormat Format)
{
if (!ColorTextures.TryGetValue(Key, out TCE Tex))
{
Tex = new TCE();
ColorTextures.Add(Key, Tex);
}
GalImageFormat ImageFormat = ImageFormatConverter.ConvertFrameBuffer(Format);
Tex.EnsureSetup(new GalImage(Width, Height, ImageFormat));
} }
public void BindColor(long Key, int Attachment) public void BindColor(long Key, int Attachment)
{ {
if (ColorTextures.TryGetValue(Key, out TCE Tex)) if (Texture.TryGetTCE(Key, out TCE Tex))
{ {
EnsureFrameBuffer(); EnsureFrameBuffer();
GL.FramebufferTexture( GL.FramebufferTexture(
FramebufferTarget.Framebuffer, FramebufferTarget.DrawFramebuffer,
FramebufferAttachment.ColorAttachment0 + Attachment, FramebufferAttachment.ColorAttachment0 + Attachment,
Tex.Handle, Tex.Handle,
0); 0);
@ -108,37 +89,58 @@ namespace Ryujinx.Graphics.Gal.OpenGL
EnsureFrameBuffer(); EnsureFrameBuffer();
GL.FramebufferTexture( GL.FramebufferTexture(
FramebufferTarget.Framebuffer, FramebufferTarget.DrawFramebuffer,
FramebufferAttachment.ColorAttachment0 + Attachment, FramebufferAttachment.ColorAttachment0 + Attachment,
0, 0,
0); 0);
} }
public void CreateZeta(long Key, int Width, int Height, GalZetaFormat Format)
{
if (!ZetaTextures.TryGetValue(Key, out TCE Tex))
{
Tex = new TCE();
ZetaTextures.Add(Key, Tex);
}
GalImageFormat ImageFormat = ImageFormatConverter.ConvertZeta(Format);
Tex.EnsureSetup(new GalImage(Width, Height, ImageFormat));
}
public void BindZeta(long Key) public void BindZeta(long Key)
{ {
if (ZetaTextures.TryGetValue(Key, out TCE Tex)) if (Texture.TryGetTCE(Key, out TCE Tex))
{ {
EnsureFrameBuffer(); EnsureFrameBuffer();
GL.FramebufferTexture( if (Tex.HasDepth && Tex.HasStencil)
FramebufferTarget.Framebuffer, {
FramebufferAttachment.DepthStencilAttachment, GL.FramebufferTexture(
Tex.Handle, FramebufferTarget.DrawFramebuffer,
0); FramebufferAttachment.DepthStencilAttachment,
Tex.Handle,
0);
}
else if (Tex.HasDepth)
{
GL.FramebufferTexture(
FramebufferTarget.DrawFramebuffer,
FramebufferAttachment.DepthAttachment,
Tex.Handle,
0);
GL.FramebufferTexture(
FramebufferTarget.DrawFramebuffer,
FramebufferAttachment.StencilAttachment,
0,
0);
}
else if (Tex.HasStencil)
{
GL.FramebufferTexture(
FramebufferTarget.DrawFramebuffer,
FramebufferAttachment.DepthAttachment,
Tex.Handle,
0);
GL.FramebufferTexture(
FramebufferTarget.DrawFramebuffer,
FramebufferAttachment.StencilAttachment,
0,
0);
}
else
{
throw new InvalidOperationException();
}
} }
else else
{ {
@ -151,7 +153,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
EnsureFrameBuffer(); EnsureFrameBuffer();
GL.FramebufferTexture( GL.FramebufferTexture(
FramebufferTarget.Framebuffer, FramebufferTarget.DrawFramebuffer,
FramebufferAttachment.DepthStencilAttachment, FramebufferAttachment.DepthStencilAttachment,
0, 0,
0); 0);
@ -159,10 +161,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void BindTexture(long Key, int Index) public void BindTexture(long Key, int Index)
{ {
TCE Tex; if (Texture.TryGetTCE(Key, out TCE Tex))
if (ColorTextures.TryGetValue(Key, out Tex) ||
ZetaTextures.TryGetValue(Key, out Tex))
{ {
GL.ActiveTexture(TextureUnit.Texture0 + Index); GL.ActiveTexture(TextureUnit.Texture0 + Index);
@ -172,7 +171,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void Set(long Key) public void Set(long Key)
{ {
if (ColorTextures.TryGetValue(Key, out TCE Tex)) if (Texture.TryGetTCE(Key, out TCE Tex))
{ {
ReadTex = Tex; ReadTex = Tex;
} }
@ -307,50 +306,72 @@ namespace Ryujinx.Graphics.Gal.OpenGL
int DstX1, int DstX1,
int DstY1) int DstY1)
{ {
bool Found = false; if (Texture.TryGetTCE(SrcKey, out TCE SrcTex) &&
Texture.TryGetTCE(DstKey, out TCE DstTex))
if (ColorTextures.TryGetValue(SrcKey, out TCE SrcTex) &&
ColorTextures.TryGetValue(DstKey, out TCE DstTex))
{ {
CopyTextures( if (SrcTex.HasColor != DstTex.HasColor ||
SrcX0, SrcY0, SrcX1, SrcY1, SrcTex.HasDepth != DstTex.HasDepth ||
DstX0, DstY0, DstX1, DstY1, SrcTex.HasStencil != DstTex.HasStencil)
SrcTex.Handle, {
DstTex.Handle, throw new NotImplementedException();
FramebufferAttachment.ColorAttachment0, }
ClearBufferMask.ColorBufferBit,
true);
Found = true; if (SrcTex.HasColor)
} {
CopyTextures(
SrcX0, SrcY0, SrcX1, SrcY1,
DstX0, DstY0, DstX1, DstY1,
SrcTex.Handle,
DstTex.Handle,
FramebufferAttachment.ColorAttachment0,
ClearBufferMask.ColorBufferBit,
true);
}
else if (SrcTex.HasDepth && SrcTex.HasStencil)
{
CopyTextures(
SrcX0, SrcY0, SrcX1, SrcY1,
DstX0, DstY0, DstX1, DstY1,
SrcTex.Handle,
DstTex.Handle,
FramebufferAttachment.DepthStencilAttachment,
ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit,
false);
}
else if (SrcTex.HasDepth)
{
CopyTextures(
SrcX0, SrcY0, SrcX1, SrcY1,
DstX0, DstY0, DstX1, DstY1,
SrcTex.Handle,
DstTex.Handle,
FramebufferAttachment.DepthAttachment,
ClearBufferMask.DepthBufferBit,
false);
}
else if (SrcTex.HasStencil)
{
CopyTextures(
SrcX0, SrcY0, SrcX1, SrcY1,
DstX0, DstY0, DstX1, DstY1,
SrcTex.Handle,
DstTex.Handle,
FramebufferAttachment.StencilAttachment,
ClearBufferMask.StencilBufferBit,
false);
}
else
{
throw new InvalidOperationException();
}
if (ZetaTextures.TryGetValue(SrcKey, out TCE ZetaSrcTex) &&
ZetaTextures.TryGetValue(DstKey, out TCE ZetaDstTex))
{
CopyTextures(
SrcX0, SrcY0, SrcX1, SrcY1,
DstX0, DstY0, DstX1, DstY1,
ZetaSrcTex.Handle,
ZetaDstTex.Handle,
FramebufferAttachment.DepthStencilAttachment,
ClearBufferMask.DepthBufferBit | ClearBufferMask.StencilBufferBit,
false);
Found = true;
}
if (Found)
{
EnsureFrameBuffer(); EnsureFrameBuffer();
} }
} }
public void GetBufferData(long Key, Action<byte[]> Callback) public void GetBufferData(long Key, Action<byte[]> Callback)
{ {
TCE Tex; if (Texture.TryGetTCE(Key, out TCE Tex))
if (ColorTextures.TryGetValue(Key, out Tex) ||
ZetaTextures.TryGetValue(Key, out Tex))
{ {
byte[] Data = new byte[Tex.Width * Tex.Height * TCE.MaxBpp]; byte[] Data = new byte[Tex.Width * Tex.Height * TCE.MaxBpp];
@ -373,10 +394,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
int Height, int Height,
byte[] Buffer) byte[] Buffer)
{ {
TCE Tex; if (Texture.TryGetTCE(Key, out TCE Tex))
if (ColorTextures.TryGetValue(Key, out Tex) ||
ZetaTextures.TryGetValue(Key, out Tex))
{ {
GL.BindTexture(TextureTarget.Texture2D, Tex.Handle); GL.BindTexture(TextureTarget.Texture2D, Tex.Handle);
@ -403,7 +421,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
DummyFrameBuffer = GL.GenFramebuffer(); DummyFrameBuffer = GL.GenFramebuffer();
} }
GL.BindFramebuffer(FramebufferTarget.Framebuffer, DummyFrameBuffer); GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DummyFrameBuffer);
GL.DrawBuffers(8, DrawBuffers); GL.DrawBuffers(8, DrawBuffers);
} }

View file

@ -50,33 +50,23 @@ namespace Ryujinx.Graphics.Gal.OpenGL
float Depth, float Depth,
int Stencil) int Stencil)
{ {
//TODO: Handle attachment
ClearBufferMask Mask = ClearBufferMask.ColorBufferBit;
if (Flags.HasFlag(GalClearBufferFlags.Depth))
{
Mask |= ClearBufferMask.DepthBufferBit;
}
if (Flags.HasFlag(GalClearBufferFlags.Stencil))
{
Mask |= ClearBufferMask.StencilBufferBit;
}
GL.ColorMask( GL.ColorMask(
Flags.HasFlag(GalClearBufferFlags.ColorRed), Flags.HasFlag(GalClearBufferFlags.ColorRed),
Flags.HasFlag(GalClearBufferFlags.ColorGreen), Flags.HasFlag(GalClearBufferFlags.ColorGreen),
Flags.HasFlag(GalClearBufferFlags.ColorBlue), Flags.HasFlag(GalClearBufferFlags.ColorBlue),
Flags.HasFlag(GalClearBufferFlags.ColorAlpha)); Flags.HasFlag(GalClearBufferFlags.ColorAlpha));
GL.ClearColor(Red, Green, Blue, Alpha); GL.ClearBuffer(ClearBuffer.Color, Attachment, new float[] { Red, Green, Blue, Alpha });
GL.ClearDepth(Depth); if (Flags.HasFlag(GalClearBufferFlags.Depth))
{
GL.ClearBuffer(ClearBuffer.Depth, 0, ref Depth);
}
GL.ClearStencil(Stencil); if (Flags.HasFlag(GalClearBufferFlags.Stencil))
{
GL.Clear(Mask); GL.ClearBuffer(ClearBuffer.Stencil, 0, ref Stencil);
}
GL.ColorMask(true, true, true, true); GL.ColorMask(true, true, true, true);
} }

View file

@ -23,7 +23,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ {
Buffer = new OGLConstBuffer(); Buffer = new OGLConstBuffer();
FrameBuffer = new OGLFrameBuffer(); Texture = new OGLTexture();
FrameBuffer = new OGLFrameBuffer(Texture as OGLTexture);
Rasterizer = new OGLRasterizer(); Rasterizer = new OGLRasterizer();
@ -31,8 +33,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Pipeline = new OGLPipeline(Buffer as OGLConstBuffer, Rasterizer as OGLRasterizer, Shader as OGLShader); Pipeline = new OGLPipeline(Buffer as OGLConstBuffer, Rasterizer as OGLRasterizer, Shader as OGLShader);
Texture = new OGLTexture();
ActionsQueue = new ConcurrentQueue<Action>(); ActionsQueue = new ConcurrentQueue<Action>();
} }

View file

@ -4,7 +4,7 @@ using System;
namespace Ryujinx.Graphics.Gal.OpenGL namespace Ryujinx.Graphics.Gal.OpenGL
{ {
public class OGLTexture : IGalTexture class OGLTexture : IGalTexture
{ {
private OGLCachedResource<TCE> TextureCache; private OGLCachedResource<TCE> TextureCache;
@ -95,6 +95,30 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, SwizzleA); GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, SwizzleA);
} }
public void CreateFb(long Key, long Size, GalImage Image)
{
if (!TryGetTCE(Key, out TCE Texture))
{
Texture = new TCE();
TextureCache.AddOrUpdate(Key, Texture, Size);
}
Texture.EnsureSetup(Image);
}
public bool TryGetTCE(long Key, out TCE CachedTexture)
{
if (TextureCache.TryGetValue(Key, out CachedTexture))
{
return true;
}
CachedTexture = null;
return false;
}
private static int GetAstcBlockWidth(GalImageFormat Format) private static int GetAstcBlockWidth(GalImageFormat Format)
{ {
switch (Format) switch (Format)

View file

@ -8,6 +8,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
//TODO: Use a variable value here //TODO: Use a variable value here
public const int MaxBpp = 16; public const int MaxBpp = 16;
private static int CopyBuffer = 0;
private static int CopyBufferSize = 0;
public GalImage Image { get; private set; } public GalImage Image { get; private set; }
public int Width { get => Image.Width; } public int Width { get => Image.Width; }
@ -36,31 +39,37 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void EnsureSetup(GalImage Image) public void EnsureSetup(GalImage Image)
{ {
if (this.Width != Image.Width || if (Width != Image.Width ||
this.Height != Image.Height || Height != Image.Height ||
this.Format != Image.Format || Format != Image.Format ||
!Initialized) !Initialized)
{ {
(PixelInternalFormat InternalFormat, PixelFormat PixelFormat, PixelType PixelType) = (PixelInternalFormat InternalFormat, PixelFormat PixelFormat, PixelType PixelType) =
OGLEnumConverter.GetImageFormat(Image.Format); OGLEnumConverter.GetImageFormat(Image.Format);
int CopyBuffer = 0;
bool ChangingFormat = Initialized && this.InternalFormat != InternalFormat;
GL.BindTexture(TextureTarget.Texture2D, Handle); GL.BindTexture(TextureTarget.Texture2D, Handle);
if (ChangingFormat) if (Initialized)
{ {
CopyBuffer = GL.GenBuffer(); if (CopyBuffer == 0)
{
CopyBuffer = GL.GenBuffer();
}
int MaxWidth = Math.Max(Image.Width, Width);
int MaxHeight = Math.Max(Image.Height, Height);
int CurrentSize = MaxWidth * MaxHeight * MaxBpp;
GL.BindBuffer(BufferTarget.PixelPackBuffer, CopyBuffer); GL.BindBuffer(BufferTarget.PixelPackBuffer, CopyBuffer);
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, CopyBuffer); GL.BindBuffer(BufferTarget.PixelUnpackBuffer, CopyBuffer);
int MaxWidth = Math.Max(Image.Width, this.Width); if (CopyBufferSize < CurrentSize)
int MaxHeight = Math.Max(Image.Height, this.Height); {
CopyBufferSize = CurrentSize;
GL.BufferData(BufferTarget.PixelPackBuffer, MaxWidth * MaxHeight * MaxBpp, IntPtr.Zero, BufferUsageHint.StaticCopy); GL.BufferData(BufferTarget.PixelPackBuffer, CurrentSize, IntPtr.Zero, BufferUsageHint.DynamicCopy);
}
GL.GetTexImage(TextureTarget.Texture2D, 0, this.PixelFormat, this.PixelType, IntPtr.Zero); GL.GetTexImage(TextureTarget.Texture2D, 0, this.PixelFormat, this.PixelType, IntPtr.Zero);
@ -91,12 +100,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
PixelType, PixelType,
IntPtr.Zero); IntPtr.Zero);
if (ChangingFormat) if (Initialized)
{ {
GL.BindBuffer(BufferTarget.PixelPackBuffer, 0); GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0); GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
GL.DeleteBuffer(CopyBuffer);
} }
this.Image = Image; this.Image = Image;
@ -108,5 +115,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Initialized = true; Initialized = true;
} }
} }
public bool HasColor { get => ImageFormatConverter.HasColor(Format); }
public bool HasDepth { get => ImageFormatConverter.HasDepth(Format); }
public bool HasStencil { get => ImageFormatConverter.HasStencil(Format); }
} }
} }

View file

@ -102,8 +102,10 @@ namespace Ryujinx.HLE.Gpu.Engines
SetAlphaBlending(State); SetAlphaBlending(State);
SetPrimitiveRestart(State); SetPrimitiveRestart(State);
SetFrameBuffer(Vmm, 0); for (int FbIndex = 0; FbIndex < 8; FbIndex++)
{
SetFrameBuffer(Vmm, FbIndex);
}
SetZeta(Vmm); SetZeta(Vmm);
long[] Keys = UploadShaders(Vmm); long[] Keys = UploadShaders(Vmm);
@ -151,6 +153,7 @@ namespace Ryujinx.HLE.Gpu.Engines
int Stencil = ReadRegister(NvGpuEngine3dReg.ClearStencil); int Stencil = ReadRegister(NvGpuEngine3dReg.ClearStencil);
SetFrameBuffer(Vmm, FbIndex); SetFrameBuffer(Vmm, FbIndex);
SetZeta(Vmm);
Gpu.Renderer.Rasterizer.ClearBuffers( Gpu.Renderer.Rasterizer.ClearBuffers(
Flags, Flags,
@ -166,7 +169,7 @@ namespace Ryujinx.HLE.Gpu.Engines
int Format = ReadRegister(NvGpuEngine3dReg.FrameBufferNFormat + FbIndex * 0x10); int Format = ReadRegister(NvGpuEngine3dReg.FrameBufferNFormat + FbIndex * 0x10);
if (VA == 0/* || Format == 0*/) if (VA == 0 || Format == 0)
{ {
Gpu.Renderer.FrameBuffer.UnbindColor(FbIndex); Gpu.Renderer.FrameBuffer.UnbindColor(FbIndex);
@ -192,7 +195,13 @@ namespace Ryujinx.HLE.Gpu.Engines
int VpW = (int)(TX + MathF.Abs(SX)) - VpX; int VpW = (int)(TX + MathF.Abs(SX)) - VpX;
int VpH = (int)(TY + MathF.Abs(SY)) - VpY; int VpH = (int)(TY + MathF.Abs(SY)) - VpY;
Gpu.Renderer.FrameBuffer.CreateColor(Key, Width, Height, (GalFrameBufferFormat)Format); GalImageFormat ImageFormat = ImageFormatConverter.ConvertFrameBuffer((GalFrameBufferFormat)Format);
GalImage Image = new GalImage(Width, Height, ImageFormat);
long Size = TextureHelper.GetTextureSize(Image);
Gpu.Renderer.Texture.CreateFb(Key, Size, Image);
Gpu.Renderer.FrameBuffer.BindColor(Key, FbIndex); Gpu.Renderer.FrameBuffer.BindColor(Key, FbIndex);
Gpu.Renderer.FrameBuffer.SetViewport(VpX, VpY, VpW, VpH); Gpu.Renderer.FrameBuffer.SetViewport(VpX, VpY, VpW, VpH);
@ -214,12 +223,17 @@ namespace Ryujinx.HLE.Gpu.Engines
} }
long Key = Vmm.GetPhysicalAddress(ZA); long Key = Vmm.GetPhysicalAddress(ZA);
int Width = ReadRegister(NvGpuEngine3dReg.ZetaHoriz); int Width = ReadRegister(NvGpuEngine3dReg.ZetaHoriz);
int Height = ReadRegister(NvGpuEngine3dReg.ZetaVert); int Height = ReadRegister(NvGpuEngine3dReg.ZetaVert);
Gpu.Renderer.FrameBuffer.CreateZeta(Key, Width, Height, (GalZetaFormat)Format); 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); Gpu.Renderer.FrameBuffer.BindZeta(Key);
} }
@ -479,15 +493,15 @@ namespace Ryujinx.HLE.Gpu.Engines
} }
else else
{ {
GalImage NewTexture = TextureFactory.MakeTexture(Vmm, TicPosition); GalImage NewImage = TextureFactory.MakeTexture(Vmm, TicPosition);
long Size = (uint)TextureHelper.GetTextureSize(NewTexture); long Size = (uint)TextureHelper.GetTextureSize(NewImage);
bool HasCachedTexture = false; bool HasCachedTexture = false;
if (Gpu.Renderer.Texture.TryGetCachedTexture(Key, Size, out GalImage Texture)) if (Gpu.Renderer.Texture.TryGetCachedTexture(Key, Size, out GalImage Image))
{ {
if (NewTexture.Equals(Texture) && !QueryKeyUpload(Vmm, Key, Size, NvGpuBufferType.Texture)) if (NewImage.Equals(Image) && !QueryKeyUpload(Vmm, Key, Size, NvGpuBufferType.Texture))
{ {
Gpu.Renderer.Texture.Bind(Key, TexIndex); Gpu.Renderer.Texture.Bind(Key, TexIndex);
@ -499,7 +513,7 @@ namespace Ryujinx.HLE.Gpu.Engines
{ {
byte[] Data = TextureFactory.GetTextureData(Vmm, TicPosition); byte[] Data = TextureFactory.GetTextureData(Vmm, TicPosition);
Gpu.Renderer.Texture.Create(Key, Data, NewTexture); Gpu.Renderer.Texture.Create(Key, Data, NewImage);
} }
Gpu.Renderer.Texture.Bind(Key, TexIndex); Gpu.Renderer.Texture.Bind(Key, TexIndex);