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
This commit is contained in:
parent
056c2840b1
commit
726de8c46a
25 changed files with 1360 additions and 441 deletions
68
Ryujinx.Graphics/Gal/GalFrameBufferFormat.cs
Normal file
68
Ryujinx.Graphics/Gal/GalFrameBufferFormat.cs
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,25 +1,25 @@
|
||||||
namespace Ryujinx.Graphics.Gal
|
namespace Ryujinx.Graphics.Gal
|
||||||
{
|
{
|
||||||
public struct GalTexture
|
public struct GalImage
|
||||||
{
|
{
|
||||||
public int Width;
|
public int Width;
|
||||||
public int Height;
|
public int Height;
|
||||||
|
|
||||||
public GalTextureFormat Format;
|
public GalImageFormat Format;
|
||||||
|
|
||||||
public GalTextureSource XSource;
|
public GalTextureSource XSource;
|
||||||
public GalTextureSource YSource;
|
public GalTextureSource YSource;
|
||||||
public GalTextureSource ZSource;
|
public GalTextureSource ZSource;
|
||||||
public GalTextureSource WSource;
|
public GalTextureSource WSource;
|
||||||
|
|
||||||
public GalTexture(
|
public GalImage(
|
||||||
int Width,
|
int Width,
|
||||||
int Height,
|
int Height,
|
||||||
GalTextureFormat Format,
|
GalImageFormat Format,
|
||||||
GalTextureSource XSource,
|
GalTextureSource XSource = GalTextureSource.Red,
|
||||||
GalTextureSource YSource,
|
GalTextureSource YSource = GalTextureSource.Green,
|
||||||
GalTextureSource ZSource,
|
GalTextureSource ZSource = GalTextureSource.Blue,
|
||||||
GalTextureSource WSource)
|
GalTextureSource WSource = GalTextureSource.Alpha)
|
||||||
{
|
{
|
||||||
this.Width = Width;
|
this.Width = Width;
|
||||||
this.Height = Height;
|
this.Height = Height;
|
204
Ryujinx.Graphics/Gal/GalImageFormat.cs
Normal file
204
Ryujinx.Graphics/Gal/GalImageFormat.cs
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,6 +9,7 @@ namespace Ryujinx.Graphics.Gal
|
||||||
R32 = 0xf,
|
R32 = 0xf,
|
||||||
BC6H_SF16 = 0x10,
|
BC6H_SF16 = 0x10,
|
||||||
BC6H_UF16 = 0x11,
|
BC6H_UF16 = 0x11,
|
||||||
|
A4B4G4R4 = 0x12,
|
||||||
A1B5G5R5 = 0x14,
|
A1B5G5R5 = 0x14,
|
||||||
B5G6R5 = 0x15,
|
B5G6R5 = 0x15,
|
||||||
BC7U = 0x17,
|
BC7U = 0x17,
|
||||||
|
|
13
Ryujinx.Graphics/Gal/GalTextureType.cs
Normal file
13
Ryujinx.Graphics/Gal/GalTextureType.cs
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
16
Ryujinx.Graphics/Gal/GalZetaFormat.cs
Normal file
16
Ryujinx.Graphics/Gal/GalZetaFormat.cs
Normal file
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,9 +4,13 @@ namespace Ryujinx.Graphics.Gal
|
||||||
{
|
{
|
||||||
public interface IGalFrameBuffer
|
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);
|
void BindTexture(long Key, int Index);
|
||||||
|
|
||||||
|
@ -40,7 +44,6 @@ namespace Ryujinx.Graphics.Gal
|
||||||
long Key,
|
long Key,
|
||||||
int Width,
|
int Width,
|
||||||
int Height,
|
int Height,
|
||||||
GalTextureFormat Format,
|
|
||||||
byte[] Buffer);
|
byte[] Buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -9,6 +9,7 @@ namespace Ryujinx.Graphics.Gal
|
||||||
|
|
||||||
void ClearBuffers(
|
void ClearBuffers(
|
||||||
GalClearBufferFlags Flags,
|
GalClearBufferFlags Flags,
|
||||||
|
int Attachment,
|
||||||
float Red, float Green, float Blue, float Alpha,
|
float Red, float Green, float Blue, float Alpha,
|
||||||
float Depth,
|
float Depth,
|
||||||
int Stencil);
|
int Stencil);
|
||||||
|
|
|
@ -5,9 +5,11 @@ namespace Ryujinx.Graphics.Gal
|
||||||
void LockCache();
|
void LockCache();
|
||||||
void UnlockCache();
|
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);
|
void Bind(long Key, int Index);
|
||||||
|
|
||||||
|
|
263
Ryujinx.Graphics/Gal/ImageFormatConverter.cs
Normal file
263
Ryujinx.Graphics/Gal/ImageFormatConverter.cs
Normal file
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
124
Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs
Normal file
124
Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs
Normal file
|
@ -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); }
|
||||||
|
}
|
||||||
|
}
|
|
@ -36,13 +36,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
public void SetData(long Key, long Size, IntPtr HostAddress)
|
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)
|
public bool TryGetUbo(long Key, out int UboHandle)
|
||||||
{
|
{
|
||||||
|
|
|
@ -125,40 +125,71 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
throw new ArgumentException(nameof(Type));
|
throw new ArgumentException(nameof(Type));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static (PixelFormat, PixelType) GetTextureFormat(GalTextureFormat Format)
|
public static (PixelInternalFormat, PixelFormat, PixelType) GetImageFormat(GalImageFormat Format)
|
||||||
{
|
{
|
||||||
switch (Format)
|
switch (Format)
|
||||||
{
|
{
|
||||||
case GalTextureFormat.R32G32B32A32: return (PixelFormat.Rgba, PixelType.Float);
|
case GalImageFormat.R32G32B32A32_SFLOAT: return (PixelInternalFormat.Rgba32f, PixelFormat.Rgba, PixelType.Float);
|
||||||
case GalTextureFormat.R16G16B16A16: return (PixelFormat.Rgba, PixelType.HalfFloat);
|
case GalImageFormat.R32G32B32A32_SINT: return (PixelInternalFormat.Rgba32i, PixelFormat.RgbaInteger, PixelType.Int);
|
||||||
case GalTextureFormat.A8B8G8R8: return (PixelFormat.Rgba, PixelType.UnsignedByte);
|
case GalImageFormat.R32G32B32A32_UINT: return (PixelInternalFormat.Rgba32ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt);
|
||||||
case GalTextureFormat.A2B10G10R10: return (PixelFormat.Rgba, PixelType.UnsignedInt2101010Reversed);
|
case GalImageFormat.R16G16B16A16_SFLOAT: return (PixelInternalFormat.Rgba16f, PixelFormat.Rgba, PixelType.HalfFloat);
|
||||||
case GalTextureFormat.R32: return (PixelFormat.Red, PixelType.Float);
|
case GalImageFormat.R16G16B16A16_SINT: return (PixelInternalFormat.Rgba16i, PixelFormat.RgbaInteger, PixelType.Short);
|
||||||
case GalTextureFormat.A1B5G5R5: return (PixelFormat.Rgba, PixelType.UnsignedShort5551);
|
case GalImageFormat.R16G16B16A16_UINT: return (PixelInternalFormat.Rgba16ui, PixelFormat.RgbaInteger, PixelType.UnsignedShort);
|
||||||
case GalTextureFormat.B5G6R5: return (PixelFormat.Rgb, PixelType.UnsignedShort565);
|
case GalImageFormat.A8B8G8R8_SNORM_PACK32: return (PixelInternalFormat.Rgba8Snorm, PixelFormat.Rgba, PixelType.Byte);
|
||||||
case GalTextureFormat.G8R8: return (PixelFormat.Rg, PixelType.UnsignedByte);
|
case GalImageFormat.A8B8G8R8_UNORM_PACK32: return (PixelInternalFormat.Rgba8, PixelFormat.Rgba, PixelType.UnsignedByte);
|
||||||
case GalTextureFormat.R16: return (PixelFormat.Red, PixelType.HalfFloat);
|
case GalImageFormat.A8B8G8R8_SINT_PACK32: return (PixelInternalFormat.Rgba8i, PixelFormat.RgbaInteger, PixelType.Byte);
|
||||||
case GalTextureFormat.R8: return (PixelFormat.Red, PixelType.UnsignedByte);
|
case GalImageFormat.A8B8G8R8_UINT_PACK32: return (PixelInternalFormat.Rgba8ui, PixelFormat.RgbaInteger, PixelType.UnsignedByte);
|
||||||
case GalTextureFormat.ZF32: return (PixelFormat.DepthComponent, PixelType.Float);
|
case GalImageFormat.A8B8G8R8_SRGB_PACK32: return (PixelInternalFormat.Srgb8Alpha8, PixelFormat.Rgba, PixelType.UnsignedByte);
|
||||||
case GalTextureFormat.BF10GF11RF11: return (PixelFormat.Rgb, PixelType.UnsignedInt10F11F11FRev);
|
case GalImageFormat.A2B10G10R10_UINT_PACK32: return (PixelInternalFormat.Rgb10A2ui, PixelFormat.RgbaInteger, PixelType.UnsignedInt2101010Reversed);
|
||||||
case GalTextureFormat.Z24S8: return (PixelFormat.DepthStencil, PixelType.UnsignedInt248);
|
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());
|
throw new NotImplementedException(Format.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static InternalFormat GetCompressedTextureFormat(GalTextureFormat Format)
|
public static InternalFormat GetCompressedImageFormat(GalImageFormat Format)
|
||||||
{
|
{
|
||||||
switch (Format)
|
switch (Format)
|
||||||
{
|
{
|
||||||
case GalTextureFormat.BC6H_UF16: return InternalFormat.CompressedRgbBptcUnsignedFloat;
|
case GalImageFormat.BC6H_UFLOAT_BLOCK: return InternalFormat.CompressedRgbBptcUnsignedFloat;
|
||||||
case GalTextureFormat.BC6H_SF16: return InternalFormat.CompressedRgbBptcSignedFloat;
|
case GalImageFormat.BC6H_SFLOAT_BLOCK: return InternalFormat.CompressedRgbBptcSignedFloat;
|
||||||
case GalTextureFormat.BC7U: return InternalFormat.CompressedRgbaBptcUnorm;
|
case GalImageFormat.BC7_UNORM_BLOCK: return InternalFormat.CompressedRgbaBptcUnorm;
|
||||||
case GalTextureFormat.BC1: return InternalFormat.CompressedRgbaS3tcDxt1Ext;
|
case GalImageFormat.BC1_RGBA_UNORM_BLOCK: return InternalFormat.CompressedRgbaS3tcDxt1Ext;
|
||||||
case GalTextureFormat.BC2: return InternalFormat.CompressedRgbaS3tcDxt3Ext;
|
case GalImageFormat.BC2_UNORM_BLOCK: return InternalFormat.CompressedRgbaS3tcDxt3Ext;
|
||||||
case GalTextureFormat.BC3: return InternalFormat.CompressedRgbaS3tcDxt5Ext;
|
case GalImageFormat.BC3_UNORM_BLOCK: return InternalFormat.CompressedRgbaS3tcDxt5Ext;
|
||||||
case GalTextureFormat.BC4: return InternalFormat.CompressedRedRgtc1;
|
case GalImageFormat.BC4_SNORM_BLOCK: return InternalFormat.CompressedSignedRedRgtc1;
|
||||||
case GalTextureFormat.BC5: return InternalFormat.CompressedRgRgtc2;
|
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());
|
throw new NotImplementedException(Format.ToString());
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
using OpenTK.Graphics.OpenGL;
|
using OpenTK.Graphics.OpenGL;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
public class OGLFrameBuffer : IGalFrameBuffer
|
class OGLFrameBuffer : IGalFrameBuffer
|
||||||
{
|
{
|
||||||
private struct Rect
|
private struct Rect
|
||||||
{
|
{
|
||||||
|
@ -22,43 +21,31 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private class FrameBuffer
|
private static readonly DrawBuffersEnum[] DrawBuffers = new DrawBuffersEnum[]
|
||||||
{
|
{
|
||||||
public int Width { get; set; }
|
DrawBuffersEnum.ColorAttachment0,
|
||||||
public int Height { get; set; }
|
DrawBuffersEnum.ColorAttachment1,
|
||||||
|
DrawBuffersEnum.ColorAttachment2,
|
||||||
public int Handle { get; private set; }
|
DrawBuffersEnum.ColorAttachment3,
|
||||||
public int RbHandle { get; private set; }
|
DrawBuffersEnum.ColorAttachment4,
|
||||||
public int TexHandle { get; private set; }
|
DrawBuffersEnum.ColorAttachment5,
|
||||||
|
DrawBuffersEnum.ColorAttachment6,
|
||||||
public FrameBuffer(int Width, int Height, bool HasRenderBuffer)
|
DrawBuffersEnum.ColorAttachment7,
|
||||||
{
|
};
|
||||||
this.Width = Width;
|
|
||||||
this.Height = Height;
|
|
||||||
|
|
||||||
Handle = GL.GenFramebuffer();
|
|
||||||
TexHandle = GL.GenTexture();
|
|
||||||
|
|
||||||
if (HasRenderBuffer)
|
|
||||||
{
|
|
||||||
RbHandle = GL.GenRenderbuffer();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private const int NativeWidth = 1280;
|
private const int NativeWidth = 1280;
|
||||||
private const int NativeHeight = 720;
|
private const int NativeHeight = 720;
|
||||||
|
|
||||||
private Dictionary<long, FrameBuffer> Fbs;
|
private const GalImageFormat RawFormat = GalImageFormat.A8B8G8R8_UNORM_PACK32;
|
||||||
|
|
||||||
|
private OGLTexture Texture;
|
||||||
|
|
||||||
|
private ImageHandler RawTex;
|
||||||
|
private ImageHandler ReadTex;
|
||||||
|
|
||||||
private Rect Viewport;
|
private Rect Viewport;
|
||||||
private Rect Window;
|
private Rect Window;
|
||||||
|
|
||||||
private FrameBuffer CurrFb;
|
|
||||||
private FrameBuffer CurrReadFb;
|
|
||||||
|
|
||||||
private FrameBuffer RawFb;
|
|
||||||
|
|
||||||
private bool FlipX;
|
private bool FlipX;
|
||||||
private bool FlipY;
|
private bool FlipY;
|
||||||
|
|
||||||
|
@ -67,111 +54,144 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
private int CropRight;
|
private int CropRight;
|
||||||
private int CropBottom;
|
private int CropBottom;
|
||||||
|
|
||||||
public OGLFrameBuffer()
|
//This framebuffer is used to attach guest rendertargets,
|
||||||
|
//think of it as a dummy OpenGL VAO
|
||||||
|
private int DummyFrameBuffer;
|
||||||
|
|
||||||
|
//These framebuffers are used to blit images
|
||||||
|
private int SrcFb;
|
||||||
|
private int DstFb;
|
||||||
|
|
||||||
|
//Holds current attachments, used to avoid unnecesary calls to OpenGL
|
||||||
|
private int[] ColorAttachments;
|
||||||
|
|
||||||
|
private int DepthAttachment;
|
||||||
|
private int StencilAttachment;
|
||||||
|
|
||||||
|
public OGLFrameBuffer(OGLTexture Texture)
|
||||||
{
|
{
|
||||||
Fbs = new Dictionary<long, FrameBuffer>();
|
ColorAttachments = new int[8];
|
||||||
|
|
||||||
|
this.Texture = Texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Create(long Key, int Width, int Height)
|
public void BindColor(long Key, int Attachment)
|
||||||
{
|
{
|
||||||
if (Fbs.TryGetValue(Key, out FrameBuffer Fb))
|
if (Texture.TryGetImage(Key, out ImageHandler Tex))
|
||||||
{
|
{
|
||||||
if (Fb.Width != Width ||
|
EnsureFrameBuffer();
|
||||||
Fb.Height != Height)
|
|
||||||
{
|
|
||||||
SetupTexture(Fb.TexHandle, Width, Height);
|
|
||||||
|
|
||||||
Fb.Width = Width;
|
Attach(ref ColorAttachments[Attachment], Tex.Handle, FramebufferAttachment.ColorAttachment0 + Attachment);
|
||||||
Fb.Height = Height;
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UnbindColor(Attachment);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return;
|
public void UnbindColor(int Attachment)
|
||||||
|
{
|
||||||
|
EnsureFrameBuffer();
|
||||||
|
|
||||||
|
Attach(ref ColorAttachments[Attachment], 0, FramebufferAttachment.ColorAttachment0 + Attachment);
|
||||||
}
|
}
|
||||||
|
|
||||||
Fb = new FrameBuffer(Width, Height, true);
|
public void BindZeta(long Key)
|
||||||
|
{
|
||||||
SetupTexture(Fb.TexHandle, Width, Height);
|
if (Texture.TryGetImage(Key, out ImageHandler Tex))
|
||||||
|
{
|
||||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fb.Handle);
|
EnsureFrameBuffer();
|
||||||
|
|
||||||
GL.BindRenderbuffer(RenderbufferTarget.Renderbuffer, Fb.RbHandle);
|
|
||||||
|
|
||||||
GL.RenderbufferStorage(
|
|
||||||
RenderbufferTarget.Renderbuffer,
|
|
||||||
RenderbufferStorage.Depth24Stencil8,
|
|
||||||
Width,
|
|
||||||
Height);
|
|
||||||
|
|
||||||
GL.FramebufferRenderbuffer(
|
|
||||||
FramebufferTarget.Framebuffer,
|
|
||||||
FramebufferAttachment.DepthStencilAttachment,
|
|
||||||
RenderbufferTarget.Renderbuffer,
|
|
||||||
Fb.RbHandle);
|
|
||||||
|
|
||||||
|
if (Tex.HasDepth && Tex.HasStencil)
|
||||||
|
{
|
||||||
|
if (DepthAttachment != Tex.Handle ||
|
||||||
|
StencilAttachment != Tex.Handle)
|
||||||
|
{
|
||||||
GL.FramebufferTexture(
|
GL.FramebufferTexture(
|
||||||
FramebufferTarget.Framebuffer,
|
FramebufferTarget.DrawFramebuffer,
|
||||||
FramebufferAttachment.ColorAttachment0,
|
FramebufferAttachment.DepthStencilAttachment,
|
||||||
Fb.TexHandle,
|
Tex.Handle,
|
||||||
0);
|
0);
|
||||||
|
|
||||||
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
|
DepthAttachment = Tex.Handle;
|
||||||
|
|
||||||
Fbs.Add(Key, Fb);
|
StencilAttachment = Tex.Handle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (Tex.HasDepth)
|
||||||
|
{
|
||||||
|
Attach(ref DepthAttachment, Tex.Handle, FramebufferAttachment.DepthAttachment);
|
||||||
|
|
||||||
|
Attach(ref StencilAttachment, 0, FramebufferAttachment.StencilAttachment);
|
||||||
|
}
|
||||||
|
else if (Tex.HasStencil)
|
||||||
|
{
|
||||||
|
Attach(ref DepthAttachment, 0, FramebufferAttachment.DepthAttachment);
|
||||||
|
|
||||||
|
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();
|
||||||
{
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, Fb.Handle);
|
|
||||||
|
|
||||||
CurrFb = Fb;
|
if (DepthAttachment != 0 ||
|
||||||
|
StencilAttachment != 0)
|
||||||
|
{
|
||||||
|
GL.FramebufferTexture(
|
||||||
|
FramebufferTarget.DrawFramebuffer,
|
||||||
|
FramebufferAttachment.DepthStencilAttachment,
|
||||||
|
0,
|
||||||
|
0);
|
||||||
|
|
||||||
|
DepthAttachment = 0;
|
||||||
|
|
||||||
|
StencilAttachment = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void BindTexture(long Key, int Index)
|
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.ActiveTexture(TextureUnit.Texture0 + Index);
|
||||||
|
|
||||||
GL.BindTexture(TextureTarget.Texture2D, Fb.TexHandle);
|
GL.BindTexture(TextureTarget.Texture2D, Tex.Handle);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Set(long Key)
|
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)
|
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 ||
|
RawTex.EnsureSetup(new GalImage(Width, Height, RawFormat));
|
||||||
RawFb.Height != Height)
|
|
||||||
{
|
|
||||||
SetupTexture(RawFb.TexHandle, Width, Height);
|
|
||||||
|
|
||||||
RawFb.Width = Width;
|
GL.BindTexture(TextureTarget.Texture2D, RawTex.Handle);
|
||||||
RawFb.Height = Height;
|
|
||||||
}
|
|
||||||
|
|
||||||
GL.ActiveTexture(TextureUnit.Texture0);
|
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, Width, Height, RawTex.PixelFormat, RawTex.PixelType, Data);
|
||||||
|
|
||||||
GL.BindTexture(TextureTarget.Texture2D, RawFb.TexHandle);
|
ReadTex = RawTex;
|
||||||
|
|
||||||
(PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(GalTextureFormat.A8B8G8R8);
|
|
||||||
|
|
||||||
GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, Width, Height, Format, Type, Data);
|
|
||||||
|
|
||||||
CurrReadFb = RawFb;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SetTransform(bool FlipX, bool FlipY, int Top, int Left, int Right, int Bottom)
|
public void SetTransform(bool FlipX, bool FlipY, int Top, int Left, int Right, int Bottom)
|
||||||
|
@ -208,14 +228,17 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
public void Render()
|
public void Render()
|
||||||
{
|
{
|
||||||
if (CurrReadFb != null)
|
if (ReadTex == null)
|
||||||
{
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
int SrcX0, SrcX1, SrcY0, SrcY1;
|
int SrcX0, SrcX1, SrcY0, SrcY1;
|
||||||
|
|
||||||
if (CropLeft == 0 && CropRight == 0)
|
if (CropLeft == 0 && CropRight == 0)
|
||||||
{
|
{
|
||||||
SrcX0 = 0;
|
SrcX0 = 0;
|
||||||
SrcX1 = CurrReadFb.Width;
|
SrcX1 = ReadTex.Width;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -226,7 +249,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
if (CropTop == 0 && CropBottom == 0)
|
if (CropTop == 0 && CropBottom == 0)
|
||||||
{
|
{
|
||||||
SrcY0 = 0;
|
SrcY0 = 0;
|
||||||
SrcY1 = CurrReadFb.Height;
|
SrcY1 = ReadTex.Height;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -249,19 +272,27 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
int DstY0 = FlipY ? DstPaddingY : Window.Height - DstPaddingY;
|
int DstY0 = FlipY ? DstPaddingY : Window.Height - DstPaddingY;
|
||||||
int DstY1 = FlipY ? Window.Height - DstPaddingY : DstPaddingY;
|
int DstY1 = FlipY ? Window.Height - DstPaddingY : DstPaddingY;
|
||||||
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, 0);
|
if (SrcFb == 0) SrcFb = GL.GenFramebuffer();
|
||||||
|
|
||||||
|
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0);
|
||||||
|
|
||||||
GL.Viewport(0, 0, Window.Width, Window.Height);
|
GL.Viewport(0, 0, Window.Width, Window.Height);
|
||||||
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, CurrReadFb.Handle);
|
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb);
|
||||||
|
|
||||||
GL.Clear(ClearBufferMask.ColorBufferBit | ClearBufferMask.DepthBufferBit);
|
GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.ColorAttachment0, ReadTex.Handle, 0);
|
||||||
|
|
||||||
|
GL.ReadBuffer(ReadBufferMode.ColorAttachment0);
|
||||||
|
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
|
||||||
|
|
||||||
|
GL.Clear(ClearBufferMask.ColorBufferBit);
|
||||||
|
|
||||||
GL.BlitFramebuffer(
|
GL.BlitFramebuffer(
|
||||||
SrcX0, SrcY0, SrcX1, SrcY1,
|
SrcX0, SrcY0, SrcX1, SrcY1,
|
||||||
DstX0, DstY0, DstX1, DstY1,
|
DstX0, DstY0, DstX1, DstY1,
|
||||||
ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Linear);
|
ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Linear);
|
||||||
}
|
|
||||||
|
EnsureFrameBuffer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Copy(
|
public void Copy(
|
||||||
|
@ -276,39 +307,80 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
int DstX1,
|
int DstX1,
|
||||||
int DstY1)
|
int DstY1)
|
||||||
{
|
{
|
||||||
if (Fbs.TryGetValue(SrcKey, out FrameBuffer SrcFb) &&
|
if (Texture.TryGetImage(SrcKey, out ImageHandler SrcTex) &&
|
||||||
Fbs.TryGetValue(DstKey, out FrameBuffer DstFb))
|
Texture.TryGetImage(DstKey, out ImageHandler DstTex))
|
||||||
{
|
{
|
||||||
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb.Handle);
|
if (SrcTex.HasColor != DstTex.HasColor ||
|
||||||
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DstFb.Handle);
|
SrcTex.HasDepth != DstTex.HasDepth ||
|
||||||
|
SrcTex.HasStencil != DstTex.HasStencil)
|
||||||
|
{
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
|
|
||||||
GL.Clear(ClearBufferMask.ColorBufferBit);
|
if (SrcTex.HasColor)
|
||||||
|
{
|
||||||
GL.BlitFramebuffer(
|
CopyTextures(
|
||||||
SrcX0, SrcY0, SrcX1, SrcY1,
|
SrcX0, SrcY0, SrcX1, SrcY1,
|
||||||
DstX0, DstY0, DstX1, DstY1,
|
DstX0, DstY0, DstX1, DstY1,
|
||||||
|
SrcTex.Handle,
|
||||||
|
DstTex.Handle,
|
||||||
|
FramebufferAttachment.ColorAttachment0,
|
||||||
ClearBufferMask.ColorBufferBit,
|
ClearBufferMask.ColorBufferBit,
|
||||||
BlitFramebufferFilter.Linear);
|
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)
|
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.GetTexImage(
|
||||||
|
TextureTarget.Texture2D,
|
||||||
GL.ReadPixels(
|
|
||||||
0,
|
0,
|
||||||
0,
|
Tex.PixelFormat,
|
||||||
Fb.Width,
|
Tex.PixelType,
|
||||||
Fb.Height,
|
|
||||||
Format,
|
|
||||||
Type,
|
|
||||||
Data);
|
Data);
|
||||||
|
|
||||||
Callback(Data);
|
Callback(Data);
|
||||||
|
@ -319,83 +391,101 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
long Key,
|
long Key,
|
||||||
int Width,
|
int Width,
|
||||||
int Height,
|
int Height,
|
||||||
GalTextureFormat Format,
|
|
||||||
byte[] Buffer)
|
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 Level = 0;
|
||||||
const int Border = 0;
|
const int Border = 0;
|
||||||
|
|
||||||
const PixelInternalFormat InternalFmt = PixelInternalFormat.Rgba;
|
|
||||||
|
|
||||||
(PixelFormat GlFormat, PixelType Type) = OGLEnumConverter.GetTextureFormat(Format);
|
|
||||||
|
|
||||||
GL.TexImage2D(
|
GL.TexImage2D(
|
||||||
TextureTarget.Texture2D,
|
TextureTarget.Texture2D,
|
||||||
Level,
|
Level,
|
||||||
InternalFmt,
|
Tex.InternalFormat,
|
||||||
Width,
|
Width,
|
||||||
Height,
|
Height,
|
||||||
Border,
|
Border,
|
||||||
GlFormat,
|
Tex.PixelFormat,
|
||||||
Type,
|
Tex.PixelType,
|
||||||
Buffer);
|
Buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void CreateRawFb(int Width, int Height)
|
private void EnsureFrameBuffer()
|
||||||
{
|
{
|
||||||
if (RawFb == null)
|
if (DummyFrameBuffer == 0)
|
||||||
{
|
{
|
||||||
RawFb = new FrameBuffer(Width, Height, false);
|
DummyFrameBuffer = GL.GenFramebuffer();
|
||||||
|
}
|
||||||
|
|
||||||
SetupTexture(RawFb.TexHandle, Width, Height);
|
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DummyFrameBuffer);
|
||||||
|
|
||||||
RawFb.Width = Width;
|
GL.DrawBuffers(8, DrawBuffers);
|
||||||
RawFb.Height = Height;
|
}
|
||||||
|
|
||||||
GL.BindFramebuffer(FramebufferTarget.Framebuffer, RawFb.Handle);
|
|
||||||
|
|
||||||
|
private void Attach(ref int OldHandle, int NewHandle, FramebufferAttachment FbAttachment)
|
||||||
|
{
|
||||||
|
if (OldHandle != NewHandle)
|
||||||
|
{
|
||||||
GL.FramebufferTexture(
|
GL.FramebufferTexture(
|
||||||
FramebufferTarget.Framebuffer,
|
FramebufferTarget.DrawFramebuffer,
|
||||||
FramebufferAttachment.ColorAttachment0,
|
FbAttachment,
|
||||||
RawFb.TexHandle,
|
NewHandle,
|
||||||
0);
|
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;
|
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb);
|
||||||
const int MagFilter = (int)TextureMagFilter.Linear;
|
GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DstFb);
|
||||||
|
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMinFilter, MinFilter);
|
GL.FramebufferTexture(
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureMagFilter, MagFilter);
|
FramebufferTarget.ReadFramebuffer,
|
||||||
|
Attachment,
|
||||||
|
SrcTexture,
|
||||||
|
0);
|
||||||
|
|
||||||
(PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(GalTextureFormat.A8B8G8R8);
|
GL.FramebufferTexture(
|
||||||
|
FramebufferTarget.DrawFramebuffer,
|
||||||
|
Attachment,
|
||||||
|
DstTexture,
|
||||||
|
0);
|
||||||
|
|
||||||
const PixelInternalFormat InternalFmt = PixelInternalFormat.Rgba;
|
if (Color)
|
||||||
|
{
|
||||||
|
GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
|
||||||
|
}
|
||||||
|
|
||||||
const int Level = 0;
|
GL.Clear(Mask);
|
||||||
const int Border = 0;
|
|
||||||
|
|
||||||
GL.TexImage2D(
|
GL.BlitFramebuffer(
|
||||||
TextureTarget.Texture2D,
|
SrcX0, SrcY0, SrcX1, SrcY1,
|
||||||
Level,
|
DstX0, DstY0, DstX1, DstY1,
|
||||||
InternalFmt,
|
Mask,
|
||||||
Width,
|
Color ? BlitFramebufferFilter.Linear : BlitFramebufferFilter.Nearest);
|
||||||
Height,
|
|
||||||
Border,
|
EnsureFrameBuffer();
|
||||||
Format,
|
|
||||||
Type,
|
|
||||||
IntPtr.Zero);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -3,7 +3,7 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
public class OGLRasterizer : IGalRasterizer
|
class OGLRasterizer : IGalRasterizer
|
||||||
{
|
{
|
||||||
private int[] VertexBuffers;
|
private int[] VertexBuffers;
|
||||||
|
|
||||||
|
@ -44,36 +44,29 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
public void ClearBuffers(
|
public void ClearBuffers(
|
||||||
GalClearBufferFlags Flags,
|
GalClearBufferFlags Flags,
|
||||||
|
int Attachment,
|
||||||
float Red, float Green, float Blue, float Alpha,
|
float Red, float Green, float Blue, float Alpha,
|
||||||
float Depth,
|
float Depth,
|
||||||
int Stencil)
|
int Stencil)
|
||||||
{
|
{
|
||||||
ClearBufferMask Mask = ClearBufferMask.ColorBufferBit;
|
|
||||||
|
|
||||||
GL.ColorMask(
|
GL.ColorMask(
|
||||||
Flags.HasFlag(GalClearBufferFlags.ColorRed),
|
Flags.HasFlag(GalClearBufferFlags.ColorRed),
|
||||||
Flags.HasFlag(GalClearBufferFlags.ColorGreen),
|
Flags.HasFlag(GalClearBufferFlags.ColorGreen),
|
||||||
Flags.HasFlag(GalClearBufferFlags.ColorBlue),
|
Flags.HasFlag(GalClearBufferFlags.ColorBlue),
|
||||||
Flags.HasFlag(GalClearBufferFlags.ColorAlpha));
|
Flags.HasFlag(GalClearBufferFlags.ColorAlpha));
|
||||||
|
|
||||||
|
GL.ClearBuffer(ClearBuffer.Color, Attachment, new float[] { Red, Green, Blue, Alpha });
|
||||||
|
|
||||||
if (Flags.HasFlag(GalClearBufferFlags.Depth))
|
if (Flags.HasFlag(GalClearBufferFlags.Depth))
|
||||||
{
|
{
|
||||||
Mask |= ClearBufferMask.DepthBufferBit;
|
GL.ClearBuffer(ClearBuffer.Depth, 0, ref Depth);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Flags.HasFlag(GalClearBufferFlags.Stencil))
|
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);
|
GL.ColorMask(true, true, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -23,7 +23,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
Buffer = new OGLConstBuffer();
|
Buffer = new OGLConstBuffer();
|
||||||
|
|
||||||
FrameBuffer = new OGLFrameBuffer();
|
Texture = new OGLTexture();
|
||||||
|
|
||||||
|
FrameBuffer = new OGLFrameBuffer(Texture as OGLTexture);
|
||||||
|
|
||||||
Rasterizer = new OGLRasterizer();
|
Rasterizer = new OGLRasterizer();
|
||||||
|
|
||||||
|
@ -31,8 +33,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
|
|
||||||
Pipeline = new OGLPipeline(Buffer as OGLConstBuffer, Rasterizer as OGLRasterizer, Shader as OGLShader);
|
Pipeline = new OGLPipeline(Buffer as OGLConstBuffer, Rasterizer as OGLRasterizer, Shader as OGLShader);
|
||||||
|
|
||||||
Texture = new OGLTexture();
|
|
||||||
|
|
||||||
ActionsQueue = new ConcurrentQueue<Action>();
|
ActionsQueue = new ConcurrentQueue<Action>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,26 +4,13 @@ using System;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gal.OpenGL
|
namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
{
|
{
|
||||||
public class OGLTexture : IGalTexture
|
class OGLTexture : IGalTexture
|
||||||
{
|
{
|
||||||
private class TCE
|
private OGLCachedResource<ImageHandler> TextureCache;
|
||||||
{
|
|
||||||
public int Handle;
|
|
||||||
|
|
||||||
public GalTexture Texture;
|
|
||||||
|
|
||||||
public TCE(int Handle, GalTexture Texture)
|
|
||||||
{
|
|
||||||
this.Handle = Handle;
|
|
||||||
this.Texture = Texture;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private OGLCachedResource<TCE> TextureCache;
|
|
||||||
|
|
||||||
public OGLTexture()
|
public OGLTexture()
|
||||||
{
|
{
|
||||||
TextureCache = new OGLCachedResource<TCE>(DeleteTexture);
|
TextureCache = new OGLCachedResource<ImageHandler>(DeleteTexture);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LockCache()
|
public void LockCache()
|
||||||
|
@ -36,73 +23,71 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
TextureCache.Unlock();
|
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();
|
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);
|
GL.BindTexture(TextureTarget.Texture2D, Handle);
|
||||||
|
|
||||||
const int Level = 0; //TODO: Support mipmap textures.
|
const int Level = 0; //TODO: Support mipmap textures.
|
||||||
const int Border = 0;
|
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(
|
GL.CompressedTexImage2D(
|
||||||
TextureTarget.Texture2D,
|
TextureTarget.Texture2D,
|
||||||
Level,
|
Level,
|
||||||
InternalFmt,
|
InternalFmt,
|
||||||
Texture.Width,
|
Image.Width,
|
||||||
Texture.Height,
|
Image.Height,
|
||||||
Border,
|
Border,
|
||||||
Data.Length,
|
Data.Length,
|
||||||
Data);
|
Data);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (Texture.Format >= GalTextureFormat.Astc2D4x4)
|
if (Image.Format >= GalImageFormat.ASTC_BEGIN && Image.Format <= GalImageFormat.ASTC_END)
|
||||||
{
|
{
|
||||||
int TextureBlockWidth = GetAstcBlockWidth(Texture.Format);
|
int TextureBlockWidth = GetAstcBlockWidth(Image.Format);
|
||||||
int TextureBlockHeight = GetAstcBlockHeight(Texture.Format);
|
int TextureBlockHeight = GetAstcBlockHeight(Image.Format);
|
||||||
|
|
||||||
Data = ASTCDecoder.DecodeToRGBA8888(
|
Data = ASTCDecoder.DecodeToRGBA8888(
|
||||||
Data,
|
Data,
|
||||||
TextureBlockWidth,
|
TextureBlockWidth,
|
||||||
TextureBlockHeight, 1,
|
TextureBlockHeight, 1,
|
||||||
Texture.Width,
|
Image.Width,
|
||||||
Texture.Height, 1);
|
Image.Height, 1);
|
||||||
|
|
||||||
Texture.Format = GalTextureFormat.A8B8G8R8;
|
Image.Format = GalImageFormat.A8B8G8R8_UNORM_PACK32;
|
||||||
}
|
}
|
||||||
|
|
||||||
const PixelInternalFormat InternalFmt = PixelInternalFormat.Rgba;
|
(PixelInternalFormat InternalFormat, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
|
||||||
|
|
||||||
(PixelFormat Format, PixelType Type) = OGLEnumConverter.GetTextureFormat(Texture.Format);
|
|
||||||
|
|
||||||
GL.TexImage2D(
|
GL.TexImage2D(
|
||||||
TextureTarget.Texture2D,
|
TextureTarget.Texture2D,
|
||||||
Level,
|
Level,
|
||||||
InternalFmt,
|
InternalFormat,
|
||||||
Texture.Width,
|
Image.Width,
|
||||||
Texture.Height,
|
Image.Height,
|
||||||
Border,
|
Border,
|
||||||
Format,
|
Format,
|
||||||
Type,
|
Type,
|
||||||
Data);
|
Data);
|
||||||
}
|
}
|
||||||
|
|
||||||
int SwizzleR = (int)OGLEnumConverter.GetTextureSwizzle(Texture.XSource);
|
int SwizzleR = (int)OGLEnumConverter.GetTextureSwizzle(Image.XSource);
|
||||||
int SwizzleG = (int)OGLEnumConverter.GetTextureSwizzle(Texture.YSource);
|
int SwizzleG = (int)OGLEnumConverter.GetTextureSwizzle(Image.YSource);
|
||||||
int SwizzleB = (int)OGLEnumConverter.GetTextureSwizzle(Texture.ZSource);
|
int SwizzleB = (int)OGLEnumConverter.GetTextureSwizzle(Image.ZSource);
|
||||||
int SwizzleA = (int)OGLEnumConverter.GetTextureSwizzle(Texture.WSource);
|
int SwizzleA = (int)OGLEnumConverter.GetTextureSwizzle(Image.WSource);
|
||||||
|
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleR, SwizzleR);
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleR, SwizzleR);
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleG, SwizzleG);
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleG, SwizzleG);
|
||||||
|
@ -110,76 +95,100 @@ namespace Ryujinx.Graphics.Gal.OpenGL
|
||||||
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, SwizzleA);
|
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)
|
switch (Format)
|
||||||
{
|
{
|
||||||
case GalTextureFormat.Astc2D4x4: return 4;
|
case GalImageFormat.ASTC_4x4_UNORM_BLOCK: return 4;
|
||||||
case GalTextureFormat.Astc2D5x5: return 5;
|
case GalImageFormat.ASTC_5x5_UNORM_BLOCK: return 5;
|
||||||
case GalTextureFormat.Astc2D6x6: return 6;
|
case GalImageFormat.ASTC_6x6_UNORM_BLOCK: return 6;
|
||||||
case GalTextureFormat.Astc2D8x8: return 8;
|
case GalImageFormat.ASTC_8x8_UNORM_BLOCK: return 8;
|
||||||
case GalTextureFormat.Astc2D10x10: return 10;
|
case GalImageFormat.ASTC_10x10_UNORM_BLOCK: return 10;
|
||||||
case GalTextureFormat.Astc2D12x12: return 12;
|
case GalImageFormat.ASTC_12x12_UNORM_BLOCK: return 12;
|
||||||
case GalTextureFormat.Astc2D5x4: return 5;
|
case GalImageFormat.ASTC_5x4_UNORM_BLOCK: return 5;
|
||||||
case GalTextureFormat.Astc2D6x5: return 6;
|
case GalImageFormat.ASTC_6x5_UNORM_BLOCK: return 6;
|
||||||
case GalTextureFormat.Astc2D8x6: return 8;
|
case GalImageFormat.ASTC_8x6_UNORM_BLOCK: return 8;
|
||||||
case GalTextureFormat.Astc2D10x8: return 10;
|
case GalImageFormat.ASTC_10x8_UNORM_BLOCK: return 10;
|
||||||
case GalTextureFormat.Astc2D12x10: return 12;
|
case GalImageFormat.ASTC_12x10_UNORM_BLOCK: return 12;
|
||||||
case GalTextureFormat.Astc2D8x5: return 8;
|
case GalImageFormat.ASTC_8x5_UNORM_BLOCK: return 8;
|
||||||
case GalTextureFormat.Astc2D10x5: return 10;
|
case GalImageFormat.ASTC_10x5_UNORM_BLOCK: return 10;
|
||||||
case GalTextureFormat.Astc2D10x6: return 10;
|
case GalImageFormat.ASTC_10x6_UNORM_BLOCK: return 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(Format));
|
throw new ArgumentException(nameof(Format));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int GetAstcBlockHeight(GalTextureFormat Format)
|
private static int GetAstcBlockHeight(GalImageFormat Format)
|
||||||
{
|
{
|
||||||
switch (Format)
|
switch (Format)
|
||||||
{
|
{
|
||||||
case GalTextureFormat.Astc2D4x4: return 4;
|
case GalImageFormat.ASTC_4x4_UNORM_BLOCK: return 4;
|
||||||
case GalTextureFormat.Astc2D5x5: return 5;
|
case GalImageFormat.ASTC_5x5_UNORM_BLOCK: return 5;
|
||||||
case GalTextureFormat.Astc2D6x6: return 6;
|
case GalImageFormat.ASTC_6x6_UNORM_BLOCK: return 6;
|
||||||
case GalTextureFormat.Astc2D8x8: return 8;
|
case GalImageFormat.ASTC_8x8_UNORM_BLOCK: return 8;
|
||||||
case GalTextureFormat.Astc2D10x10: return 10;
|
case GalImageFormat.ASTC_10x10_UNORM_BLOCK: return 10;
|
||||||
case GalTextureFormat.Astc2D12x12: return 12;
|
case GalImageFormat.ASTC_12x12_UNORM_BLOCK: return 12;
|
||||||
case GalTextureFormat.Astc2D5x4: return 4;
|
case GalImageFormat.ASTC_5x4_UNORM_BLOCK: return 4;
|
||||||
case GalTextureFormat.Astc2D6x5: return 5;
|
case GalImageFormat.ASTC_6x5_UNORM_BLOCK: return 5;
|
||||||
case GalTextureFormat.Astc2D8x6: return 6;
|
case GalImageFormat.ASTC_8x6_UNORM_BLOCK: return 6;
|
||||||
case GalTextureFormat.Astc2D10x8: return 8;
|
case GalImageFormat.ASTC_10x8_UNORM_BLOCK: return 8;
|
||||||
case GalTextureFormat.Astc2D12x10: return 10;
|
case GalImageFormat.ASTC_12x10_UNORM_BLOCK: return 10;
|
||||||
case GalTextureFormat.Astc2D8x5: return 5;
|
case GalImageFormat.ASTC_8x5_UNORM_BLOCK: return 5;
|
||||||
case GalTextureFormat.Astc2D10x5: return 5;
|
case GalImageFormat.ASTC_10x5_UNORM_BLOCK: return 5;
|
||||||
case GalTextureFormat.Astc2D10x6: return 6;
|
case GalImageFormat.ASTC_10x6_UNORM_BLOCK: return 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new ArgumentException(nameof(Format));
|
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.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;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Texture = default(GalTexture);
|
Image = default(GalImage);
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Bind(long Key, int Index)
|
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.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);
|
GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureBorderColor, Color);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static bool IsCompressedTextureFormat(GalTextureFormat Format)
|
private static bool IsCompressedTextureFormat(GalImageFormat Format)
|
||||||
{
|
{
|
||||||
switch (Format)
|
switch (Format)
|
||||||
{
|
{
|
||||||
case GalTextureFormat.BC6H_UF16:
|
case GalImageFormat.BC6H_UFLOAT_BLOCK:
|
||||||
case GalTextureFormat.BC6H_SF16:
|
case GalImageFormat.BC6H_SFLOAT_BLOCK:
|
||||||
case GalTextureFormat.BC7U:
|
case GalImageFormat.BC7_UNORM_BLOCK:
|
||||||
case GalTextureFormat.BC1:
|
case GalImageFormat.BC1_RGBA_UNORM_BLOCK:
|
||||||
case GalTextureFormat.BC2:
|
case GalImageFormat.BC2_UNORM_BLOCK:
|
||||||
case GalTextureFormat.BC3:
|
case GalImageFormat.BC3_UNORM_BLOCK:
|
||||||
case GalTextureFormat.BC4:
|
case GalImageFormat.BC4_SNORM_BLOCK:
|
||||||
case GalTextureFormat.BC5:
|
case GalImageFormat.BC4_UNORM_BLOCK:
|
||||||
|
case GalImageFormat.BC5_SNORM_BLOCK:
|
||||||
|
case GalImageFormat.BC5_UNORM_BLOCK:
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,6 +16,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
public const int VertexIdAttr = 0x2fc;
|
public const int VertexIdAttr = 0x2fc;
|
||||||
public const int FaceAttr = 0x3fc;
|
public const int FaceAttr = 0x3fc;
|
||||||
|
|
||||||
|
public const int MaxFrameBufferAttachments = 8;
|
||||||
public const int MaxUboSize = 1024;
|
public const int MaxUboSize = 1024;
|
||||||
|
|
||||||
public const int GlPositionVec4Index = 7;
|
public const int GlPositionVec4Index = 7;
|
||||||
|
@ -99,7 +100,11 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
|
||||||
if (ShaderType == GalShaderType.Fragment)
|
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)
|
foreach (ShaderIrBlock Block in Blocks)
|
||||||
|
|
|
@ -352,9 +352,9 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
{
|
{
|
||||||
Name = CustomType + " " + DeclInfo.Name + Suffix + ";";
|
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
|
else
|
||||||
{
|
{
|
||||||
|
@ -829,8 +829,11 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
{
|
{
|
||||||
return "gl_PointSize";
|
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)
|
if (Decl.ShaderType == GalShaderType.Geometry)
|
||||||
|
@ -876,7 +879,7 @@ namespace Ryujinx.Graphics.Gal.Shader
|
||||||
|
|
||||||
private string GetNameWithSwizzle(IReadOnlyDictionary<int, ShaderDeclInfo> Dict, int Index)
|
private string GetNameWithSwizzle(IReadOnlyDictionary<int, ShaderDeclInfo> Dict, int Index)
|
||||||
{
|
{
|
||||||
int VecIndex = Index >> 2;
|
int VecIndex = Index & ~3;
|
||||||
|
|
||||||
if (Dict.TryGetValue(VecIndex, out ShaderDeclInfo DeclInfo))
|
if (Dict.TryGetValue(VecIndex, out ShaderDeclInfo DeclInfo))
|
||||||
{
|
{
|
||||||
|
|
|
@ -154,16 +154,12 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
}
|
}
|
||||||
else if (IsDstFb)
|
else if (IsDstFb)
|
||||||
{
|
{
|
||||||
//Texture -> Frame Buffer copy.
|
|
||||||
const GalTextureFormat Format = GalTextureFormat.A8B8G8R8;
|
|
||||||
|
|
||||||
byte[] Buffer = TextureReader.Read(Vmm, SrcTexture());
|
byte[] Buffer = TextureReader.Read(Vmm, SrcTexture());
|
||||||
|
|
||||||
Gpu.Renderer.FrameBuffer.SetBufferData(
|
Gpu.Renderer.FrameBuffer.SetBufferData(
|
||||||
DstKey,
|
DstKey,
|
||||||
DstWidth,
|
DstWidth,
|
||||||
DstHeight,
|
DstHeight,
|
||||||
Format,
|
|
||||||
Buffer);
|
Buffer);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -102,7 +102,9 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
SetAlphaBlending(State);
|
SetAlphaBlending(State);
|
||||||
SetPrimitiveRestart(State);
|
SetPrimitiveRestart(State);
|
||||||
|
|
||||||
|
//Enabling multiple framebuffer attachments cause graphics reggresions
|
||||||
SetFrameBuffer(Vmm, 0);
|
SetFrameBuffer(Vmm, 0);
|
||||||
|
SetZeta(Vmm);
|
||||||
|
|
||||||
long[] Keys = UploadShaders(Vmm);
|
long[] Keys = UploadShaders(Vmm);
|
||||||
|
|
||||||
|
@ -149,9 +151,11 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
int Stencil = ReadRegister(NvGpuEngine3dReg.ClearStencil);
|
int Stencil = ReadRegister(NvGpuEngine3dReg.ClearStencil);
|
||||||
|
|
||||||
SetFrameBuffer(Vmm, FbIndex);
|
SetFrameBuffer(Vmm, FbIndex);
|
||||||
|
SetZeta(Vmm);
|
||||||
|
|
||||||
Gpu.Renderer.Rasterizer.ClearBuffers(
|
Gpu.Renderer.Rasterizer.ClearBuffers(
|
||||||
Flags,
|
Flags,
|
||||||
|
FbIndex,
|
||||||
Red, Green, Blue, Alpha,
|
Red, Green, Blue, Alpha,
|
||||||
Depth,
|
Depth,
|
||||||
Stencil);
|
Stencil);
|
||||||
|
@ -161,6 +165,15 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
{
|
{
|
||||||
long VA = MakeInt64From2xInt32(NvGpuEngine3dReg.FrameBufferNAddress + FbIndex * 0x10);
|
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);
|
long Key = Vmm.GetPhysicalAddress(VA);
|
||||||
|
|
||||||
FrameBuffers.Add(Key);
|
FrameBuffers.Add(Key);
|
||||||
|
@ -168,11 +181,11 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
int Width = ReadRegister(NvGpuEngine3dReg.FrameBufferNWidth + FbIndex * 0x10);
|
int Width = ReadRegister(NvGpuEngine3dReg.FrameBufferNWidth + FbIndex * 0x10);
|
||||||
int Height = ReadRegister(NvGpuEngine3dReg.FrameBufferNHeight + FbIndex * 0x10);
|
int Height = ReadRegister(NvGpuEngine3dReg.FrameBufferNHeight + FbIndex * 0x10);
|
||||||
|
|
||||||
float TX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateX + FbIndex * 4);
|
float TX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateX + FbIndex * 8);
|
||||||
float TY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateY + FbIndex * 4);
|
float TY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateY + FbIndex * 8);
|
||||||
|
|
||||||
float SX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleX + FbIndex * 4);
|
float SX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleX + FbIndex * 8);
|
||||||
float SY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleY + FbIndex * 4);
|
float SY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNScaleY + FbIndex * 8);
|
||||||
|
|
||||||
int VpX = (int)MathF.Max(0, TX - MathF.Abs(SX));
|
int VpX = (int)MathF.Max(0, TX - MathF.Abs(SX));
|
||||||
int VpY = (int)MathF.Max(0, TY - MathF.Abs(SY));
|
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 VpW = (int)(TX + MathF.Abs(SX)) - VpX;
|
||||||
int VpH = (int)(TY + MathF.Abs(SY)) - VpY;
|
int VpH = (int)(TY + MathF.Abs(SY)) - VpY;
|
||||||
|
|
||||||
Gpu.Renderer.FrameBuffer.Create(Key, Width, Height);
|
GalImageFormat ImageFormat = ImageFormatConverter.ConvertFrameBuffer((GalFrameBufferFormat)Format);
|
||||||
Gpu.Renderer.FrameBuffer.Bind(Key);
|
|
||||||
|
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);
|
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)
|
private long[] UploadShaders(NvGpuVmm Vmm)
|
||||||
{
|
{
|
||||||
long[] Keys = new long[5];
|
long[] Keys = new long[5];
|
||||||
|
@ -442,15 +491,15 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
}
|
}
|
||||||
else
|
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;
|
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);
|
Gpu.Renderer.Texture.Bind(Key, TexIndex);
|
||||||
|
|
||||||
|
@ -462,7 +511,7 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
{
|
{
|
||||||
byte[] Data = TextureFactory.GetTextureData(Vmm, TicPosition);
|
byte[] Data = TextureFactory.GetTextureData(Vmm, TicPosition);
|
||||||
|
|
||||||
Gpu.Renderer.Texture.Create(Key, Data, NewTexture);
|
Gpu.Renderer.Texture.Create(Key, Data, NewImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
Gpu.Renderer.Texture.Bind(Key, TexIndex);
|
Gpu.Renderer.Texture.Bind(Key, TexIndex);
|
||||||
|
|
|
@ -22,7 +22,14 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
StencilBackFuncRef = 0x3d5,
|
StencilBackFuncRef = 0x3d5,
|
||||||
StencilBackMask = 0x3d6,
|
StencilBackMask = 0x3d6,
|
||||||
StencilBackFuncMask = 0x3d7,
|
StencilBackFuncMask = 0x3d7,
|
||||||
|
ZetaAddress = 0x3f8,
|
||||||
|
ZetaFormat = 0x3fa,
|
||||||
|
ZetaBlockDimensions = 0x3fb,
|
||||||
|
ZetaLayerStride = 0x3fc,
|
||||||
VertexAttribNFormat = 0x458,
|
VertexAttribNFormat = 0x458,
|
||||||
|
ZetaHoriz = 0x48a,
|
||||||
|
ZetaVert = 0x48b,
|
||||||
|
ZetaArrayMode = 0x48c,
|
||||||
DepthTestEnable = 0x4b3,
|
DepthTestEnable = 0x4b3,
|
||||||
IBlendEnable = 0x4b9,
|
IBlendEnable = 0x4b9,
|
||||||
DepthTestFunction = 0x4c3,
|
DepthTestFunction = 0x4c3,
|
||||||
|
@ -44,6 +51,7 @@ namespace Ryujinx.HLE.Gpu.Engines
|
||||||
StencilFrontFuncMask = 0x4e6,
|
StencilFrontFuncMask = 0x4e6,
|
||||||
StencilFrontMask = 0x4e7,
|
StencilFrontMask = 0x4e7,
|
||||||
VertexArrayElemBase = 0x50d,
|
VertexArrayElemBase = 0x50d,
|
||||||
|
ZetaEnable = 0x54e,
|
||||||
TexHeaderPoolOffset = 0x55d,
|
TexHeaderPoolOffset = 0x55d,
|
||||||
TexSamplerPoolOffset = 0x557,
|
TexSamplerPoolOffset = 0x557,
|
||||||
StencilTwoSideEnable = 0x565,
|
StencilTwoSideEnable = 0x565,
|
||||||
|
|
|
@ -6,11 +6,16 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
{
|
{
|
||||||
static class TextureFactory
|
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);
|
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 XSource = (GalTextureSource)((Tic[0] >> 19) & 7);
|
||||||
GalTextureSource YSource = (GalTextureSource)((Tic[0] >> 22) & 7);
|
GalTextureSource YSource = (GalTextureSource)((Tic[0] >> 22) & 7);
|
||||||
|
@ -20,7 +25,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
int Width = (Tic[4] & 0xffff) + 1;
|
int Width = (Tic[4] & 0xffff) + 1;
|
||||||
int Height = (Tic[5] & 0xffff) + 1;
|
int Height = (Tic[5] & 0xffff) + 1;
|
||||||
|
|
||||||
return new GalTexture(
|
return new GalImage(
|
||||||
Width,
|
Width,
|
||||||
Height,
|
Height,
|
||||||
Format,
|
Format,
|
||||||
|
|
|
@ -30,117 +30,151 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
throw new NotImplementedException(Texture.Swizzle.ToString());
|
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:
|
case GalImageFormat.R32G32B32A32_SFLOAT:
|
||||||
return Texture.Width * Texture.Height * 16;
|
case GalImageFormat.R32G32B32A32_SINT:
|
||||||
|
case GalImageFormat.R32G32B32A32_UINT:
|
||||||
|
return Image.Width * Image.Height * 16;
|
||||||
|
|
||||||
case GalTextureFormat.R16G16B16A16:
|
case GalImageFormat.R16G16B16A16_SFLOAT:
|
||||||
return Texture.Width * Texture.Height * 8;
|
case GalImageFormat.R16G16B16A16_SINT:
|
||||||
|
case GalImageFormat.R16G16B16A16_SNORM:
|
||||||
|
case GalImageFormat.R16G16B16A16_UINT:
|
||||||
|
case GalImageFormat.R16G16B16A16_UNORM:
|
||||||
|
return Image.Width * Image.Height * 8;
|
||||||
|
|
||||||
case GalTextureFormat.A8B8G8R8:
|
case GalImageFormat.A8B8G8R8_SINT_PACK32:
|
||||||
case GalTextureFormat.A2B10G10R10:
|
case GalImageFormat.A8B8G8R8_SNORM_PACK32:
|
||||||
case GalTextureFormat.R32:
|
case GalImageFormat.A8B8G8R8_UINT_PACK32:
|
||||||
case GalTextureFormat.ZF32:
|
case GalImageFormat.A8B8G8R8_UNORM_PACK32:
|
||||||
case GalTextureFormat.BF10GF11RF11:
|
case GalImageFormat.A8B8G8R8_SRGB_PACK32:
|
||||||
case GalTextureFormat.Z24S8:
|
case GalImageFormat.A2B10G10R10_SINT_PACK32:
|
||||||
return Texture.Width * Texture.Height * 4;
|
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 GalTextureFormat.A1B5G5R5:
|
case GalImageFormat.B4G4R4A4_UNORM_PACK16:
|
||||||
case GalTextureFormat.B5G6R5:
|
case GalImageFormat.A1R5G5B5_UNORM_PACK16:
|
||||||
case GalTextureFormat.G8R8:
|
case GalImageFormat.B5G6R5_UNORM_PACK16:
|
||||||
case GalTextureFormat.R16:
|
case GalImageFormat.R8G8_SINT:
|
||||||
return Texture.Width * Texture.Height * 2;
|
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 GalTextureFormat.R8:
|
case GalImageFormat.R8_SINT:
|
||||||
return Texture.Width * Texture.Height;
|
case GalImageFormat.R8_SNORM:
|
||||||
|
case GalImageFormat.R8_UINT:
|
||||||
|
case GalImageFormat.R8_UNORM:
|
||||||
|
return Image.Width * Image.Height;
|
||||||
|
|
||||||
case GalTextureFormat.BC1:
|
case GalImageFormat.BC1_RGBA_UNORM_BLOCK:
|
||||||
case GalTextureFormat.BC4:
|
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 GalImageFormat.BC6H_SFLOAT_BLOCK:
|
||||||
case GalTextureFormat.BC6H_UF16:
|
case GalImageFormat.BC6H_UFLOAT_BLOCK:
|
||||||
case GalTextureFormat.BC7U:
|
case GalImageFormat.BC7_UNORM_BLOCK:
|
||||||
case GalTextureFormat.BC2:
|
case GalImageFormat.BC2_UNORM_BLOCK:
|
||||||
case GalTextureFormat.BC3:
|
case GalImageFormat.BC3_UNORM_BLOCK:
|
||||||
case GalTextureFormat.BC5:
|
case GalImageFormat.BC5_SNORM_BLOCK:
|
||||||
case GalTextureFormat.Astc2D4x4:
|
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)
|
public static int CompressedTextureSize(int TextureWidth, int TextureHeight, int BlockWidth, int BlockHeight, int Bpb)
|
||||||
|
|
|
@ -19,6 +19,7 @@ namespace Ryujinx.HLE.Gpu.Texture
|
||||||
case GalTextureFormat.Z24S8: return Read4Bpp (Memory, Texture);
|
case GalTextureFormat.Z24S8: return Read4Bpp (Memory, Texture);
|
||||||
case GalTextureFormat.A1B5G5R5: return Read5551 (Memory, Texture);
|
case GalTextureFormat.A1B5G5R5: return Read5551 (Memory, Texture);
|
||||||
case GalTextureFormat.B5G6R5: return Read565 (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.G8R8: return Read2Bpp (Memory, Texture);
|
||||||
case GalTextureFormat.R16: return Read2Bpp (Memory, Texture);
|
case GalTextureFormat.R16: return Read2Bpp (Memory, Texture);
|
||||||
case GalTextureFormat.R8: return Read1Bpp (Memory, Texture);
|
case GalTextureFormat.R8: return Read1Bpp (Memory, Texture);
|
||||||
|
|
Reference in a new issue