Share images between framebuffers and textures
This commit is contained in:
parent
65c7842d6d
commit
5ea1382aff
9 changed files with 211 additions and 146 deletions
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
|
@ -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>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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); }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue