aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics/Gal/OpenGL
diff options
context:
space:
mode:
authorReinUsesLisp <reinuseslisp@airmail.cc>2018-08-19 22:25:26 -0300
committergdkchan <gab.dark.100@gmail.com>2018-08-19 22:25:26 -0300
commit726de8c46ab10f1b0684fe14bca1ca96ba6d2832 (patch)
tree5da68699e9062f1c01ef3da9d9eceb75657b2f93 /Ryujinx.Graphics/Gal/OpenGL
parent056c2840b1851657c3855fb72776837c89ff59d3 (diff)
Rendertarget attachments, texture and image changes (#358)
* Add multiple color outputs for fragment shaders * Add registers and gal enums * Use textures for framebuffers and split color and zeta framebuffers * Abstract texture and framebuffer targets as an image * Share images between framebuffers and textures * Unstub formats * Add some formats * Disable multiple attachments * Cache framebuffer attachments * Handle format types * Add some rendertarget formats * Code cleanup * Fixup half float types * Address feedback * Disable multiple attachments in shaders * Add A4B4G4R4 image format * Add reversed section for image enums
Diffstat (limited to 'Ryujinx.Graphics/Gal/OpenGL')
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs124
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs6
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs77
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs494
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs19
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs6
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs181
7 files changed, 577 insertions, 330 deletions
diff --git a/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs b/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs
new file mode 100644
index 00000000..74f18dcd
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs
@@ -0,0 +1,124 @@
+using OpenTK.Graphics.OpenGL;
+using System;
+
+namespace Ryujinx.Graphics.Gal.OpenGL
+{
+ class ImageHandler
+ {
+ //TODO: Use a variable value here
+ public const int MaxBpp = 16;
+
+ private static int CopyBuffer = 0;
+ private static int CopyBufferSize = 0;
+
+ public GalImage Image { get; private set; }
+
+ public int Width => Image.Width;
+ public int Height => Image.Height;
+
+ public GalImageFormat Format => Image.Format;
+
+ public PixelInternalFormat InternalFormat { get; private set; }
+ public PixelFormat PixelFormat { get; private set; }
+ public PixelType PixelType { get; private set; }
+
+ public int Handle { get; private set; }
+
+ private bool Initialized;
+
+ public ImageHandler()
+ {
+ Handle = GL.GenTexture();
+ }
+
+ public ImageHandler(int Handle, GalImage Image)
+ {
+ this.Handle = Handle;
+
+ this.Image = Image;
+ }
+
+ public void EnsureSetup(GalImage Image)
+ {
+ if (Width != Image.Width ||
+ Height != Image.Height ||
+ Format != Image.Format ||
+ !Initialized)
+ {
+ (PixelInternalFormat InternalFormat, PixelFormat PixelFormat, PixelType PixelType) =
+ OGLEnumConverter.GetImageFormat(Image.Format);
+
+ GL.BindTexture(TextureTarget.Texture2D, Handle);
+
+ if (Initialized)
+ {
+ 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.PixelUnpackBuffer, CopyBuffer);
+
+ if (CopyBufferSize < CurrentSize)
+ {
+ CopyBufferSize = CurrentSize;
+
+ GL.BufferData(BufferTarget.PixelPackBuffer, CurrentSize, IntPtr.Zero, BufferUsageHint.StreamCopy);
+ }
+
+ GL.GetTexImage(TextureTarget.Texture2D, 0, this.PixelFormat, this.PixelType, IntPtr.Zero);
+
+ GL.DeleteTexture(Handle);
+
+ Handle = GL.GenTexture();
+
+ GL.BindTexture(TextureTarget.Texture2D, Handle);
+ }
+
+ const int MinFilter = (int)TextureMinFilter.Linear;
+ const int MagFilter = (int)TextureMagFilter.Linear;
+
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, MinFilter);
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, MagFilter);
+
+ const int Level = 0;
+ const int Border = 0;
+
+ GL.TexImage2D(
+ TextureTarget.Texture2D,
+ Level,
+ InternalFormat,
+ Image.Width,
+ Image.Height,
+ Border,
+ PixelFormat,
+ PixelType,
+ IntPtr.Zero);
+
+ if (Initialized)
+ {
+ GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
+ GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
+ }
+
+ this.Image = Image;
+
+ this.InternalFormat = InternalFormat;
+ this.PixelFormat = PixelFormat;
+ this.PixelType = PixelType;
+
+ Initialized = true;
+ }
+ }
+
+ public bool HasColor { get => ImageFormatConverter.HasColor(Format); }
+ public bool HasDepth { get => ImageFormatConverter.HasDepth(Format); }
+ public bool HasStencil { get => ImageFormatConverter.HasStencil(Format); }
+ }
+}
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs
index 50825541..4958b53b 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLConstBuffer.cs
@@ -36,12 +36,10 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void SetData(long Key, long Size, IntPtr HostAddress)
{
- if (!Cache.TryGetValue(Key, out OGLStreamBuffer Buffer))
+ if (Cache.TryGetValue(Key, out OGLStreamBuffer Buffer))
{
- throw new InvalidOperationException();
+ Buffer.SetData(Size, HostAddress);
}
-
- Buffer.SetData(Size, HostAddress);
}
public bool TryGetUbo(long Key, out int UboHandle)
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
index 3c42e5d3..e04a59d4 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
@@ -125,40 +125,71 @@ namespace Ryujinx.Graphics.Gal.OpenGL
throw new ArgumentException(nameof(Type));
}
- public static (PixelFormat, PixelType) GetTextureFormat(GalTextureFormat Format)
+ public static (PixelInternalFormat, PixelFormat, PixelType) GetImageFormat(GalImageFormat Format)
{
switch (Format)
{
- case GalTextureFormat.R32G32B32A32: return (PixelFormat.Rgba, PixelType.Float);
- case GalTextureFormat.R16G16B16A16: return (PixelFormat.Rgba, PixelType.HalfFloat);
- case GalTextureFormat.A8B8G8R8: return (PixelFormat.Rgba, PixelType.UnsignedByte);
- case GalTextureFormat.A2B10G10R10: return (PixelFormat.Rgba, PixelType.UnsignedInt2101010Reversed);
- case GalTextureFormat.R32: return (PixelFormat.Red, PixelType.Float);
- case GalTextureFormat.A1B5G5R5: return (PixelFormat.Rgba, PixelType.UnsignedShort5551);
- case GalTextureFormat.B5G6R5: return (PixelFormat.Rgb, PixelType.UnsignedShort565);
- case GalTextureFormat.G8R8: return (PixelFormat.Rg, PixelType.UnsignedByte);
- case GalTextureFormat.R16: return (PixelFormat.Red, PixelType.HalfFloat);
- case GalTextureFormat.R8: return (PixelFormat.Red, PixelType.UnsignedByte);
- case GalTextureFormat.ZF32: return (PixelFormat.DepthComponent, PixelType.Float);
- case GalTextureFormat.BF10GF11RF11: return (PixelFormat.Rgb, PixelType.UnsignedInt10F11F11FRev);
- case GalTextureFormat.Z24S8: return (PixelFormat.DepthStencil, PixelType.UnsignedInt248);
+ case GalImageFormat.R32G32B32A32_SFLOAT: return (PixelInternalFormat.Rgba32f, PixelFormat.Rgba, PixelType.Float);
+ case GalImageFormat.R32G32B32A32_SINT: return (PixelInternalFormat.Rgba32i, PixelFormat.RgbaInteger, PixelType.Int);
+ case GalImageFormat.R32G32B32A32_UINT: return (PixelInternalFormat.Rgba32ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt);
+ case GalImageFormat.R16G16B16A16_SFLOAT: return (PixelInternalFormat.Rgba16f, PixelFormat.Rgba, PixelType.HalfFloat);
+ case GalImageFormat.R16G16B16A16_SINT: return (PixelInternalFormat.Rgba16i, PixelFormat.RgbaInteger, PixelType.Short);
+ case GalImageFormat.R16G16B16A16_UINT: return (PixelInternalFormat.Rgba16ui, PixelFormat.RgbaInteger, PixelType.UnsignedShort);
+ case GalImageFormat.A8B8G8R8_SNORM_PACK32: return (PixelInternalFormat.Rgba8Snorm, PixelFormat.Rgba, PixelType.Byte);
+ case GalImageFormat.A8B8G8R8_UNORM_PACK32: return (PixelInternalFormat.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte);
+ case GalImageFormat.A8B8G8R8_SINT_PACK32: return (PixelInternalFormat.Rgba8i, PixelFormat.RgbaInteger, PixelType.Byte);
+ case GalImageFormat.A8B8G8R8_UINT_PACK32: return (PixelInternalFormat.Rgba8ui, PixelFormat.RgbaInteger, PixelType.UnsignedByte);
+ case GalImageFormat.A8B8G8R8_SRGB_PACK32: return (PixelInternalFormat.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte);
+ case GalImageFormat.A2B10G10R10_UINT_PACK32: return (PixelInternalFormat.Rgb10A2ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed);
+ case GalImageFormat.A2B10G10R10_UNORM_PACK32: return (PixelInternalFormat.Rgb10A2, PixelFormat.Rgba, PixelType.UnsignedInt2101010Reversed);
+ case GalImageFormat.R32_SFLOAT: return (PixelInternalFormat.R32f, PixelFormat.Red, PixelType.Float);
+ case GalImageFormat.R32_SINT: return (PixelInternalFormat.R32i, PixelFormat.Red, PixelType.Int);
+ case GalImageFormat.R32_UINT: return (PixelInternalFormat.R32ui, PixelFormat.Red, PixelType.UnsignedInt);
+ case GalImageFormat.A1R5G5B5_UNORM_PACK16: return (PixelInternalFormat.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort5551);
+ case GalImageFormat.B5G6R5_UNORM_PACK16: return (PixelInternalFormat.Rgba, PixelFormat.Rgb, PixelType.UnsignedShort565);
+ case GalImageFormat.R16G16_SFLOAT: return (PixelInternalFormat.Rg16f, PixelFormat.Rg, PixelType.HalfFloat);
+ case GalImageFormat.R16G16_SINT: return (PixelInternalFormat.Rg16i, PixelFormat.RgInteger, PixelType.Short);
+ case GalImageFormat.R16G16_SNORM: return (PixelInternalFormat.Rg16Snorm, PixelFormat.Rg, PixelType.Byte);
+ case GalImageFormat.R16G16_UNORM: return (PixelInternalFormat.Rg16, PixelFormat.Rg, PixelType.UnsignedShort);
+ case GalImageFormat.R8G8_SINT: return (PixelInternalFormat.Rg8i, PixelFormat.RgInteger, PixelType.Byte);
+ case GalImageFormat.R8G8_SNORM: return (PixelInternalFormat.Rg8Snorm, PixelFormat.Rg, PixelType.Byte);
+ case GalImageFormat.R8G8_UINT: return (PixelInternalFormat.Rg8ui, PixelFormat.RgInteger, PixelType.UnsignedByte);
+ case GalImageFormat.R8G8_UNORM: return (PixelInternalFormat.Rg8, PixelFormat.Rg, PixelType.UnsignedByte);
+ case GalImageFormat.R16_SFLOAT: return (PixelInternalFormat.R16f, PixelFormat.Red, PixelType.HalfFloat);
+ case GalImageFormat.R16_SINT: return (PixelInternalFormat.R16i, PixelFormat.RedInteger, PixelType.Short);
+ case GalImageFormat.R16_SNORM: return (PixelInternalFormat.R16Snorm, PixelFormat.Red, PixelType.Byte);
+ case GalImageFormat.R16_UINT: return (PixelInternalFormat.R16ui, PixelFormat.RedInteger, PixelType.UnsignedShort);
+ case GalImageFormat.R16_UNORM: return (PixelInternalFormat.R16, PixelFormat.Red, PixelType.UnsignedShort);
+ case GalImageFormat.R8_SINT: return (PixelInternalFormat.R8i, PixelFormat.RedInteger, PixelType.Byte);
+ case GalImageFormat.R8_SNORM: return (PixelInternalFormat.R8Snorm, PixelFormat.Red, PixelType.Byte);
+ case GalImageFormat.R8_UINT: return (PixelInternalFormat.R8ui, PixelFormat.RedInteger, PixelType.UnsignedByte);
+ case GalImageFormat.R8_UNORM: return (PixelInternalFormat.R8, PixelFormat.Red, PixelType.UnsignedByte);
+ case GalImageFormat.B10G11R11_UFLOAT_PACK32: return (PixelInternalFormat.R11fG11fB10f, PixelFormat.Rgb, PixelType.UnsignedInt10F11F11FRev);
+
+ case GalImageFormat.R4G4B4A4_UNORM_PACK16_REVERSED: return (PixelInternalFormat.Rgba4, PixelFormat.Rgba, PixelType.UnsignedShort4444Reversed);
+
+ case GalImageFormat.D24_UNORM_S8_UINT: return (PixelInternalFormat.Depth24Stencil8, PixelFormat.DepthStencil, PixelType.UnsignedInt248);
+ case GalImageFormat.D32_SFLOAT: return (PixelInternalFormat.DepthComponent32f, PixelFormat.DepthComponent, PixelType.Float);
+ case GalImageFormat.D16_UNORM: return (PixelInternalFormat.DepthComponent16, PixelFormat.DepthComponent, PixelType.UnsignedShort);
}
throw new NotImplementedException(Format.ToString());
}
- public static InternalFormat GetCompressedTextureFormat(GalTextureFormat Format)
+ public static InternalFormat GetCompressedImageFormat(GalImageFormat Format)
{
switch (Format)
{
- case GalTextureFormat.BC6H_UF16: return InternalFormat.CompressedRgbBptcUnsignedFloat;
- case GalTextureFormat.BC6H_SF16: return InternalFormat.CompressedRgbBptcSignedFloat;
- case GalTextureFormat.BC7U: return InternalFormat.CompressedRgbaBptcUnorm;
- case GalTextureFormat.BC1: return InternalFormat.CompressedRgbaS3tcDxt1Ext;
- case GalTextureFormat.BC2: return InternalFormat.CompressedRgbaS3tcDxt3Ext;
- case GalTextureFormat.BC3: return InternalFormat.CompressedRgbaS3tcDxt5Ext;
- case GalTextureFormat.BC4: return InternalFormat.CompressedRedRgtc1;
- case GalTextureFormat.BC5: return InternalFormat.CompressedRgRgtc2;
+ case GalImageFormat.BC6H_UFLOAT_BLOCK: return InternalFormat.CompressedRgbBptcUnsignedFloat;
+ case GalImageFormat.BC6H_SFLOAT_BLOCK: return InternalFormat.CompressedRgbBptcSignedFloat;
+ case GalImageFormat.BC7_UNORM_BLOCK: return InternalFormat.CompressedRgbaBptcUnorm;
+ case GalImageFormat.BC1_RGBA_UNORM_BLOCK: return InternalFormat.CompressedRgbaS3tcDxt1Ext;
+ case GalImageFormat.BC2_UNORM_BLOCK: return InternalFormat.CompressedRgbaS3tcDxt3Ext;
+ case GalImageFormat.BC3_UNORM_BLOCK: return InternalFormat.CompressedRgbaS3tcDxt5Ext;
+ case GalImageFormat.BC4_SNORM_BLOCK: return InternalFormat.CompressedSignedRedRgtc1;
+ case GalImageFormat.BC4_UNORM_BLOCK: return InternalFormat.CompressedRedRgtc1;
+ case GalImageFormat.BC5_SNORM_BLOCK: return InternalFormat.CompressedSignedRgRgtc2;
+ case GalImageFormat.BC5_UNORM_BLOCK: return InternalFormat.CompressedRgRgtc2;
}
throw new NotImplementedException(Format.ToString());
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs
index 62f82495..e0f12e4e 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLFrameBuffer.cs
@@ -1,10 +1,9 @@
using OpenTK.Graphics.OpenGL;
using System;
-using System.Collections.Generic;
namespace Ryujinx.Graphics.Gal.OpenGL
{
- public class OGLFrameBuffer : IGalFrameBuffer
+ class OGLFrameBuffer : IGalFrameBuffer
{
private struct Rect
{
@@ -15,49 +14,37 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public Rect(int X, int Y, int Width, int Height)
{
- this.X = X;
- this.Y = Y;
- this.Width = Width;
+ this.X = X;
+ this.Y = Y;
+ this.Width = Width;
this.Height = Height;
}
}
- private class FrameBuffer
+ private static readonly DrawBuffersEnum[] DrawBuffers = new DrawBuffersEnum[]
{
- public int Width { get; set; }
- public int Height { get; set; }
-
- public int Handle { get; private set; }
- public int RbHandle { get; private set; }
- public int TexHandle { get; private set; }
-
- public FrameBuffer(int Width, int Height, bool HasRenderBuffer)
- {
- this.Width = Width;
- this.Height = Height;
-
- Handle = GL.GenFramebuffer();
- TexHandle = GL.GenTexture();
-
- if (HasRenderBuffer)
- {
- RbHandle = GL.GenRenderbuffer();
- }
- }
- }
+ DrawBuffersEnum.ColorAttachment0,
+ DrawBuffersEnum.ColorAttachment1,
+ DrawBuffersEnum.ColorAttachment2,
+ DrawBuffersEnum.ColorAttachment3,
+ DrawBuffersEnum.ColorAttachment4,
+ DrawBuffersEnum.ColorAttachment5,
+ DrawBuffersEnum.ColorAttachment6,
+ DrawBuffersEnum.ColorAttachment7,
+ };
private const int NativeWidth = 1280;
private const int NativeHeight = 720;
- private Dictionary<long, FrameBuffer> Fbs;
+ private const GalImageFormat RawFormat = GalImageFormat.A8B8G8R8_UNORM_PACK32;
- private Rect Viewport;
- private Rect Window;
+ private OGLTexture Texture;
- private FrameBuffer CurrFb;
- private FrameBuffer CurrReadFb;
+ private ImageHandler RawTex;
+ private ImageHandler ReadTex;
- private FrameBuffer RawFb;
+ private Rect Viewport;
+ private Rect Window;
private bool FlipX;
private bool FlipY;
@@ -67,111 +54,144 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private int CropRight;
private int CropBottom;
- public OGLFrameBuffer()
- {
- Fbs = new Dictionary<long, FrameBuffer>();
- }
+ //This framebuffer is used to attach guest rendertargets,
+ //think of it as a dummy OpenGL VAO
+ private int DummyFrameBuffer;
- public void Create(long Key, int Width, int Height)
- {
- if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
- {
- if (Fb.Width != Width ||
- Fb.Height != Height)
- {
- SetupTexture(Fb.TexHandle, Width, Height);
+ //These framebuffers are used to blit images
+ private int SrcFb;
+ private int DstFb;
- Fb.Width = Width;
- Fb.Height = Height;
- }
+ //Holds current attachments, used to avoid unnecesary calls to OpenGL
+ private int[] ColorAttachments;
- return;
- }
+ private int DepthAttachment;
+ private int StencilAttachment;
- Fb = new FrameBuffer(Width, Height, true);
+ public OGLFrameBuffer(OGLTexture Texture)
+ {
+ ColorAttachments = new int[8];
- SetupTexture(Fb.TexHandle, Width, Height);
+ this.Texture = Texture;
+ }
- GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fb.Handle);
+ public void BindColor(long Key, int Attachment)
+ {
+ if (Texture.TryGetImage(Key, out ImageHandler Tex))
+ {
+ EnsureFrameBuffer();
- GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, Fb.RbHandle);
+ Attach(ref ColorAttachments[Attachment], Tex.Handle, FramebufferAttachment.ColorAttachment0 + Attachment);
+ }
+ else
+ {
+ UnbindColor(Attachment);
+ }
+ }
- GL.RenderbufferStorage(
- RenderbufferTarget.Renderbuffer,
- RenderbufferStorage.Depth24Stencil8,
- Width,
- Height);
+ public void UnbindColor(int Attachment)
+ {
+ EnsureFrameBuffer();
- GL.FramebufferRenderbuffer(
- FramebufferTarget.Framebuffer,
- FramebufferAttachment.DepthStencilAttachment,
- RenderbufferTarget.Renderbuffer,
- Fb.RbHandle);
+ Attach(ref ColorAttachments[Attachment], 0, FramebufferAttachment.ColorAttachment0 + Attachment);
+ }
+
+ public void BindZeta(long Key)
+ {
+ if (Texture.TryGetImage(Key, out ImageHandler Tex))
+ {
+ EnsureFrameBuffer();
- GL.FramebufferTexture(
- FramebufferTarget.Framebuffer,
- FramebufferAttachment.ColorAttachment0,
- Fb.TexHandle,
- 0);
+ if (Tex.HasDepth && Tex.HasStencil)
+ {
+ if (DepthAttachment != Tex.Handle ||
+ StencilAttachment != Tex.Handle)
+ {
+ GL.FramebufferTexture(
+ FramebufferTarget.DrawFramebuffer,
+ FramebufferAttachment.DepthStencilAttachment,
+ Tex.Handle,
+ 0);
+
+ DepthAttachment = Tex.Handle;
+
+ StencilAttachment = Tex.Handle;
+ }
+ }
+ else if (Tex.HasDepth)
+ {
+ Attach(ref DepthAttachment, Tex.Handle, FramebufferAttachment.DepthAttachment);
- GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
+ Attach(ref StencilAttachment, 0, FramebufferAttachment.StencilAttachment);
+ }
+ else if (Tex.HasStencil)
+ {
+ Attach(ref DepthAttachment, 0, FramebufferAttachment.DepthAttachment);
- Fbs.Add(Key, Fb);
+ Attach(ref StencilAttachment, Tex.Handle, FramebufferAttachment.StencilAttachment);
+ }
+ else
+ {
+ throw new InvalidOperationException();
+ }
+ }
+ else
+ {
+ UnbindZeta();
+ }
}
- public void Bind(long Key)
+ public void UnbindZeta()
{
- if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
+ EnsureFrameBuffer();
+
+ if (DepthAttachment != 0 ||
+ StencilAttachment != 0)
{
- GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fb.Handle);
+ GL.FramebufferTexture(
+ FramebufferTarget.DrawFramebuffer,
+ FramebufferAttachment.DepthStencilAttachment,
+ 0,
+ 0);
+
+ DepthAttachment = 0;
- CurrFb = Fb;
+ StencilAttachment = 0;
}
}
public void BindTexture(long Key, int Index)
{
- if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
+ if (Texture.TryGetImage(Key, out ImageHandler Tex))
{
GL.ActiveTexture(TextureUnit.Texture0 + Index);
- GL.BindTexture(TextureTarget.Texture2D, Fb.TexHandle);
+ GL.BindTexture(TextureTarget.Texture2D, Tex.Handle);
}
}
public void Set(long Key)
{
- if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
+ if (Texture.TryGetImage(Key, out ImageHandler Tex))
{
- CurrReadFb = Fb;
+ ReadTex = Tex;
}
}
public void Set(byte[] Data, int Width, int Height)
{
- if (RawFb == null)
+ if (RawTex == null)
{
- CreateRawFb(Width, Height);
+ RawTex = new ImageHandler();
}
- if (RawFb.Width != Width ||
- RawFb.Height != Height)
- {
- SetupTexture(RawFb.TexHandle, Width, Height);
-
- RawFb.Width = Width;
- RawFb.Height = Height;
- }
-
- GL.ActiveTexture(TextureUnit.Texture0);
-
- GL.BindTexture(TextureTarget.Texture2D, RawFb.TexHandle);
+ RawTex.EnsureSetup(new GalImage(Width, Height, RawFormat));
- (PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(GalTextureFormat.A8B8G8R8);
+ GL.BindTexture(TextureTarget.Texture2D, RawTex.Handle);
- GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, Width, Height, Format, Type, Data);
+ GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, Width, Height, RawTex.PixelFormat, RawTex.PixelType, Data);
- CurrReadFb = RawFb;
+ ReadTex = RawTex;
}
public void SetTransform(bool FlipX, bool FlipY, int Top, int Left, int Right, int Bottom)
@@ -208,60 +228,71 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void Render()
{
- if (CurrReadFb != null)
+ if (ReadTex == null)
{
- int SrcX0, SrcX1, SrcY0, SrcY1;
+ return;
+ }
- if (CropLeft == 0 && CropRight == 0)
- {
- SrcX0 = 0;
- SrcX1 = CurrReadFb.Width;
- }
- else
- {
- SrcX0 = CropLeft;
- SrcX1 = CropRight;
- }
+ int SrcX0, SrcX1, SrcY0, SrcY1;
- if (CropTop == 0 && CropBottom == 0)
- {
- SrcY0 = 0;
- SrcY1 = CurrReadFb.Height;
- }
- else
- {
- SrcY0 = CropTop;
- SrcY1 = CropBottom;
- }
+ if (CropLeft == 0 && CropRight == 0)
+ {
+ SrcX0 = 0;
+ SrcX1 = ReadTex.Width;
+ }
+ else
+ {
+ SrcX0 = CropLeft;
+ SrcX1 = CropRight;
+ }
+
+ if (CropTop == 0 && CropBottom == 0)
+ {
+ SrcY0 = 0;
+ SrcY1 = ReadTex.Height;
+ }
+ else
+ {
+ SrcY0 = CropTop;
+ SrcY1 = CropBottom;
+ }
- float RatioX = MathF.Min(1f, (Window.Height * (float)NativeWidth) / ((float)NativeHeight * Window.Width));
- float RatioY = MathF.Min(1f, (Window.Width * (float)NativeHeight) / ((float)NativeWidth * Window.Height));
+ float RatioX = MathF.Min(1f, (Window.Height * (float)NativeWidth) / ((float)NativeHeight * Window.Width));
+ float RatioY = MathF.Min(1f, (Window.Width * (float)NativeHeight) / ((float)NativeWidth * Window.Height));
- int DstWidth = (int)(Window.Width * RatioX);
- int DstHeight = (int)(Window.Height * RatioY);
+ int DstWidth = (int)(Window.Width * RatioX);
+ int DstHeight = (int)(Window.Height * RatioY);
- int DstPaddingX = (Window.Width - DstWidth) / 2;
- int DstPaddingY = (Window.Height - DstHeight) / 2;
+ int DstPaddingX = (Window.Width - DstWidth) / 2;
+ int DstPaddingY = (Window.Height - DstHeight) / 2;
- int DstX0 = FlipX ? Window.Width - DstPaddingX : DstPaddingX;
- int DstX1 = FlipX ? DstPaddingX : Window.Width - DstPaddingX;
+ int DstX0 = FlipX ? Window.Width - DstPaddingX : DstPaddingX;
+ int DstX1 = FlipX ? DstPaddingX : Window.Width - DstPaddingX;
- int DstY0 = FlipY ? DstPaddingY : Window.Height - DstPaddingY;
- int DstY1 = FlipY ? Window.Height - DstPaddingY : DstPaddingY;
+ int DstY0 = FlipY ? DstPaddingY : Window.Height - DstPaddingY;
+ int DstY1 = FlipY ? Window.Height - DstPaddingY : DstPaddingY;
- GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
+ if (SrcFb == 0) SrcFb = GL.GenFramebuffer();
- GL.Viewport(0, 0, Window.Width, Window.Height);
+ GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0);
- GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, CurrReadFb.Handle);
+ GL.Viewport(0, 0, Window.Width, Window.Height);
- GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
+ GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb);
- GL.BlitFramebuffer(
- SrcX0, SrcY0, SrcX1, SrcY1,
- DstX0, DstY0, DstX1, DstY1,
- ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Linear);
- }
+ GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.ColorAttachment0, ReadTex.Handle, 0);
+
+ GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
+ GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
+
+ GL.Clear(ClearBufferMask.ColorBufferBit);
+
+ GL.BlitFramebuffer(
+ SrcX0, SrcY0, SrcX1, SrcY1,
+ DstX0, DstY0, DstX1, DstY1,
+ ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Linear);
+
+ EnsureFrameBuffer();
}
public void Copy(
@@ -276,39 +307,80 @@ namespace Ryujinx.Graphics.Gal.OpenGL
int DstX1,
int DstY1)
{
- if (Fbs.TryGetValue(SrcKey, out FrameBuffer SrcFb) &&
- Fbs.TryGetValue(DstKey, out FrameBuffer DstFb))
+ if (Texture.TryGetImage(SrcKey, out ImageHandler SrcTex) &&
+ Texture.TryGetImage(DstKey, out ImageHandler DstTex))
{
- GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb.Handle);
- GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DstFb.Handle);
-
- GL.Clear(ClearBufferMask.ColorBufferBit);
+ if (SrcTex.HasColor != DstTex.HasColor ||
+ SrcTex.HasDepth != DstTex.HasDepth ||
+ SrcTex.HasStencil != DstTex.HasStencil)
+ {
+ throw new NotImplementedException();
+ }
- GL.BlitFramebuffer(
- SrcX0, SrcY0, SrcX1, SrcY1,
- DstX0, DstY0, DstX1, DstY1,
- ClearBufferMask.ColorBufferBit,
- BlitFramebufferFilter.Linear);
+ 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();
+ }
}
-}
+ }
public void GetBufferData(long Key, Action<byte[]> Callback)
{
- if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
+ if (Texture.TryGetImage(Key, out ImageHandler Tex))
{
- GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, Fb.Handle);
+ byte[] Data = new byte[Tex.Width * Tex.Height * ImageHandler.MaxBpp];
- byte[] Data = new byte[Fb.Width * Fb.Height * 4];
+ GL.BindTexture(TextureTarget.Texture2D, Tex.Handle);
- (PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(GalTextureFormat.A8B8G8R8);
-
- GL.ReadPixels(
- 0,
+ GL.GetTexImage(
+ TextureTarget.Texture2D,
0,
- Fb.Width,
- Fb.Height,
- Format,
- Type,
+ Tex.PixelFormat,
+ Tex.PixelType,
Data);
Callback(Data);
@@ -319,83 +391,101 @@ namespace Ryujinx.Graphics.Gal.OpenGL
long Key,
int Width,
int Height,
- GalTextureFormat Format,
byte[] Buffer)
{
- if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
+ if (Texture.TryGetImage(Key, out ImageHandler Tex))
{
- GL.BindTexture(TextureTarget.Texture2D, Fb.TexHandle);
+ GL.BindTexture(TextureTarget.Texture2D, Tex.Handle);
const int Level = 0;
const int Border = 0;
- const PixelInternalFormat InternalFmt = PixelInternalFormat.Rgba;
-
- (PixelFormat GlFormat, PixelType Type) = OGLEnumConverter.GetTextureFormat(Format);
-
GL.TexImage2D(
TextureTarget.Texture2D,
Level,
- InternalFmt,
+ Tex.InternalFormat,
Width,
Height,
Border,
- GlFormat,
- Type,
+ Tex.PixelFormat,
+ Tex.PixelType,
Buffer);
}
}
- private void CreateRawFb(int Width, int Height)
+ private void EnsureFrameBuffer()
{
- if (RawFb == null)
+ if (DummyFrameBuffer == 0)
{
- RawFb = new FrameBuffer(Width, Height, false);
-
- SetupTexture(RawFb.TexHandle, Width, Height);
+ DummyFrameBuffer = GL.GenFramebuffer();
+ }
- RawFb.Width = Width;
- RawFb.Height = Height;
+ GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DummyFrameBuffer);
- GL.BindFramebuffer(FramebufferTarget.Framebuffer, RawFb.Handle);
+ GL.DrawBuffers(8, DrawBuffers);
+ }
+ private void Attach(ref int OldHandle, int NewHandle, FramebufferAttachment FbAttachment)
+ {
+ if (OldHandle != NewHandle)
+ {
GL.FramebufferTexture(
- FramebufferTarget.Framebuffer,
- FramebufferAttachment.ColorAttachment0,
- RawFb.TexHandle,
+ FramebufferTarget.DrawFramebuffer,
+ FbAttachment,
+ NewHandle,
0);
- GL.Viewport(0, 0, Width, Height);
+ OldHandle = NewHandle;
}
}
- private void SetupTexture(int Handle, int Width, int Height)
+ private void CopyTextures(
+ int SrcX0,
+ int SrcY0,
+ int SrcX1,
+ int SrcY1,
+ int DstX0,
+ int DstY0,
+ int DstX1,
+ int DstY1,
+ int SrcTexture,
+ int DstTexture,
+ FramebufferAttachment Attachment,
+ ClearBufferMask Mask,
+ bool Color)
{
- GL.BindTexture(TextureTarget.Texture2D, Handle);
+ if (SrcFb == 0) SrcFb = GL.GenFramebuffer();
+ if (DstFb == 0) DstFb = GL.GenFramebuffer();
- const int MinFilter = (int)TextureMinFilter.Linear;
- const int MagFilter = (int)TextureMagFilter.Linear;
+ GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb);
+ GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DstFb);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, MinFilter);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, MagFilter);
+ GL.FramebufferTexture(
+ FramebufferTarget.ReadFramebuffer,
+ Attachment,
+ SrcTexture,
+ 0);
- (PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(GalTextureFormat.A8B8G8R8);
+ GL.FramebufferTexture(
+ FramebufferTarget.DrawFramebuffer,
+ Attachment,
+ DstTexture,
+ 0);
+
+ if (Color)
+ {
+ GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
+ }
- const PixelInternalFormat InternalFmt = PixelInternalFormat.Rgba;
+ GL.Clear(Mask);
- const int Level = 0;
- const int Border = 0;
+ GL.BlitFramebuffer(
+ SrcX0, SrcY0, SrcX1, SrcY1,
+ DstX0, DstY0, DstX1, DstY1,
+ Mask,
+ Color ? BlitFramebufferFilter.Linear : BlitFramebufferFilter.Nearest);
- GL.TexImage2D(
- TextureTarget.Texture2D,
- Level,
- InternalFmt,
- Width,
- Height,
- Border,
- Format,
- Type,
- IntPtr.Zero);
+ EnsureFrameBuffer();
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
index b6e97454..45106692 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
@@ -3,7 +3,7 @@ using System;
namespace Ryujinx.Graphics.Gal.OpenGL
{
- public class OGLRasterizer : IGalRasterizer
+ class OGLRasterizer : IGalRasterizer
{
private int[] VertexBuffers;
@@ -44,36 +44,29 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public void ClearBuffers(
GalClearBufferFlags Flags,
+ int Attachment,
float Red, float Green, float Blue, float Alpha,
float Depth,
int Stencil)
{
- ClearBufferMask Mask = ClearBufferMask.ColorBufferBit;
-
GL.ColorMask(
Flags.HasFlag(GalClearBufferFlags.ColorRed),
Flags.HasFlag(GalClearBufferFlags.ColorGreen),
Flags.HasFlag(GalClearBufferFlags.ColorBlue),
Flags.HasFlag(GalClearBufferFlags.ColorAlpha));
+ GL.ClearBuffer(ClearBuffer.Color, Attachment, new float[] { Red, Green, Blue, Alpha });
+
if (Flags.HasFlag(GalClearBufferFlags.Depth))
{
- Mask |= ClearBufferMask.DepthBufferBit;
+ GL.ClearBuffer(ClearBuffer.Depth, 0, ref Depth);
}
if (Flags.HasFlag(GalClearBufferFlags.Stencil))
{
- Mask |= ClearBufferMask.StencilBufferBit;
+ GL.ClearBuffer(ClearBuffer.Stencil, 0, ref Stencil);
}
- GL.ClearColor(Red, Green, Blue, Alpha);
-
- GL.ClearDepth(Depth);
-
- GL.ClearStencil(Stencil);
-
- GL.Clear(Mask);
-
GL.ColorMask(true, true, true, true);
}
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs
index b0f6da45..985f1086 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderer.cs
@@ -23,7 +23,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
Buffer = new OGLConstBuffer();
- FrameBuffer = new OGLFrameBuffer();
+ Texture = new OGLTexture();
+
+ FrameBuffer = new OGLFrameBuffer(Texture as OGLTexture);
Rasterizer = new OGLRasterizer();
@@ -31,8 +33,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Pipeline = new OGLPipeline(Buffer as OGLConstBuffer, Rasterizer as OGLRasterizer, Shader as OGLShader);
- Texture = new OGLTexture();
-
ActionsQueue = new ConcurrentQueue<Action>();
}
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs
index ac30e6fd..e4d4bd64 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs
@@ -4,26 +4,13 @@ using System;
namespace Ryujinx.Graphics.Gal.OpenGL
{
- public class OGLTexture : IGalTexture
+ class OGLTexture : IGalTexture
{
- private class TCE
- {
- public int Handle;
-
- public GalTexture Texture;
-
- public TCE(int Handle, GalTexture Texture)
- {
- this.Handle = Handle;
- this.Texture = Texture;
- }
- }
-
- private OGLCachedResource<TCE> TextureCache;
+ private OGLCachedResource<ImageHandler> TextureCache;
public OGLTexture()
{
- TextureCache = new OGLCachedResource<TCE>(DeleteTexture);
+ TextureCache = new OGLCachedResource<ImageHandler>(DeleteTexture);
}
public void LockCache()
@@ -36,73 +23,71 @@ namespace Ryujinx.Graphics.Gal.OpenGL
TextureCache.Unlock();
}
- private static void DeleteTexture(TCE CachedTexture)
+ private static void DeleteTexture(ImageHandler CachedImage)
{
- GL.DeleteTexture(CachedTexture.Handle);
+ GL.DeleteTexture(CachedImage.Handle);
}
- public void Create(long Key, byte[] Data, GalTexture Texture)
+ public void Create(long Key, byte[] Data, GalImage Image)
{
int Handle = GL.GenTexture();
- TextureCache.AddOrUpdate(Key, new TCE(Handle, Texture), (uint)Data.Length);
+ TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length);
GL.BindTexture(TextureTarget.Texture2D, Handle);
const int Level = 0; //TODO: Support mipmap textures.
const int Border = 0;
- if (IsCompressedTextureFormat(Texture.Format))
+ if (IsCompressedTextureFormat(Image.Format))
{
- InternalFormat InternalFmt = OGLEnumConverter.GetCompressedTextureFormat(Texture.Format);
+ InternalFormat InternalFmt = OGLEnumConverter.GetCompressedImageFormat(Image.Format);
GL.CompressedTexImage2D(
TextureTarget.Texture2D,
Level,
InternalFmt,
- Texture.Width,
- Texture.Height,
+ Image.Width,
+ Image.Height,
Border,
Data.Length,
Data);
}
else
{
- if (Texture.Format >= GalTextureFormat.Astc2D4x4)
+ if (Image.Format >= GalImageFormat.ASTC_BEGIN && Image.Format <= GalImageFormat.ASTC_END)
{
- int TextureBlockWidth = GetAstcBlockWidth(Texture.Format);
- int TextureBlockHeight = GetAstcBlockHeight(Texture.Format);
+ int TextureBlockWidth = GetAstcBlockWidth(Image.Format);
+ int TextureBlockHeight = GetAstcBlockHeight(Image.Format);
Data = ASTCDecoder.DecodeToRGBA8888(
Data,
TextureBlockWidth,
TextureBlockHeight, 1,
- Texture.Width,
- Texture.Height, 1);
+ Image.Width,
+ Image.Height, 1);
- Texture.Format = GalTextureFormat.A8B8G8R8;
+ Image.Format = GalImageFormat.A8B8G8R8_UNORM_PACK32;
}
- const PixelInternalFormat InternalFmt = PixelInternalFormat.Rgba;
-
- (PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(Texture.Format);
+ (PixelInternalFormat InternalFormat, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
GL.TexImage2D(
TextureTarget.Texture2D,
Level,
- InternalFmt,
- Texture.Width,
- Texture.Height,
+ InternalFormat,
+ Image.Width,
+ Image.Height,
Border,
Format,
Type,
Data);
}
- int SwizzleR = (int)OGLEnumConverter.GetTextureSwizzle(Texture.XSource);
- int SwizzleG = (int)OGLEnumConverter.GetTextureSwizzle(Texture.YSource);
- int SwizzleB = (int)OGLEnumConverter.GetTextureSwizzle(Texture.ZSource);
- int SwizzleA = (int)OGLEnumConverter.GetTextureSwizzle(Texture.WSource);
+ int SwizzleR = (int)OGLEnumConverter.GetTextureSwizzle(Image.XSource);
+ int SwizzleG = (int)OGLEnumConverter.GetTextureSwizzle(Image.YSource);
+ int SwizzleB = (int)OGLEnumConverter.GetTextureSwizzle(Image.ZSource);
+ int SwizzleA = (int)OGLEnumConverter.GetTextureSwizzle(Image.WSource);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleR, SwizzleR);
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleG, SwizzleG);
@@ -110,76 +95,100 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, SwizzleA);
}
- private static int GetAstcBlockWidth(GalTextureFormat Format)
+ 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);
+ }
+
+ public bool TryGetImage(long Key, out ImageHandler CachedImage)
+ {
+ if (TextureCache.TryGetValue(Key, out CachedImage))
+ {
+ return true;
+ }
+
+ CachedImage = null;
+
+ return false;
+ }
+
+ private static int GetAstcBlockWidth(GalImageFormat Format)
{
switch (Format)
{
- case GalTextureFormat.Astc2D4x4: return 4;
- case GalTextureFormat.Astc2D5x5: return 5;
- case GalTextureFormat.Astc2D6x6: return 6;
- case GalTextureFormat.Astc2D8x8: return 8;
- case GalTextureFormat.Astc2D10x10: return 10;
- case GalTextureFormat.Astc2D12x12: return 12;
- case GalTextureFormat.Astc2D5x4: return 5;
- case GalTextureFormat.Astc2D6x5: return 6;
- case GalTextureFormat.Astc2D8x6: return 8;
- case GalTextureFormat.Astc2D10x8: return 10;
- case GalTextureFormat.Astc2D12x10: return 12;
- case GalTextureFormat.Astc2D8x5: return 8;
- case GalTextureFormat.Astc2D10x5: return 10;
- case GalTextureFormat.Astc2D10x6: return 10;
+ case GalImageFormat.ASTC_4x4_UNORM_BLOCK: return 4;
+ case GalImageFormat.ASTC_5x5_UNORM_BLOCK: return 5;
+ case GalImageFormat.ASTC_6x6_UNORM_BLOCK: return 6;
+ case GalImageFormat.ASTC_8x8_UNORM_BLOCK: return 8;
+ case GalImageFormat.ASTC_10x10_UNORM_BLOCK: return 10;
+ case GalImageFormat.ASTC_12x12_UNORM_BLOCK: return 12;
+ case GalImageFormat.ASTC_5x4_UNORM_BLOCK: return 5;
+ case GalImageFormat.ASTC_6x5_UNORM_BLOCK: return 6;
+ case GalImageFormat.ASTC_8x6_UNORM_BLOCK: return 8;
+ case GalImageFormat.ASTC_10x8_UNORM_BLOCK: return 10;
+ case GalImageFormat.ASTC_12x10_UNORM_BLOCK: return 12;
+ case GalImageFormat.ASTC_8x5_UNORM_BLOCK: return 8;
+ case GalImageFormat.ASTC_10x5_UNORM_BLOCK: return 10;
+ case GalImageFormat.ASTC_10x6_UNORM_BLOCK: return 10;
}
throw new ArgumentException(nameof(Format));
}
- private static int GetAstcBlockHeight(GalTextureFormat Format)
+ private static int GetAstcBlockHeight(GalImageFormat Format)
{
switch (Format)
{
- case GalTextureFormat.Astc2D4x4: return 4;
- case GalTextureFormat.Astc2D5x5: return 5;
- case GalTextureFormat.Astc2D6x6: return 6;
- case GalTextureFormat.Astc2D8x8: return 8;
- case GalTextureFormat.Astc2D10x10: return 10;
- case GalTextureFormat.Astc2D12x12: return 12;
- case GalTextureFormat.Astc2D5x4: return 4;
- case GalTextureFormat.Astc2D6x5: return 5;
- case GalTextureFormat.Astc2D8x6: return 6;
- case GalTextureFormat.Astc2D10x8: return 8;
- case GalTextureFormat.Astc2D12x10: return 10;
- case GalTextureFormat.Astc2D8x5: return 5;
- case GalTextureFormat.Astc2D10x5: return 5;
- case GalTextureFormat.Astc2D10x6: return 6;
+ case GalImageFormat.ASTC_4x4_UNORM_BLOCK: return 4;
+ case GalImageFormat.ASTC_5x5_UNORM_BLOCK: return 5;
+ case GalImageFormat.ASTC_6x6_UNORM_BLOCK: return 6;
+ case GalImageFormat.ASTC_8x8_UNORM_BLOCK: return 8;
+ case GalImageFormat.ASTC_10x10_UNORM_BLOCK: return 10;
+ case GalImageFormat.ASTC_12x12_UNORM_BLOCK: return 12;
+ case GalImageFormat.ASTC_5x4_UNORM_BLOCK: return 4;
+ case GalImageFormat.ASTC_6x5_UNORM_BLOCK: return 5;
+ case GalImageFormat.ASTC_8x6_UNORM_BLOCK: return 6;
+ case GalImageFormat.ASTC_10x8_UNORM_BLOCK: return 8;
+ case GalImageFormat.ASTC_12x10_UNORM_BLOCK: return 10;
+ case GalImageFormat.ASTC_8x5_UNORM_BLOCK: return 5;
+ case GalImageFormat.ASTC_10x5_UNORM_BLOCK: return 5;
+ case GalImageFormat.ASTC_10x6_UNORM_BLOCK: return 6;
}
throw new ArgumentException(nameof(Format));
}
- public bool TryGetCachedTexture(long Key, long DataSize, out GalTexture Texture)
+ public bool TryGetCachedTexture(long Key, long DataSize, out GalImage Image)
{
if (TextureCache.TryGetSize(Key, out long Size) && Size == DataSize)
{
- if (TextureCache.TryGetValue(Key, out TCE CachedTexture))
+ if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
{
- Texture = CachedTexture.Texture;
+ Image = CachedImage.Image;
return true;
}
}
- Texture = default(GalTexture);
+ Image = default(GalImage);
return false;
}
public void Bind(long Key, int Index)
{
- if (TextureCache.TryGetValue(Key, out TCE CachedTexture))
+ if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
{
GL.ActiveTexture(TextureUnit.Texture0 + Index);
- GL.BindTexture(TextureTarget.Texture2D, CachedTexture.Handle);
+ GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle);
}
}
@@ -208,18 +217,20 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, Color);
}
- private static bool IsCompressedTextureFormat(GalTextureFormat Format)
+ private static bool IsCompressedTextureFormat(GalImageFormat Format)
{
switch (Format)
{
- case GalTextureFormat.BC6H_UF16:
- case GalTextureFormat.BC6H_SF16:
- case GalTextureFormat.BC7U:
- case GalTextureFormat.BC1:
- case GalTextureFormat.BC2:
- case GalTextureFormat.BC3:
- case GalTextureFormat.BC4:
- case GalTextureFormat.BC5:
+ case GalImageFormat.BC6H_UFLOAT_BLOCK:
+ case GalImageFormat.BC6H_SFLOAT_BLOCK:
+ case GalImageFormat.BC7_UNORM_BLOCK:
+ case GalImageFormat.BC1_RGBA_UNORM_BLOCK:
+ case GalImageFormat.BC2_UNORM_BLOCK:
+ case GalImageFormat.BC3_UNORM_BLOCK:
+ case GalImageFormat.BC4_SNORM_BLOCK:
+ case GalImageFormat.BC4_UNORM_BLOCK:
+ case GalImageFormat.BC5_SNORM_BLOCK:
+ case GalImageFormat.BC5_UNORM_BLOCK:
return true;
}