aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-09-18 01:30:35 -0300
committerGitHub <noreply@github.com>2018-09-18 01:30:35 -0300
commitd4187aaa9d7194aa26d04aee838edbc3a38f1862 (patch)
tree06fe725c1067b4aeca21749799b835d85e7d2787
parentbec95cacc1061f91373a1e3a1411981af7fe2e4e (diff)
Allow "reinterpretation" of framebuffer/zeta formats (#418)
* (Re)Implement format reinterpretation, other changes * Implement writeback to guest memory, some refactoring * More refactoring, implement reinterpretation the old way again * Clean up * Some fixes on M2MF (old Dma engine), added partial support for P2MF, fix conditional ssy, add Z24S8 zeta format, other fixes * nit: Formatting * Address PR feedback
-rw-r--r--ChocolArm64/Memory/AMemory.cs29
-rw-r--r--Ryujinx.Graphics/Gal/GalImage.cs48
-rw-r--r--Ryujinx.Graphics/Gal/GalMemoryLayout.cs8
-rw-r--r--Ryujinx.Graphics/Gal/GalPipelineState.cs2
-rw-r--r--Ryujinx.Graphics/Gal/GalSurfaceFormat.cs (renamed from Ryujinx.Graphics/Gal/GalFrameBufferFormat.cs)0
-rw-r--r--Ryujinx.Graphics/Gal/GalTextureFormat.cs1
-rw-r--r--Ryujinx.Graphics/Gal/IGalRasterizer.cs2
-rw-r--r--Ryujinx.Graphics/Gal/IGalRenderTarget.cs18
-rw-r--r--Ryujinx.Graphics/Gal/IGalTexture.cs8
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs143
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs6
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs4
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs11
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs6
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs336
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs161
-rw-r--r--Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs1
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs128
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs24
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeFunc.cs (renamed from Ryujinx.Graphics/Gal/Shader/ShaderDecode.cs)2
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs2
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs16
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs42
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecodeSpecial.cs6
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs44
-rw-r--r--Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs6
-rw-r--r--Ryujinx.Graphics/GpuResourceManager.cs122
-rw-r--r--Ryujinx.Graphics/Memory/NvGpuVmmCache.cs293
-rw-r--r--Ryujinx.Graphics/NvGpu.cs19
-rw-r--r--Ryujinx.Graphics/NvGpuBufferType.cs (renamed from Ryujinx.Graphics/Memory/NvGpuBufferType.cs)2
-rw-r--r--Ryujinx.Graphics/NvGpuEngine.cs4
-rw-r--r--Ryujinx.Graphics/NvGpuEngine2d.cs131
-rw-r--r--Ryujinx.Graphics/NvGpuEngine3d.cs123
-rw-r--r--Ryujinx.Graphics/NvGpuEngine3dReg.cs2
-rw-r--r--Ryujinx.Graphics/NvGpuEngineDma.cs143
-rw-r--r--Ryujinx.Graphics/NvGpuEngineM2mf.cs192
-rw-r--r--Ryujinx.Graphics/NvGpuEngineM2mfReg.cs (renamed from Ryujinx.Graphics/NvGpuEngineDmaReg.cs)5
-rw-r--r--Ryujinx.Graphics/NvGpuEngineP2mf.cs102
-rw-r--r--Ryujinx.Graphics/NvGpuEngineP2mfReg.cs17
-rw-r--r--Ryujinx.Graphics/NvGpuFifo.cs65
-rw-r--r--Ryujinx.Graphics/Texture/ImageUtils.cs364
-rw-r--r--Ryujinx.Graphics/Texture/TextureFactory.cs52
-rw-r--r--Ryujinx.Graphics/Texture/TextureHelper.cs29
-rw-r--r--Ryujinx.Graphics/Texture/TextureInfo.cs60
-rw-r--r--Ryujinx.Graphics/Texture/TextureReader.cs398
-rw-r--r--Ryujinx.Graphics/Texture/TextureWriter.cs35
-rw-r--r--Ryujinx.Graphics/ValueRange.cs17
-rw-r--r--Ryujinx.Graphics/ValueRangeSet.cs234
-rw-r--r--Ryujinx.HLE/HOS/Kernel/SvcSystem.cs3
-rw-r--r--Ryujinx.HLE/HOS/Services/Acc/IProfile.cs1
-rw-r--r--Ryujinx.HLE/HOS/Services/Vi/IHOSBinderDriver.cs12
-rw-r--r--Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs48
52 files changed, 1571 insertions, 1956 deletions
diff --git a/ChocolArm64/Memory/AMemory.cs b/ChocolArm64/Memory/AMemory.cs
index 566e6b54..806a0b86 100644
--- a/ChocolArm64/Memory/AMemory.cs
+++ b/ChocolArm64/Memory/AMemory.cs
@@ -287,6 +287,14 @@ namespace ChocolArm64.Memory
return Data;
}
+ public void ReadBytes(long Position, byte[] Data, int StartIndex, int Size)
+ {
+ //Note: This will be moved later.
+ EnsureRangeIsValid(Position, (uint)Size);
+
+ Marshal.Copy((IntPtr)Translate(Position), Data, StartIndex, Size);
+ }
+
public void WriteSByte(long Position, sbyte Value)
{
WriteByte(Position, (byte)Value);
@@ -403,6 +411,27 @@ namespace ChocolArm64.Memory
Marshal.Copy(Data, 0, (IntPtr)TranslateWrite(Position), Data.Length);
}
+ public void WriteBytes(long Position, byte[] Data, int StartIndex, int Size)
+ {
+ //Note: This will be moved later.
+ //Using Translate instead of TranslateWrite is on purpose.
+ EnsureRangeIsValid(Position, (uint)Size);
+
+ Marshal.Copy(Data, StartIndex, (IntPtr)Translate(Position), Size);
+ }
+
+ public void CopyBytes(long Src, long Dst, long Size)
+ {
+ //Note: This will be moved later.
+ EnsureRangeIsValid(Src, Size);
+ EnsureRangeIsValid(Dst, Size);
+
+ byte* SrcPtr = Translate(Src);
+ byte* DstPtr = TranslateWrite(Dst);
+
+ Buffer.MemoryCopy(SrcPtr, DstPtr, Size, Size);
+ }
+
public void Map(long VA, long PA, long Size)
{
SetPTEntries(VA, RamPtr + PA, Size);
diff --git a/Ryujinx.Graphics/Gal/GalImage.cs b/Ryujinx.Graphics/Gal/GalImage.cs
index dc6f02e0..92f43cc9 100644
--- a/Ryujinx.Graphics/Gal/GalImage.cs
+++ b/Ryujinx.Graphics/Gal/GalImage.cs
@@ -1,12 +1,17 @@
+using Ryujinx.Graphics.Texture;
+
namespace Ryujinx.Graphics.Gal
{
public struct GalImage
{
public int Width;
public int Height;
+ public int TileWidth;
+ public int GobBlockHeight;
+ public int Pitch;
- public GalImageFormat Format;
-
+ public GalImageFormat Format;
+ public GalMemoryLayout Layout;
public GalTextureSource XSource;
public GalTextureSource YSource;
public GalTextureSource ZSource;
@@ -15,19 +20,44 @@ namespace Ryujinx.Graphics.Gal
public GalImage(
int Width,
int Height,
+ int TileWidth,
+ int GobBlockHeight,
+ GalMemoryLayout Layout,
GalImageFormat Format,
GalTextureSource XSource = GalTextureSource.Red,
GalTextureSource YSource = GalTextureSource.Green,
GalTextureSource ZSource = GalTextureSource.Blue,
GalTextureSource WSource = GalTextureSource.Alpha)
{
- this.Width = Width;
- this.Height = Height;
- this.Format = Format;
- this.XSource = XSource;
- this.YSource = YSource;
- this.ZSource = ZSource;
- this.WSource = WSource;
+ this.Width = Width;
+ this.Height = Height;
+ this.TileWidth = TileWidth;
+ this.GobBlockHeight = GobBlockHeight;
+ this.Layout = Layout;
+ this.Format = Format;
+ this.XSource = XSource;
+ this.YSource = YSource;
+ this.ZSource = ZSource;
+ this.WSource = WSource;
+
+ Pitch = ImageUtils.GetPitch(Format, Width);
+ }
+
+ public bool SizeMatches(GalImage Image)
+ {
+ if (ImageUtils.GetBytesPerPixel(Format) !=
+ ImageUtils.GetBytesPerPixel(Image.Format))
+ {
+ return false;
+ }
+
+ if (ImageUtils.GetAlignedWidth(this) !=
+ ImageUtils.GetAlignedWidth(Image))
+ {
+ return false;
+ }
+
+ return Height == Image.Height;
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/GalMemoryLayout.cs b/Ryujinx.Graphics/Gal/GalMemoryLayout.cs
new file mode 100644
index 00000000..73fabf8c
--- /dev/null
+++ b/Ryujinx.Graphics/Gal/GalMemoryLayout.cs
@@ -0,0 +1,8 @@
+namespace Ryujinx.Graphics.Gal
+{
+ public enum GalMemoryLayout
+ {
+ BlockLinear = 0,
+ Pitch = 1
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/GalPipelineState.cs b/Ryujinx.Graphics/Gal/GalPipelineState.cs
index 7c669514..6ee6c93e 100644
--- a/Ryujinx.Graphics/Gal/GalPipelineState.cs
+++ b/Ryujinx.Graphics/Gal/GalPipelineState.cs
@@ -21,6 +21,8 @@
public GalVertexBinding[] VertexBindings;
+ public bool FramebufferSrgb;
+
public float FlipX;
public float FlipY;
diff --git a/Ryujinx.Graphics/Gal/GalFrameBufferFormat.cs b/Ryujinx.Graphics/Gal/GalSurfaceFormat.cs
index 08bd622b..08bd622b 100644
--- a/Ryujinx.Graphics/Gal/GalFrameBufferFormat.cs
+++ b/Ryujinx.Graphics/Gal/GalSurfaceFormat.cs
diff --git a/Ryujinx.Graphics/Gal/GalTextureFormat.cs b/Ryujinx.Graphics/Gal/GalTextureFormat.cs
index e8658595..5ad76943 100644
--- a/Ryujinx.Graphics/Gal/GalTextureFormat.cs
+++ b/Ryujinx.Graphics/Gal/GalTextureFormat.cs
@@ -7,6 +7,7 @@ namespace Ryujinx.Graphics.Gal
R32G32 = 0x4,
A8B8G8R8 = 0x8,
A2B10G10R10 = 0x9,
+ R16G16 = 0xc,
R32 = 0xf,
BC6H_SF16 = 0x10,
BC6H_UF16 = 0x11,
diff --git a/Ryujinx.Graphics/Gal/IGalRasterizer.cs b/Ryujinx.Graphics/Gal/IGalRasterizer.cs
index a20b6f53..1ee630e2 100644
--- a/Ryujinx.Graphics/Gal/IGalRasterizer.cs
+++ b/Ryujinx.Graphics/Gal/IGalRasterizer.cs
@@ -24,7 +24,7 @@ namespace Ryujinx.Graphics.Gal
void SetIndexArray(int Size, GalIndexFormat Format);
- void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType);
+ void DrawArrays(int First, int Count, GalPrimitiveType PrimType);
void DrawElements(long IboKey, int First, int VertexBase, GalPrimitiveType PrimType);
}
diff --git a/Ryujinx.Graphics/Gal/IGalRenderTarget.cs b/Ryujinx.Graphics/Gal/IGalRenderTarget.cs
index c44434ef..6c9166f2 100644
--- a/Ryujinx.Graphics/Gal/IGalRenderTarget.cs
+++ b/Ryujinx.Graphics/Gal/IGalRenderTarget.cs
@@ -1,23 +1,17 @@
-using System;
-
namespace Ryujinx.Graphics.Gal
{
public interface IGalRenderTarget
{
- void BindColor(long Key, int Attachment);
+ void BindColor(long Key, int Attachment, GalImage Image);
void UnbindColor(int Attachment);
- void BindZeta(long Key);
+ void BindZeta(long Key, GalImage Image);
void UnbindZeta();
- void BindTexture(long Key, int Index);
-
void Set(long Key);
- void Set(byte[] Data, int Width, int Height);
-
void SetMap(int[] Map);
void SetTransform(bool FlipX, bool FlipY, int Top, int Left, int Right, int Bottom);
@@ -40,12 +34,8 @@ namespace Ryujinx.Graphics.Gal
int DstX1,
int DstY1);
- void GetBufferData(long Key, Action<byte[]> Callback);
+ void Reinterpret(long Key, GalImage NewImage);
- void SetBufferData(
- long Key,
- int Width,
- int Height,
- byte[] Buffer);
+ byte[] GetData(long Key);
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/IGalTexture.cs b/Ryujinx.Graphics/Gal/IGalTexture.cs
index 292f59ef..aeecdf1a 100644
--- a/Ryujinx.Graphics/Gal/IGalTexture.cs
+++ b/Ryujinx.Graphics/Gal/IGalTexture.cs
@@ -5,13 +5,13 @@ namespace Ryujinx.Graphics.Gal
void LockCache();
void UnlockCache();
- void Create(long Key, byte[] Data, GalImage Image);
+ void Create(long Key, int Size, GalImage Image);
- void CreateFb(long Key, long Size, GalImage Image);
+ void Create(long Key, byte[] Data, GalImage Image);
- bool TryGetCachedTexture(long Key, long DataSize, out GalImage Image);
+ bool TryGetImage(long Key, out GalImage Image);
- void Bind(long Key, int Index);
+ void Bind(long Key, int Index, GalImage Image);
void SetSampler(GalTextureSampler Sampler);
}
diff --git a/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs b/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs
index dda82538..8db0b8a8 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/ImageHandler.cs
@@ -1,14 +1,9 @@
-using OpenTK.Graphics.OpenGL;
-using Ryujinx.Graphics.Texture;
-using System;
+using Ryujinx.Graphics.Texture;
namespace Ryujinx.Graphics.Gal.OpenGL
{
class ImageHandler
{
- private static int CopyBuffer = 0;
- private static int CopyBufferSize = 0;
-
public GalImage Image { get; private set; }
public int Width => Image.Width;
@@ -16,144 +11,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL
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 bool HasColor => ImageUtils.HasColor(Image.Format);
+ public bool HasDepth => ImageUtils.HasDepth(Image.Format);
+ public bool HasStencil => ImageUtils.HasStencil(Image.Format);
public ImageHandler(int Handle, GalImage Image)
{
this.Handle = Handle;
-
- this.Image = Image;
- }
-
- public void EnsureSetup(GalImage NewImage)
- {
- if (Width == NewImage.Width &&
- Height == NewImage.Height &&
- Format == NewImage.Format &&
- Initialized)
- {
- return;
- }
-
- PixelInternalFormat InternalFmt;
- PixelFormat PixelFormat;
- PixelType PixelType;
-
- if (ImageUtils.IsCompressed(NewImage.Format))
- {
- InternalFmt = (PixelInternalFormat)OGLEnumConverter.GetCompressedImageFormat(NewImage.Format);
-
- PixelFormat = default(PixelFormat);
- PixelType = default(PixelType);
- }
- else
- {
- (InternalFmt, PixelFormat, PixelType) = OGLEnumConverter.GetImageFormat(NewImage.Format);
- }
-
- GL.BindTexture(TextureTarget.Texture2D, Handle);
-
- if (Initialized)
- {
- if (CopyBuffer == 0)
- {
- CopyBuffer = GL.GenBuffer();
- }
-
- int CurrentSize = Math.Max(ImageUtils.GetSize(NewImage),
- ImageUtils.GetSize(Image));
-
- GL.BindBuffer(BufferTarget.PixelPackBuffer, CopyBuffer);
- GL.BindBuffer(BufferTarget.PixelUnpackBuffer, CopyBuffer);
-
- if (CopyBufferSize < CurrentSize)
- {
- CopyBufferSize = CurrentSize;
-
- GL.BufferData(BufferTarget.PixelPackBuffer, CurrentSize, IntPtr.Zero, BufferUsageHint.StreamCopy);
- }
-
- if (ImageUtils.IsCompressed(Image.Format))
- {
- GL.GetCompressedTexImage(TextureTarget.Texture2D, 0, IntPtr.Zero);
- }
- else
- {
- 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;
-
- if (ImageUtils.IsCompressed(NewImage.Format))
- {
- Console.WriteLine("Hit");
-
- GL.CompressedTexImage2D(
- TextureTarget.Texture2D,
- Level,
- (InternalFormat)InternalFmt,
- NewImage.Width,
- NewImage.Height,
- Border,
- ImageUtils.GetSize(NewImage),
- IntPtr.Zero);
- }
- else
- {
- GL.TexImage2D(
- TextureTarget.Texture2D,
- Level,
- InternalFmt,
- NewImage.Width,
- NewImage.Height,
- Border,
- PixelFormat,
- PixelType,
- IntPtr.Zero);
- }
-
- if (Initialized)
- {
- GL.BindBuffer(BufferTarget.PixelPackBuffer, 0);
- GL.BindBuffer(BufferTarget.PixelUnpackBuffer, 0);
- }
-
- Image = NewImage;
-
- this.InternalFormat = InternalFmt;
- this.PixelFormat = PixelFormat;
- this.PixelType = PixelType;
-
- Initialized = true;
+ this.Image = Image;
}
-
- public bool HasColor => ImageUtils.HasColor(Image.Format);
- public bool HasDepth => ImageUtils.HasDepth(Image.Format);
- public bool HasStencil => ImageUtils.HasStencil(Image.Format);
}
}
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs
index 01ebf982..839915ea 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLCachedResource.cs
@@ -22,9 +22,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public CacheBucket(T Value, long DataSize, LinkedListNode<long> Node)
{
- this.Value = Value;
- this.DataSize = DataSize;
- this.Node = Node;
+ this.Value = Value;
+ this.DataSize = DataSize;
+ this.Node = Node;
Timestamp = Environment.TickCount;
}
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
index 876c7b99..fac3875e 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLEnumConverter.cs
@@ -149,8 +149,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
case GalImageFormat.R32 | GalImageFormat.Sfloat: return (PixelInternalFormat.R32f, PixelFormat.Red, PixelType.Float);
case GalImageFormat.R32 | GalImageFormat.Sint: return (PixelInternalFormat.R32i, PixelFormat.Red, PixelType.Int);
case GalImageFormat.R32 | GalImageFormat.Uint: return (PixelInternalFormat.R32ui, PixelFormat.Red, PixelType.UnsignedInt);
- case GalImageFormat.A1R5G5B5 | GalImageFormat.Unorm: return (PixelInternalFormat.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort5551);
- case GalImageFormat.B5G6R5 | GalImageFormat.Unorm: return (PixelInternalFormat.Rgba, PixelFormat.Rgb, PixelType.UnsignedShort565);
+ case GalImageFormat.A1R5G5B5 | GalImageFormat.Unorm: return (PixelInternalFormat.Rgb5A1, PixelFormat.Rgba, PixelType.UnsignedShort1555Reversed);
+ case GalImageFormat.B5G6R5 | GalImageFormat.Unorm: return (PixelInternalFormat.Rgba, PixelFormat.Rgb, PixelType.UnsignedShort565Reversed);
case GalImageFormat.R16G16 | GalImageFormat.Sfloat: return (PixelInternalFormat.Rg16f, PixelFormat.Rg, PixelType.HalfFloat);
case GalImageFormat.R16G16 | GalImageFormat.Sint: return (PixelInternalFormat.Rg16i, PixelFormat.RgInteger, PixelType.Short);
case GalImageFormat.R16G16 | GalImageFormat.Snorm: return (PixelInternalFormat.Rg16Snorm, PixelFormat.Rg, PixelType.Byte);
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs
index 051b1050..cf856a15 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLPipeline.cs
@@ -126,6 +126,11 @@ namespace Ryujinx.Graphics.Gal.OpenGL
BindVertexLayout(New);
+ if (New.FramebufferSrgb != Old.FramebufferSrgb)
+ {
+ Enable(EnableCap.FramebufferSrgb, New.FramebufferSrgb);
+ }
+
if (New.FlipX != Old.FlipX || New.FlipY != Old.FlipY || New.Instance != Old.Instance)
{
Shader.SetExtraData(New.FlipX, New.FlipY, New.Instance);
@@ -337,6 +342,12 @@ namespace Ryujinx.Graphics.Gal.OpenGL
foreach (GalVertexAttrib Attrib in Binding.Attribs)
{
+ //Skip uninitialized attributes.
+ if (Attrib.Size == 0)
+ {
+ continue;
+ }
+
GL.EnableVertexAttribArray(Attrib.Index);
GL.BindBuffer(BufferTarget.ArrayBuffer, VboHandle);
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
index 45106692..ebfba63d 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
@@ -113,14 +113,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
IndexBuffer.ElemSizeLog2 = (int)Format;
}
- public void DrawArrays(int First, int PrimCount, GalPrimitiveType PrimType)
+ public void DrawArrays(int First, int Count, GalPrimitiveType PrimType)
{
- if (PrimCount == 0)
+ if (Count == 0)
{
return;
}
- GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount);
+ GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, Count);
}
public void DrawElements(long IboKey, int First, int VertexBase, GalPrimitiveType PrimType)
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs
index 99bfa350..7dde32d8 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRenderTarget.cs
@@ -15,9 +15,9 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public Rect(int X, int Y, int Width, int Height)
{
- this.X = X;
- this.Y = Y;
- this.Width = Width;
+ this.X = X;
+ this.Y = Y;
+ this.Width = Width;
this.Height = Height;
}
}
@@ -29,7 +29,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private OGLTexture Texture;
- private ImageHandler RawTex;
private ImageHandler ReadTex;
private Rect Viewport;
@@ -64,13 +63,13 @@ namespace Ryujinx.Graphics.Gal.OpenGL
this.Texture = Texture;
}
- public void BindColor(long Key, int Attachment)
+ public void BindColor(long Key, int Attachment, GalImage Image)
{
- if (Texture.TryGetImage(Key, out ImageHandler Tex))
+ if (Texture.TryGetImageHandler(Key, out ImageHandler CachedImage))
{
EnsureFrameBuffer();
- Attach(ref ColorAttachments[Attachment], Tex.Handle, FramebufferAttachment.ColorAttachment0 + Attachment);
+ Attach(ref ColorAttachments[Attachment], CachedImage.Handle, FramebufferAttachment.ColorAttachment0 + Attachment);
}
else
{
@@ -84,40 +83,39 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Attach(ref ColorAttachments[Attachment], 0, FramebufferAttachment.ColorAttachment0 + Attachment);
}
-
- public void BindZeta(long Key)
+
+ public void BindZeta(long Key, GalImage Image)
{
- if (Texture.TryGetImage(Key, out ImageHandler Tex))
+ if (Texture.TryGetImageHandler(Key, out ImageHandler CachedImage))
{
EnsureFrameBuffer();
- if (Tex.HasDepth && Tex.HasStencil)
+ if (CachedImage.HasDepth && CachedImage.HasStencil)
{
- if (DepthAttachment != Tex.Handle ||
- StencilAttachment != Tex.Handle)
+ if (DepthAttachment != CachedImage.Handle ||
+ StencilAttachment != CachedImage.Handle)
{
GL.FramebufferTexture(
FramebufferTarget.DrawFramebuffer,
FramebufferAttachment.DepthStencilAttachment,
- Tex.Handle,
+ CachedImage.Handle,
0);
- DepthAttachment = Tex.Handle;
-
- StencilAttachment = Tex.Handle;
+ DepthAttachment = CachedImage.Handle;
+ StencilAttachment = CachedImage.Handle;
}
}
- else if (Tex.HasDepth)
+ else if (CachedImage.HasDepth)
{
- Attach(ref DepthAttachment, Tex.Handle, FramebufferAttachment.DepthAttachment);
+ Attach(ref DepthAttachment, CachedImage.Handle, FramebufferAttachment.DepthAttachment);
Attach(ref StencilAttachment, 0, FramebufferAttachment.StencilAttachment);
}
- else if (Tex.HasStencil)
+ else if (CachedImage.HasStencil)
{
Attach(ref DepthAttachment, 0, FramebufferAttachment.DepthAttachment);
- Attach(ref StencilAttachment, Tex.Handle, FramebufferAttachment.StencilAttachment);
+ Attach(ref StencilAttachment, CachedImage.Handle, FramebufferAttachment.StencilAttachment);
}
else
{
@@ -130,57 +128,40 @@ namespace Ryujinx.Graphics.Gal.OpenGL
}
}
- public void UnbindZeta()
+ private void Attach(ref int OldHandle, int NewHandle, FramebufferAttachment FbAttachment)
{
- EnsureFrameBuffer();
-
- if (DepthAttachment != 0 ||
- StencilAttachment != 0)
+ if (OldHandle != NewHandle)
{
GL.FramebufferTexture(
FramebufferTarget.DrawFramebuffer,
- FramebufferAttachment.DepthStencilAttachment,
- 0,
+ FbAttachment,
+ NewHandle,
0);
- DepthAttachment = 0;
-
- StencilAttachment = 0;
+ OldHandle = NewHandle;
}
}
- public void BindTexture(long Key, int Index)
+ public void UnbindZeta()
{
- if (Texture.TryGetImage(Key, out ImageHandler Tex))
+ EnsureFrameBuffer();
+
+ if (DepthAttachment != 0 || StencilAttachment != 0)
{
- GL.ActiveTexture(TextureUnit.Texture0 + Index);
+ GL.FramebufferTexture(
+ FramebufferTarget.DrawFramebuffer,
+ FramebufferAttachment.DepthStencilAttachment,
+ 0,
+ 0);
- GL.BindTexture(TextureTarget.Texture2D, Tex.Handle);
+ DepthAttachment = 0;
+ StencilAttachment = 0;
}
}
public void Set(long Key)
{
- if (Texture.TryGetImage(Key, out ImageHandler Tex))
- {
- ReadTex = Tex;
- }
- }
-
- public void Set(byte[] Data, int Width, int Height)
- {
- if (RawTex == null)
- {
- RawTex = new ImageHandler();
- }
-
- RawTex.EnsureSetup(new GalImage(Width, Height, RawFormat));
-
- GL.BindTexture(TextureTarget.Texture2D, RawTex.Handle);
-
- GL.TexSubImage2D(TextureTarget.Texture2D, 0, 0, 0, Width, Height, RawTex.PixelFormat, RawTex.PixelType, Data);
-
- ReadTex = RawTex;
+ Texture.TryGetImageHandler(Key, out ReadTex);
}
public void SetMap(int[] Map)
@@ -280,13 +261,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL
int DstY0 = FlipY ? DstPaddingY : Window.Height - DstPaddingY;
int DstY1 = FlipY ? Window.Height - DstPaddingY : DstPaddingY;
- if (SrcFb == 0) SrcFb = GL.GenFramebuffer();
-
- GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0);
-
GL.Viewport(0, 0, Window.Width, Window.Height);
+ if (SrcFb == 0)
+ {
+ SrcFb = GL.GenFramebuffer();
+ }
+
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb);
+ GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, 0);
GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, FramebufferAttachment.ColorAttachment0, ReadTex.Handle, 0);
@@ -298,7 +281,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.BlitFramebuffer(
SrcX0, SrcY0, SrcX1, SrcY1,
DstX0, DstY0, DstX1, DstY1,
- ClearBufferMask.ColorBufferBit, BlitFramebufferFilter.Linear);
+ ClearBufferMask.ColorBufferBit,
+ BlitFramebufferFilter.Linear);
EnsureFrameBuffer();
}
@@ -315,183 +299,145 @@ namespace Ryujinx.Graphics.Gal.OpenGL
int DstX1,
int DstY1)
{
- if (Texture.TryGetImage(SrcKey, out ImageHandler SrcTex) &&
- Texture.TryGetImage(DstKey, out ImageHandler DstTex))
+ if (Texture.TryGetImageHandler(SrcKey, out ImageHandler SrcTex) &&
+ Texture.TryGetImageHandler(DstKey, out ImageHandler DstTex))
{
- if (SrcTex.HasColor != DstTex.HasColor ||
- SrcTex.HasDepth != DstTex.HasDepth ||
+ if (SrcTex.HasColor != DstTex.HasColor ||
+ SrcTex.HasDepth != DstTex.HasDepth ||
SrcTex.HasStencil != DstTex.HasStencil)
{
throw new NotImplementedException();
}
- if (SrcTex.HasColor)
+ if (SrcFb == 0)
{
- CopyTextures(
- SrcX0, SrcY0, SrcX1, SrcY1,
- DstX0, DstY0, DstX1, DstY1,
- SrcTex.Handle,
- DstTex.Handle,
- FramebufferAttachment.ColorAttachment0,
- ClearBufferMask.ColorBufferBit,
- true);
+ SrcFb = GL.GenFramebuffer();
}
- 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)
+
+ if (DstFb == 0)
{
- CopyTextures(
- SrcX0, SrcY0, SrcX1, SrcY1,
- DstX0, DstY0, DstX1, DstY1,
- SrcTex.Handle,
- DstTex.Handle,
- FramebufferAttachment.StencilAttachment,
- ClearBufferMask.StencilBufferBit,
- false);
+ DstFb = GL.GenFramebuffer();
}
- else
+
+ GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb);
+ GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DstFb);
+
+ FramebufferAttachment Attachment = GetAttachment(SrcTex);
+
+ GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, Attachment, SrcTex.Handle, 0);
+ GL.FramebufferTexture(FramebufferTarget.DrawFramebuffer, Attachment, DstTex.Handle, 0);
+
+ BlitFramebufferFilter Filter = BlitFramebufferFilter.Nearest;
+
+ if (SrcTex.HasColor)
{
- throw new InvalidOperationException();
+ GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
+
+ Filter = BlitFramebufferFilter.Linear;
}
- }
- }
- public void GetBufferData(long Key, Action<byte[]> Callback)
- {
- if (Texture.TryGetImage(Key, out ImageHandler Tex))
- {
- byte[] Data = new byte[ImageUtils.GetSize(Tex.Image)];
+ ClearBufferMask Mask = GetClearMask(SrcTex);
- GL.BindTexture(TextureTarget.Texture2D, Tex.Handle);
+ GL.Clear(Mask);
- GL.GetTexImage(
- TextureTarget.Texture2D,
- 0,
- Tex.PixelFormat,
- Tex.PixelType,
- Data);
+ GL.BlitFramebuffer(SrcX0, SrcY0, SrcX1, SrcY1, DstX0, DstY0, DstX1, DstY1, Mask, Filter);
- Callback(Data);
+ EnsureFrameBuffer();
}
}
- public void SetBufferData(
- long Key,
- int Width,
- int Height,
- byte[] Buffer)
+ public void Reinterpret(long Key, GalImage NewImage)
{
- if (Texture.TryGetImage(Key, out ImageHandler Tex))
+ if (!Texture.TryGetImage(Key, out GalImage OldImage))
{
- GL.BindTexture(TextureTarget.Texture2D, Tex.Handle);
-
- const int Level = 0;
- const int Border = 0;
-
- GL.TexImage2D(
- TextureTarget.Texture2D,
- Level,
- Tex.InternalFormat,
- Width,
- Height,
- Border,
- Tex.PixelFormat,
- Tex.PixelType,
- Buffer);
+ return;
}
- }
- private void EnsureFrameBuffer()
- {
- if (DummyFrameBuffer == 0)
+ if (NewImage.Format == OldImage.Format)
{
- DummyFrameBuffer = GL.GenFramebuffer();
+ return;
}
- GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DummyFrameBuffer);
+ byte[] Data = GetData(Key);
+
+ GL.PixelStore(PixelStoreParameter.UnpackRowLength, OldImage.Width);
+
+ Texture.Create(Key, Data, NewImage);
+
+ GL.PixelStore(PixelStoreParameter.UnpackRowLength, 0);
}
- private void Attach(ref int OldHandle, int NewHandle, FramebufferAttachment FbAttachment)
+ public byte[] GetData(long Key)
{
- if (OldHandle != NewHandle)
+ if (!Texture.TryGetImageHandler(Key, out ImageHandler CachedImage))
{
- GL.FramebufferTexture(
- FramebufferTarget.DrawFramebuffer,
- FbAttachment,
- NewHandle,
- 0);
-
- OldHandle = NewHandle;
+ return null;
}
- }
- 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)
- {
- if (SrcFb == 0) SrcFb = GL.GenFramebuffer();
- if (DstFb == 0) DstFb = GL.GenFramebuffer();
+ if (SrcFb == 0)
+ {
+ SrcFb = GL.GenFramebuffer();
+ }
GL.BindFramebuffer(FramebufferTarget.ReadFramebuffer, SrcFb);
- GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DstFb);
- GL.FramebufferTexture(
- FramebufferTarget.ReadFramebuffer,
- Attachment,
- SrcTexture,
- 0);
+ FramebufferAttachment Attachment = GetAttachment(CachedImage);
+
+ GL.FramebufferTexture(FramebufferTarget.ReadFramebuffer, Attachment, CachedImage.Handle, 0);
+
+ int Size = ImageUtils.GetSize(CachedImage.Image);
+
+ byte[] Data = new byte[Size];
- GL.FramebufferTexture(
- FramebufferTarget.DrawFramebuffer,
- Attachment,
- DstTexture,
- 0);
+ int Width = CachedImage.Width;
+ int Height = CachedImage.Height;
- if (Color)
+ (_, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(CachedImage.Format);
+
+ GL.ReadPixels(0, 0, Width, Height, Format, Type, Data);
+
+ return Data;
+ }
+
+ private static FramebufferAttachment GetAttachment(ImageHandler CachedImage)
+ {
+ if (CachedImage.HasColor)
{
- GL.DrawBuffer(DrawBufferMode.ColorAttachment0);
+ return FramebufferAttachment.ColorAttachment0;
+ }
+ else if (CachedImage.HasDepth && CachedImage.HasStencil)
+ {
+ return FramebufferAttachment.DepthStencilAttachment;
+ }
+ else if (CachedImage.HasDepth)
+ {
+ return FramebufferAttachment.DepthAttachment;
+ }
+ else if (CachedImage.HasStencil)
+ {
+ return FramebufferAttachment.StencilAttachment;
+ }
+ else
+ {
+ throw new InvalidOperationException();
}
+ }
- GL.Clear(Mask);
+ private static ClearBufferMask GetClearMask(ImageHandler CachedImage)
+ {
+ return (CachedImage.HasColor ? ClearBufferMask.ColorBufferBit : 0) |
+ (CachedImage.HasDepth ? ClearBufferMask.DepthBufferBit : 0) |
+ (CachedImage.HasStencil ? ClearBufferMask.StencilBufferBit : 0);
+ }
- GL.BlitFramebuffer(
- SrcX0, SrcY0, SrcX1, SrcY1,
- DstX0, DstY0, DstX1, DstY1,
- Mask,
- Color ? BlitFramebufferFilter.Linear : BlitFramebufferFilter.Nearest);
+ private void EnsureFrameBuffer()
+ {
+ if (DummyFrameBuffer == 0)
+ {
+ DummyFrameBuffer = GL.GenFramebuffer();
+ }
- EnsureFrameBuffer();
+ GL.BindFramebuffer(FramebufferTarget.DrawFramebuffer, DummyFrameBuffer);
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs
index 7e1c0e53..3347afbd 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLTexture.cs
@@ -28,17 +28,65 @@ namespace Ryujinx.Graphics.Gal.OpenGL
GL.DeleteTexture(CachedImage.Handle);
}
- public void Create(long Key, byte[] Data, GalImage Image)
+ public void Create(long Key, int Size, GalImage Image)
{
int Handle = GL.GenTexture();
- TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length);
+ GL.BindTexture(TextureTarget.Texture2D, Handle);
+
+ const int Level = 0; //TODO: Support mipmap textures.
+ const int Border = 0;
+
+ TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Size);
+
+ GalImageFormat TypeLess = Image.Format & GalImageFormat.FormatMask;
+
+ bool IsASTC = TypeLess >= GalImageFormat.ASTC_BEGIN && TypeLess <= GalImageFormat.ASTC_END;
+
+ if (ImageUtils.IsCompressed(Image.Format) && !IsASTC)
+ {
+ InternalFormat InternalFmt = OGLEnumConverter.GetCompressedImageFormat(Image.Format);
+
+ GL.CompressedTexImage2D(
+ TextureTarget.Texture2D,
+ Level,
+ InternalFmt,
+ Image.Width,
+ Image.Height,
+ Border,
+ Size,
+ IntPtr.Zero);
+ }
+ else
+ {
+ (PixelInternalFormat InternalFmt,
+ PixelFormat Format,
+ PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
+
+ GL.TexImage2D(
+ TextureTarget.Texture2D,
+ Level,
+ InternalFmt,
+ Image.Width,
+ Image.Height,
+ Border,
+ Format,
+ Type,
+ IntPtr.Zero);
+ }
+ }
+
+ public void Create(long Key, byte[] Data, GalImage Image)
+ {
+ int Handle = GL.GenTexture();
GL.BindTexture(TextureTarget.Texture2D, Handle);
const int Level = 0; //TODO: Support mipmap textures.
const int Border = 0;
+ TextureCache.AddOrUpdate(Key, new ImageHandler(Handle, Image), (uint)Data.Length);
+
GalImageFormat TypeLess = Image.Format & GalImageFormat.FormatMask;
bool IsASTC = TypeLess >= GalImageFormat.ASTC_BEGIN && TypeLess <= GalImageFormat.ASTC_END;
@@ -62,8 +110,8 @@ namespace Ryujinx.Graphics.Gal.OpenGL
//TODO: Use KHR_texture_compression_astc_hdr when available
if (IsASTC)
{
- int TextureBlockWidth = GetAstcBlockWidth(Image.Format);
- int TextureBlockHeight = GetAstcBlockHeight(Image.Format);
+ int TextureBlockWidth = ImageUtils.GetBlockWidth(Image.Format);
+ int TextureBlockHeight = ImageUtils.GetBlockHeight(Image.Format);
Data = ASTCDecoder.DecodeToRGBA8888(
Data,
@@ -85,12 +133,14 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Image.Format = GalImageFormat.R8G8 | (Image.Format & GalImageFormat.TypeMask);
}
- (PixelInternalFormat InternalFormat, PixelFormat Format, PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
+ (PixelInternalFormat InternalFmt,
+ PixelFormat Format,
+ PixelType Type) = OGLEnumConverter.GetImageFormat(Image.Format);
GL.TexImage2D(
TextureTarget.Texture2D,
Level,
- InternalFormat,
+ InternalFmt,
Image.Width,
Image.Height,
Border,
@@ -98,112 +148,51 @@ namespace Ryujinx.Graphics.Gal.OpenGL
Type,
Data);
}
-
- int SwizzleR = (int)OGLEnumConverter.GetTextureSwizzle(Image.XSource);
- int SwizzleG = (int)OGLEnumConverter.GetTextureSwizzle(Image.YSource);
- int SwizzleB = (int)OGLEnumConverter.GetTextureSwizzle(Image.ZSource);
- int SwizzleA = (int)OGLEnumConverter.GetTextureSwizzle(Image.WSource);
-
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleR, SwizzleR);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleG, SwizzleG);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleB, SwizzleB);
- GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleA, SwizzleA);
}
- public void CreateFb(long Key, long Size, GalImage Image)
+ public bool TryGetImage(long Key, out GalImage Image)
{
- if (!TryGetImage(Key, out ImageHandler CachedImage))
+ if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
{
- CachedImage = new ImageHandler();
-
- TextureCache.AddOrUpdate(Key, CachedImage, Size);
- }
+ Image = CachedImage.Image;
- CachedImage.EnsureSetup(Image);
- }
-
- public bool TryGetImage(long Key, out ImageHandler CachedImage)
- {
- if (TextureCache.TryGetValue(Key, out CachedImage))
- {
return true;
}
- CachedImage = null;
+ Image = default(GalImage);
return false;
}
- private static int GetAstcBlockWidth(GalImageFormat Format)
+ public bool TryGetImageHandler(long Key, out ImageHandler CachedImage)
{
- switch (Format)
- {
- case GalImageFormat.ASTC_4x4 | GalImageFormat.Unorm: return 4;
- case GalImageFormat.ASTC_5x5 | GalImageFormat.Unorm: return 5;
- case GalImageFormat.ASTC_6x6 | GalImageFormat.Unorm: return 6;
- case GalImageFormat.ASTC_8x8 | GalImageFormat.Unorm: return 8;
- case GalImageFormat.ASTC_10x10 | GalImageFormat.Unorm: return 10;
- case GalImageFormat.ASTC_12x12 | GalImageFormat.Unorm: return 12;
- case GalImageFormat.ASTC_5x4 | GalImageFormat.Unorm: return 5;
- case GalImageFormat.ASTC_6x5 | GalImageFormat.Unorm: return 6;
- case GalImageFormat.ASTC_8x6 | GalImageFormat.Unorm: return 8;
- case GalImageFormat.ASTC_10x8 | GalImageFormat.Unorm: return 10;
- case GalImageFormat.ASTC_12x10 | GalImageFormat.Unorm: return 12;
- case GalImageFormat.ASTC_8x5 | GalImageFormat.Unorm: return 8;
- case GalImageFormat.ASTC_10x5 | GalImageFormat.Unorm: return 10;
- case GalImageFormat.ASTC_10x6 | GalImageFormat.Unorm: return 10;
- }
-
- throw new ArgumentException(nameof(Format));
- }
-
- private static int GetAstcBlockHeight(GalImageFormat Format)
- {
- switch (Format)
- {
- case GalImageFormat.ASTC_4x4 | GalImageFormat.Unorm: return 4;
- case GalImageFormat.ASTC_5x5 | GalImageFormat.Unorm: return 5;
- case GalImageFormat.ASTC_6x6 | GalImageFormat.Unorm: return 6;
- case GalImageFormat.ASTC_8x8 | GalImageFormat.Unorm: return 8;
- case GalImageFormat.ASTC_10x10 | GalImageFormat.Unorm: return 10;
- case GalImageFormat.ASTC_12x12 | GalImageFormat.Unorm: return 12;
- case GalImageFormat.ASTC_5x4 | GalImageFormat.Unorm: return 4;
- case GalImageFormat.ASTC_6x5 | GalImageFormat.Unorm: return 5;
- case GalImageFormat.ASTC_8x6 | GalImageFormat.Unorm: return 6;
- case GalImageFormat.ASTC_10x8 | GalImageFormat.Unorm: return 8;
- case GalImageFormat.ASTC_12x10 | GalImageFormat.Unorm: return 10;
- case GalImageFormat.ASTC_8x5 | GalImageFormat.Unorm: return 5;
- case GalImageFormat.ASTC_10x5 | GalImageFormat.Unorm: return 5;
- case GalImageFormat.ASTC_10x6 | GalImageFormat.Unorm: return 6;
- }
-
- throw new ArgumentException(nameof(Format));
- }
-
- public bool TryGetCachedTexture(long Key, long DataSize, out GalImage Image)
- {
- if (TextureCache.TryGetSize(Key, out long Size) && Size == DataSize)
+ if (TextureCache.TryGetValue(Key, out CachedImage))
{
- if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
- {
- Image = CachedImage.Image;
-
- return true;
- }
+ return true;
}
- Image = default(GalImage);
+ CachedImage = null;
return false;
}
- public void Bind(long Key, int Index)
+ public void Bind(long Key, int Index, GalImage Image)
{
if (TextureCache.TryGetValue(Key, out ImageHandler CachedImage))
{
GL.ActiveTexture(TextureUnit.Texture0 + Index);
GL.BindTexture(TextureTarget.Texture2D, CachedImage.Handle);
+
+ int[] SwizzleRgba = new int[]
+ {
+ (int)OGLEnumConverter.GetTextureSwizzle(Image.XSource),
+ (int)OGLEnumConverter.GetTextureSwizzle(Image.YSource),
+ (int)OGLEnumConverter.GetTextureSwizzle(Image.ZSource),
+ (int)OGLEnumConverter.GetTextureSwizzle(Image.WSource)
+ };
+
+ GL.TexParameter(TextureTarget.Texture2D, TextureParameterName.TextureSwizzleRgba, SwizzleRgba);
}
}
diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
index ac34400e..60fe91c2 100644
--- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
+++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
@@ -641,6 +641,7 @@ namespace Ryujinx.Graphics.Gal.Shader
default:
SB.AppendLine(Identation + GetSrcExpr(Op, true) + ";");
+
break;
}
}
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs
index c2ee474b..0a3c0da9 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeAlu.cs
@@ -6,32 +6,32 @@ namespace Ryujinx.Graphics.Gal.Shader
{
static partial class ShaderDecode
{
- public static void Bfe_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Bfe_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitBfe(Block, OpCode, ShaderOper.CR);
}
- public static void Bfe_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Bfe_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitBfe(Block, OpCode, ShaderOper.Imm);
}
- public static void Bfe_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Bfe_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitBfe(Block, OpCode, ShaderOper.RR);
}
- public static void Fadd_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fadd_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFadd(Block, OpCode, ShaderOper.CR);
}
- public static void Fadd_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fadd_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFadd(Block, OpCode, ShaderOper.Immf);
}
- public static void Fadd_I32(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fadd_I32(ShaderIrBlock Block, long OpCode, int Position)
{
ShaderIrNode OperA = OpCode.Gpr8();
ShaderIrNode OperB = OpCode.Immf32_20();
@@ -49,47 +49,47 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op)));
}
- public static void Fadd_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fadd_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFadd(Block, OpCode, ShaderOper.RR);
}
- public static void Ffma_CR(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Ffma_CR(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFfma(Block, OpCode, ShaderOper.CR);
}
- public static void Ffma_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Ffma_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFfma(Block, OpCode, ShaderOper.Immf);
}
- public static void Ffma_RC(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Ffma_RC(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFfma(Block, OpCode, ShaderOper.RC);
}
- public static void Ffma_RR(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Ffma_RR(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFfma(Block, OpCode, ShaderOper.RR);
}
- public static void Fmnmx_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fmnmx_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFmnmx(Block, OpCode, ShaderOper.CR);
}
- public static void Fmnmx_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fmnmx_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFmnmx(Block, OpCode, ShaderOper.Immf);
}
- public static void Fmnmx_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fmnmx_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFmnmx(Block, OpCode, ShaderOper.RR);
}
- public static void Fmul_I32(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fmul_I32(ShaderIrBlock Block, long OpCode, int Position)
{
ShaderIrNode OperA = OpCode.Gpr8();
ShaderIrNode OperB = OpCode.Immf32_20();
@@ -99,62 +99,62 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op)));
}
- public static void Fmul_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fmul_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFmul(Block, OpCode, ShaderOper.CR);
}
- public static void Fmul_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fmul_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFmul(Block, OpCode, ShaderOper.Immf);
}
- public static void Fmul_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fmul_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFmul(Block, OpCode, ShaderOper.RR);
}
- public static void Fset_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fset_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFset(Block, OpCode, ShaderOper.CR);
}
- public static void Fset_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fset_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFset(Block, OpCode, ShaderOper.Immf);
}
- public static void Fset_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fset_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFset(Block, OpCode, ShaderOper.RR);
}
- public static void Fsetp_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fsetp_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFsetp(Block, OpCode, ShaderOper.CR);
}
- public static void Fsetp_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fsetp_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFsetp(Block, OpCode, ShaderOper.Immf);
}
- public static void Fsetp_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Fsetp_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitFsetp(Block, OpCode, ShaderOper.RR);
}
- public static void Iadd_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Iadd_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIadd(Block, OpCode, ShaderOper.CR);
}
- public static void Iadd_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Iadd_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIadd(Block, OpCode, ShaderOper.Imm);
}
- public static void Iadd_I32(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Iadd_I32(ShaderIrBlock Block, long OpCode, int Position)
{
ShaderIrNode OperA = OpCode.Gpr8();
ShaderIrNode OperB = OpCode.Imm32_20();
@@ -168,42 +168,42 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op)));
}
- public static void Iadd_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Iadd_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIadd(Block, OpCode, ShaderOper.RR);
}
- public static void Iadd3_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Iadd3_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIadd3(Block, OpCode, ShaderOper.CR);
}
- public static void Iadd3_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Iadd3_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIadd3(Block, OpCode, ShaderOper.Imm);
}
- public static void Iadd3_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Iadd3_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIadd3(Block, OpCode, ShaderOper.RR);
}
- public static void Imnmx_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Imnmx_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitImnmx(Block, OpCode, ShaderOper.CR);
}
- public static void Imnmx_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Imnmx_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitImnmx(Block, OpCode, ShaderOper.Imm);
}
- public static void Imnmx_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Imnmx_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitImnmx(Block, OpCode, ShaderOper.RR);
}
- public static void Ipa(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Ipa(ShaderIrBlock Block, long OpCode, int Position)
{
ShaderIrNode OperA = OpCode.Abuf28();
ShaderIrNode OperB = OpCode.Gpr20();
@@ -217,52 +217,52 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op)));
}
- public static void Iscadd_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Iscadd_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIscadd(Block, OpCode, ShaderOper.CR);
}
- public static void Iscadd_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Iscadd_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIscadd(Block, OpCode, ShaderOper.Imm);
}
- public static void Iscadd_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Iscadd_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIscadd(Block, OpCode, ShaderOper.RR);
}
- public static void Iset_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Iset_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIset(Block, OpCode, ShaderOper.CR);
}
- public static void Iset_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Iset_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIset(Block, OpCode, ShaderOper.Imm);
}
- public static void Iset_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Iset_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIset(Block, OpCode, ShaderOper.RR);
}
- public static void Isetp_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Isetp_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIsetp(Block, OpCode, ShaderOper.CR);
}
- public static void Isetp_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Isetp_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIsetp(Block, OpCode, ShaderOper.Imm);
}
- public static void Isetp_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Isetp_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitIsetp(Block, OpCode, ShaderOper.RR);
}
- public static void Lop_I32(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Lop_I32(ShaderIrBlock Block, long OpCode, int Position)
{
int SubOp = OpCode.Read(53, 3);
@@ -296,22 +296,22 @@ namespace Ryujinx.Graphics.Gal.Shader
}
}
- public static void Lop_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Lop_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitLop(Block, OpCode, ShaderOper.CR);
}
- public static void Lop_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Lop_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitLop(Block, OpCode, ShaderOper.Imm);
}
- public static void Lop_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Lop_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitLop(Block, OpCode, ShaderOper.RR);
}
- public static void Mufu(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Mufu(ShaderIrBlock Block, long OpCode, int Position)
{
int SubOp = OpCode.Read(20, 0xf);
@@ -340,7 +340,7 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Op)));
}
- public static void Psetp(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Psetp(ShaderIrBlock Block, long OpCode, int Position)
{
bool NegA = OpCode.Read(15);
bool NegB = OpCode.Read(32);
@@ -394,47 +394,47 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(P0Node, Op)));
}
- public static void Rro_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Rro_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitRro(Block, OpCode, ShaderOper.CR);
}
- public static void Rro_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Rro_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitRro(Block, OpCode, ShaderOper.Immf);
}
- public static void Rro_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Rro_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitRro(Block, OpCode, ShaderOper.RR);
}
- public static void Shl_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Shl_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitAluBinary(Block, OpCode, ShaderOper.CR, ShaderIrInst.Lsl);
}
- public static void Shl_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Shl_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitAluBinary(Block, OpCode, ShaderOper.Imm, ShaderIrInst.Lsl);
}
- public static void Shl_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Shl_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitAluBinary(Block, OpCode, ShaderOper.RR, ShaderIrInst.Lsl);
}
- public static void Shr_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Shr_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitAluBinary(Block, OpCode, ShaderOper.CR, GetShrInst(OpCode));
}
- public static void Shr_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Shr_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitAluBinary(Block, OpCode, ShaderOper.Imm, GetShrInst(OpCode));
}
- public static void Shr_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Shr_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitAluBinary(Block, OpCode, ShaderOper.RR, GetShrInst(OpCode));
}
@@ -446,7 +446,7 @@ namespace Ryujinx.Graphics.Gal.Shader
return Signed ? ShaderIrInst.Asr : ShaderIrInst.Lsr;
}
- public static void Vmad(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Vmad(ShaderIrBlock Block, long OpCode, int Position)
{
ShaderIrNode OperA = OpCode.Gpr8();
@@ -481,22 +481,22 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Final)));
}
- public static void Xmad_CR(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Xmad_CR(ShaderIrBlock Block, long OpCode, int Position)
{
EmitXmad(Block, OpCode, ShaderOper.CR);
}
- public static void Xmad_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Xmad_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitXmad(Block, OpCode, ShaderOper.Imm);
}
- public static void Xmad_RC(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Xmad_RC(ShaderIrBlock Block, long OpCode, int Position)
{
EmitXmad(Block, OpCode, ShaderOper.RC);
}
- public static void Xmad_RR(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Xmad_RR(ShaderIrBlock Block, long OpCode, int Position)
{
EmitXmad(Block, OpCode, ShaderOper.RR);
}
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs
index dfd10e00..bc2539bd 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFlow.cs
@@ -1,12 +1,10 @@
using System;
-using static Ryujinx.Graphics.Gal.Shader.ShaderDecodeHelper;
-
namespace Ryujinx.Graphics.Gal.Shader
{
static partial class ShaderDecode
{
- public static void Bra(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Bra(ShaderIrBlock Block, long OpCode, int Position)
{
if ((OpCode & 0x20) != 0)
{
@@ -15,14 +13,12 @@ namespace Ryujinx.Graphics.Gal.Shader
throw new NotImplementedException();
}
- int Target = OpCode.Branch();
-
- ShaderIrOperImm Imm = new ShaderIrOperImm(Target);
+ ShaderIrOperImm Imm = new ShaderIrOperImm(Position + OpCode.Branch());
Block.AddNode(OpCode.PredNode(new ShaderIrOp(ShaderIrInst.Bra, Imm)));
}
- public static void Exit(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Exit(ShaderIrBlock Block, long OpCode, int Position)
{
int CCode = (int)OpCode & 0x1f;
@@ -31,15 +27,14 @@ namespace Ryujinx.Graphics.Gal.Shader
{
Block.AddNode(OpCode.PredNode(new ShaderIrOp(ShaderIrInst.Exit)));
}
-
}
- public static void Kil(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Kil(ShaderIrBlock Block, long OpCode, int Position)
{
Block.AddNode(OpCode.PredNode(new ShaderIrOp(ShaderIrInst.Kil)));
}
- public static void Ssy(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Ssy(ShaderIrBlock Block, long OpCode, int Position)
{
if ((OpCode & 0x20) != 0)
{
@@ -48,19 +43,14 @@ namespace Ryujinx.Graphics.Gal.Shader
throw new NotImplementedException();
}
- int Offset = OpCode.Branch();
-
- int Target = (int)(Position + Offset);
-
- ShaderIrOperImm Imm = new ShaderIrOperImm(Target);
+ ShaderIrOperImm Imm = new ShaderIrOperImm(Position + OpCode.Branch());
Block.AddNode(new ShaderIrOp(ShaderIrInst.Ssy, Imm));
}
- public static void Sync(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Sync(ShaderIrBlock Block, long OpCode, int Position)
{
//TODO: Implement Sync condition codes
-
Block.AddNode(OpCode.PredNode(new ShaderIrOp(ShaderIrInst.Sync)));
}
}
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecode.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFunc.cs
index 73625f65..73248aa0 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecode.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeFunc.cs
@@ -1,4 +1,4 @@
namespace Ryujinx.Graphics.Gal.Shader
{
- delegate void ShaderDecodeFunc(ShaderIrBlock Block, long OpCode, long Position);
+ delegate void ShaderDecodeFunc(ShaderIrBlock Block, long OpCode, int Position);
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs
index 010f06aa..ebacd53a 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeHelper.cs
@@ -1,5 +1,3 @@
-using System;
-
namespace Ryujinx.Graphics.Gal.Shader
{
static class ShaderDecodeHelper
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs
index 508a0205..cd655995 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMem.cs
@@ -31,7 +31,7 @@ namespace Ryujinx.Graphics.Gal.Shader
{ RGB_, RG_A, R_BA, _GBA, RGBA, ____, ____, ____ }
};
- public static void Ld_A(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Ld_A(ShaderIrBlock Block, long OpCode, int Position)
{
ShaderIrNode[] Opers = OpCode.Abuf20();
@@ -50,7 +50,7 @@ namespace Ryujinx.Graphics.Gal.Shader
}
}
- public static void Ld_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Ld_C(ShaderIrBlock Block, long OpCode, int Position)
{
int CbufPos = OpCode.Read(22, 0x3fff);
int CbufIndex = OpCode.Read(36, 0x1f);
@@ -97,7 +97,7 @@ namespace Ryujinx.Graphics.Gal.Shader
}
}
- public static void St_A(ShaderIrBlock Block, long OpCode, long Position)
+ public static void St_A(ShaderIrBlock Block, long OpCode, int Position)
{
ShaderIrNode[] Opers = OpCode.Abuf20();
@@ -113,7 +113,7 @@ namespace Ryujinx.Graphics.Gal.Shader
}
}
- public static void Texq(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Texq(ShaderIrBlock Block, long OpCode, int Position)
{
ShaderIrNode OperD = OpCode.Gpr0();
ShaderIrNode OperA = OpCode.Gpr8();
@@ -132,12 +132,12 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OperA, Op1))); //Is this right?
}
- public static void Tex(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Tex(ShaderIrBlock Block, long OpCode, int Position)
{
EmitTex(Block, OpCode, GprHandle: false);
}
- public static void Tex_B(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Tex_B(ShaderIrBlock Block, long OpCode, int Position)
{
EmitTex(Block, OpCode, GprHandle: true);
}
@@ -202,12 +202,12 @@ namespace Ryujinx.Graphics.Gal.Shader
}
}
- public static void Texs(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Texs(ShaderIrBlock Block, long OpCode, int Position)
{
EmitTexs(Block, OpCode, ShaderIrInst.Texs);
}
- public static void Tlds(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Tlds(ShaderIrBlock Block, long OpCode, int Position)
{
EmitTexs(Block, OpCode, ShaderIrInst.Txlf);
}
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs
index add39402..cd602db7 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeMove.cs
@@ -25,67 +25,67 @@ namespace Ryujinx.Graphics.Gal.Shader
F64 = 3
}
- public static void F2f_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void F2f_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitF2f(Block, OpCode, ShaderOper.CR);
}
- public static void F2f_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void F2f_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitF2f(Block, OpCode, ShaderOper.Immf);
}
- public static void F2f_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void F2f_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitF2f(Block, OpCode, ShaderOper.RR);
}
- public static void F2i_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void F2i_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitF2i(Block, OpCode, ShaderOper.CR);
}
- public static void F2i_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void F2i_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitF2i(Block, OpCode, ShaderOper.Immf);
}
- public static void F2i_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void F2i_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitF2i(Block, OpCode, ShaderOper.RR);
}
- public static void I2f_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void I2f_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitI2f(Block, OpCode, ShaderOper.CR);
}
- public static void I2f_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void I2f_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitI2f(Block, OpCode, ShaderOper.Imm);
}
- public static void I2f_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void I2f_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitI2f(Block, OpCode, ShaderOper.RR);
}
- public static void I2i_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void I2i_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitI2i(Block, OpCode, ShaderOper.CR);
}
- public static void I2i_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void I2i_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitI2i(Block, OpCode, ShaderOper.Imm);
}
- public static void I2i_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void I2i_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitI2i(Block, OpCode, ShaderOper.RR);
}
- public static void Isberd(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Isberd(ShaderIrBlock Block, long OpCode, int Position)
{
//This instruction seems to be used to translate from an address to a vertex index in a GS
//Stub it as such
@@ -95,50 +95,50 @@ namespace Ryujinx.Graphics.Gal.Shader
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), OpCode.Gpr8())));
}
- public static void Mov_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Mov_C(ShaderIrBlock Block, long OpCode, int Position)
{
ShaderIrOperCbuf Cbuf = OpCode.Cbuf34();
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Cbuf)));
}
- public static void Mov_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Mov_I(ShaderIrBlock Block, long OpCode, int Position)
{
ShaderIrOperImm Imm = OpCode.Imm19_20();
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Imm)));
}
- public static void Mov_I32(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Mov_I32(ShaderIrBlock Block, long OpCode, int Position)
{
ShaderIrOperImm Imm = OpCode.Imm32_20();
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Imm)));
}
- public static void Mov_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Mov_R(ShaderIrBlock Block, long OpCode, int Position)
{
ShaderIrOperGpr Gpr = OpCode.Gpr20();
Block.AddNode(OpCode.PredNode(new ShaderIrAsg(OpCode.Gpr0(), Gpr)));
}
- public static void Sel_C(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Sel_C(ShaderIrBlock Block, long OpCode, int Position)
{
EmitSel(Block, OpCode, ShaderOper.CR);
}
- public static void Sel_I(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Sel_I(ShaderIrBlock Block, long OpCode, int Position)
{
EmitSel(Block, OpCode, ShaderOper.Imm);
}
- public static void Sel_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Sel_R(ShaderIrBlock Block, long OpCode, int Position)
{
EmitSel(Block, OpCode, ShaderOper.RR);
}
- public static void Mov_S(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Mov_S(ShaderIrBlock Block, long OpCode, int Position)
{
Block.AddNode(new ShaderIrCmnt("Stubbed."));
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeSpecial.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeSpecial.cs
index c3e42654..35abdb76 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecodeSpecial.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecodeSpecial.cs
@@ -1,10 +1,8 @@
-using static Ryujinx.Graphics.Gal.Shader.ShaderDecodeHelper;
-
-namespace Ryujinx.Graphics.Gal.Shader
+namespace Ryujinx.Graphics.Gal.Shader
{
static partial class ShaderDecode
{
- public static void Out_R(ShaderIrBlock Block, long OpCode, long Position)
+ public static void Out_R(ShaderIrBlock Block, long OpCode, int Position)
{
//TODO: Those registers have to be used for something
ShaderIrOperGpr Gpr0 = OpCode.Gpr0();
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs b/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
index 81d8f312..ac6ae8d5 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderDecoder.cs
@@ -10,12 +10,14 @@ namespace Ryujinx.Graphics.Gal.Shader
public static ShaderIrBlock[] Decode(IGalMemory Memory, long Start)
{
- Dictionary<long, ShaderIrBlock> Visited = new Dictionary<long, ShaderIrBlock>();
- Dictionary<long, ShaderIrBlock> VisitedEnd = new Dictionary<long, ShaderIrBlock>();
+ Dictionary<int, ShaderIrBlock> Visited = new Dictionary<int, ShaderIrBlock>();
+ Dictionary<int, ShaderIrBlock> VisitedEnd = new Dictionary<int, ShaderIrBlock>();
Queue<ShaderIrBlock> Blocks = new Queue<ShaderIrBlock>();
- ShaderIrBlock Enqueue(long Position, ShaderIrBlock Source = null)
+ long Beginning = Start + HeaderSize;
+
+ ShaderIrBlock Enqueue(int Position, ShaderIrBlock Source = null)
{
if (!Visited.TryGetValue(Position, out ShaderIrBlock Output))
{
@@ -34,13 +36,13 @@ namespace Ryujinx.Graphics.Gal.Shader
return Output;
}
- ShaderIrBlock Entry = Enqueue(Start + HeaderSize);
+ ShaderIrBlock Entry = Enqueue(0);
while (Blocks.Count > 0)
{
ShaderIrBlock Current = Blocks.Dequeue();
- FillBlock(Memory, Current, Start + HeaderSize);
+ FillBlock(Memory, Current, Beginning);
//Set child blocks. "Branch" is the block the branch instruction
//points to (when taken), "Next" is the block at the next address,
@@ -54,20 +56,18 @@ namespace Ryujinx.Graphics.Gal.Shader
if (InnerOp?.Inst == ShaderIrInst.Bra)
{
- int Offset = ((ShaderIrOperImm)InnerOp.OperandA).Value;
-
- long Target = Current.EndPosition + Offset;
+ int Target = ((ShaderIrOperImm)InnerOp.OperandA).Value;
Current.Branch = Enqueue(Target, Current);
}
foreach (ShaderIrNode Node in Current.Nodes)
{
- if (Node is ShaderIrOp CurrOp && CurrOp.Inst == ShaderIrInst.Ssy)
- {
- int Offset = ((ShaderIrOperImm)CurrOp.OperandA).Value;
+ InnerOp = GetInnermostOp(Node);
- long Target = Offset;
+ if (InnerOp is ShaderIrOp CurrOp && CurrOp.Inst == ShaderIrInst.Ssy)
+ {
+ int Target = ((ShaderIrOperImm)CurrOp.OperandA).Value;
Current.Branch = Enqueue(Target, Current);
}
@@ -112,15 +112,15 @@ namespace Ryujinx.Graphics.Gal.Shader
while (Visited.Count > 0)
{
- ulong FirstPos = ulong.MaxValue;
+ uint FirstPos = uint.MaxValue;
foreach (ShaderIrBlock Block in Visited.Values)
{
- if (FirstPos > (ulong)Block.Position)
- FirstPos = (ulong)Block.Position;
+ if (FirstPos > (uint)Block.Position)
+ FirstPos = (uint)Block.Position;
}
- ShaderIrBlock Current = Visited[(long)FirstPos];
+ ShaderIrBlock Current = Visited[(int)FirstPos];
do
{
@@ -138,20 +138,20 @@ namespace Ryujinx.Graphics.Gal.Shader
private static void FillBlock(IGalMemory Memory, ShaderIrBlock Block, long Beginning)
{
- long Position = Block.Position;
+ int Position = Block.Position;
do
{
//Ignore scheduling instructions, which are written every 32 bytes.
- if (((Position - Beginning) & 0x1f) == 0)
+ if ((Position & 0x1f) == 0)
{
Position += 8;
continue;
}
- uint Word0 = (uint)Memory.ReadInt32(Position + 0);
- uint Word1 = (uint)Memory.ReadInt32(Position + 4);
+ uint Word0 = (uint)Memory.ReadInt32(Position + Beginning + 0);
+ uint Word1 = (uint)Memory.ReadInt32(Position + Beginning + 4);
Position += 8;
@@ -161,7 +161,7 @@ namespace Ryujinx.Graphics.Gal.Shader
if (AddDbgComments)
{
- string DbgOpCode = $"0x{(Position - Beginning - 8):x16}: 0x{OpCode:x16} ";
+ string DbgOpCode = $"0x{(Position - 8):x16}: 0x{OpCode:x16} ";
DbgOpCode += (Decode?.Method.Name ?? "???");
@@ -169,7 +169,7 @@ namespace Ryujinx.Graphics.Gal.Shader
{
int Offset = ((int)(OpCode >> 20) << 8) >> 8;
- long Target = Position + Offset - Beginning;
+ long Target = Position + Offset;
DbgOpCode += " (0x" + Target.ToString("x16") + ")";
}
diff --git a/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs b/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs
index 50e563b8..782f9626 100644
--- a/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs
+++ b/Ryujinx.Graphics/Gal/Shader/ShaderIrBlock.cs
@@ -4,8 +4,8 @@ namespace Ryujinx.Graphics.Gal.Shader
{
class ShaderIrBlock
{
- public long Position { get; set; }
- public long EndPosition { get; set; }
+ public int Position { get; set; }
+ public int EndPosition { get; set; }
public ShaderIrBlock Next { get; set; }
public ShaderIrBlock Branch { get; set; }
@@ -14,7 +14,7 @@ namespace Ryujinx.Graphics.Gal.Shader
public List<ShaderIrNode> Nodes { get; private set; }
- public ShaderIrBlock(long Position)
+ public ShaderIrBlock(int Position)
{
this.Position = Position;
diff --git a/Ryujinx.Graphics/GpuResourceManager.cs b/Ryujinx.Graphics/GpuResourceManager.cs
new file mode 100644
index 00000000..ba35910d
--- /dev/null
+++ b/Ryujinx.Graphics/GpuResourceManager.cs
@@ -0,0 +1,122 @@
+using Ryujinx.Graphics.Gal;
+using Ryujinx.Graphics.Memory;
+using Ryujinx.Graphics.Texture;
+using System.Collections.Generic;
+
+namespace Ryujinx.Graphics
+{
+ public class GpuResourceManager
+ {
+ private NvGpu Gpu;
+
+ private HashSet<long>[] UploadedKeys;
+
+ public GpuResourceManager(NvGpu Gpu)
+ {
+ this.Gpu = Gpu;
+
+ UploadedKeys = new HashSet<long>[(int)NvGpuBufferType.Count];
+
+ for (int Index = 0; Index < UploadedKeys.Length; Index++)
+ {
+ UploadedKeys[Index] = new HashSet<long>();
+ }
+ }
+
+ public void SendColorBuffer(NvGpuVmm Vmm, long Position, int Attachment, GalImage NewImage)
+ {
+ long Size = (uint)ImageUtils.GetSize(NewImage);
+
+ MarkAsCached(Vmm, Position, Size, NvGpuBufferType.Texture);
+
+ bool IsCached = Gpu.Renderer.Texture.TryGetImage(Position, out GalImage CachedImage);
+
+ if (IsCached && CachedImage.SizeMatches(NewImage))
+ {
+ Gpu.Renderer.RenderTarget.Reinterpret(Position, NewImage);
+ Gpu.Renderer.RenderTarget.BindColor(Position, Attachment, NewImage);
+
+ return;
+ }
+
+ Gpu.Renderer.Texture.Create(Position, (int)Size, NewImage);
+
+ Gpu.Renderer.RenderTarget.BindColor(Position, Attachment, NewImage);
+ }
+
+ public void SendZetaBuffer(NvGpuVmm Vmm, long Position, GalImage NewImage)
+ {
+ long Size = (uint)ImageUtils.GetSize(NewImage);
+
+ MarkAsCached(Vmm, Position, Size, NvGpuBufferType.Texture);
+
+ bool IsCached = Gpu.Renderer.Texture.TryGetImage(Position, out GalImage CachedImage);
+
+ if (IsCached && CachedImage.SizeMatches(NewImage))
+ {
+ Gpu.Renderer.RenderTarget.Reinterpret(Position, NewImage);
+ Gpu.Renderer.RenderTarget.BindZeta(Position, NewImage);
+
+ return;
+ }
+
+ Gpu.Renderer.Texture.Create(Position, (int)Size, NewImage);
+
+ Gpu.Renderer.RenderTarget.BindZeta(Position, NewImage);
+ }
+
+ public void SendTexture(NvGpuVmm Vmm, long Position, GalImage NewImage, int TexIndex = -1)
+ {
+ long Size = (uint)ImageUtils.GetSize(NewImage);
+
+ if (!MemoryRegionModified(Vmm, Position, Size, NvGpuBufferType.Texture))
+ {
+ if (Gpu.Renderer.Texture.TryGetImage(Position, out GalImage CachedImage) && CachedImage.SizeMatches(NewImage))
+ {
+ Gpu.Renderer.RenderTarget.Reinterpret(Position, NewImage);
+
+ if (TexIndex >= 0)
+ {
+ Gpu.Renderer.Texture.Bind(Position, TexIndex, NewImage);
+ }
+
+ return;
+ }
+ }
+
+ byte[] Data = ImageUtils.ReadTexture(Vmm, NewImage, Position);
+
+ Gpu.Renderer.Texture.Create(Position, Data, NewImage);
+
+ if (TexIndex >= 0)
+ {
+ Gpu.Renderer.Texture.Bind(Position, TexIndex, NewImage);
+ }
+ }
+
+ private void MarkAsCached(NvGpuVmm Vmm, long Position, long Size, NvGpuBufferType Type)
+ {
+ Vmm.IsRegionModified(Position, Size, Type);
+ }
+
+ private bool MemoryRegionModified(NvGpuVmm Vmm, long Position, long Size, NvGpuBufferType Type)
+ {
+ HashSet<long> Uploaded = UploadedKeys[(int)Type];
+
+ if (!Uploaded.Add(Position))
+ {
+ return false;
+ }
+
+ return Vmm.IsRegionModified(Position, Size, Type);
+ }
+
+ public void ClearPbCache()
+ {
+ for (int Index = 0; Index < UploadedKeys.Length; Index++)
+ {
+ UploadedKeys[Index].Clear();
+ }
+ }
+ }
+}
diff --git a/Ryujinx.Graphics/Memory/NvGpuVmmCache.cs b/Ryujinx.Graphics/Memory/NvGpuVmmCache.cs
index 56979e1f..f1c16a36 100644
--- a/Ryujinx.Graphics/Memory/NvGpuVmmCache.cs
+++ b/Ryujinx.Graphics/Memory/NvGpuVmmCache.cs
@@ -1,309 +1,82 @@
using ChocolArm64.Memory;
using System;
-using System.Collections.Generic;
namespace Ryujinx.Graphics.Memory
{
class NvGpuVmmCache
{
- private const long RamSize = 4L * 1024 * 1024 * 1024;
-
- private const int MaxCpCount = 10000;
- private const int MaxCpTimeDelta = 60000;
-
- private class CachedPage
- {
- private struct Range
- {
- public long Start;
- public long End;
-
- public Range(long Start, long End)
- {
- this.Start = Start;
- this.End = End;
- }
- }
-
- private List<Range>[] Regions;
-
- private HashSet<long> ResidencyKeys;
-
- public LinkedListNode<long> Node { get; set; }
-
- public int Timestamp { get; private set; }
-
- public CachedPage()
- {
- Regions = new List<Range>[(int)NvGpuBufferType.Count];
-
- for (int Index = 0; Index < Regions.Length; Index++)
- {
- Regions[Index] = new List<Range>();
- }
-
- ResidencyKeys = new HashSet<long>();
- }
-
- public void AddResidency(long Key)
- {
- ResidencyKeys.Add(Key);
- }
-
- public void RemoveResidency(HashSet<long>[] Residency, long PageSize)
- {
- for (int i = 0; i < (int)NvGpuBufferType.Count; i++)
- {
- foreach (Range Region in Regions[i])
- {
- foreach (long Key in ResidencyKeys)
- {
- Residency[Region.Start / PageSize].Remove(Key);
- }
- }
- }
- }
-
- public bool AddRange(long Start, long End, NvGpuBufferType BufferType)
- {
- List<Range> BtRegions = Regions[(int)BufferType];
-
- for (int Index = 0; Index < BtRegions.Count; Index++)
- {
- Range Rg = BtRegions[Index];
-
- if (Start >= Rg.Start && End <= Rg.End)
- {
- return false;
- }
-
- if (Start <= Rg.End && Rg.Start <= End)
- {
- long MinStart = Math.Min(Rg.Start, Start);
- long MaxEnd = Math.Max(Rg.End, End);
-
- BtRegions[Index] = new Range(MinStart, MaxEnd);
-
- Timestamp = Environment.TickCount;
-
- return true;
- }
- }
-
- BtRegions.Add(new Range(Start, End));
-
- Timestamp = Environment.TickCount;
-
- return true;
- }
-
- public int GetTotalCount()
- {
- int Count = 0;
-
- for (int Index = 0; Index < Regions.Length; Index++)
- {
- Count += Regions[Index].Count;
- }
-
- return Count;
- }
- }
-
- private Dictionary<long, CachedPage> Cache;
-
- private LinkedList<long> SortedCache;
-
- private HashSet<long>[] Residency;
-
- private long ResidencyPageSize;
-
- private int CpCount;
+ private ValueRangeSet<int> CachedRanges;
public NvGpuVmmCache()
{
- Cache = new Dictionary<long, CachedPage>();
-
- SortedCache = new LinkedList<long>();
+ CachedRanges = new ValueRangeSet<int>();
}
public bool IsRegionModified(AMemory Memory, NvGpuBufferType BufferType, long PA, long Size)
{
(bool[] Modified, long ModifiedCount) = Memory.IsRegionModified(PA, Size);
- PA = Memory.GetPhysicalAddress(PA);
-
- ClearCachedPagesIfNeeded();
-
- long PageSize = AMemory.PageSize;
-
- EnsureResidencyInitialized(PageSize);
-
- bool HasResidents = AddResidency(PA, Size);
-
- if (!HasResidents && ModifiedCount == 0)
- {
- return false;
- }
-
- long Mask = PageSize - 1;
-
- long ResidencyKey = PA;
-
- long PAEnd = PA + Size;
-
- bool RegMod = false;
-
+ //Remove all modified ranges.
int Index = 0;
- while (PA < PAEnd)
- {
- long Key = PA & ~AMemory.PageMask;
-
- long PAPgEnd = Math.Min((PA + AMemory.PageSize) & ~AMemory.PageMask, PAEnd);
-
- bool IsCached = Cache.TryGetValue(Key, out CachedPage Cp);
-
- if (IsCached)
- {
- CpCount -= Cp.GetTotalCount();
-
- SortedCache.Remove(Cp.Node);
- }
- else
- {
- Cp = new CachedPage();
-
- Cache.Add(Key, Cp);
- }
+ long Position = PA & ~NvGpuVmm.PageMask;
- if (Modified[Index++] && IsCached)
+ while (ModifiedCount > 0)
+ {
+ if (Modified[Index++])
{
- Cp = new CachedPage();
+ CachedRanges.Remove(new ValueRange<int>(Position, Position + NvGpuVmm.PageSize));
- Cache[Key] = Cp;
+ ModifiedCount--;
}
- Cp.AddResidency(ResidencyKey);
-
- Cp.Node = SortedCache.AddLast(Key);
-
- RegMod |= Cp.AddRange(PA, PAPgEnd, BufferType);
-
- CpCount += Cp.GetTotalCount();
-
- PA = PAPgEnd;
+ Position += NvGpuVmm.PageSize;
}
- return RegMod;
- }
+ //Mask has the bit set for the current resource type.
+ //If the region is not yet present on the list, then a new ValueRange
+ //is directly added with the current resource type as the only bit set.
+ //Otherwise, it just sets the bit for this new resource type on the current mask.
+ int Mask = 1 << (int)BufferType;
- private bool AddResidency(long PA, long Size)
- {
- long PageSize = ResidencyPageSize;
+ ValueRange<int> NewCached = new ValueRange<int>(PA, PA + Size);
- long Mask = PageSize - 1;
+ ValueRange<int>[] Ranges = CachedRanges.GetAllIntersections(NewCached);
- long Key = PA;
+ long LastEnd = NewCached.Start;
- bool ResidentFound = false;
+ long Coverage = 0;
- for (long Cursor = PA & ~Mask; Cursor < ((PA + Size + PageSize - 1) & ~Mask); Cursor += PageSize)
+ for (Index = 0; Index < Ranges.Length; Index++)
{
- long PageIndex = Cursor / PageSize;
-
- Residency[PageIndex].Add(Key);
+ ValueRange<int> Current = Ranges[Index];
- if (Residency[PageIndex].Count > 1)
- {
- ResidentFound = true;
- }
- }
-
- return ResidentFound;
- }
-
- private void EnsureResidencyInitialized(long PageSize)
- {
- if (Residency == null)
- {
- Residency = new HashSet<long>[RamSize / PageSize];
+ long RgStart = Math.Max(Current.Start, NewCached.Start);
+ long RgEnd = Math.Min(Current.End, NewCached.End);
- for (int i = 0; i < Residency.Length; i++)
+ if ((Current.Value & Mask) == 0)
{
- Residency[i] = new HashSet<long>();
+ CachedRanges.Add(new ValueRange<int>(RgStart, RgEnd, Current.Value | Mask));
}
-
- ResidencyPageSize = PageSize;
- }
- else
- {
- if (ResidencyPageSize != PageSize)
+ else
{
- throw new InvalidOperationException("Tried to change residency page size");
+ Coverage += RgEnd - RgStart;
}
- }
- }
-
- private void ClearCachedPagesIfNeeded()
- {
- if (CpCount <= MaxCpCount)
- {
- return;
- }
-
- int Timestamp = Environment.TickCount;
- int TimeDelta;
-
- do
- {
- if (!TryPopOldestCachedPageKey(Timestamp, out long Key))
+ if (RgStart > LastEnd)
{
- break;
+ CachedRanges.Add(new ValueRange<int>(LastEnd, RgStart, Mask));
}
- CachedPage Cp = Cache[Key];
-
- Cp.RemoveResidency(Residency, ResidencyPageSize);
-
- Cache.Remove(Key);
-
- CpCount -= Cp.GetTotalCount();
-
- TimeDelta = RingDelta(Cp.Timestamp, Timestamp);
+ LastEnd = RgEnd;
}
- while (CpCount > (MaxCpCount >> 1) || (uint)TimeDelta > (uint)MaxCpTimeDelta);
- }
-
- private bool TryPopOldestCachedPageKey(int Timestamp, out long Key)
- {
- LinkedListNode<long> Node = SortedCache.First;
- if (Node == null)
+ if (LastEnd < NewCached.End)
{
- Key = 0;
-
- return false;
+ CachedRanges.Add(new ValueRange<int>(LastEnd, NewCached.End, Mask));
}
- SortedCache.Remove(Node);
-
- Key = Node.Value;
-
- return true;
- }
-
- private int RingDelta(int Old, int New)
- {
- if ((uint)New < (uint)Old)
- {
- return New + (~Old + 1);
- }
- else
- {
- return New - Old;
- }
+ return Coverage != Size;
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/NvGpu.cs b/Ryujinx.Graphics/NvGpu.cs
index 7ba700b8..4c6abd23 100644
--- a/Ryujinx.Graphics/NvGpu.cs
+++ b/Ryujinx.Graphics/NvGpu.cs
@@ -1,5 +1,4 @@
using Ryujinx.Graphics.Gal;
-using Ryujinx.Graphics;
namespace Ryujinx.Graphics
{
@@ -7,21 +6,27 @@ namespace Ryujinx.Graphics
{
public IGalRenderer Renderer { get; private set; }
+ public GpuResourceManager ResourceManager { get; private set; }
+
public NvGpuFifo Fifo { get; private set; }
- public NvGpuEngine2d Engine2d { get; private set; }
- public NvGpuEngine3d Engine3d { get; private set; }
- public NvGpuEngineDma EngineDma { get; private set; }
+ internal NvGpuEngine2d Engine2d { get; private set; }
+ internal NvGpuEngine3d Engine3d { get; private set; }
+ internal NvGpuEngineM2mf EngineM2mf { get; private set; }
+ internal NvGpuEngineP2mf EngineP2mf { get; private set; }
public NvGpu(IGalRenderer Renderer)
{
this.Renderer = Renderer;
+ ResourceManager = new GpuResourceManager(this);
+
Fifo = new NvGpuFifo(this);
- Engine2d = new NvGpuEngine2d(this);
- Engine3d = new NvGpuEngine3d(this);
- EngineDma = new NvGpuEngineDma(this);
+ Engine2d = new NvGpuEngine2d(this);
+ Engine3d = new NvGpuEngine3d(this);
+ EngineM2mf = new NvGpuEngineM2mf(this);
+ EngineP2mf = new NvGpuEngineP2mf(this);
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Memory/NvGpuBufferType.cs b/Ryujinx.Graphics/NvGpuBufferType.cs
index 6f0d2571..f6b55597 100644
--- a/Ryujinx.Graphics/Memory/NvGpuBufferType.cs
+++ b/Ryujinx.Graphics/NvGpuBufferType.cs
@@ -1,4 +1,4 @@
-namespace Ryujinx.Graphics.Memory
+namespace Ryujinx.Graphics
{
public enum NvGpuBufferType
{
diff --git a/Ryujinx.Graphics/NvGpuEngine.cs b/Ryujinx.Graphics/NvGpuEngine.cs
index 3d5e118a..d533e478 100644
--- a/Ryujinx.Graphics/NvGpuEngine.cs
+++ b/Ryujinx.Graphics/NvGpuEngine.cs
@@ -5,7 +5,7 @@ namespace Ryujinx.Graphics
_2d = 0x902d,
_3d = 0xb197,
Compute = 0xb1c0,
- Kepler = 0xa140,
- Dma = 0xb0b5
+ P2mf = 0xa140,
+ M2mf = 0xb0b5
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/NvGpuEngine2d.cs b/Ryujinx.Graphics/NvGpuEngine2d.cs
index f26b0020..4bf7c1e8 100644
--- a/Ryujinx.Graphics/NvGpuEngine2d.cs
+++ b/Ryujinx.Graphics/NvGpuEngine2d.cs
@@ -1,7 +1,6 @@
using Ryujinx.Graphics.Gal;
using Ryujinx.Graphics.Memory;
using Ryujinx.Graphics.Texture;
-using System;
using System.Collections.Generic;
namespace Ryujinx.Graphics
@@ -62,25 +61,25 @@ namespace Ryujinx.Graphics
{
CopyOperation Operation = (CopyOperation)ReadRegister(NvGpuEngine2dReg.CopyOperation);
+ int SrcFormat = ReadRegister(NvGpuEngine2dReg.SrcFormat);
bool SrcLinear = ReadRegister(NvGpuEngine2dReg.SrcLinear) != 0;
int SrcWidth = ReadRegister(NvGpuEngine2dReg.SrcWidth);
int SrcHeight = ReadRegister(NvGpuEngine2dReg.SrcHeight);
int SrcPitch = ReadRegister(NvGpuEngine2dReg.SrcPitch);
int SrcBlkDim = ReadRegister(NvGpuEngine2dReg.SrcBlockDimensions);
+ int DstFormat = ReadRegister(NvGpuEngine2dReg.DstFormat);
bool DstLinear = ReadRegister(NvGpuEngine2dReg.DstLinear) != 0;
int DstWidth = ReadRegister(NvGpuEngine2dReg.DstWidth);
int DstHeight = ReadRegister(NvGpuEngine2dReg.DstHeight);
int DstPitch = ReadRegister(NvGpuEngine2dReg.DstPitch);
int DstBlkDim = ReadRegister(NvGpuEngine2dReg.DstBlockDimensions);
- TextureSwizzle SrcSwizzle = SrcLinear
- ? TextureSwizzle.Pitch
- : TextureSwizzle.BlockLinear;
+ GalImageFormat SrcImgFormat = ImageUtils.ConvertSurface((GalSurfaceFormat)SrcFormat);
+ GalImageFormat DstImgFormat = ImageUtils.ConvertSurface((GalSurfaceFormat)DstFormat);
- TextureSwizzle DstSwizzle = DstLinear
- ? TextureSwizzle.Pitch
- : TextureSwizzle.BlockLinear;
+ GalMemoryLayout SrcLayout = GetLayout(SrcLinear);
+ GalMemoryLayout DstLayout = GetLayout(DstLinear);
int SrcBlockHeight = 1 << ((SrcBlkDim >> 4) & 0xf);
int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf);
@@ -91,91 +90,41 @@ namespace Ryujinx.Graphics
long SrcKey = Vmm.GetPhysicalAddress(SrcAddress);
long DstKey = Vmm.GetPhysicalAddress(DstAddress);
- bool IsSrcFb = Gpu.Engine3d.IsFrameBufferPosition(SrcKey);
- bool IsDstFb = Gpu.Engine3d.IsFrameBufferPosition(DstKey);
-
- TextureInfo SrcTexture()
- {
- return new TextureInfo(
- SrcAddress,
- SrcWidth,
- SrcHeight,
- SrcPitch,
- SrcBlockHeight, 1,
- SrcSwizzle,
- GalImageFormat.A8B8G8R8 | GalImageFormat.Unorm);
- }
-
- TextureInfo DstTexture()
- {
- return new TextureInfo(
- DstAddress,
- DstWidth,
- DstHeight,
- DstPitch,
- DstBlockHeight, 1,
- DstSwizzle,
- GalImageFormat.A8B8G8R8 | GalImageFormat.Unorm);
- }
-
- //TODO: fb -> fb copies, tex -> fb copies, formats other than RGBA8,
- //make it throw for unimpl stuff (like the copy mode)...
- if (IsSrcFb && IsDstFb)
- {
- //Frame Buffer -> Frame Buffer copy.
- Gpu.Renderer.RenderTarget.Copy(
- SrcKey,
- DstKey,
- 0,
- 0,
- SrcWidth,
- SrcHeight,
- 0,
- 0,
- DstWidth,
- DstHeight);
- }
- if (IsSrcFb)
- {
- //Frame Buffer -> Texture copy.
- Gpu.Renderer.RenderTarget.GetBufferData(SrcKey, (byte[] Buffer) =>
- {
- TextureInfo Src = SrcTexture();
- TextureInfo Dst = DstTexture();
-
- if (Src.Width != Dst.Width ||
- Src.Height != Dst.Height)
- {
- throw new NotImplementedException("Texture resizing is not supported");
- }
-
- TextureWriter.Write(Vmm, Dst, Buffer);
- });
- }
- else if (IsDstFb)
- {
- byte[] Buffer = TextureReader.Read(Vmm, SrcTexture());
-
- Gpu.Renderer.RenderTarget.SetBufferData(
- DstKey,
- DstWidth,
- DstHeight,
- Buffer);
- }
- else
- {
- //Texture -> Texture copy.
- TextureInfo Src = SrcTexture();
- TextureInfo Dst = DstTexture();
-
- if (Src.Width != Dst.Width ||
- Src.Height != Dst.Height)
- {
- throw new NotImplementedException("Texture resizing is not supported");
- }
+ GalImage SrcTexture = new GalImage(
+ SrcWidth,
+ SrcHeight, 1,
+ SrcBlockHeight,
+ SrcLayout,
+ SrcImgFormat);
+
+ GalImage DstTexture = new GalImage(
+ DstWidth,
+ DstHeight, 1,
+ DstBlockHeight,
+ DstLayout,
+ DstImgFormat);
+
+ Gpu.ResourceManager.SendTexture(Vmm, SrcKey, SrcTexture);
+ Gpu.ResourceManager.SendTexture(Vmm, DstKey, DstTexture);
+
+ Gpu.Renderer.RenderTarget.Copy(
+ SrcKey,
+ DstKey,
+ 0,
+ 0,
+ SrcWidth,
+ SrcHeight,
+ 0,
+ 0,
+ DstWidth,
+ DstHeight);
+ }
- TextureWriter.Write(Vmm, Dst, TextureReader.Read(Vmm, Src));
- }
+ private static GalMemoryLayout GetLayout(bool Linear)
+ {
+ return Linear
+ ? GalMemoryLayout.Pitch
+ : GalMemoryLayout.BlockLinear;
}
private long MakeInt64From2xInt32(NvGpuEngine2dReg Reg)
diff --git a/Ryujinx.Graphics/NvGpuEngine3d.cs b/Ryujinx.Graphics/NvGpuEngine3d.cs
index 624eddae..a1d0ec80 100644
--- a/Ryujinx.Graphics/NvGpuEngine3d.cs
+++ b/Ryujinx.Graphics/NvGpuEngine3d.cs
@@ -23,8 +23,6 @@ namespace Ryujinx.Graphics
private ConstBuffer[][] ConstBuffers;
- private HashSet<long> FrameBuffers;
-
private List<long>[] UploadedKeys;
private int CurrentInstance = 0;
@@ -60,8 +58,6 @@ namespace Ryujinx.Graphics
ConstBuffers[Index] = new ConstBuffer[18];
}
- FrameBuffers = new HashSet<long>();
-
UploadedKeys = new List<long>[(int)NvGpuBufferType.Count];
for (int i = 0; i < UploadedKeys.Length; i++)
@@ -96,7 +92,7 @@ namespace Ryujinx.Graphics
GalPipelineState State = new GalPipelineState();
- SetFlip(State);
+ SetFrameBuffer(State);
SetFrontFace(State);
SetCullFace(State);
SetDepth(State);
@@ -104,10 +100,7 @@ namespace Ryujinx.Graphics
SetAlphaBlending(State);
SetPrimitiveRestart(State);
- for (int FbIndex = 0; FbIndex < 8; FbIndex++)
- {
- SetFrameBuffer(Vmm, 0);
- }
+ SetFrameBuffer(Vmm, 0);
SetZeta(Vmm);
@@ -173,9 +166,9 @@ namespace Ryujinx.Graphics
{
long VA = MakeInt64From2xInt32(NvGpuEngine3dReg.FrameBufferNAddress + FbIndex * 0x10);
- int Format = ReadRegister(NvGpuEngine3dReg.FrameBufferNFormat + FbIndex * 0x10);
+ int SurfFormat = ReadRegister(NvGpuEngine3dReg.FrameBufferNFormat + FbIndex * 0x10);
- if (VA == 0 || Format == 0)
+ if (VA == 0 || SurfFormat == 0)
{
Gpu.Renderer.RenderTarget.UnbindColor(FbIndex);
@@ -184,11 +177,15 @@ namespace Ryujinx.Graphics
long Key = Vmm.GetPhysicalAddress(VA);
- FrameBuffers.Add(Key);
-
int Width = ReadRegister(NvGpuEngine3dReg.FrameBufferNWidth + FbIndex * 0x10);
int Height = ReadRegister(NvGpuEngine3dReg.FrameBufferNHeight + FbIndex * 0x10);
+ int BlockDim = ReadRegister(NvGpuEngine3dReg.FrameBufferNBlockDim + FbIndex * 0x10);
+
+ int GobBlockHeight = 1 << ((BlockDim >> 4) & 7);
+
+ GalMemoryLayout Layout = (GalMemoryLayout)((BlockDim >> 12) & 1);
+
float TX = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateX + FbIndex * 8);
float TY = ReadRegisterFloat(NvGpuEngine3dReg.ViewportNTranslateY + FbIndex * 8);
@@ -201,48 +198,54 @@ namespace Ryujinx.Graphics
int VpW = (int)(TX + MathF.Abs(SX)) - VpX;
int VpH = (int)(TY + MathF.Abs(SY)) - VpY;
- GalImageFormat ImageFormat = ImageUtils.ConvertSurface((GalSurfaceFormat)Format);
+ GalImageFormat Format = ImageUtils.ConvertSurface((GalSurfaceFormat)SurfFormat);
- GalImage Image = new GalImage(Width, Height, ImageFormat);
+ GalImage Image = new GalImage(Width, Height, 1, GobBlockHeight, Layout, Format);
- long Size = ImageUtils.GetSize(Image);
+ Gpu.ResourceManager.SendColorBuffer(Vmm, Key, FbIndex, Image);
- Gpu.Renderer.Texture.CreateFb(Key, Size, Image);
+ Gpu.Renderer.RenderTarget.SetViewport(VpX, VpY, VpW, VpH);
+ }
- Gpu.Renderer.RenderTarget.BindColor(Key, FbIndex);
+ private void SetFrameBuffer(GalPipelineState State)
+ {
+ State.FramebufferSrgb = (ReadRegister(NvGpuEngine3dReg.FrameBufferSrgb) & 1) != 0;
- Gpu.Renderer.RenderTarget.SetViewport(VpX, VpY, VpW, VpH);
+ State.FlipX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
+ State.FlipY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
}
private void SetZeta(NvGpuVmm Vmm)
{
- long ZA = MakeInt64From2xInt32(NvGpuEngine3dReg.ZetaAddress);
+ long VA = MakeInt64From2xInt32(NvGpuEngine3dReg.ZetaAddress);
+
+ int ZetaFormat = ReadRegister(NvGpuEngine3dReg.ZetaFormat);
+
+ int BlockDim = ReadRegister(NvGpuEngine3dReg.ZetaBlockDimensions);
+
+ int GobBlockHeight = 1 << ((BlockDim >> 4) & 7);
- int Format = ReadRegister(NvGpuEngine3dReg.ZetaFormat);
+ GalMemoryLayout Layout = (GalMemoryLayout)((BlockDim >> 12) & 1); //?
bool ZetaEnable = (ReadRegister(NvGpuEngine3dReg.ZetaEnable) & 1) != 0;
- if (ZA == 0 || Format == 0 || !ZetaEnable)
+ if (VA == 0 || ZetaFormat == 0 || !ZetaEnable)
{
Gpu.Renderer.RenderTarget.UnbindZeta();
return;
}
- long Key = Vmm.GetPhysicalAddress(ZA);
+ long Key = Vmm.GetPhysicalAddress(VA);
int Width = ReadRegister(NvGpuEngine3dReg.ZetaHoriz);
int Height = ReadRegister(NvGpuEngine3dReg.ZetaVert);
- GalImageFormat ImageFormat = ImageUtils.ConvertZeta((GalZetaFormat)Format);
-
- GalImage Image = new GalImage(Width, Height, ImageFormat);
-
- long Size = ImageUtils.GetSize(Image);
+ GalImageFormat Format = ImageUtils.ConvertZeta((GalZetaFormat)ZetaFormat);
- Gpu.Renderer.Texture.CreateFb(Key, Size, Image);
+ GalImage Image = new GalImage(Width, Height, 1, GobBlockHeight, Layout, Format);
- Gpu.Renderer.RenderTarget.BindZeta(Key);
+ Gpu.ResourceManager.SendZetaBuffer(Vmm, Key, Image);
}
private long[] UploadShaders(NvGpuVmm Vmm)
@@ -322,12 +325,6 @@ namespace Ryujinx.Graphics
throw new ArgumentOutOfRangeException(nameof(Program));
}
- private void SetFlip(GalPipelineState State)
- {
- State.FlipX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
- State.FlipY = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleY);
- }
-
private void SetFrontFace(GalPipelineState State)
{
float SignX = GetFlipSign(NvGpuEngine3dReg.ViewportNScaleX);
@@ -504,54 +501,31 @@ namespace Ryujinx.Graphics
TicPosition += TicIndex * 0x20;
TscPosition += TscIndex * 0x20;
+ GalImage Image = TextureFactory.MakeTexture(Vmm, TicPosition);
+
GalTextureSampler Sampler = TextureFactory.MakeSampler(Gpu, Vmm, TscPosition);
long Key = Vmm.ReadInt64(TicPosition + 4) & 0xffffffffffff;
- Key = Vmm.GetPhysicalAddress(Key);
-
- if (Key == -1)
+ if (Image.Layout == GalMemoryLayout.BlockLinear)
{
- //FIXME: Should'nt ignore invalid addresses.
- return;
+ Key &= ~0x1ffL;
}
-
- if (IsFrameBufferPosition(Key))
+ else if (Image.Layout == GalMemoryLayout.Pitch)
{
- //This texture is a frame buffer texture,
- //we shouldn't read anything from memory and bind
- //the frame buffer texture instead, since we're not
- //really writing anything to memory.
- Gpu.Renderer.RenderTarget.BindTexture(Key, TexIndex);
+ Key &= ~0x1fL;
}
- else
- {
- GalImage NewImage = TextureFactory.MakeTexture(Vmm, TicPosition);
-
- long Size = (uint)ImageUtils.GetSize(NewImage);
-
- bool HasCachedTexture = false;
-
- if (Gpu.Renderer.Texture.TryGetCachedTexture(Key, Size, out GalImage Image))
- {
- if (NewImage.Equals(Image) && !QueryKeyUpload(Vmm, Key, Size, NvGpuBufferType.Texture))
- {
- Gpu.Renderer.Texture.Bind(Key, TexIndex);
-
- HasCachedTexture = true;
- }
- }
-
- if (!HasCachedTexture)
- {
- byte[] Data = TextureFactory.GetTextureData(Vmm, TicPosition);
- Gpu.Renderer.Texture.Create(Key, Data, NewImage);
- }
+ Key = Vmm.GetPhysicalAddress(Key);
- Gpu.Renderer.Texture.Bind(Key, TexIndex);
+ if (Key == -1)
+ {
+ //FIXME: Shouldn't ignore invalid addresses.
+ return;
}
+ Gpu.ResourceManager.SendTexture(Vmm, Key, Image, TexIndex);
+
Gpu.Renderer.Texture.SetSampler(Sampler);
}
@@ -876,11 +850,6 @@ namespace Ryujinx.Graphics
Registers[(int)Reg] = Value;
}
- public bool IsFrameBufferPosition(long Position)
- {
- return FrameBuffers.Contains(Position);
- }
-
private bool QueryKeyUpload(NvGpuVmm Vmm, long Key, long Size, NvGpuBufferType Type)
{
List<long> Uploaded = UploadedKeys[(int)Type];
diff --git a/Ryujinx.Graphics/NvGpuEngine3dReg.cs b/Ryujinx.Graphics/NvGpuEngine3dReg.cs
index f96e7115..3abcf6f5 100644
--- a/Ryujinx.Graphics/NvGpuEngine3dReg.cs
+++ b/Ryujinx.Graphics/NvGpuEngine3dReg.cs
@@ -6,6 +6,7 @@ namespace Ryujinx.Graphics
FrameBufferNWidth = 0x202,
FrameBufferNHeight = 0x203,
FrameBufferNFormat = 0x204,
+ FrameBufferNBlockDim = 0x205,
ViewportNScaleX = 0x280,
ViewportNScaleY = 0x281,
ViewportNScaleZ = 0x282,
@@ -62,6 +63,7 @@ namespace Ryujinx.Graphics
StencilBackOpZFail = 0x567,
StencilBackOpZPass = 0x568,
StencilBackFuncFunc = 0x569,
+ FrameBufferSrgb = 0x56e,
ShaderAddress = 0x582,
VertexBeginGl = 0x586,
PrimRestartEnable = 0x591,
diff --git a/Ryujinx.Graphics/NvGpuEngineDma.cs b/Ryujinx.Graphics/NvGpuEngineDma.cs
deleted file mode 100644
index 04be742f..00000000
--- a/Ryujinx.Graphics/NvGpuEngineDma.cs
+++ /dev/null
@@ -1,143 +0,0 @@
-using Ryujinx.Graphics.Memory;
-using Ryujinx.Graphics.Texture;
-using System.Collections.Generic;
-
-namespace Ryujinx.Graphics
-{
- public class NvGpuEngineDma : INvGpuEngine
- {
- public int[] Registers { get; private set; }
-
- private NvGpu Gpu;
-
- private Dictionary<int, NvGpuMethod> Methods;
-
- public NvGpuEngineDma(NvGpu Gpu)
- {
- this.Gpu = Gpu;
-
- Registers = new int[0x1d6];
-
- Methods = new Dictionary<int, NvGpuMethod>();
-
- void AddMethod(int Meth, int Count, int Stride, NvGpuMethod Method)
- {
- while (Count-- > 0)
- {
- Methods.Add(Meth, Method);
-
- Meth += Stride;
- }
- }
-
- AddMethod(0xc0, 1, 1, Execute);
- }
-
- public void CallMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
- {
- if (Methods.TryGetValue(PBEntry.Method, out NvGpuMethod Method))
- {
- Method(Vmm, PBEntry);
- }
- else
- {
- WriteRegister(PBEntry);
- }
- }
-
- private void Execute(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
- {
- int Control = PBEntry.Arguments[0];
-
- bool SrcLinear = ((Control >> 7) & 1) != 0;
- bool DstLinear = ((Control >> 8) & 1) != 0;
-
- long SrcAddress = MakeInt64From2xInt32(NvGpuEngineDmaReg.SrcAddress);
- long DstAddress = MakeInt64From2xInt32(NvGpuEngineDmaReg.DstAddress);
-
- int SrcPitch = ReadRegister(NvGpuEngineDmaReg.SrcPitch);
- int DstPitch = ReadRegister(NvGpuEngineDmaReg.DstPitch);
-
- int DstBlkDim = ReadRegister(NvGpuEngineDmaReg.DstBlkDim);
- int DstSizeX = ReadRegister(NvGpuEngineDmaReg.DstSizeX);
- int DstSizeY = ReadRegister(NvGpuEngineDmaReg.DstSizeY);
- int DstSizeZ = ReadRegister(NvGpuEngineDmaReg.DstSizeZ);
- int DstPosXY = ReadRegister(NvGpuEngineDmaReg.DstPosXY);
- int DstPosZ = ReadRegister(NvGpuEngineDmaReg.DstPosZ);
-
- int SrcBlkDim = ReadRegister(NvGpuEngineDmaReg.SrcBlkDim);
- int SrcSizeX = ReadRegister(NvGpuEngineDmaReg.SrcSizeX);
- int SrcSizeY = ReadRegister(NvGpuEngineDmaReg.SrcSizeY);
- int SrcSizeZ = ReadRegister(NvGpuEngineDmaReg.SrcSizeZ);
- int SrcPosXY = ReadRegister(NvGpuEngineDmaReg.SrcPosXY);
- int SrcPosZ = ReadRegister(NvGpuEngineDmaReg.SrcPosZ);
-
- int DstPosX = (DstPosXY >> 0) & 0xffff;
- int DstPosY = (DstPosXY >> 16) & 0xffff;
-
- int SrcPosX = (SrcPosXY >> 0) & 0xffff;
- int SrcPosY = (SrcPosXY >> 16) & 0xffff;
-
- int SrcBlockHeight = 1 << ((SrcBlkDim >> 4) & 0xf);
- int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf);
-
- ISwizzle SrcSwizzle;
-
- if (SrcLinear)
- {
- SrcSwizzle = new LinearSwizzle(SrcPitch, 1);
- }
- else
- {
- SrcSwizzle = new BlockLinearSwizzle(SrcSizeX, 1, SrcBlockHeight);
- }
-
- ISwizzle DstSwizzle;
-
- if (DstLinear)
- {
- DstSwizzle = new LinearSwizzle(DstPitch, 1);
- }
- else
- {
- DstSwizzle = new BlockLinearSwizzle(DstSizeX, 1, DstBlockHeight);
- }
-
- for (int Y = 0; Y < DstSizeY; Y++)
- for (int X = 0; X < DstSizeX; X++)
- {
- long SrcOffset = SrcAddress + (uint)SrcSwizzle.GetSwizzleOffset(X, Y);
- long DstOffset = DstAddress + (uint)DstSwizzle.GetSwizzleOffset(X, Y);
-
- Vmm.WriteByte(DstOffset, Vmm.ReadByte(SrcOffset));
- }
- }
-
- private long MakeInt64From2xInt32(NvGpuEngineDmaReg Reg)
- {
- return
- (long)Registers[(int)Reg + 0] << 32 |
- (uint)Registers[(int)Reg + 1];
- }
-
- private void WriteRegister(NvGpuPBEntry PBEntry)
- {
- int ArgsCount = PBEntry.Arguments.Count;
-
- if (ArgsCount > 0)
- {
- Registers[PBEntry.Method] = PBEntry.Arguments[ArgsCount - 1];
- }
- }
-
- private int ReadRegister(NvGpuEngineDmaReg Reg)
- {
- return Registers[(int)Reg];
- }
-
- private void WriteRegister(NvGpuEngineDmaReg Reg, int Value)
- {
- Registers[(int)Reg] = Value;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/NvGpuEngineM2mf.cs b/Ryujinx.Graphics/NvGpuEngineM2mf.cs
new file mode 100644
index 00000000..d6121280
--- /dev/null
+++ b/Ryujinx.Graphics/NvGpuEngineM2mf.cs
@@ -0,0 +1,192 @@
+using Ryujinx.Graphics.Memory;
+using Ryujinx.Graphics.Texture;
+using System.Collections.Generic;
+
+namespace Ryujinx.Graphics
+{
+ public class NvGpuEngineM2mf : INvGpuEngine
+ {
+ public int[] Registers { get; private set; }
+
+ private NvGpu Gpu;
+
+ private Dictionary<int, NvGpuMethod> Methods;
+
+ public NvGpuEngineM2mf(NvGpu Gpu)
+ {
+ this.Gpu = Gpu;
+
+ Registers = new int[0x1d6];
+
+ Methods = new Dictionary<int, NvGpuMethod>();
+
+ void AddMethod(int Meth, int Count, int Stride, NvGpuMethod Method)
+ {
+ while (Count-- > 0)
+ {
+ Methods.Add(Meth, Method);
+
+ Meth += Stride;
+ }
+ }
+
+ AddMethod(0xc0, 1, 1, Execute);
+ }
+
+ public void CallMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
+ {
+ if (Methods.TryGetValue(PBEntry.Method, out NvGpuMethod Method))
+ {
+ Method(Vmm, PBEntry);
+ }
+ else
+ {
+ WriteRegister(PBEntry);
+ }
+ }
+
+ private void Execute(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
+ {
+ //TODO: Some registers and copy modes are still not implemented.
+ int Control = PBEntry.Arguments[0];
+
+ bool SrcLinear = ((Control >> 7) & 1) != 0;
+ bool DstLinear = ((Control >> 8) & 1) != 0;
+ bool Copy2d = ((Control >> 9) & 1) != 0;
+
+ long SrcAddress = MakeInt64From2xInt32(NvGpuEngineM2mfReg.SrcAddress);
+ long DstAddress = MakeInt64From2xInt32(NvGpuEngineM2mfReg.DstAddress);
+
+ int SrcPitch = ReadRegister(NvGpuEngineM2mfReg.SrcPitch);
+ int DstPitch = ReadRegister(NvGpuEngineM2mfReg.DstPitch);
+
+ int XCount = ReadRegister(NvGpuEngineM2mfReg.XCount);
+ int YCount = ReadRegister(NvGpuEngineM2mfReg.YCount);
+
+ int Swizzle = ReadRegister(NvGpuEngineM2mfReg.Swizzle);
+
+ int DstBlkDim = ReadRegister(NvGpuEngineM2mfReg.DstBlkDim);
+ int DstSizeX = ReadRegister(NvGpuEngineM2mfReg.DstSizeX);
+ int DstSizeY = ReadRegister(NvGpuEngineM2mfReg.DstSizeY);
+ int DstSizeZ = ReadRegister(NvGpuEngineM2mfReg.DstSizeZ);
+ int DstPosXY = ReadRegister(NvGpuEngineM2mfReg.DstPosXY);
+ int DstPosZ = ReadRegister(NvGpuEngineM2mfReg.DstPosZ);
+
+ int SrcBlkDim = ReadRegister(NvGpuEngineM2mfReg.SrcBlkDim);
+ int SrcSizeX = ReadRegister(NvGpuEngineM2mfReg.SrcSizeX);
+ int SrcSizeY = ReadRegister(NvGpuEngineM2mfReg.SrcSizeY);
+ int SrcSizeZ = ReadRegister(NvGpuEngineM2mfReg.SrcSizeZ);
+ int SrcPosXY = ReadRegister(NvGpuEngineM2mfReg.SrcPosXY);
+ int SrcPosZ = ReadRegister(NvGpuEngineM2mfReg.SrcPosZ);
+
+ int SrcCpp = ((Swizzle >> 20) & 7) + 1;
+ int DstCpp = ((Swizzle >> 24) & 7) + 1;
+
+ int DstPosX = (DstPosXY >> 0) & 0xffff;
+ int DstPosY = (DstPosXY >> 16) & 0xffff;
+
+ int SrcPosX = (SrcPosXY >> 0) & 0xffff;
+ int SrcPosY = (SrcPosXY >> 16) & 0xffff;
+
+ int SrcBlockHeight = 1 << ((SrcBlkDim >> 4) & 0xf);
+ int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf);
+
+ long SrcPA = Vmm.GetPhysicalAddress(SrcAddress);
+ long DstPA = Vmm.GetPhysicalAddress(DstAddress);
+
+ if (Copy2d)
+ {
+ if (SrcLinear)
+ {
+ SrcPosX = SrcPosY = SrcPosZ = 0;
+ }
+
+ if (DstLinear)
+ {
+ DstPosX = DstPosY = DstPosZ = 0;
+ }
+
+ if (SrcLinear && DstLinear)
+ {
+ for (int Y = 0; Y < YCount; Y++)
+ {
+ int SrcOffset = (SrcPosY + Y) * SrcPitch + SrcPosX * SrcCpp;
+ int DstOffset = (DstPosY + Y) * DstPitch + DstPosX * DstCpp;
+
+ long Src = SrcPA + (uint)SrcOffset;
+ long Dst = DstPA + (uint)DstOffset;
+
+ Vmm.Memory.CopyBytes(Src, Dst, XCount * SrcCpp);
+ }
+ }
+ else
+ {
+ ISwizzle SrcSwizzle;
+
+ if (SrcLinear)
+ {
+ SrcSwizzle = new LinearSwizzle(SrcPitch, SrcCpp);
+ }
+ else
+ {
+ SrcSwizzle = new BlockLinearSwizzle(SrcSizeX, SrcCpp, SrcBlockHeight);
+ }
+
+ ISwizzle DstSwizzle;
+
+ if (DstLinear)
+ {
+ DstSwizzle = new LinearSwizzle(DstPitch, DstCpp);
+ }
+ else
+ {
+ DstSwizzle = new BlockLinearSwizzle(DstSizeX, DstCpp, DstBlockHeight);
+ }
+
+ for (int Y = 0; Y < YCount; Y++)
+ for (int X = 0; X < XCount; X++)
+ {
+ int SrcOffset = SrcSwizzle.GetSwizzleOffset(SrcPosX + X, SrcPosY + Y);
+ int DstOffset = DstSwizzle.GetSwizzleOffset(DstPosX + X, DstPosY + Y);
+
+ long Src = SrcPA + (uint)SrcOffset;
+ long Dst = DstPA + (uint)DstOffset;
+
+ Vmm.Memory.CopyBytes(Src, Dst, SrcCpp);
+ }
+ }
+ }
+ else
+ {
+ Vmm.Memory.CopyBytes(SrcPA, DstPA, XCount);
+ }
+ }
+
+ private long MakeInt64From2xInt32(NvGpuEngineM2mfReg Reg)
+ {
+ return
+ (long)Registers[(int)Reg + 0] << 32 |
+ (uint)Registers[(int)Reg + 1];
+ }
+
+ private void WriteRegister(NvGpuPBEntry PBEntry)
+ {
+ int ArgsCount = PBEntry.Arguments.Count;
+
+ if (ArgsCount > 0)
+ {
+ Registers[PBEntry.Method] = PBEntry.Arguments[ArgsCount - 1];
+ }
+ }
+
+ private int ReadRegister(NvGpuEngineM2mfReg Reg)
+ {
+ return Registers[(int)Reg];
+ }
+
+ private void WriteRegister(NvGpuEngineM2mfReg Reg, int Value)
+ {
+ Registers[(int)Reg] = Value;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/NvGpuEngineDmaReg.cs b/Ryujinx.Graphics/NvGpuEngineM2mfReg.cs
index b0fa1fbf..170e0b7b 100644
--- a/Ryujinx.Graphics/NvGpuEngineDmaReg.cs
+++ b/Ryujinx.Graphics/NvGpuEngineM2mfReg.cs
@@ -1,11 +1,14 @@
namespace Ryujinx.Graphics
{
- enum NvGpuEngineDmaReg
+ enum NvGpuEngineM2mfReg
{
SrcAddress = 0x100,
DstAddress = 0x102,
SrcPitch = 0x104,
DstPitch = 0x105,
+ XCount = 0x106,
+ YCount = 0x107,
+ Swizzle = 0x1c2,
DstBlkDim = 0x1c3,
DstSizeX = 0x1c4,
DstSizeY = 0x1c5,
diff --git a/Ryujinx.Graphics/NvGpuEngineP2mf.cs b/Ryujinx.Graphics/NvGpuEngineP2mf.cs
new file mode 100644
index 00000000..842dfc52
--- /dev/null
+++ b/Ryujinx.Graphics/NvGpuEngineP2mf.cs
@@ -0,0 +1,102 @@
+using Ryujinx.Graphics.Memory;
+using System.Collections.Generic;
+using System.Collections.ObjectModel;
+
+namespace Ryujinx.Graphics
+{
+ public class NvGpuEngineP2mf : INvGpuEngine
+ {
+ public int[] Registers { get; private set; }
+
+ private NvGpu Gpu;
+
+ private Dictionary<int, NvGpuMethod> Methods;
+
+ private ReadOnlyCollection<int> DataBuffer;
+
+ public NvGpuEngineP2mf(NvGpu Gpu)
+ {
+ this.Gpu = Gpu;
+
+ Registers = new int[0x80];
+
+ Methods = new Dictionary<int, NvGpuMethod>();
+
+ void AddMethod(int Meth, int Count, int Stride, NvGpuMethod Method)
+ {
+ while (Count-- > 0)
+ {
+ Methods.Add(Meth, Method);
+
+ Meth += Stride;
+ }
+ }
+
+ AddMethod(0x6c, 1, 1, Execute);
+ AddMethod(0x6d, 1, 1, PushData);
+ }
+
+ public void CallMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
+ {
+ if (Methods.TryGetValue(PBEntry.Method, out NvGpuMethod Method))
+ {
+ Method(Vmm, PBEntry);
+ }
+ else
+ {
+ WriteRegister(PBEntry);
+ }
+ }
+
+ private void Execute(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
+ {
+ //TODO: Some registers and copy modes are still not implemented.
+ int Control = PBEntry.Arguments[0];
+
+ long DstAddress = MakeInt64From2xInt32(NvGpuEngineP2mfReg.DstAddress);
+
+ int LineLengthIn = ReadRegister(NvGpuEngineP2mfReg.LineLengthIn);
+
+ DataBuffer = null;
+
+ Gpu.Fifo.Step();
+
+ for (int Offset = 0; Offset < LineLengthIn; Offset += 4)
+ {
+ Vmm.WriteInt32(DstAddress + Offset, DataBuffer[Offset >> 2]);
+ }
+ }
+
+ private void PushData(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
+ {
+ DataBuffer = PBEntry.Arguments;
+ }
+
+ private long MakeInt64From2xInt32(NvGpuEngineP2mfReg Reg)
+ {
+ return
+ (long)Registers[(int)Reg + 0] << 32 |
+ (uint)Registers[(int)Reg + 1];
+ }
+
+ private void WriteRegister(NvGpuPBEntry PBEntry)
+ {
+ int ArgsCount = PBEntry.Arguments.Count;
+
+ if (ArgsCount > 0)
+ {
+ Registers[PBEntry.Method] = PBEntry.Arguments[ArgsCount - 1];
+ }
+ }
+
+ private int ReadRegister(NvGpuEngineP2mfReg Reg)
+ {
+ return Registers[(int)Reg];
+ }
+
+ private void WriteRegister(NvGpuEngineP2mfReg Reg, int Value)
+ {
+ Registers[(int)Reg] = Value;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/NvGpuEngineP2mfReg.cs b/Ryujinx.Graphics/NvGpuEngineP2mfReg.cs
new file mode 100644
index 00000000..803ed299
--- /dev/null
+++ b/Ryujinx.Graphics/NvGpuEngineP2mfReg.cs
@@ -0,0 +1,17 @@
+namespace Ryujinx.Graphics
+{
+ enum NvGpuEngineP2mfReg
+ {
+ LineLengthIn = 0x60,
+ LineCount = 0x61,
+ DstAddress = 0x62,
+ DstPitch = 0x64,
+ DstBlockDim = 0x65,
+ DstWidth = 0x66,
+ DstHeight = 0x67,
+ DstDepth = 0x68,
+ DstZ = 0x69,
+ DstX = 0x6a,
+ DstY = 0x6b
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/NvGpuFifo.cs b/Ryujinx.Graphics/NvGpuFifo.cs
index 3b79a055..16d16f5e 100644
--- a/Ryujinx.Graphics/NvGpuFifo.cs
+++ b/Ryujinx.Graphics/NvGpuFifo.cs
@@ -94,6 +94,8 @@ namespace Ryujinx.Graphics
Gpu.Engine3d.ResetCache();
+ Gpu.ResourceManager.ClearPbCache();
+
CurrPbEntryIndex = 0;
}
@@ -104,19 +106,35 @@ namespace Ryujinx.Graphics
private void CallMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
{
- if (PBEntry.Method < 0x80)
+ if ((NvGpuFifoMeth)PBEntry.Method == NvGpuFifoMeth.BindChannel)
{
- switch ((NvGpuFifoMeth)PBEntry.Method)
- {
- case NvGpuFifoMeth.BindChannel:
- {
- NvGpuEngine Engine = (NvGpuEngine)PBEntry.Arguments[0];
+ NvGpuEngine Engine = (NvGpuEngine)PBEntry.Arguments[0];
- SubChannels[PBEntry.SubChannel] = Engine;
+ SubChannels[PBEntry.SubChannel] = Engine;
+ }
+ else
+ {
+ switch (SubChannels[PBEntry.SubChannel])
+ {
+ case NvGpuEngine._2d: Call2dMethod (Vmm, PBEntry); break;
+ case NvGpuEngine._3d: Call3dMethod (Vmm, PBEntry); break;
+ case NvGpuEngine.P2mf: CallP2mfMethod(Vmm, PBEntry); break;
+ case NvGpuEngine.M2mf: CallM2mfMethod(Vmm, PBEntry); break;
+ }
+ }
+ }
- break;
- }
+ private void Call2dMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
+ {
+ Gpu.Engine2d.CallMethod(Vmm, PBEntry);
+ }
+ private void Call3dMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
+ {
+ if (PBEntry.Method < 0x80)
+ {
+ switch ((NvGpuFifoMeth)PBEntry.Method)
+ {
case NvGpuFifoMeth.SetMacroUploadAddress:
{
CurrMacroPosition = PBEntry.Arguments[0];
@@ -150,25 +168,7 @@ namespace Ryujinx.Graphics
}
}
}
- else
- {
- switch (SubChannels[PBEntry.SubChannel])
- {
- case NvGpuEngine._2d: Call2dMethod (Vmm, PBEntry); break;
- case NvGpuEngine._3d: Call3dMethod (Vmm, PBEntry); break;
- case NvGpuEngine.Dma: CallDmaMethod(Vmm, PBEntry); break;
- }
- }
- }
-
- private void Call2dMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
- {
- Gpu.Engine2d.CallMethod(Vmm, PBEntry);
- }
-
- private void Call3dMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
- {
- if (PBEntry.Method < 0xe00)
+ else if (PBEntry.Method < 0xe00)
{
Gpu.Engine3d.CallMethod(Vmm, PBEntry);
}
@@ -190,9 +190,14 @@ namespace Ryujinx.Graphics
}
}
- private void CallDmaMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
+ private void CallP2mfMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
+ {
+ Gpu.EngineP2mf.CallMethod(Vmm, PBEntry);
+ }
+
+ private void CallM2mfMethod(NvGpuVmm Vmm, NvGpuPBEntry PBEntry)
{
- Gpu.EngineDma.CallMethod(Vmm, PBEntry);
+ Gpu.EngineM2mf.CallMethod(Vmm, PBEntry);
}
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Texture/ImageUtils.cs b/Ryujinx.Graphics/Texture/ImageUtils.cs
index f6db0894..7d3dde49 100644
--- a/Ryujinx.Graphics/Texture/ImageUtils.cs
+++ b/Ryujinx.Graphics/Texture/ImageUtils.cs
@@ -1,33 +1,37 @@
-using Ryujinx.Graphics.Gal;
+using ChocolArm64.Memory;
+using Ryujinx.Graphics.Gal;
+using Ryujinx.Graphics.Memory;
using System;
using System.Collections.Generic;
namespace Ryujinx.Graphics.Texture
{
- static class ImageUtils
+ public static class ImageUtils
{
- struct ImageDescriptor
+ [Flags]
+ private enum TargetBuffer
{
- public TextureReaderDelegate Reader;
+ Color = 1 << 0,
+ Depth = 1 << 1,
+ Stencil = 1 << 2,
- public bool HasColor;
- public bool HasDepth;
- public bool HasStencil;
+ DepthStencil = Depth | Stencil
+ }
+
+ private struct ImageDescriptor
+ {
+ public int BytesPerPixel { get; private set; }
+ public int BlockWidth { get; private set; }
+ public int BlockHeight { get; private set; }
- public bool Compressed;
+ public TargetBuffer Target { get; private set; }
- public ImageDescriptor(
- TextureReaderDelegate Reader,
- bool HasColor,
- bool HasDepth,
- bool HasStencil,
- bool Compressed)
+ public ImageDescriptor(int BytesPerPixel, int BlockWidth, int BlockHeight, TargetBuffer Target)
{
- this.Reader = Reader;
- this.HasColor = HasColor;
- this.HasDepth = HasDepth;
- this.HasStencil = HasStencil;
- this.Compressed = Compressed;
+ this.BytesPerPixel = BytesPerPixel;
+ this.BlockWidth = BlockWidth;
+ this.BlockHeight = BlockHeight;
+ this.Target = Target;
}
}
@@ -48,6 +52,7 @@ namespace Ryujinx.Graphics.Texture
{ GalTextureFormat.G8R8, GalImageFormat.G8R8 | Snorm | Unorm | Sint | Uint },
{ GalTextureFormat.R16, GalImageFormat.R16 | Snorm | Unorm | Sint | Uint | Sfloat },
{ GalTextureFormat.R8, GalImageFormat.R8 | Snorm | Unorm | Sint | Uint },
+ { GalTextureFormat.R16G16, GalImageFormat.R16G16 | Snorm },
{ GalTextureFormat.R32, GalImageFormat.R32 | Sint | Uint | Sfloat },
{ GalTextureFormat.A4B4G4R4, GalImageFormat.A4B4G4R4 | Unorm },
{ GalTextureFormat.A1B5G5R5, GalImageFormat.A1R5G5B5 | Unorm },
@@ -85,58 +90,58 @@ namespace Ryujinx.Graphics.Texture
private static readonly Dictionary<GalImageFormat, ImageDescriptor> s_ImageTable =
new Dictionary<GalImageFormat, ImageDescriptor>()
- {
- { GalImageFormat.R32G32B32A32, new ImageDescriptor(TextureReader.Read16Bpp, true, false, false, false) },
- { GalImageFormat.R16G16B16A16, new ImageDescriptor(TextureReader.Read8Bpp, true, false, false, false) },
- { GalImageFormat.R32G32, new ImageDescriptor(TextureReader.Read8Bpp, true, false, false, false) },
- { GalImageFormat.A8B8G8R8, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false, false) },
- { GalImageFormat.A2B10G10R10, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false, false) },
- { GalImageFormat.R32, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false, false) },
- { GalImageFormat.A4B4G4R4, new ImageDescriptor(TextureReader.Read2Bpp, true, false, false, false) },
- { GalImageFormat.BC6H_SF16, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false, true) },
- { GalImageFormat.BC6H_UF16, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false, true) },
- { GalImageFormat.A1R5G5B5, new ImageDescriptor(TextureReader.Read5551, true, false, false, false) },
- { GalImageFormat.B5G6R5, new ImageDescriptor(TextureReader.Read565, true, false, false, false) },
- { GalImageFormat.BC7, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false, true) },
- { GalImageFormat.R16G16, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false, false) },
- { GalImageFormat.R8G8, new ImageDescriptor(TextureReader.Read2Bpp, true, false, false, false) },
- { GalImageFormat.G8R8, new ImageDescriptor(TextureReader.Read2Bpp, true, false, false, false) },
- { GalImageFormat.R16, new ImageDescriptor(TextureReader.Read2Bpp, true, false, false, false) },
- { GalImageFormat.R8, new ImageDescriptor(TextureReader.Read1Bpp, true, false, false, false) },
- { GalImageFormat.B10G11R11, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false, false) },
- { GalImageFormat.A8B8G8R8_SRGB, new ImageDescriptor(TextureReader.Read4Bpp, true, false, false, false) },
- { GalImageFormat.BC1_RGBA, new ImageDescriptor(TextureReader.Read8Bpt4x4, true, false, false, true) },
- { GalImageFormat.BC2, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false, true) },
- { GalImageFormat.BC3, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false, true) },
- { GalImageFormat.BC4, new ImageDescriptor(TextureReader.Read8Bpt4x4, true, false, false, true) },
- { GalImageFormat.BC5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false, true) },
- { GalImageFormat.ASTC_4x4, new ImageDescriptor(TextureReader.Read16BptCompressedTexture4x4, true, false, false, true) },
- { GalImageFormat.ASTC_5x5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture5x5, true, false, false, true) },
- { GalImageFormat.ASTC_6x6, new ImageDescriptor(TextureReader.Read16BptCompressedTexture6x6, true, false, false, true) },
- { GalImageFormat.ASTC_8x8, new ImageDescriptor(TextureReader.Read16BptCompressedTexture8x8, true, false, false, true) },
- { GalImageFormat.ASTC_10x10, new ImageDescriptor(TextureReader.Read16BptCompressedTexture10x10, true, false, false, true) },
- { GalImageFormat.ASTC_12x12, new ImageDescriptor(TextureReader.Read16BptCompressedTexture12x12, true, false, false, true) },
- { GalImageFormat.ASTC_5x4, new ImageDescriptor(TextureReader.Read16BptCompressedTexture5x4, true, false, false, true) },
- { GalImageFormat.ASTC_6x5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture6x5, true, false, false, true) },
- { GalImageFormat.ASTC_8x6, new ImageDescriptor(TextureReader.Read16BptCompressedTexture8x6, true, false, false, true) },
- { GalImageFormat.ASTC_10x8, new ImageDescriptor(TextureReader.Read16BptCompressedTexture10x8, true, false, false, true) },
- { GalImageFormat.ASTC_12x10, new ImageDescriptor(TextureReader.Read16BptCompressedTexture12x10, true, false, false, true) },
- { GalImageFormat.ASTC_8x5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture8x5, true, false, false, true) },
- { GalImageFormat.ASTC_10x5, new ImageDescriptor(TextureReader.Read16BptCompressedTexture10x5, true, false, false, true) },
- { GalImageFormat.ASTC_10x6, new ImageDescriptor(TextureReader.Read16BptCompressedTexture10x6, true, false, false, true) },
-
- { GalImageFormat.D24_S8, new ImageDescriptor(TextureReader.Read4Bpp, false, true, true, false) },
- { GalImageFormat.D32, new ImageDescriptor(TextureReader.Read4Bpp, false, true, false, false) },
- { GalImageFormat.D16, new ImageDescriptor(TextureReader.Read2Bpp, false, true, false, false) },
- { GalImageFormat.D32_S8, new ImageDescriptor(TextureReader.Read8Bpp, false, true, true, false) },
- };
+ {
+ { GalImageFormat.R32G32B32A32, new ImageDescriptor(16, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.R16G16B16A16, new ImageDescriptor(8, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.R32G32, new ImageDescriptor(8, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.A8B8G8R8, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.A2B10G10R10, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.R32, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.A4B4G4R4, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.BC6H_SF16, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.BC6H_UF16, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.A1R5G5B5, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.B5G6R5, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.BC7, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.R16G16, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.R8G8, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.G8R8, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.R16, new ImageDescriptor(2, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.R8, new ImageDescriptor(1, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.B10G11R11, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.A8B8G8R8_SRGB, new ImageDescriptor(4, 1, 1, TargetBuffer.Color) },
+ { GalImageFormat.BC1_RGBA, new ImageDescriptor(8, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.BC2, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.BC3, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.BC4, new ImageDescriptor(8, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.BC5, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_4x4, new ImageDescriptor(16, 4, 4, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_5x5, new ImageDescriptor(16, 5, 5, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_6x6, new ImageDescriptor(16, 6, 6, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_8x8, new ImageDescriptor(16, 8, 8, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_10x10, new ImageDescriptor(16, 10, 10, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_12x12, new ImageDescriptor(16, 12, 12, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_5x4, new ImageDescriptor(16, 5, 4, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_6x5, new ImageDescriptor(16, 6, 5, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_8x6, new ImageDescriptor(16, 8, 6, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_10x8, new ImageDescriptor(16, 10, 8, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_12x10, new ImageDescriptor(16, 12, 10, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_8x5, new ImageDescriptor(16, 8, 5, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_10x5, new ImageDescriptor(16, 10, 5, TargetBuffer.Color) },
+ { GalImageFormat.ASTC_10x6, new ImageDescriptor(16, 10, 6, TargetBuffer.Color) },
+
+ { GalImageFormat.D24_S8, new ImageDescriptor(4, 1, 1, TargetBuffer.DepthStencil) },
+ { GalImageFormat.D32, new ImageDescriptor(4, 1, 1, TargetBuffer.Depth) },
+ { GalImageFormat.D16, new ImageDescriptor(2, 1, 1, TargetBuffer.Depth) },
+ { GalImageFormat.D32_S8, new ImageDescriptor(8, 1, 1, TargetBuffer.DepthStencil) },
+ };
public static GalImageFormat ConvertTexture(
GalTextureFormat Format,
- GalTextureType RType,
- GalTextureType GType,
- GalTextureType BType,
- GalTextureType AType)
+ GalTextureType RType,
+ GalTextureType GType,
+ GalTextureType BType,
+ GalTextureType AType)
{
if (RType != GType || RType != BType || RType != AType)
{
@@ -202,128 +207,157 @@ namespace Ryujinx.Graphics.Texture
case GalZetaFormat.Z32Float: return GalImageFormat.D32 | Sfloat;
case GalZetaFormat.S8Z24Unorm: return GalImageFormat.D24_S8 | Unorm;
case GalZetaFormat.Z16Unorm: return GalImageFormat.D16 | Unorm;
- //This one might not be Uint, change when a texture uses this format
- case GalZetaFormat.Z32S8X24Float: return GalImageFormat.D32_S8 | Uint;
+ case GalZetaFormat.Z24S8Unorm: return GalImageFormat.D24_S8 | Unorm;
+ case GalZetaFormat.Z32S8X24Float: return GalImageFormat.D32_S8 | Sfloat;
}
throw new NotImplementedException(Format.ToString());
}
- public static TextureReaderDelegate GetReader(GalImageFormat Format)
+ public static byte[] ReadTexture(IAMemory Memory, GalImage Image, long Position)
+ {
+ AMemory CpuMemory;
+
+ if (Memory is NvGpuVmm Vmm)
+ {
+ CpuMemory = Vmm.Memory;
+ }
+ else
+ {
+ CpuMemory = (AMemory)Memory;
+ }
+
+ ISwizzle Swizzle = TextureHelper.GetSwizzle(Image);
+
+ ImageDescriptor Desc = GetImageDescriptor(Image.Format);
+
+ (int Width, int Height) = GetImageSizeInBlocks(Image);
+
+ int BytesPerPixel = Desc.BytesPerPixel;
+
+ int OutOffs = 0;
+
+ byte[] Data = new byte[Width * Height * BytesPerPixel];
+
+ for (int Y = 0; Y < Height; Y++)
+ for (int X = 0; X < Width; X++)
+ {
+ long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
+
+ CpuMemory.ReadBytes(Position + Offset, Data, OutOffs, BytesPerPixel);
+
+ OutOffs += BytesPerPixel;
+ }
+
+ return Data;
+ }
+
+ public static void WriteTexture(NvGpuVmm Vmm, GalImage Image, long Position, byte[] Data)
{
- return GetImageDescriptor(Format).Reader;
+ ISwizzle Swizzle = TextureHelper.GetSwizzle(Image);
+
+ ImageDescriptor Desc = GetImageDescriptor(Image.Format);
+
+ (int Width, int Height) = ImageUtils.GetImageSizeInBlocks(Image);
+
+ int BytesPerPixel = Desc.BytesPerPixel;
+
+ int InOffs = 0;
+
+ for (int Y = 0; Y < Height; Y++)
+ for (int X = 0; X < Width; X++)
+ {
+ long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
+
+ Vmm.Memory.WriteBytes(Position + Offset, Data, InOffs, BytesPerPixel);
+
+ InOffs += BytesPerPixel;
+ }
}
public static int GetSize(GalImage Image)
{
- switch (Image.Format & GalImageFormat.FormatMask)
+ ImageDescriptor Desc = GetImageDescriptor(Image.Format);
+
+ int Width = DivRoundUp(Image.Width, Desc.BlockWidth);
+ int Height = DivRoundUp(Image.Height, Desc.BlockHeight);
+
+ return Desc.BytesPerPixel * Width * Height;
+ }
+
+ public static int GetPitch(GalImageFormat Format, int Width)
+ {
+ ImageDescriptor Desc = GetImageDescriptor(Format);
+
+ return Desc.BytesPerPixel * DivRoundUp(Width, Desc.BlockWidth);
+ }
+
+ public static int GetBlockWidth(GalImageFormat Format)
+ {
+ return GetImageDescriptor(Format).BlockWidth;
+ }
+
+ public static int GetBlockHeight(GalImageFormat Format)
+ {
+ return GetImageDescriptor(Format).BlockHeight;
+ }
+
+ public static int GetAlignedWidth(GalImage Image)
+ {
+ ImageDescriptor Desc = GetImageDescriptor(Image.Format);
+
+ int AlignMask;
+
+ if (Image.Layout == GalMemoryLayout.BlockLinear)
{
- case GalImageFormat.R32G32B32A32:
- return Image.Width * Image.Height * 16;
-
- case GalImageFormat.R16G16B16A16:
- case GalImageFormat.D32_S8:
- case GalImageFormat.R32G32:
- return Image.Width * Image.Height * 8;
-
- case GalImageFormat.A8B8G8R8:
- case GalImageFormat.A8B8G8R8_SRGB:
- case GalImageFormat.A2B10G10R10:
- case GalImageFormat.R16G16:
- case GalImageFormat.R32:
- case GalImageFormat.D32:
- case GalImageFormat.B10G11R11:
- case GalImageFormat.D24_S8:
- return Image.Width * Image.Height * 4;
-
- case GalImageFormat.B4G4R4A4:
- case GalImageFormat.A1R5G5B5:
- case GalImageFormat.B5G6R5:
- case GalImageFormat.R8G8:
- case GalImageFormat.G8R8:
- case GalImageFormat.R16:
- case GalImageFormat.D16:
- return Image.Width * Image.Height * 2;
-
- case GalImageFormat.R8:
- return Image.Width * Image.Height;
-
- case GalImageFormat.BC1_RGBA:
- case GalImageFormat.BC4:
- {
- return CompressedTextureSize(Image.Width, Image.Height, 4, 4, 8);
- }
-
- case GalImageFormat.BC6H_SF16:
- case GalImageFormat.BC6H_UF16:
- case GalImageFormat.BC7:
- case GalImageFormat.BC2:
- case GalImageFormat.BC3:
- case GalImageFormat.BC5:
- case GalImageFormat.ASTC_4x4:
- return CompressedTextureSize(Image.Width, Image.Height, 4, 4, 16);
-
- case GalImageFormat.ASTC_5x5:
- return CompressedTextureSize(Image.Width, Image.Height, 5, 5, 16);
-
- case GalImageFormat.ASTC_6x6:
- return CompressedTextureSize(Image.Width, Image.Height, 6, 6, 16);
-
- case GalImageFormat.ASTC_8x8:
- return CompressedTextureSize(Image.Width, Image.Height, 8, 8, 16);
-
- case GalImageFormat.ASTC_10x10:
- return CompressedTextureSize(Image.Width, Image.Height, 10, 10, 16);
-
- case GalImageFormat.ASTC_12x12:
- return CompressedTextureSize(Image.Width, Image.Height, 12, 12, 16);
-
- case GalImageFormat.ASTC_5x4:
- return CompressedTextureSize(Image.Width, Image.Height, 5, 4, 16);
-
- case GalImageFormat.ASTC_6x5:
- return CompressedTextureSize(Image.Width, Image.Height, 6, 5, 16);
-
- case GalImageFormat.ASTC_8x6:
- return CompressedTextureSize(Image.Width, Image.Height, 8, 6, 16);
-
- case GalImageFormat.ASTC_10x8:
- return CompressedTextureSize(Image.Width, Image.Height, 10, 8, 16);
-
- case GalImageFormat.ASTC_12x10:
- return CompressedTextureSize(Image.Width, Image.Height, 12, 10, 16);
-
- case GalImageFormat.ASTC_8x5:
- return CompressedTextureSize(Image.Width, Image.Height, 8, 5, 16);
-
- case GalImageFormat.ASTC_10x5:
- return CompressedTextureSize(Image.Width, Image.Height, 10, 5, 16);
-
- case GalImageFormat.ASTC_10x6:
- return CompressedTextureSize(Image.Width, Image.Height, 10, 6, 16);
+ AlignMask = Image.TileWidth * (64 / Desc.BytesPerPixel) - 1;
+ }
+ else
+ {
+ AlignMask = (32 / Desc.BytesPerPixel) - 1;
}
- throw new NotImplementedException((Image.Format & GalImageFormat.FormatMask).ToString());
+ return (Image.Width + AlignMask) & ~AlignMask;
+ }
+
+ public static (int Width, int Height) GetImageSizeInBlocks(GalImage Image)
+ {
+ ImageDescriptor Desc = GetImageDescriptor(Image.Format);
+
+ return (DivRoundUp(Image.Width, Desc.BlockWidth),
+ DivRoundUp(Image.Height, Desc.BlockHeight));
+ }
+
+ public static int GetBytesPerPixel(GalImageFormat Format)
+ {
+ return GetImageDescriptor(Format).BytesPerPixel;
+ }
+
+ private static int DivRoundUp(int LHS, int RHS)
+ {
+ return (LHS + (RHS - 1)) / RHS;
}
public static bool HasColor(GalImageFormat Format)
{
- return GetImageDescriptor(Format).HasColor;
+ return (GetImageDescriptor(Format).Target & TargetBuffer.Color) != 0;
}
public static bool HasDepth(GalImageFormat Format)
{
- return GetImageDescriptor(Format).HasDepth;
+ return (GetImageDescriptor(Format).Target & TargetBuffer.Depth) != 0;
}
public static bool HasStencil(GalImageFormat Format)
{
- return GetImageDescriptor(Format).HasStencil;
+ return (GetImageDescriptor(Format).Target & TargetBuffer.Stencil) != 0;
}
public static bool IsCompressed(GalImageFormat Format)
{
- return GetImageDescriptor(Format).Compressed;
+ ImageDescriptor Desc = GetImageDescriptor(Format);
+
+ return (Desc.BlockWidth | Desc.BlockHeight) != 1;
}
private static ImageDescriptor GetImageDescriptor(GalImageFormat Format)
@@ -351,13 +385,5 @@ namespace Ryujinx.Graphics.Texture
default: throw new NotImplementedException(((int)Type).ToString());
}
}
-
- private static int CompressedTextureSize(int TextureWidth, int TextureHeight, int BlockWidth, int BlockHeight, int Bpb)
- {
- int W = (TextureWidth + (BlockWidth - 1)) / BlockWidth;
- int H = (TextureHeight + (BlockHeight - 1)) / BlockHeight;
-
- return W * H * Bpb;
- }
}
} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Texture/TextureFactory.cs b/Ryujinx.Graphics/Texture/TextureFactory.cs
index fa7a0f80..766c53da 100644
--- a/Ryujinx.Graphics/Texture/TextureFactory.cs
+++ b/Ryujinx.Graphics/Texture/TextureFactory.cs
@@ -17,44 +17,20 @@ namespace Ryujinx.Graphics.Texture
GalTextureSource ZSource = (GalTextureSource)((Tic[0] >> 25) & 7);
GalTextureSource WSource = (GalTextureSource)((Tic[0] >> 28) & 7);
- int Width = (Tic[4] & 0xffff) + 1;
- int Height = (Tic[5] & 0xffff) + 1;
-
- return new GalImage(
- Width,
- Height,
- Format,
- XSource,
- YSource,
- ZSource,
- WSource);
- }
-
- public static byte[] GetTextureData(NvGpuVmm Vmm, long TicPosition)
- {
- int[] Tic = ReadWords(Vmm, TicPosition, 8);
-
- GalImageFormat Format = GetImageFormat(Tic);
-
- long TextureAddress = (uint)Tic[1];
-
- TextureAddress |= (long)((ushort)Tic[2]) << 32;
-
TextureSwizzle Swizzle = (TextureSwizzle)((Tic[2] >> 21) & 7);
+ GalMemoryLayout Layout;
+
if (Swizzle == TextureSwizzle.BlockLinear ||
Swizzle == TextureSwizzle.BlockLinearColorKey)
{
- TextureAddress &= ~0x1ffL;
+ Layout = GalMemoryLayout.BlockLinear;
}
- else if (Swizzle == TextureSwizzle.Pitch ||
- Swizzle == TextureSwizzle.PitchColorKey)
+ else
{
- TextureAddress &= ~0x1fL;
+ Layout = GalMemoryLayout.Pitch;
}
- int Pitch = (Tic[3] & 0xffff) << 5;
-
int BlockHeightLog2 = (Tic[3] >> 3) & 7;
int TileWidthLog2 = (Tic[3] >> 10) & 7;
@@ -64,17 +40,17 @@ namespace Ryujinx.Graphics.Texture
int Width = (Tic[4] & 0xffff) + 1;
int Height = (Tic[5] & 0xffff) + 1;
- TextureInfo Texture = new TextureInfo(
- TextureAddress,
+ return new GalImage(
Width,
Height,
- Pitch,
- BlockHeight,
TileWidth,
- Swizzle,
- Format);
-
- return TextureReader.Read(Vmm, Texture);
+ BlockHeight,
+ Layout,
+ Format,
+ XSource,
+ YSource,
+ ZSource,
+ WSource);
}
public static GalTextureSampler MakeSampler(NvGpu Gpu, NvGpuVmm Vmm, long TscPosition)
@@ -107,7 +83,7 @@ namespace Ryujinx.Graphics.Texture
private static GalImageFormat GetImageFormat(int[] Tic)
{
- GalTextureType RType = (GalTextureType)((Tic[0] >> 7) & 7);
+ 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);
diff --git a/Ryujinx.Graphics/Texture/TextureHelper.cs b/Ryujinx.Graphics/Texture/TextureHelper.cs
index 8130ab41..9e966e6b 100644
--- a/Ryujinx.Graphics/Texture/TextureHelper.cs
+++ b/Ryujinx.Graphics/Texture/TextureHelper.cs
@@ -1,33 +1,30 @@
using ChocolArm64.Memory;
using Ryujinx.Graphics.Gal;
using Ryujinx.Graphics.Memory;
-using System;
namespace Ryujinx.Graphics.Texture
{
static class TextureHelper
{
- public static ISwizzle GetSwizzle(TextureInfo Texture, int BlockWidth, int Bpp)
+ public static ISwizzle GetSwizzle(GalImage Image)
{
- int Width = (Texture.Width + (BlockWidth - 1)) / BlockWidth;
+ int BlockWidth = ImageUtils.GetBlockWidth (Image.Format);
+ int BytesPerPixel = ImageUtils.GetBytesPerPixel(Image.Format);
- int AlignMask = Texture.TileWidth * (64 / Bpp) - 1;
+ int Width = (Image.Width + (BlockWidth - 1)) / BlockWidth;
- Width = (Width + AlignMask) & ~AlignMask;
-
- switch (Texture.Swizzle)
+ if (Image.Layout == GalMemoryLayout.BlockLinear)
{
- case TextureSwizzle._1dBuffer:
- case TextureSwizzle.Pitch:
- case TextureSwizzle.PitchColorKey:
- return new LinearSwizzle(Texture.Pitch, Bpp);
+ int AlignMask = Image.TileWidth * (64 / BytesPerPixel) - 1;
- case TextureSwizzle.BlockLinear:
- case TextureSwizzle.BlockLinearColorKey:
- return new BlockLinearSwizzle(Width, Bpp, Texture.BlockHeight);
- }
+ Width = (Width + AlignMask) & ~AlignMask;
- throw new NotImplementedException(Texture.Swizzle.ToString());
+ return new BlockLinearSwizzle(Width, BytesPerPixel, Image.GobBlockHeight);
+ }
+ else
+ {
+ return new LinearSwizzle(Image.Pitch, BytesPerPixel);
+ }
}
public static (AMemory Memory, long Position) GetMemoryAndPosition(
diff --git a/Ryujinx.Graphics/Texture/TextureInfo.cs b/Ryujinx.Graphics/Texture/TextureInfo.cs
deleted file mode 100644
index 66445dcc..00000000
--- a/Ryujinx.Graphics/Texture/TextureInfo.cs
+++ /dev/null
@@ -1,60 +0,0 @@
-using Ryujinx.Graphics.Gal;
-
-namespace Ryujinx.Graphics.Texture
-{
- public struct TextureInfo
- {
- public long Position { get; private set; }
-
- public int Width { get; private set; }
- public int Height { get; private set; }
- public int Pitch { get; private set; }
-
- public int BlockHeight { get; private set; }
- public int TileWidth { get; private set; }
-
- public TextureSwizzle Swizzle { get; private set; }
-
- public GalImageFormat Format { get; private set; }
-
- public TextureInfo(
- long Position,
- int Width,
- int Height)
- {
- this.Position = Position;
- this.Width = Width;
- this.Height = Height;
-
- Pitch = 0;
-
- BlockHeight = 16;
-
- TileWidth = 1;
-
- Swizzle = TextureSwizzle.BlockLinear;
-
- Format = GalImageFormat.A8B8G8R8 | GalImageFormat.Unorm;
- }
-
- public TextureInfo(
- long Position,
- int Width,
- int Height,
- int Pitch,
- int BlockHeight,
- int TileWidth,
- TextureSwizzle Swizzle,
- GalImageFormat Format)
- {
- this.Position = Position;
- this.Width = Width;
- this.Height = Height;
- this.Pitch = Pitch;
- this.BlockHeight = BlockHeight;
- this.TileWidth = TileWidth;
- this.Swizzle = Swizzle;
- this.Format = Format;
- }
- }
-} \ No newline at end of file
diff --git a/Ryujinx.Graphics/Texture/TextureReader.cs b/Ryujinx.Graphics/Texture/TextureReader.cs
deleted file mode 100644
index dbaed1a8..00000000
--- a/Ryujinx.Graphics/Texture/TextureReader.cs
+++ /dev/null
@@ -1,398 +0,0 @@
-using ChocolArm64.Memory;
-using Ryujinx.Graphics.Gal;
-using System;
-
-namespace Ryujinx.Graphics.Texture
-{
- delegate byte[] TextureReaderDelegate(IAMemory Memory, TextureInfo Texture);
-
- public static class TextureReader
- {
- public static byte[] Read(IAMemory Memory, TextureInfo Texture)
- {
- TextureReaderDelegate Reader = ImageUtils.GetReader(Texture.Format);
-
- return Reader(Memory, Texture);
- }
-
- internal unsafe static byte[] Read1Bpp(IAMemory Memory, TextureInfo Texture)
- {
- int Width = Texture.Width;
- int Height = Texture.Height;
-
- byte[] Output = new byte[Width * Height];
-
- ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 1);
-
- (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
- Memory,
- Texture.Position);
-
- fixed (byte* BuffPtr = Output)
- {
- long OutOffs = 0;
-
- for (int Y = 0; Y < Height; Y++)
- for (int X = 0; X < Width; X++)
- {
- long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
-
- byte Pixel = CpuMem.ReadByte(Position + Offset);
-
- *(BuffPtr + OutOffs) = Pixel;
-
- OutOffs++;
- }
- }
-
- return Output;
- }
-
- internal unsafe static byte[] Read5551(IAMemory Memory, TextureInfo Texture)
- {
- int Width = Texture.Width;
- int Height = Texture.Height;
-
- byte[] Output = new byte[Width * Height * 2];
-
- ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
-
- (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
- Memory,
- Texture.Position);
-
- fixed (byte* BuffPtr = Output)
- {
- long OutOffs = 0;
-
- for (int Y = 0; Y < Height; Y++)
- for (int X = 0; X < Width; X++)
- {
- long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
-
- uint Pixel = (uint)CpuMem.ReadInt16(Position + Offset);
-
- Pixel = (Pixel & 0x001f) << 11 |
- (Pixel & 0x03e0) << 1 |
- (Pixel & 0x7c00) >> 9 |
- (Pixel & 0x8000) >> 15;
-
- *(short*)(BuffPtr + OutOffs) = (short)Pixel;
-
- OutOffs += 2;
- }
- }
-
- return Output;
- }
-
- internal unsafe static byte[] Read565(IAMemory Memory, TextureInfo Texture)
- {
- int Width = Texture.Width;
- int Height = Texture.Height;
-
- byte[] Output = new byte[Width * Height * 2];
-
- ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
-
- (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
- Memory,
- Texture.Position);
-
- fixed (byte* BuffPtr = Output)
- {
- long OutOffs = 0;
-
- for (int Y = 0; Y < Height; Y++)
- for (int X = 0; X < Width; X++)
- {
- long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
-
- uint Pixel = (uint)CpuMem.ReadInt16(Position + Offset);
-
- Pixel = (Pixel & 0x001f) << 11 |
- (Pixel & 0x07e0) |
- (Pixel & 0xf800) >> 11;
-
- *(short*)(BuffPtr + OutOffs) = (short)Pixel;
-
- OutOffs += 2;
- }
- }
-
- return Output;
- }
-
- internal unsafe static byte[] Read2Bpp(IAMemory Memory, TextureInfo Texture)
- {
- int Width = Texture.Width;
- int Height = Texture.Height;
-
- byte[] Output = new byte[Width * Height * 2];
-
- ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 2);
-
- (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
- Memory,
- Texture.Position);
-
- fixed (byte* BuffPtr = Output)
- {
- long OutOffs = 0;
-
- for (int Y = 0; Y < Height; Y++)
- for (int X = 0; X < Width; X++)
- {
- long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
-
- short Pixel = CpuMem.ReadInt16(Position + Offset);
-
- *(short*)(BuffPtr + OutOffs) = Pixel;
-
- OutOffs += 2;
- }
- }
-
- return Output;
- }
-
- internal unsafe static byte[] Read4Bpp(IAMemory Memory, TextureInfo Texture)
- {
- int Width = Texture.Width;
- int Height = Texture.Height;
-
- byte[] Output = new byte[Width * Height * 4];
-
- ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 4);
-
- (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
- Memory,
- Texture.Position);
-
- fixed (byte* BuffPtr = Output)
- {
- long OutOffs = 0;
-
- for (int Y = 0; Y < Height; Y++)
- for (int X = 0; X < Width; X++)
- {
- long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
-
- int Pixel = CpuMem.ReadInt32(Position + Offset);
-
- *(int*)(BuffPtr + OutOffs) = Pixel;
-
- OutOffs += 4;
- }
- }
-
- return Output;
- }
-
- internal unsafe static byte[] Read8Bpp(IAMemory Memory, TextureInfo Texture)
- {
- int Width = Texture.Width;
- int Height = Texture.Height;
-
- byte[] Output = new byte[Width * Height * 8];
-
- ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 8);
-
- (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
- Memory,
- Texture.Position);
-
- fixed (byte* BuffPtr = Output)
- {
- long OutOffs = 0;
-
- for (int Y = 0; Y < Height; Y++)
- for (int X = 0; X < Width; X++)
- {
- long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
-
- long Pixel = CpuMem.ReadInt64(Position + Offset);
-
- *(long*)(BuffPtr + OutOffs) = Pixel;
-
- OutOffs += 8;
- }
- }
-
- return Output;
- }
-
- internal unsafe static byte[] Read16Bpp(IAMemory Memory, TextureInfo Texture)
- {
- int Width = Texture.Width;
- int Height = Texture.Height;
-
- byte[] Output = new byte[Width * Height * 16];
-
- ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 16);
-
- (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
- Memory,
- Texture.Position);
-
- fixed (byte* BuffPtr = Output)
- {
- long OutOffs = 0;
-
- for (int Y = 0; Y < Height; Y++)
- for (int X = 0; X < Width; X++)
- {
- long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
-
- long PxLow = CpuMem.ReadInt64(Position + Offset + 0);
- long PxHigh = CpuMem.ReadInt64(Position + Offset + 8);
-
- *(long*)(BuffPtr + OutOffs + 0) = PxLow;
- *(long*)(BuffPtr + OutOffs + 8) = PxHigh;
-
- OutOffs += 16;
- }
- }
-
- return Output;
- }
-
- internal unsafe static byte[] Read8Bpt4x4(IAMemory Memory, TextureInfo Texture)
- {
- int Width = (Texture.Width + 3) / 4;
- int Height = (Texture.Height + 3) / 4;
-
- byte[] Output = new byte[Width * Height * 8];
-
- ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 4, 8);
-
- (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
- Memory,
- Texture.Position);
-
- fixed (byte* BuffPtr = Output)
- {
- long OutOffs = 0;
-
- for (int Y = 0; Y < Height; Y++)
- for (int X = 0; X < Width; X++)
- {
- long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
-
- long Tile = CpuMem.ReadInt64(Position + Offset);
-
- *(long*)(BuffPtr + OutOffs) = Tile;
-
- OutOffs += 8;
- }
- }
-
- return Output;
- }
-
- internal unsafe static byte[] Read16BptCompressedTexture(IAMemory Memory, TextureInfo Texture, int BlockWidth, int BlockHeight)
- {
- int Width = (Texture.Width + (BlockWidth - 1)) / BlockWidth;
- int Height = (Texture.Height + (BlockHeight - 1)) / BlockHeight;
-
- byte[] Output = new byte[Width * Height * 16];
-
- ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, BlockWidth, 16);
-
- (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
- Memory,
- Texture.Position);
-
- fixed (byte* BuffPtr = Output)
- {
- long OutOffs = 0;
-
- for (int Y = 0; Y < Height; Y++)
- for (int X = 0; X < Width; X++)
- {
- long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
-
- long Tile0 = CpuMem.ReadInt64(Position + Offset + 0);
- long Tile1 = CpuMem.ReadInt64(Position + Offset + 8);
-
- *(long*)(BuffPtr + OutOffs + 0) = Tile0;
- *(long*)(BuffPtr + OutOffs + 8) = Tile1;
-
- OutOffs += 16;
- }
- }
-
- return Output;
- }
-
- internal static byte[] Read16BptCompressedTexture4x4(IAMemory Memory, TextureInfo Texture)
- {
- return Read16BptCompressedTexture(Memory, Texture, 4, 4);
- }
-
- internal static byte[] Read16BptCompressedTexture5x5(IAMemory Memory, TextureInfo Texture)
- {
- return Read16BptCompressedTexture(Memory, Texture, 5, 5);
- }
-
- internal static byte[] Read16BptCompressedTexture6x6(IAMemory Memory, TextureInfo Texture)
- {
- return Read16BptCompressedTexture(Memory, Texture, 6, 6);
- }
-
- internal static byte[] Read16BptCompressedTexture8x8(IAMemory Memory, TextureInfo Texture)
- {
- return Read16BptCompressedTexture(Memory, Texture, 8, 8);
- }
-
- internal static byte[] Read16BptCompressedTexture10x10(IAMemory Memory, TextureInfo Texture)
- {
- return Read16BptCompressedTexture(Memory, Texture, 10, 10);
- }
-
- internal static byte[] Read16BptCompressedTexture12x12(IAMemory Memory, TextureInfo Texture)
- {
- return Read16BptCompressedTexture(Memory, Texture, 12, 12);
- }
-
- internal static byte[] Read16BptCompressedTexture5x4(IAMemory Memory, TextureInfo Texture)
- {
- return Read16BptCompressedTexture(Memory, Texture, 5, 4);
- }
-
- internal static byte[] Read16BptCompressedTexture6x5(IAMemory Memory, TextureInfo Texture)
- {
- return Read16BptCompressedTexture(Memory, Texture, 6, 5);
- }
-
- internal static byte[] Read16BptCompressedTexture8x6(IAMemory Memory, TextureInfo Texture)
- {
- return Read16BptCompressedTexture(Memory, Texture, 8, 6);
- }
-
- internal static byte[] Read16BptCompressedTexture10x8(IAMemory Memory, TextureInfo Texture)
- {
- return Read16BptCompressedTexture(Memory, Texture, 10, 8);
- }
-
- internal static byte[] Read16BptCompressedTexture12x10(IAMemory Memory, TextureInfo Texture)
- {
- return Read16BptCompressedTexture(Memory, Texture, 12, 10);
- }
-
- internal static byte[] Read16BptCompressedTexture8x5(IAMemory Memory, TextureInfo Texture)
- {
- return Read16BptCompressedTexture(Memory, Texture, 5, 5);
- }
-
- internal static byte[] Read16BptCompressedTexture10x5(IAMemory Memory, TextureInfo Texture)
- {
- return Read16BptCompressedTexture(Memory, Texture, 10, 5);
- }
-
- internal static byte[] Read16BptCompressedTexture10x6(IAMemory Memory, TextureInfo Texture)
- {
- return Read16BptCompressedTexture(Memory, Texture, 10, 6);
- }
- }
-}
diff --git a/Ryujinx.Graphics/Texture/TextureWriter.cs b/Ryujinx.Graphics/Texture/TextureWriter.cs
deleted file mode 100644
index 16e78c56..00000000
--- a/Ryujinx.Graphics/Texture/TextureWriter.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-using ChocolArm64.Memory;
-using Ryujinx.Graphics.Gal;
-using Ryujinx.Graphics.Memory;
-
-namespace Ryujinx.Graphics.Texture
-{
- static class TextureWriter
- {
- public unsafe static void Write(IAMemory Memory, TextureInfo Texture, byte[] Data)
- {
- ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, 1, 4);
-
- (AMemory CpuMem, long Position) = TextureHelper.GetMemoryAndPosition(
- Memory,
- Texture.Position);
-
- fixed (byte* BuffPtr = Data)
- {
- long InOffs = 0;
-
- for (int Y = 0; Y < Texture.Height; Y++)
- for (int X = 0; X < Texture.Width; X++)
- {
- long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y);
-
- int Pixel = *(int*)(BuffPtr + InOffs);
-
- CpuMem.WriteInt32(Position + Offset, Pixel);
-
- InOffs += 4;
- }
- }
- }
- }
-}
diff --git a/Ryujinx.Graphics/ValueRange.cs b/Ryujinx.Graphics/ValueRange.cs
new file mode 100644
index 00000000..6298bd8e
--- /dev/null
+++ b/Ryujinx.Graphics/ValueRange.cs
@@ -0,0 +1,17 @@
+namespace Ryujinx.Graphics
+{
+ struct ValueRange<T>
+ {
+ public long Start { get; private set; }
+ public long End { get; private set; }
+
+ public T Value { get; set; }
+
+ public ValueRange(long Start, long End, T Value = default(T))
+ {
+ this.Start = Start;
+ this.End = End;
+ this.Value = Value;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.Graphics/ValueRangeSet.cs b/Ryujinx.Graphics/ValueRangeSet.cs
new file mode 100644
index 00000000..479f41ed
--- /dev/null
+++ b/Ryujinx.Graphics/ValueRangeSet.cs
@@ -0,0 +1,234 @@
+using System.Collections.Generic;
+
+namespace Ryujinx.Graphics
+{
+ class ValueRangeSet<T>
+ {
+ private List<ValueRange<T>> Ranges;
+
+ public ValueRangeSet()
+ {
+ Ranges = new List<ValueRange<T>>();
+ }
+
+ public void Add(ValueRange<T> Range)
+ {
+ if (Range.End <= Range.Start)
+ {
+ //Empty or invalid range, do nothing.
+ return;
+ }
+
+ int First = BinarySearchFirstIntersection(Range);
+
+ if (First == -1)
+ {
+ //No intersections case.
+ //Find first greater than range (after the current one).
+ //If found, add before, otherwise add to the end of the list.
+ int GtIndex = BinarySearchGt(Range);
+
+ if (GtIndex != -1)
+ {
+ Ranges.Insert(GtIndex, Range);
+ }
+ else
+ {
+ Ranges.Add(Range);
+ }
+
+ return;
+ }
+
+ (int Start, int End) = GetAllIntersectionRanges(Range, First);
+
+ ValueRange<T> Prev = Ranges[Start];
+ ValueRange<T> Next = Ranges[End];
+
+ Ranges.RemoveRange(Start, (End - Start) + 1);
+
+ InsertNextNeighbour(Start, Range, Next);
+
+ int NewIndex = Start;
+
+ Ranges.Insert(Start, Range);
+
+ InsertPrevNeighbour(Start, Range, Prev);
+
+ //Try merging neighbours if the value is equal.
+ if (NewIndex > 0)
+ {
+ Prev = Ranges[NewIndex - 1];
+
+ if (Prev.End == Range.Start && CompareValues(Prev, Range))
+ {
+ Ranges.RemoveAt(--NewIndex);
+
+ Ranges[NewIndex] = new ValueRange<T>(Prev.Start, Range.End, Range.Value);
+ }
+ }
+
+ if (NewIndex < Ranges.Count - 1)
+ {
+ Next = Ranges[NewIndex + 1];
+
+ if (Next.Start == Range.End && CompareValues(Next, Range))
+ {
+ Ranges.RemoveAt(NewIndex + 1);
+
+ Ranges[NewIndex] = new ValueRange<T>(Range.Start, Next.End, Range.Value);
+ }
+ }
+ }
+
+ private bool CompareValues(ValueRange<T> LHS, ValueRange<T> RHS)
+ {
+ return LHS.Value?.Equals(RHS.Value) ?? RHS.Value == null;
+ }
+
+ public void Remove(ValueRange<T> Range)
+ {
+ int First = BinarySearchFirstIntersection(Range);
+
+ if (First == -1)
+ {
+ //Nothing to remove.
+ return;
+ }
+
+ (int Start, int End) = GetAllIntersectionRanges(Range, First);
+
+ ValueRange<T> Prev = Ranges[Start];
+ ValueRange<T> Next = Ranges[End];
+
+ Ranges.RemoveRange(Start, (End - Start) + 1);
+
+ InsertNextNeighbour(Start, Range, Next);
+ InsertPrevNeighbour(Start, Range, Prev);
+ }
+
+ private void InsertNextNeighbour(int Index, ValueRange<T> Range, ValueRange<T> Next)
+ {
+ //Split last intersection (ordered by Start) if necessary.
+ if (Range.End < Next.End)
+ {
+ InsertNewRange(Index, Range.End, Next.End, Next.Value);
+ }
+ }
+
+ private void InsertPrevNeighbour(int Index, ValueRange<T> Range, ValueRange<T> Prev)
+ {
+ //Split first intersection (ordered by Start) if necessary.
+ if (Range.Start > Prev.Start)
+ {
+ InsertNewRange(Index, Prev.Start, Range.Start, Prev.Value);
+ }
+ }
+
+ private void InsertNewRange(int Index, long Start, long End, T Value)
+ {
+ Ranges.Insert(Index, new ValueRange<T>(Start, End, Value));
+ }
+
+ public ValueRange<T>[] GetAllIntersections(ValueRange<T> Range)
+ {
+ int First = BinarySearchFirstIntersection(Range);
+
+ if (First == -1)
+ {
+ return new ValueRange<T>[0];
+ }
+
+ (int Start, int End) = GetAllIntersectionRanges(Range, First);
+
+ return Ranges.GetRange(Start, (End - Start) + 1).ToArray();
+ }
+
+ private (int Start, int End) GetAllIntersectionRanges(ValueRange<T> Range, int BaseIndex)
+ {
+ int Start = BaseIndex;
+ int End = BaseIndex;
+
+ while (Start > 0 && Intersects(Range, Ranges[Start - 1]))
+ {
+ Start--;
+ }
+
+ while (End < Ranges.Count - 1 && Intersects(Range, Ranges[End + 1]))
+ {
+ End++;
+ }
+
+ return (Start, End);
+ }
+
+ private int BinarySearchFirstIntersection(ValueRange<T> Range)
+ {
+ int Left = 0;
+ int Right = Ranges.Count - 1;
+
+ while (Left <= Right)
+ {
+ int Size = Right - Left;
+
+ int Middle = Left + (Size >> 1);
+
+ ValueRange<T> Current = Ranges[Middle];
+
+ if (Intersects(Range, Current))
+ {
+ return Middle;
+ }
+
+ if (Range.Start < Current.Start)
+ {
+ Right = Middle - 1;
+ }
+ else
+ {
+ Left = Middle + 1;
+ }
+ }
+
+ return -1;
+ }
+
+ private int BinarySearchGt(ValueRange<T> Range)
+ {
+ int GtIndex = -1;
+
+ int Left = 0;
+ int Right = Ranges.Count - 1;
+
+ while (Left <= Right)
+ {
+ int Size = Right - Left;
+
+ int Middle = Left + (Size >> 1);
+
+ ValueRange<T> Current = Ranges[Middle];
+
+ if (Range.Start < Current.Start)
+ {
+ Right = Middle - 1;
+
+ if (GtIndex == -1 || Current.Start < Ranges[GtIndex].Start)
+ {
+ GtIndex = Middle;
+ }
+ }
+ else
+ {
+ Left = Middle + 1;
+ }
+ }
+
+ return GtIndex;
+ }
+
+ private bool Intersects(ValueRange<T> LHS, ValueRange<T> RHS)
+ {
+ return LHS.Start < RHS.End && RHS.Start < LHS.End;
+ }
+ }
+} \ No newline at end of file
diff --git a/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs b/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
index 7cc1c858..d10eb117 100644
--- a/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
+++ b/Ryujinx.HLE/HOS/Kernel/SvcSystem.cs
@@ -288,7 +288,8 @@ namespace Ryujinx.HLE.HOS.Kernel
//Fail for info not available on older Kernel versions.
if (InfoType == 18 ||
InfoType == 19 ||
- InfoType == 20)
+ InfoType == 20 ||
+ InfoType == 21)
{
ThreadState.X0 = MakeError(ErrorModule.Kernel, KernelErr.InvalidEnumValue);
diff --git a/Ryujinx.HLE/HOS/Services/Acc/IProfile.cs b/Ryujinx.HLE/HOS/Services/Acc/IProfile.cs
index 316f16d0..f68c8191 100644
--- a/Ryujinx.HLE/HOS/Services/Acc/IProfile.cs
+++ b/Ryujinx.HLE/HOS/Services/Acc/IProfile.cs
@@ -3,7 +3,6 @@ using Ryujinx.HLE.HOS.Ipc;
using Ryujinx.HLE.HOS.SystemState;
using Ryujinx.HLE.Logging;
using Ryujinx.HLE.Utilities;
-using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
diff --git a/Ryujinx.HLE/HOS/Services/Vi/IHOSBinderDriver.cs b/Ryujinx.HLE/HOS/Services/Vi/IHOSBinderDriver.cs
index bf5f20a2..19e0d949 100644
--- a/Ryujinx.HLE/HOS/Services/Vi/IHOSBinderDriver.cs
+++ b/Ryujinx.HLE/HOS/Services/Vi/IHOSBinderDriver.cs
@@ -13,7 +13,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
public override IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands;
- private KEvent ReleaseEvent;
+ private KEvent BinderEvent;
private NvFlinger Flinger;
@@ -27,9 +27,11 @@ namespace Ryujinx.HLE.HOS.Services.Vi
{ 3, TransactParcelAuto }
};
- ReleaseEvent = new KEvent();
+ BinderEvent = new KEvent();
- Flinger = new NvFlinger(Renderer, ReleaseEvent);
+ BinderEvent.WaitEvent.Set();
+
+ Flinger = new NvFlinger(Renderer, BinderEvent);
}
public long TransactParcel(ServiceCtx Context)
@@ -75,7 +77,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
int Id = Context.RequestData.ReadInt32();
uint Unk = Context.RequestData.ReadUInt32();
- int Handle = Context.Process.HandleTable.OpenHandle(ReleaseEvent);
+ int Handle = Context.Process.HandleTable.OpenHandle(BinderEvent);
Context.Response.HandleDesc = IpcHandleDesc.MakeMove(Handle);
@@ -91,7 +93,7 @@ namespace Ryujinx.HLE.HOS.Services.Vi
{
if (Disposing)
{
- ReleaseEvent.Dispose();
+ BinderEvent.Dispose();
Flinger.Dispose();
}
diff --git a/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs b/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs
index 2a6918c4..a8493758 100644
--- a/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs
+++ b/Ryujinx.HLE/HOS/Services/Vi/NvFlinger.cs
@@ -1,6 +1,7 @@
using Ryujinx.Graphics.Gal;
-using Ryujinx.Graphics.Texture;
+using Ryujinx.Graphics.Memory;
using Ryujinx.HLE.HOS.Kernel;
+using Ryujinx.HLE.HOS.Services.Nv.NvGpuAS;
using Ryujinx.HLE.HOS.Services.Nv.NvMap;
using Ryujinx.HLE.Logging;
using System;
@@ -19,7 +20,7 @@ namespace Ryujinx.HLE.HOS.Services.Android
private Dictionary<(string, int), ServiceProcessParcel> Commands;
- private KEvent ReleaseEvent;
+ private KEvent BinderEvent;
private IGalRenderer Renderer;
@@ -67,7 +68,7 @@ namespace Ryujinx.HLE.HOS.Services.Android
private bool Disposed;
- public NvFlinger(IGalRenderer Renderer, KEvent ReleaseEvent)
+ public NvFlinger(IGalRenderer Renderer, KEvent BinderEvent)
{
Commands = new Dictionary<(string, int), ServiceProcessParcel>()
{
@@ -82,8 +83,8 @@ namespace Ryujinx.HLE.HOS.Services.Android
{ ("android.gui.IGraphicBufferProducer", 0xe), GbpPreallocBuffer }
};
- this.Renderer = Renderer;
- this.ReleaseEvent = ReleaseEvent;
+ this.Renderer = Renderer;
+ this.BinderEvent = BinderEvent;
BufferQueue = new BufferEntry[0x40];
@@ -301,42 +302,41 @@ namespace Ryujinx.HLE.HOS.Services.Android
bool FlipX = BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipX);
bool FlipY = BufferQueue[Slot].Transform.HasFlag(HalTransform.FlipY);
- //Rotation is being ignored
+ //Note: Rotation is being ignored.
int Top = Crop.Top;
int Left = Crop.Left;
int Right = Crop.Right;
int Bottom = Crop.Bottom;
- Renderer.QueueAction(() => Renderer.RenderTarget.SetTransform(FlipX, FlipY, Top, Left, Right, Bottom));
+ NvGpuVmm Vmm = NvGpuASIoctl.GetASCtx(Context).Vmm;
- //TODO: Support double buffering here aswell, it is broken for GPU
- //frame buffers because it seems to be completely out of sync.
- if (Context.Device.Gpu.Engine3d.IsFrameBufferPosition(FbAddr))
+ Renderer.QueueAction(() =>
{
- //Frame buffer is rendered to by the GPU, we can just
- //bind the frame buffer texture, it's not necessary to read anything.
- Renderer.QueueAction(() => Renderer.RenderTarget.Set(FbAddr));
- }
- else
- {
- //Frame buffer is not set on the GPU registers, in this case
- //assume that the app is manually writing to it.
- TextureInfo Texture = new TextureInfo(FbAddr, FbWidth, FbHeight);
+ if (!Renderer.Texture.TryGetImage(FbAddr, out GalImage Image))
+ {
+ Image = new GalImage(
+ FbWidth,
+ FbHeight, 1, 16,
+ GalMemoryLayout.BlockLinear,
+ GalImageFormat.A8B8G8R8 | GalImageFormat.Unorm);
+ }
- byte[] Data = TextureReader.Read(Context.Memory, Texture);
+ Context.Device.Gpu.ResourceManager.ClearPbCache();
+ Context.Device.Gpu.ResourceManager.SendTexture(Vmm, FbAddr, Image);
- Renderer.QueueAction(() => Renderer.RenderTarget.Set(Data, FbWidth, FbHeight));
- }
+ Renderer.RenderTarget.SetTransform(FlipX, FlipY, Top, Left, Right, Bottom);
+ Renderer.RenderTarget.Set(FbAddr);
- Context.Device.Gpu.Renderer.QueueAction(() => ReleaseBuffer(Slot));
+ ReleaseBuffer(Slot);
+ });
}
private void ReleaseBuffer(int Slot)
{
BufferQueue[Slot].State = BufferState.Free;
- ReleaseEvent.WaitEvent.Set();
+ BinderEvent.WaitEvent.Set();
lock (WaitBufferFree)
{