aboutsummaryrefslogtreecommitdiff
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
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
-rw-r--r--Ryujinx.Graphics/Gal/GalFrameBufferFormat.cs68
-rw-r--r--Ryujinx.Graphics/Gal/GalImage.cs (renamed from Ryujinx.Graphics/Gal/GalTexture.cs)16
-rw-r--r--Ryujinx.Graphics/Gal/GalImageFormat.cs204
-rw-r--r--Ryujinx.Graphics/Gal/GalTextureFormat.cs1
-rw-r--r--Ryujinx.Graphics/Gal/GalTextureType.cs13
-rw-r--r--Ryujinx.Graphics/Gal/GalZetaFormat.cs16
-rw-r--r--Ryujinx.Graphics/Gal/IGalFrameBuffer.cs9
-rw-r--r--Ryujinx.Graphics/Gal/IGalRasterizer.cs1
-rw-r--r--Ryujinx.Graphics/Gal/IGalTexture.cs6
-rw-r--r--Ryujinx.Graphics/Gal/ImageFormatConverter.cs263
-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
-rw-r--r--Ryujinx.Graphics/Gal/Shader/GlslDecl.cs7
-rw-r--r--Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs11
-rw-r--r--Ryujinx.HLE/Gpu/Engines/NvGpuEngine2d.cs4
-rw-r--r--Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs71
-rw-r--r--Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs8
-rw-r--r--Ryujinx.HLE/Gpu/Texture/TextureFactory.cs11
-rw-r--r--Ryujinx.HLE/Gpu/Texture/TextureHelper.cs160
-rw-r--r--Ryujinx.HLE/Gpu/Texture/TextureReader.cs1
25 files changed, 1348 insertions, 429 deletions
diff --git a/Ryujinx.Graphics/Gal/GalFrameBufferFormat.cs b/Ryujinx.Graphics/Gal/GalFrameBufferFormat.cs
new file mode 100644
index 00000000..3180aeff
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/GalFrameBufferFormat.cs
@@ -0,0 +1,68 @@
+namespace Ryujinx.Graphics.Gal
+{
+ public enum GalFrameBufferFormat
+ {
+ Bitmap = 0x1c,
+ Unknown1D = 0x1d,
+ RGBA32Float = 0xc0,
+ RGBA32Sint = 0xc1,
+ RGBA32Uint = 0xc2,
+ RGBX32Float = 0xc3,
+ RGBX32Sint = 0xc4,
+ RGBX32Uint = 0xc5,
+ RGBA16Unorm = 0xc6,
+ RGBA16Snorm = 0xc7,
+ RGBA16Sint = 0xc8,
+ RGBA16Uint = 0xc9,
+ RGBA16Float = 0xca,
+ RG32Float = 0xcb,
+ RG32Sint = 0xcc,
+ RG32Uint = 0xcd,
+ RGBX16Float = 0xce,
+ BGRA8Unorm = 0xcf,
+ BGRA8Srgb = 0xd0,
+ RGB10A2Unorm = 0xd1,
+ RGB10A2Uint = 0xd2,
+ RGBA8Unorm = 0xd5,
+ RGBA8Srgb = 0xd6,
+ RGBA8Snorm = 0xd7,
+ RGBA8Sint = 0xd8,
+ RGBA8Uint = 0xd9,
+ RG16Unorm = 0xda,
+ RG16Snorm = 0xdb,
+ RG16Sint = 0xdc,
+ RG16Uint = 0xdd,
+ RG16Float = 0xde,
+ BGR10A2Unorm = 0xdf,
+ R11G11B10Float = 0xe0,
+ R32Sint = 0xe3,
+ R32Uint = 0xe4,
+ R32Float = 0xe5,
+ BGRX8Unorm = 0xe6,
+ BGRX8Srgb = 0xe7,
+ B5G6R5Unorm = 0xe8,
+ BGR5A1Unorm = 0xe9,
+ RG8Unorm = 0xea,
+ RG8Snorm = 0xeb,
+ RG8Sint = 0xec,
+ RG8Uint = 0xed,
+ R16Unorm = 0xee,
+ R16Snorm = 0xef,
+ R16Sint = 0xf0,
+ R16Uint = 0xf1,
+ R16Float = 0xf2,
+ R8Unorm = 0xf3,
+ R8Snorm = 0xf4,
+ R8Sint = 0xf5,
+ R8Uint = 0xf6,
+ A8Unorm = 0xf7,
+ BGR5X1Unorm = 0xf8,
+ RGBX8Unorm = 0xf9,
+ RGBX8Srgb = 0xfa,
+ BGR5X1UnormUnknownFB = 0xfb,
+ BGR5X1UnormUnknownFC = 0xfc,
+ BGRX8UnormUnknownFD = 0xfd,
+ BGRX8UnormUnknownFE = 0xfe,
+ Y32UintUnknownFF = 0xff
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/GalTexture.cs b/Ryujinx.Graphics/Gal/GalImage.cs
index 2c1be65b..dc6f02e0 100644
--- a/Ryujinx.Graphics/Gal/GalTexture.cs
+++ b/Ryujinx.Graphics/Gal/GalImage.cs
@@ -1,25 +1,25 @@
namespace Ryujinx.Graphics.Gal
{
- public struct GalTexture
+ public struct GalImage
{
public int Width;
public int Height;
- public GalTextureFormat Format;
+ public GalImageFormat Format;
public GalTextureSource XSource;
public GalTextureSource YSource;
public GalTextureSource ZSource;
public GalTextureSource WSource;
- public GalTexture(
+ public GalImage(
int Width,
int Height,
- GalTextureFormat Format,
- GalTextureSource XSource,
- GalTextureSource YSource,
- GalTextureSource ZSource,
- GalTextureSource WSource)
+ GalImageFormat Format,
+ GalTextureSource XSource = GalTextureSource.Red,
+ GalTextureSource YSource = GalTextureSource.Green,
+ GalTextureSource ZSource = GalTextureSource.Blue,
+ GalTextureSource WSource = GalTextureSource.Alpha)
{
this.Width = Width;
this.Height = Height;
diff --git a/Ryujinx.Graphics/Gal/GalImageFormat.cs b/Ryujinx.Graphics/Gal/GalImageFormat.cs
new file mode 100644
index 00000000..4e84067b
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/GalImageFormat.cs
@@ -0,0 +1,204 @@
+namespace Ryujinx.Graphics.Gal
+{
+ //These are Vulkan-based enumerations, do not take them as Tegra values
+ public enum GalImageFormat
+ {
+ Undefined = 0,
+
+ R4G4_UNORM_PACK8 = 1,
+ R4G4B4A4_UNORM_PACK16 = 2,
+ B4G4R4A4_UNORM_PACK16 = 3,
+ R5G6B5_UNORM_PACK16 = 4,
+ B5G6R5_UNORM_PACK16 = 5,
+ R5G5B5A1_UNORM_PACK16 = 6,
+ B5G5R5A1_UNORM_PACK16 = 7,
+ A1R5G5B5_UNORM_PACK16 = 8,
+ R8_UNORM = 9,
+ R8_SNORM = 10,
+ R8_USCALED = 11,
+ R8_SSCALED = 12,
+ R8_UINT = 13,
+ R8_SINT = 14,
+ R8_SRGB = 15,
+ R8G8_UNORM = 16,
+ R8G8_SNORM = 17,
+ R8G8_USCALED = 18,
+ R8G8_SSCALED = 19,
+ R8G8_UINT = 20,
+ R8G8_SINT = 21,
+ R8G8_SRGB = 22,
+ R8G8B8_UNORM = 23,
+ R8G8B8_SNORM = 24,
+ R8G8B8_USCALED = 25,
+ R8G8B8_SSCALED = 26,
+ R8G8B8_UINT = 27,
+ R8G8B8_SINT = 28,
+ R8G8B8_SRGB = 29,
+ B8G8R8_UNORM = 30,
+ B8G8R8_SNORM = 31,
+ B8G8R8_USCALED = 32,
+ B8G8R8_SSCALED = 33,
+ B8G8R8_UINT = 34,
+ B8G8R8_SINT = 35,
+ B8G8R8_SRGB = 36,
+ R8G8B8A8_UNORM = 37,
+ R8G8B8A8_SNORM = 38,
+ R8G8B8A8_USCALED = 39,
+ R8G8B8A8_SSCALED = 40,
+ R8G8B8A8_UINT = 41,
+ R8G8B8A8_SINT = 42,
+ R8G8B8A8_SRGB = 43,
+ B8G8R8A8_UNORM = 44,
+ B8G8R8A8_SNORM = 45,
+ B8G8R8A8_USCALED = 46,
+ B8G8R8A8_SSCALED = 47,
+ B8G8R8A8_UINT = 48,
+ B8G8R8A8_SINT = 49,
+ B8G8R8A8_SRGB = 50,
+ A8B8G8R8_UNORM_PACK32 = 51,
+ A8B8G8R8_SNORM_PACK32 = 52,
+ A8B8G8R8_USCALED_PACK32 = 53,
+ A8B8G8R8_SSCALED_PACK32 = 54,
+ A8B8G8R8_UINT_PACK32 = 55,
+ A8B8G8R8_SINT_PACK32 = 56,
+ A8B8G8R8_SRGB_PACK32 = 57,
+ A2R10G10B10_UNORM_PACK32 = 58,
+ A2R10G10B10_SNORM_PACK32 = 59,
+ A2R10G10B10_USCALED_PACK32 = 60,
+ A2R10G10B10_SSCALED_PACK32 = 61,
+ A2R10G10B10_UINT_PACK32 = 62,
+ A2R10G10B10_SINT_PACK32 = 63,
+ A2B10G10R10_UNORM_PACK32 = 64,
+ A2B10G10R10_SNORM_PACK32 = 65,
+ A2B10G10R10_USCALED_PACK32 = 66,
+ A2B10G10R10_SSCALED_PACK32 = 67,
+ A2B10G10R10_UINT_PACK32 = 68,
+ A2B10G10R10_SINT_PACK32 = 69,
+ R16_UNORM = 70,
+ R16_SNORM = 71,
+ R16_USCALED = 72,
+ R16_SSCALED = 73,
+ R16_UINT = 74,
+ R16_SINT = 75,
+ R16_SFLOAT = 76,
+ R16G16_UNORM = 77,
+ R16G16_SNORM = 78,
+ R16G16_USCALED = 79,
+ R16G16_SSCALED = 80,
+ R16G16_UINT = 81,
+ R16G16_SINT = 82,
+ R16G16_SFLOAT = 83,
+ R16G16B16_UNORM = 84,
+ R16G16B16_SNORM = 85,
+ R16G16B16_USCALED = 86,
+ R16G16B16_SSCALED = 87,
+ R16G16B16_UINT = 88,
+ R16G16B16_SINT = 89,
+ R16G16B16_SFLOAT = 90,
+ R16G16B16A16_UNORM = 91,
+ R16G16B16A16_SNORM = 92,
+ R16G16B16A16_USCALED = 93,
+ R16G16B16A16_SSCALED = 94,
+ R16G16B16A16_UINT = 95,
+ R16G16B16A16_SINT = 96,
+ R16G16B16A16_SFLOAT = 97,
+ R32_UINT = 98,
+ R32_SINT = 99,
+ R32_SFLOAT = 100,
+ R32G32_UINT = 101,
+ R32G32_SINT = 102,
+ R32G32_SFLOAT = 103,
+ R32G32B32_UINT = 104,
+ R32G32B32_SINT = 105,
+ R32G32B32_SFLOAT = 106,
+ R32G32B32A32_UINT = 107,
+ R32G32B32A32_SINT = 108,
+ R32G32B32A32_SFLOAT = 109,
+ R64_UINT = 110,
+ R64_SINT = 111,
+ R64_SFLOAT = 112,
+ R64G64_UINT = 113,
+ R64G64_SINT = 114,
+ R64G64_SFLOAT = 115,
+ R64G64B64_UINT = 116,
+ R64G64B64_SINT = 117,
+ R64G64B64_SFLOAT = 118,
+ R64G64B64A64_UINT = 119,
+ R64G64B64A64_SINT = 120,
+ R64G64B64A64_SFLOAT = 121,
+ B10G11R11_UFLOAT_PACK32 = 122,
+ E5B9G9R9_UFLOAT_PACK32 = 123,
+ D16_UNORM = 124,
+ X8_D24_UNORM_PACK32 = 125,
+ D32_SFLOAT = 126,
+ S8_UINT = 127,
+ D16_UNORM_S8_UINT = 128,
+ D24_UNORM_S8_UINT = 129,
+ D32_SFLOAT_S8_UINT = 130,
+ BC1_RGB_UNORM_BLOCK = 131,
+ BC1_RGB_SRGB_BLOCK = 132,
+ BC1_RGBA_UNORM_BLOCK = 133,
+ BC1_RGBA_SRGB_BLOCK = 134,
+ BC2_UNORM_BLOCK = 135,
+ BC2_SRGB_BLOCK = 136,
+ BC3_UNORM_BLOCK = 137,
+ BC3_SRGB_BLOCK = 138,
+ BC4_UNORM_BLOCK = 139,
+ BC4_SNORM_BLOCK = 140,
+ BC5_UNORM_BLOCK = 141,
+ BC5_SNORM_BLOCK = 142,
+ BC6H_UFLOAT_BLOCK = 143,
+ BC6H_SFLOAT_BLOCK = 144,
+ BC7_UNORM_BLOCK = 145,
+ BC7_SRGB_BLOCK = 146,
+ ETC2_R8G8B8_UNORM_BLOCK = 147,
+ ETC2_R8G8B8_SRGB_BLOCK = 148,
+ ETC2_R8G8B8A1_UNORM_BLOCK = 149,
+ ETC2_R8G8B8A1_SRGB_BLOCK = 150,
+ ETC2_R8G8B8A8_UNORM_BLOCK = 151,
+ ETC2_R8G8B8A8_SRGB_BLOCK = 152,
+ EAC_R11_UNORM_BLOCK = 153,
+ EAC_R11_SNORM_BLOCK = 154,
+ EAC_R11G11_UNORM_BLOCK = 155,
+ EAC_R11G11_SNORM_BLOCK = 156,
+
+ ASTC_BEGIN = ASTC_4x4_UNORM_BLOCK,
+
+ ASTC_4x4_UNORM_BLOCK = 157,
+ ASTC_4x4_SRGB_BLOCK = 158,
+ ASTC_5x4_UNORM_BLOCK = 159,
+ ASTC_5x4_SRGB_BLOCK = 160,
+ ASTC_5x5_UNORM_BLOCK = 161,
+ ASTC_5x5_SRGB_BLOCK = 162,
+ ASTC_6x5_UNORM_BLOCK = 163,
+ ASTC_6x5_SRGB_BLOCK = 164,
+ ASTC_6x6_UNORM_BLOCK = 165,
+ ASTC_6x6_SRGB_BLOCK = 166,
+ ASTC_8x5_UNORM_BLOCK = 167,
+ ASTC_8x5_SRGB_BLOCK = 168,
+ ASTC_8x6_UNORM_BLOCK = 169,
+ ASTC_8x6_SRGB_BLOCK = 170,
+ ASTC_8x8_UNORM_BLOCK = 171,
+ ASTC_8x8_SRGB_BLOCK = 172,
+ ASTC_10x5_UNORM_BLOCK = 173,
+ ASTC_10x5_SRGB_BLOCK = 174,
+ ASTC_10x6_UNORM_BLOCK = 175,
+ ASTC_10x6_SRGB_BLOCK = 176,
+ ASTC_10x8_UNORM_BLOCK = 177,
+ ASTC_10x8_SRGB_BLOCK = 178,
+ ASTC_10x10_UNORM_BLOCK = 179,
+ ASTC_10x10_SRGB_BLOCK = 180,
+ ASTC_12x10_UNORM_BLOCK = 181,
+ ASTC_12x10_SRGB_BLOCK = 182,
+ ASTC_12x12_UNORM_BLOCK = 183,
+ ASTC_12x12_SRGB_BLOCK = 184,
+
+ ASTC_END = ASTC_12x12_SRGB_BLOCK,
+
+ REVERSED_BEGIN,
+
+ R4G4B4A4_UNORM_PACK16_REVERSED = REVERSED_BEGIN,
+
+ REVERSED_END
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/GalTextureFormat.cs b/Ryujinx.Graphics/Gal/GalTextureFormat.cs
index 7e3e65e8..5ab7be89 100644
--- a/Ryujinx.Graphics/Gal/GalTextureFormat.cs
+++ b/Ryujinx.Graphics/Gal/GalTextureFormat.cs
@@ -9,6 +9,7 @@ namespace Ryujinx.Graphics.Gal
R32 = 0xf,
BC6H_SF16 = 0x10,
BC6H_UF16 = 0x11,
+ A4B4G4R4 = 0x12,
A1B5G5R5 = 0x14,
B5G6R5 = 0x15,
BC7U = 0x17,
diff --git a/Ryujinx.Graphics/Gal/GalTextureType.cs b/Ryujinx.Graphics/Gal/GalTextureType.cs
new file mode 100644
index 00000000..f7dd16d1
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/GalTextureType.cs
@@ -0,0 +1,13 @@
+namespace Ryujinx.Graphics.Gal
+{
+ public enum GalTextureType
+ {
+ Snorm = 1,
+ Unorm = 2,
+ Sint = 3,
+ Uint = 4,
+ Snorm_Force_Fp16 = 5,
+ Unorm_Force_Fp16 = 6,
+ Float = 7
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/GalZetaFormat.cs b/Ryujinx.Graphics/Gal/GalZetaFormat.cs
new file mode 100644
index 00000000..759e3121
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/GalZetaFormat.cs
@@ -0,0 +1,16 @@
+namespace Ryujinx.Graphics.Gal
+{
+ public enum GalZetaFormat
+ {
+ Z32Float = 0x0a,
+ Z16Unorm = 0x13,
+ S8Z24Unorm = 0x14,
+ Z24X8Unorm = 0x15,
+ Z24S8Unorm = 0x16,
+ Z24C8Unorm = 0x18,
+ Z32S8X24Float = 0x19,
+ Z24X8S8C8X16Unorm = 0x1d,
+ Z32X8C8X16Float = 0x1e,
+ Z32S8C8X16Float = 0x1f
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/IGalFrameBuffer.cs b/Ryujinx.Graphics/Gal/IGalFrameBuffer.cs
index c0287ef8..bce1981a 100644
--- a/Ryujinx.Graphics/Gal/IGalFrameBuffer.cs
+++ b/Ryujinx.Graphics/Gal/IGalFrameBuffer.cs
@@ -4,9 +4,13 @@ namespace Ryujinx.Graphics.Gal
{
public interface IGalFrameBuffer
{
- void Create(long Key, int Width, int Height);
+ void BindColor(long Key, int Attachment);
- void Bind(long Key);
+ void UnbindColor(int Attachment);
+
+ void BindZeta(long Key);
+
+ void UnbindZeta();
void BindTexture(long Key, int Index);
@@ -40,7 +44,6 @@ namespace Ryujinx.Graphics.Gal
long Key,
int Width,
int Height,
- GalTextureFormat Format,
byte[] Buffer);
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/IGalRasterizer.cs b/Ryujinx.Graphics/Gal/IGalRasterizer.cs
index 89e50b1f..a20b6f53 100644
--- a/Ryujinx.Graphics/Gal/IGalRasterizer.cs
+++ b/Ryujinx.Graphics/Gal/IGalRasterizer.cs
@@ -9,6 +9,7 @@ namespace Ryujinx.Graphics.Gal
void ClearBuffers(
GalClearBufferFlags Flags,
+ int Attachment,
float Red, float Green, float Blue, float Alpha,
float Depth,
int Stencil);
diff --git a/Ryujinx.Graphics/Gal/IGalTexture.cs b/Ryujinx.Graphics/Gal/IGalTexture.cs
index 2ab41199..292f59ef 100644
--- a/Ryujinx.Graphics/Gal/IGalTexture.cs
+++ b/Ryujinx.Graphics/Gal/IGalTexture.cs
@@ -5,9 +5,11 @@ namespace Ryujinx.Graphics.Gal
void LockCache();
void UnlockCache();
- void Create(long Key, byte[] Data, GalTexture Texture);
+ void Create(long Key, byte[] Data, GalImage Image);
- bool TryGetCachedTexture(long Key, long DataSize, out GalTexture Texture);
+ void CreateFb(long Key, long Size, GalImage Image);
+
+ bool TryGetCachedTexture(long Key, long DataSize, out GalImage Image);
void Bind(long Key, int Index);
diff --git a/Ryujinx.Graphics/Gal/ImageFormatConverter.cs b/Ryujinx.Graphics/Gal/ImageFormatConverter.cs
new file mode 100644
index 00000000..2d20a8a0
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/ImageFormatConverter.cs
@@ -0,0 +1,263 @@
+using System;
+
+namespace Ryujinx.Graphics.Gal
+{
+ public static class ImageFormatConverter
+ {
+ public static GalImageFormat ConvertTexture(
+ GalTextureFormat Format,
+ GalTextureType RType,
+ GalTextureType GType,
+ GalTextureType BType,
+ GalTextureType AType)
+ {
+ if (RType != GType || RType != BType || RType != AType)
+ {
+ throw new NotImplementedException("Per component types are not implemented");
+ }
+
+ GalTextureType Type = RType;
+
+ switch (Type)
+ {
+ case GalTextureType.Snorm:
+ switch (Format)
+ {
+ case GalTextureFormat.R16G16B16A16: return GalImageFormat.R16G16B16A16_SNORM;
+ case GalTextureFormat.A8B8G8R8: return GalImageFormat.A8B8G8R8_SNORM_PACK32;
+ case GalTextureFormat.A2B10G10R10: return GalImageFormat.A2B10G10R10_SNORM_PACK32;
+ case GalTextureFormat.G8R8: return GalImageFormat.R8G8_SNORM;
+ case GalTextureFormat.R16: return GalImageFormat.R16_SNORM;
+ case GalTextureFormat.R8: return GalImageFormat.R8_SNORM;
+ case GalTextureFormat.BC4: return GalImageFormat.BC4_SNORM_BLOCK;
+ case GalTextureFormat.BC5: return GalImageFormat.BC5_SNORM_BLOCK;
+ }
+ break;
+
+ case GalTextureType.Unorm:
+ switch (Format)
+ {
+ case GalTextureFormat.R16G16B16A16: return GalImageFormat.R16G16B16A16_UNORM;
+ case GalTextureFormat.A8B8G8R8: return GalImageFormat.A8B8G8R8_UNORM_PACK32;
+ case GalTextureFormat.A2B10G10R10: return GalImageFormat.A2B10G10R10_UNORM_PACK32;
+ case GalTextureFormat.A4B4G4R4: return GalImageFormat.R4G4B4A4_UNORM_PACK16_REVERSED;
+ case GalTextureFormat.A1B5G5R5: return GalImageFormat.A1R5G5B5_UNORM_PACK16;
+ case GalTextureFormat.B5G6R5: return GalImageFormat.B5G6R5_UNORM_PACK16;
+ case GalTextureFormat.BC7U: return GalImageFormat.BC7_UNORM_BLOCK;
+ case GalTextureFormat.G8R8: return GalImageFormat.R8G8_UNORM;
+ case GalTextureFormat.R16: return GalImageFormat.R16_UNORM;
+ case GalTextureFormat.R8: return GalImageFormat.R8_UNORM;
+ case GalTextureFormat.BC1: return GalImageFormat.BC1_RGBA_UNORM_BLOCK;
+ case GalTextureFormat.BC2: return GalImageFormat.BC2_UNORM_BLOCK;
+ case GalTextureFormat.BC3: return GalImageFormat.BC3_UNORM_BLOCK;
+ case GalTextureFormat.BC4: return GalImageFormat.BC4_UNORM_BLOCK;
+ case GalTextureFormat.BC5: return GalImageFormat.BC5_UNORM_BLOCK;
+ case GalTextureFormat.Z24S8: return GalImageFormat.D24_UNORM_S8_UINT;
+ case GalTextureFormat.Astc2D4x4: return GalImageFormat.ASTC_4x4_UNORM_BLOCK;
+ case GalTextureFormat.Astc2D5x5: return GalImageFormat.ASTC_5x5_UNORM_BLOCK;
+ case GalTextureFormat.Astc2D6x6: return GalImageFormat.ASTC_6x6_UNORM_BLOCK;
+ case GalTextureFormat.Astc2D8x8: return GalImageFormat.ASTC_8x8_UNORM_BLOCK;
+ case GalTextureFormat.Astc2D10x10: return GalImageFormat.ASTC_10x10_UNORM_BLOCK;
+ case GalTextureFormat.Astc2D12x12: return GalImageFormat.ASTC_12x12_UNORM_BLOCK;
+ case GalTextureFormat.Astc2D5x4: return GalImageFormat.ASTC_5x4_UNORM_BLOCK;
+ case GalTextureFormat.Astc2D6x5: return GalImageFormat.ASTC_6x5_UNORM_BLOCK;
+ case GalTextureFormat.Astc2D8x6: return GalImageFormat.ASTC_8x6_UNORM_BLOCK;
+ case GalTextureFormat.Astc2D10x8: return GalImageFormat.ASTC_10x8_UNORM_BLOCK;
+ case GalTextureFormat.Astc2D12x10: return GalImageFormat.ASTC_12x10_UNORM_BLOCK;
+ case GalTextureFormat.Astc2D8x5: return GalImageFormat.ASTC_8x5_UNORM_BLOCK;
+ case GalTextureFormat.Astc2D10x5: return GalImageFormat.ASTC_10x5_UNORM_BLOCK;
+ case GalTextureFormat.Astc2D10x6: return GalImageFormat.ASTC_10x6_UNORM_BLOCK;
+ }
+ break;
+
+ case GalTextureType.Sint:
+ switch (Format)
+ {
+ case GalTextureFormat.R32G32B32A32: return GalImageFormat.R32G32B32A32_SINT;
+ case GalTextureFormat.R16G16B16A16: return GalImageFormat.R16G16B16A16_SINT;
+ case GalTextureFormat.A8B8G8R8: return GalImageFormat.A8B8G8R8_SINT_PACK32;
+ case GalTextureFormat.A2B10G10R10: return GalImageFormat.A2B10G10R10_SINT_PACK32;
+ case GalTextureFormat.R32: return GalImageFormat.R32_SINT;
+ case GalTextureFormat.G8R8: return GalImageFormat.R8G8_SINT;
+ case GalTextureFormat.R16: return GalImageFormat.R16_SINT;
+ case GalTextureFormat.R8: return GalImageFormat.R8_SINT;
+ }
+ break;
+
+ case GalTextureType.Uint:
+ switch (Format)
+ {
+ case GalTextureFormat.R32G32B32A32: return GalImageFormat.R32G32B32A32_UINT;
+ case GalTextureFormat.R16G16B16A16: return GalImageFormat.R16G16B16A16_UINT;
+ case GalTextureFormat.A8B8G8R8: return GalImageFormat.A8B8G8R8_UINT_PACK32;
+ case GalTextureFormat.A2B10G10R10: return GalImageFormat.A2B10G10R10_UINT_PACK32;
+ case GalTextureFormat.R32: return GalImageFormat.R32_UINT;
+ case GalTextureFormat.G8R8: return GalImageFormat.R8G8_UINT;
+ case GalTextureFormat.R16: return GalImageFormat.R16_UINT;
+ case GalTextureFormat.R8: return GalImageFormat.R8_UINT;
+ }
+ break;
+
+ case GalTextureType.Snorm_Force_Fp16:
+ //TODO
+ break;
+
+ case GalTextureType.Unorm_Force_Fp16:
+ //TODO
+ break;
+
+ case GalTextureType.Float:
+ switch (Format)
+ {
+ case GalTextureFormat.R32G32B32A32: return GalImageFormat.R32G32B32A32_SFLOAT;
+ case GalTextureFormat.R16G16B16A16: return GalImageFormat.R16G16B16A16_SFLOAT;
+ case GalTextureFormat.R32: return GalImageFormat.R32_SFLOAT;
+ case GalTextureFormat.BC6H_SF16: return GalImageFormat.BC6H_SFLOAT_BLOCK;
+ case GalTextureFormat.BC6H_UF16: return GalImageFormat.BC6H_UFLOAT_BLOCK;
+ case GalTextureFormat.R16: return GalImageFormat.R16_SFLOAT;
+ case GalTextureFormat.BF10GF11RF11: return GalImageFormat.B10G11R11_UFLOAT_PACK32;
+ case GalTextureFormat.ZF32: return GalImageFormat.D32_SFLOAT;
+ }
+ break;
+ }
+
+ throw new NotImplementedException("0x" + Format.ToString("x2") + " " + Type.ToString());
+ }
+
+ public static GalImageFormat ConvertFrameBuffer(GalFrameBufferFormat Format)
+ {
+ switch (Format)
+ {
+ case GalFrameBufferFormat.R32Float: return GalImageFormat.R32_SFLOAT;
+ case GalFrameBufferFormat.RGB10A2Unorm: return GalImageFormat.A2B10G10R10_UNORM_PACK32;
+ case GalFrameBufferFormat.RGBA8Srgb: return GalImageFormat.A8B8G8R8_SRGB_PACK32;
+ case GalFrameBufferFormat.RGBA16Float: return GalImageFormat.R16G16B16A16_SFLOAT;
+ case GalFrameBufferFormat.R16Float: return GalImageFormat.R16_SFLOAT;
+ case GalFrameBufferFormat.R8Unorm: return GalImageFormat.R8_UNORM;
+ case GalFrameBufferFormat.RGBA8Unorm: return GalImageFormat.A8B8G8R8_UNORM_PACK32;
+ case GalFrameBufferFormat.R11G11B10Float: return GalImageFormat.B10G11R11_UFLOAT_PACK32;
+ case GalFrameBufferFormat.RGBA32Float: return GalImageFormat.R32G32B32A32_SFLOAT;
+ case GalFrameBufferFormat.RG16Snorm: return GalImageFormat.R16G16_SNORM;
+ case GalFrameBufferFormat.RG16Float: return GalImageFormat.R16G16_SFLOAT;
+ case GalFrameBufferFormat.RG8Snorm: return GalImageFormat.R8_SNORM;
+ case GalFrameBufferFormat.RGBA8Snorm: return GalImageFormat.A8B8G8R8_SNORM_PACK32;
+ case GalFrameBufferFormat.RG8Unorm: return GalImageFormat.R8G8_UNORM;
+ }
+
+ throw new NotImplementedException(Format.ToString());
+ }
+
+ public static GalImageFormat ConvertZeta(GalZetaFormat Format)
+ {
+ switch (Format)
+ {
+ case GalZetaFormat.Z32Float: return GalImageFormat.D32_SFLOAT;
+ case GalZetaFormat.S8Z24Unorm: return GalImageFormat.D24_UNORM_S8_UINT;
+ case GalZetaFormat.Z16Unorm: return GalImageFormat.D16_UNORM;
+ }
+
+ throw new NotImplementedException(Format.ToString());
+ }
+
+ public static bool HasColor(GalImageFormat Format)
+ {
+ switch (Format)
+ {
+ case GalImageFormat.R32G32B32A32_SFLOAT:
+ case GalImageFormat.R32G32B32A32_SINT:
+ case GalImageFormat.R32G32B32A32_UINT:
+ case GalImageFormat.R16G16B16A16_SFLOAT:
+ case GalImageFormat.R16G16B16A16_SINT:
+ case GalImageFormat.R16G16B16A16_UINT:
+ case GalImageFormat.A8B8G8R8_SNORM_PACK32:
+ case GalImageFormat.A8B8G8R8_UNORM_PACK32:
+ case GalImageFormat.A8B8G8R8_SINT_PACK32:
+ case GalImageFormat.A8B8G8R8_UINT_PACK32:
+ case GalImageFormat.A2B10G10R10_SINT_PACK32:
+ case GalImageFormat.A2B10G10R10_SNORM_PACK32:
+ case GalImageFormat.A2B10G10R10_UINT_PACK32:
+ case GalImageFormat.A2B10G10R10_UNORM_PACK32:
+ case GalImageFormat.R32_SFLOAT:
+ case GalImageFormat.R32_SINT:
+ case GalImageFormat.R32_UINT:
+ case GalImageFormat.BC6H_SFLOAT_BLOCK:
+ case GalImageFormat.BC6H_UFLOAT_BLOCK:
+ case GalImageFormat.A1R5G5B5_UNORM_PACK16:
+ case GalImageFormat.B5G6R5_UNORM_PACK16:
+ case GalImageFormat.BC7_UNORM_BLOCK:
+ case GalImageFormat.R16G16_SFLOAT:
+ case GalImageFormat.R16G16_SINT:
+ case GalImageFormat.R16G16_SNORM:
+ case GalImageFormat.R16G16_UNORM:
+ case GalImageFormat.R8G8_SINT:
+ case GalImageFormat.R8G8_SNORM:
+ case GalImageFormat.R8G8_UINT:
+ case GalImageFormat.R8G8_UNORM:
+ case GalImageFormat.R16_SFLOAT:
+ case GalImageFormat.R16_SINT:
+ case GalImageFormat.R16_SNORM:
+ case GalImageFormat.R16_UINT:
+ case GalImageFormat.R16_UNORM:
+ case GalImageFormat.R8_SINT:
+ case GalImageFormat.R8_SNORM:
+ case GalImageFormat.R8_UINT:
+ case GalImageFormat.R8_UNORM:
+ case GalImageFormat.B10G11R11_UFLOAT_PACK32:
+ case GalImageFormat.BC1_RGBA_UNORM_BLOCK:
+ case GalImageFormat.BC2_UNORM_BLOCK:
+ case GalImageFormat.BC3_UNORM_BLOCK:
+ case GalImageFormat.BC4_UNORM_BLOCK:
+ case GalImageFormat.BC5_UNORM_BLOCK:
+ case GalImageFormat.ASTC_4x4_UNORM_BLOCK:
+ case GalImageFormat.ASTC_5x5_UNORM_BLOCK:
+ case GalImageFormat.ASTC_6x6_UNORM_BLOCK:
+ case GalImageFormat.ASTC_8x8_UNORM_BLOCK:
+ case GalImageFormat.ASTC_10x10_UNORM_BLOCK:
+ case GalImageFormat.ASTC_12x12_UNORM_BLOCK:
+ case GalImageFormat.ASTC_5x4_UNORM_BLOCK:
+ case GalImageFormat.ASTC_6x5_UNORM_BLOCK:
+ case GalImageFormat.ASTC_8x6_UNORM_BLOCK:
+ case GalImageFormat.ASTC_10x8_UNORM_BLOCK:
+ case GalImageFormat.ASTC_12x10_UNORM_BLOCK:
+ case GalImageFormat.ASTC_8x5_UNORM_BLOCK:
+ case GalImageFormat.ASTC_10x5_UNORM_BLOCK:
+ case GalImageFormat.ASTC_10x6_UNORM_BLOCK:
+ case GalImageFormat.R4G4B4A4_UNORM_PACK16_REVERSED:
+ return true;
+
+ case GalImageFormat.D24_UNORM_S8_UINT:
+ case GalImageFormat.D32_SFLOAT:
+ case GalImageFormat.D16_UNORM:
+ return true;
+ }
+
+ throw new NotImplementedException(Format.ToString());
+ }
+
+ public static bool HasDepth(GalImageFormat Format)
+ {
+ switch (Format)
+ {
+ case GalImageFormat.D24_UNORM_S8_UINT:
+ case GalImageFormat.D32_SFLOAT:
+ case GalImageFormat.D16_UNORM:
+ return true;
+ }
+
+ //Depth formats are fewer than colors, so it's harder to miss one
+ //Instead of checking for individual formats, return false
+ return false;
+ }
+
+ public static bool HasStencil(GalImageFormat Format)
+ {
+ switch (Format)
+ {
+ case GalImageFormat.D24_UNORM_S8_UINT:
+ return true;
+ }
+
+ return false;
+ }
+ }
+} \ No newline at end of file
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;
}
diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs
index ccc59e04..56745bc1 100644
--- a/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs
+++ b/Ryujinx.Graphics/Gal/Shader/GlslDecl.cs
@@ -16,6 +16,7 @@ namespace Ryujinx.Graphics.Gal.Shader
public const int VertexIdAttr = 0x2fc;
public const int FaceAttr = 0x3fc;
+ public const int MaxFrameBufferAttachments = 8;
public const int MaxUboSize = 1024;
public const int GlPositionVec4Index = 7;
@@ -99,7 +100,11 @@ namespace Ryujinx.Graphics.Gal.Shader
if (ShaderType == GalShaderType.Fragment)
{
- m_Gprs.Add(0, new ShaderDeclInfo(FragmentOutputName, 0, false, 0, 4));
+ //Note: Replace 1 with MaxFrameBufferAttachments when attachments start to work
+ for (int Index = 0; Index < 1; Index++)
+ {
+ m_Gprs.Add(Index * 4, new ShaderDeclInfo(FragmentOutputName + Index, Index * 4, false, 0, 4));
+ }
}
foreach (ShaderIrBlock Block in Blocks)
diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
index 7f1cfabc..72637984 100644
--- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
+++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
@@ -352,9 +352,9 @@ namespace Ryujinx.Graphics.Gal.Shader
{
Name = CustomType + " " + DeclInfo.Name + Suffix + ";";
}
- else if (DeclInfo.Name == GlslDecl.FragmentOutputName)
+ else if (DeclInfo.Name.Contains(GlslDecl.FragmentOutputName))
{
- Name = "layout (location = 0) out vec4 " + DeclInfo.Name + Suffix + ";" + Environment.NewLine;
+ Name = "layout (location = " + DeclInfo.Index / 4 + ") out vec4 " + DeclInfo.Name + Suffix + ";";
}
else
{
@@ -829,8 +829,11 @@ namespace Ryujinx.Graphics.Gal.Shader
{
return "gl_PointSize";
}
+ }
- throw new InvalidOperationException();
+ if (DeclInfo.Index >= 16)
+ {
+ throw new InvalidOperationException($"Shader attribute offset {Abuf.Offs} is invalid.");
}
if (Decl.ShaderType == GalShaderType.Geometry)
@@ -876,7 +879,7 @@ namespace Ryujinx.Graphics.Gal.Shader
private string GetNameWithSwizzle(IReadOnlyDictionary<int, ShaderDeclInfo> Dict, int Index)
{
- int VecIndex = Index >> 2;
+ int VecIndex = Index & ~3;
if (Dict.TryGetValue(VecIndex, out ShaderDeclInfo DeclInfo))
{
diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine2d.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine2d.cs
index d2c5f126..7fb5ea8a 100644
--- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine2d.cs
+++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine2d.cs
@@ -154,16 +154,12 @@ namespace Ryujinx.HLE.Gpu.Engines
}
else if (IsDstFb)
{
- //Texture -> Frame Buffer copy.
- const GalTextureFormat Format = GalTextureFormat.A8B8G8R8;
-
byte[] Buffer = TextureReader.Read(Vmm, SrcTexture());
Gpu.Renderer.FrameBuffer.SetBufferData(
DstKey,
DstWidth,
DstHeight,
- Format,
Buffer);
}
else
diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs
index 6f601244..1d0834dd 100644
--- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs
+++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs
@@ -102,7 +102,9 @@ namespace Ryujinx.HLE.Gpu.Engines
SetAlphaBlending(State);
SetPrimitiveRestart(State);
+ //Enabling multiple framebuffer attachments cause graphics reggresions
SetFrameBuffer(Vmm, 0);
+ SetZeta(Vmm);
long[] Keys = UploadShaders(Vmm);
@@ -149,9 +151,11 @@ namespace Ryujinx.HLE.Gpu.Engines
int Stencil = ReadRegister(NvGpuEngine3dReg.ClearStencil);
SetFrameBuffer(Vmm, FbIndex);
+ SetZeta(Vmm);
Gpu.Renderer.Rasterizer.ClearBuffers(
Flags,
+ FbIndex,
Red, Green, Blue, Alpha,
Depth,
Stencil);
@@ -161,6 +165,15 @@ namespace Ryujinx.HLE.Gpu.Engines
{
long VA = MakeInt64From2xInt32(NvGpuEngine3dReg.FrameBufferNAddress + FbIndex * 0x10);
+ int Format = ReadRegister(NvGpuEngine3dReg.FrameBufferNFormat + FbIndex * 0x10);
+
+ if (VA == 0 || Format == 0)
+ {
+ Gpu.Renderer.FrameBuffer.UnbindColor(FbIndex);
+
+ return;
+ }
+
long Key = Vmm.GetPhysicalAddress(VA);
FrameBuffers.Add(Key);
@@ -168,11 +181,11 @@ namespace Ryujinx.HLE.Gpu.Engines
int Width = ReadRegister(NvGpuEngine3dReg.FrameBufferNWidth + FbIndex * 0x10);
int Height = ReadRegister(NvGpuEngine3dReg.FrameBufferNHeight + FbIndex * 0x10);
- float TX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateX + FbIndex * 4);
- float TY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateY + FbIndex * 4);
+ float TX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateX + FbIndex * 8);
+ float TY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateY + FbIndex * 8);
- float SX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleX + FbIndex * 4);
- float SY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleY + FbIndex * 4);
+ float SX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleX + FbIndex * 8);
+ float SY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleY + FbIndex * 8);
int VpX = (int)MathF.Max(0, TX - MathF.Abs(SX));
int VpY = (int)MathF.Max(0, TY - MathF.Abs(SY));
@@ -180,12 +193,48 @@ namespace Ryujinx.HLE.Gpu.Engines
int VpW = (int)(TX + MathF.Abs(SX)) - VpX;
int VpH = (int)(TY + MathF.Abs(SY)) - VpY;
- Gpu.Renderer.FrameBuffer.Create(Key, Width, Height);
- Gpu.Renderer.FrameBuffer.Bind(Key);
+ 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.SetViewport(VpX, VpY, VpW, VpH);
}
+ 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);
+ }
+
private long[] UploadShaders(NvGpuVmm Vmm)
{
long[] Keys = new long[5];
@@ -442,15 +491,15 @@ namespace Ryujinx.HLE.Gpu.Engines
}
else
{
- GalTexture 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;
- if (Gpu.Renderer.Texture.TryGetCachedTexture(Key, Size, out GalTexture 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);
@@ -462,7 +511,7 @@ namespace Ryujinx.HLE.Gpu.Engines
{
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);
diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs
index 39a5ee8c..b03aef02 100644
--- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs
+++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs
@@ -22,7 +22,14 @@ namespace Ryujinx.HLE.Gpu.Engines
StencilBackFuncRef = 0x3d5,
StencilBackMask = 0x3d6,
StencilBackFuncMask = 0x3d7,
+ ZetaAddress = 0x3f8,
+ ZetaFormat = 0x3fa,
+ ZetaBlockDimensions = 0x3fb,
+ ZetaLayerStride = 0x3fc,
VertexAttribNFormat = 0x458,
+ ZetaHoriz = 0x48a,
+ ZetaVert = 0x48b,
+ ZetaArrayMode = 0x48c,
DepthTestEnable = 0x4b3,
IBlendEnable = 0x4b9,
DepthTestFunction = 0x4c3,
@@ -44,6 +51,7 @@ namespace Ryujinx.HLE.Gpu.Engines
StencilFrontFuncMask = 0x4e6,
StencilFrontMask = 0x4e7,
VertexArrayElemBase = 0x50d,
+ ZetaEnable = 0x54e,
TexHeaderPoolOffset = 0x55d,
TexSamplerPoolOffset = 0x557,
StencilTwoSideEnable = 0x565,
diff --git a/Ryujinx.HLE/Gpu/Texture/TextureFactory.cs b/Ryujinx.HLE/Gpu/Texture/TextureFactory.cs
index 4db0b6f1..0ef33d3b 100644
--- a/Ryujinx.HLE/Gpu/Texture/TextureFactory.cs
+++ b/Ryujinx.HLE/Gpu/Texture/TextureFactory.cs
@@ -6,11 +6,16 @@ namespace Ryujinx.HLE.Gpu.Texture
{
static class TextureFactory
{
- public static GalTexture MakeTexture(NvGpuVmm Vmm, long TicPosition)
+ public static GalImage MakeTexture(NvGpuVmm Vmm, long TicPosition)
{
int[] Tic = ReadWords(Vmm, TicPosition, 8);
- GalTextureFormat Format = (GalTextureFormat)(Tic[0] & 0x7f);
+ GalTextureType RType = (GalTextureType)((Tic[0] >> 7) & 7);
+ GalTextureType GType = (GalTextureType)((Tic[0] >> 10) & 7);
+ GalTextureType BType = (GalTextureType)((Tic[0] >> 13) & 7);
+ GalTextureType AType = (GalTextureType)((Tic[0] >> 16) & 7);
+
+ GalImageFormat Format = ImageFormatConverter.ConvertTexture((GalTextureFormat)(Tic[0] & 0x7f), RType, GType, BType, AType);
GalTextureSource XSource = (GalTextureSource)((Tic[0] >> 19) & 7);
GalTextureSource YSource = (GalTextureSource)((Tic[0] >> 22) & 7);
@@ -20,7 +25,7 @@ namespace Ryujinx.HLE.Gpu.Texture
int Width = (Tic[4] & 0xffff) + 1;
int Height = (Tic[5] & 0xffff) + 1;
- return new GalTexture(
+ return new GalImage(
Width,
Height,
Format,
diff --git a/Ryujinx.HLE/Gpu/Texture/TextureHelper.cs b/Ryujinx.HLE/Gpu/Texture/TextureHelper.cs
index 10a64f36..92b608a9 100644
--- a/Ryujinx.HLE/Gpu/Texture/TextureHelper.cs
+++ b/Ryujinx.HLE/Gpu/Texture/TextureHelper.cs
@@ -30,117 +30,151 @@ namespace Ryujinx.HLE.Gpu.Texture
throw new NotImplementedException(Texture.Swizzle.ToString());
}
- public static int GetTextureSize(GalTexture Texture)
+ public static int GetTextureSize(GalImage Image)
{
- switch (Texture.Format)
+ switch (Image.Format)
{
- case GalTextureFormat.R32G32B32A32:
- return Texture.Width * Texture.Height * 16;
-
- case GalTextureFormat.R16G16B16A16:
- return Texture.Width * Texture.Height * 8;
-
- case GalTextureFormat.A8B8G8R8:
- case GalTextureFormat.A2B10G10R10:
- case GalTextureFormat.R32:
- case GalTextureFormat.ZF32:
- case GalTextureFormat.BF10GF11RF11:
- case GalTextureFormat.Z24S8:
- return Texture.Width * Texture.Height * 4;
-
- case GalTextureFormat.A1B5G5R5:
- case GalTextureFormat.B5G6R5:
- case GalTextureFormat.G8R8:
- case GalTextureFormat.R16:
- return Texture.Width * Texture.Height * 2;
-
- case GalTextureFormat.R8:
- return Texture.Width * Texture.Height;
-
- case GalTextureFormat.BC1:
- case GalTextureFormat.BC4:
+ case GalImageFormat.R32G32B32A32_SFLOAT:
+ case GalImageFormat.R32G32B32A32_SINT:
+ case GalImageFormat.R32G32B32A32_UINT:
+ return Image.Width * Image.Height * 16;
+
+ case GalImageFormat.R16G16B16A16_SFLOAT:
+ case GalImageFormat.R16G16B16A16_SINT:
+ case GalImageFormat.R16G16B16A16_SNORM:
+ case GalImageFormat.R16G16B16A16_UINT:
+ case GalImageFormat.R16G16B16A16_UNORM:
+ return Image.Width * Image.Height * 8;
+
+ case GalImageFormat.A8B8G8R8_SINT_PACK32:
+ case GalImageFormat.A8B8G8R8_SNORM_PACK32:
+ case GalImageFormat.A8B8G8R8_UINT_PACK32:
+ case GalImageFormat.A8B8G8R8_UNORM_PACK32:
+ case GalImageFormat.A8B8G8R8_SRGB_PACK32:
+ case GalImageFormat.A2B10G10R10_SINT_PACK32:
+ case GalImageFormat.A2B10G10R10_SNORM_PACK32:
+ case GalImageFormat.A2B10G10R10_UINT_PACK32:
+ case GalImageFormat.A2B10G10R10_UNORM_PACK32:
+ case GalImageFormat.R16G16_SFLOAT:
+ case GalImageFormat.R16G16_SINT:
+ case GalImageFormat.R16G16_SNORM:
+ case GalImageFormat.R16G16_UINT:
+ case GalImageFormat.R16G16_UNORM:
+ case GalImageFormat.R32_SFLOAT:
+ case GalImageFormat.R32_SINT:
+ case GalImageFormat.R32_UINT:
+ case GalImageFormat.D32_SFLOAT:
+ case GalImageFormat.B10G11R11_UFLOAT_PACK32:
+ case GalImageFormat.D24_UNORM_S8_UINT:
+ return Image.Width * Image.Height * 4;
+
+ case GalImageFormat.B4G4R4A4_UNORM_PACK16:
+ case GalImageFormat.A1R5G5B5_UNORM_PACK16:
+ case GalImageFormat.B5G6R5_UNORM_PACK16:
+ case GalImageFormat.R8G8_SINT:
+ case GalImageFormat.R8G8_SNORM:
+ case GalImageFormat.R8G8_UINT:
+ case GalImageFormat.R8G8_UNORM:
+ case GalImageFormat.R16_SFLOAT:
+ case GalImageFormat.R16_SINT:
+ case GalImageFormat.R16_SNORM:
+ case GalImageFormat.R16_UINT:
+ case GalImageFormat.R16_UNORM:
+ case GalImageFormat.D16_UNORM:
+ return Image.Width * Image.Height * 2;
+
+ case GalImageFormat.R8_SINT:
+ case GalImageFormat.R8_SNORM:
+ case GalImageFormat.R8_UINT:
+ case GalImageFormat.R8_UNORM:
+ return Image.Width * Image.Height;
+
+ case GalImageFormat.BC1_RGBA_UNORM_BLOCK:
+ case GalImageFormat.BC4_SNORM_BLOCK:
+ case GalImageFormat.BC4_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 4, 4, 8);
+ return CompressedTextureSize(Image.Width, Image.Height, 4, 4, 8);
}
- case GalTextureFormat.BC6H_SF16:
- case GalTextureFormat.BC6H_UF16:
- case GalTextureFormat.BC7U:
- case GalTextureFormat.BC2:
- case GalTextureFormat.BC3:
- case GalTextureFormat.BC5:
- case GalTextureFormat.Astc2D4x4:
+ case GalImageFormat.BC6H_SFLOAT_BLOCK:
+ case GalImageFormat.BC6H_UFLOAT_BLOCK:
+ case GalImageFormat.BC7_UNORM_BLOCK:
+ case GalImageFormat.BC2_UNORM_BLOCK:
+ case GalImageFormat.BC3_UNORM_BLOCK:
+ case GalImageFormat.BC5_SNORM_BLOCK:
+ case GalImageFormat.BC5_UNORM_BLOCK:
+ case GalImageFormat.ASTC_4x4_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 4, 4, 16);
+ return CompressedTextureSize(Image.Width, Image.Height, 4, 4, 16);
}
- case GalTextureFormat.Astc2D5x5:
+ case GalImageFormat.ASTC_5x5_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 5, 5, 16);
+ return CompressedTextureSize(Image.Width, Image.Height, 5, 5, 16);
}
- case GalTextureFormat.Astc2D6x6:
+ case GalImageFormat.ASTC_6x6_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 6, 6, 16);
+ return CompressedTextureSize(Image.Width, Image.Height, 6, 6, 16);
}
- case GalTextureFormat.Astc2D8x8:
+ case GalImageFormat.ASTC_8x8_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 8, 8, 16);
+ return CompressedTextureSize(Image.Width, Image.Height, 8, 8, 16);
}
- case GalTextureFormat.Astc2D10x10:
+ case GalImageFormat.ASTC_10x10_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 10, 10, 16);
+ return CompressedTextureSize(Image.Width, Image.Height, 10, 10, 16);
}
- case GalTextureFormat.Astc2D12x12:
+ case GalImageFormat.ASTC_12x12_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 12, 12, 16);
+ return CompressedTextureSize(Image.Width, Image.Height, 12, 12, 16);
}
- case GalTextureFormat.Astc2D5x4:
+ case GalImageFormat.ASTC_5x4_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 5, 4, 16);
+ return CompressedTextureSize(Image.Width, Image.Height, 5, 4, 16);
}
- case GalTextureFormat.Astc2D6x5:
+ case GalImageFormat.ASTC_6x5_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 6, 5, 16);
+ return CompressedTextureSize(Image.Width, Image.Height, 6, 5, 16);
}
- case GalTextureFormat.Astc2D8x6:
+ case GalImageFormat.ASTC_8x6_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 8, 6, 16);
+ return CompressedTextureSize(Image.Width, Image.Height, 8, 6, 16);
}
- case GalTextureFormat.Astc2D10x8:
+ case GalImageFormat.ASTC_10x8_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 10, 8, 16);
+ return CompressedTextureSize(Image.Width, Image.Height, 10, 8, 16);
}
- case GalTextureFormat.Astc2D12x10:
+ case GalImageFormat.ASTC_12x10_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 12, 10, 16);
+ return CompressedTextureSize(Image.Width, Image.Height, 12, 10, 16);
}
- case GalTextureFormat.Astc2D8x5:
+ case GalImageFormat.ASTC_8x5_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 8, 5, 16);
+ return CompressedTextureSize(Image.Width, Image.Height, 8, 5, 16);
}
- case GalTextureFormat.Astc2D10x5:
+ case GalImageFormat.ASTC_10x5_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 10, 5, 16);
+ return CompressedTextureSize(Image.Width, Image.Height, 10, 5, 16);
}
- case GalTextureFormat.Astc2D10x6:
+ case GalImageFormat.ASTC_10x6_UNORM_BLOCK:
{
- return CompressedTextureSize(Texture.Width, Texture.Height, 10, 6, 16);
+ return CompressedTextureSize(Image.Width, Image.Height, 10, 6, 16);
}
}
- throw new NotImplementedException("0x" + Texture.Format.ToString("x2"));
+ throw new NotImplementedException("0x" + Image.Format.ToString("x2"));
}
public static int CompressedTextureSize(int TextureWidth, int TextureHeight, int BlockWidth, int BlockHeight, int Bpb)
diff --git a/Ryujinx.HLE/Gpu/Texture/TextureReader.cs b/Ryujinx.HLE/Gpu/Texture/TextureReader.cs
index 0cf055db..19aa25d7 100644
--- a/Ryujinx.HLE/Gpu/Texture/TextureReader.cs
+++ b/Ryujinx.HLE/Gpu/Texture/TextureReader.cs
@@ -19,6 +19,7 @@ namespace Ryujinx.HLE.Gpu.Texture
case GalTextureFormat.Z24S8: return Read4Bpp (Memory, Texture);
case GalTextureFormat.A1B5G5R5: return Read5551 (Memory, Texture);
case GalTextureFormat.B5G6R5: return Read565 (Memory, Texture);
+ case GalTextureFormat.A4B4G4R4: return Read2Bpp (Memory, Texture);
case GalTextureFormat.G8R8: return Read2Bpp (Memory, Texture);
case GalTextureFormat.R16: return Read2Bpp (Memory, Texture);
case GalTextureFormat.R8: return Read1Bpp (Memory, Texture);