diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-04-25 23:11:26 -0300 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-04-25 23:12:26 -0300 |
| commit | a38a72b0622f89897bdcd01b6d00ea6bc142c34f (patch) | |
| tree | 2025cdddaa7ef6769ac69c51eeede0924ffcba5f /Ryujinx.Graphics/Gpu | |
| parent | 211f7f69db4d84b82caa3ee62d4ecdfbbd95604d (diff) | |
Some small sync primitive fixes, logging fixes, started to implement the 2D engine on the GPU, fixed DrawArrays, implemented a few more shader instructions, made a start on nvdrv refactor, etc...
Diffstat (limited to 'Ryujinx.Graphics/Gpu')
| -rw-r--r-- | Ryujinx.Graphics/Gpu/NsGpu.cs | 4 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs | 12 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gpu/NvGpuEngine2d.cs | 158 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gpu/NvGpuEngine2dReg.cs | 25 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs | 5 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs | 2 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gpu/NvGpuFifo.cs | 6 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gpu/TextureHelper.cs | 23 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gpu/TextureReader.cs | 24 | ||||
| -rw-r--r-- | Ryujinx.Graphics/Gpu/TextureWriter.cs | 45 |
10 files changed, 280 insertions, 24 deletions
diff --git a/Ryujinx.Graphics/Gpu/NsGpu.cs b/Ryujinx.Graphics/Gpu/NsGpu.cs index 9a2e9012..e1088982 100644 --- a/Ryujinx.Graphics/Gpu/NsGpu.cs +++ b/Ryujinx.Graphics/Gpu/NsGpu.cs @@ -7,10 +7,11 @@ namespace Ryujinx.Graphics.Gpu { public IGalRenderer Renderer { get; private set; } - internal NsGpuMemoryMgr MemoryMgr { get; private set; } + public NsGpuMemoryMgr MemoryMgr { get; private set; } public NvGpuFifo Fifo { get; private set; } + public NvGpuEngine2d Engine2d { get; private set; } public NvGpuEngine3d Engine3d { get; private set; } private Thread FifoProcessing; @@ -25,6 +26,7 @@ namespace Ryujinx.Graphics.Gpu Fifo = new NvGpuFifo(this); + Engine2d = new NvGpuEngine2d(this); Engine3d = new NvGpuEngine3d(this); KeepRunning = true; diff --git a/Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs b/Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs index 7f50640d..eff51783 100644 --- a/Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs +++ b/Ryujinx.Graphics/Gpu/NsGpuMemoryMgr.cs @@ -1,6 +1,6 @@ namespace Ryujinx.Graphics.Gpu { - class NsGpuMemoryMgr + public class NsGpuMemoryMgr { private const long AddrSize = 1L << 40; @@ -50,12 +50,20 @@ namespace Ryujinx.Graphics.Gpu return GpuAddr; } + public void Unmap(long Position, long Size) + { + for (long Offset = 0; Offset < Size; Offset += PageSize) + { + SetPTAddr(Position + Offset, PteUnmapped); + } + } + public long Map(long CpuAddr, long Size) { CpuAddr &= ~PageMask; long Position = GetFreePosition(Size); - + if (Position != -1) { for (long Offset = 0; Offset < Size; Offset += PageSize) diff --git a/Ryujinx.Graphics/Gpu/NvGpuEngine2d.cs b/Ryujinx.Graphics/Gpu/NvGpuEngine2d.cs new file mode 100644 index 00000000..c2bee167 --- /dev/null +++ b/Ryujinx.Graphics/Gpu/NvGpuEngine2d.cs @@ -0,0 +1,158 @@ +using ChocolArm64.Memory; +using Ryujinx.Graphics.Gal; +using System.Collections.Generic; + +namespace Ryujinx.Graphics.Gpu +{ + public class NvGpuEngine2d : INvGpuEngine + { + private enum CopyOperation + { + SrcCopyAnd, + RopAnd, + Blend, + SrcCopy, + Rop, + SrcCopyPremult, + BlendPremult + } + + public int[] Registers { get; private set; } + + private NsGpu Gpu; + + private Dictionary<int, NvGpuMethod> Methods; + + public NvGpuEngine2d(NsGpu Gpu) + { + this.Gpu = Gpu; + + Registers = new int[0xe00]; + + 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(0xb5, 1, 1, TextureCopy); + } + + public void CallMethod(AMemory Memory, NsGpuPBEntry PBEntry) + { + if (Methods.TryGetValue(PBEntry.Method, out NvGpuMethod Method)) + { + Method(Memory, PBEntry); + } + else + { + WriteRegister(PBEntry); + } + } + + private void TextureCopy(AMemory Memory, NsGpuPBEntry PBEntry) + { + CopyOperation Operation = (CopyOperation)ReadRegister(NvGpuEngine2dReg.CopyOperation); + + bool SrcLinear = ReadRegister(NvGpuEngine2dReg.SrcLinear) != 0; + int SrcWidth = ReadRegister(NvGpuEngine2dReg.SrcWidth); + int SrcHeight = ReadRegister(NvGpuEngine2dReg.SrcHeight); + + 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 DstSwizzle = DstLinear + ? TextureSwizzle.Pitch + : TextureSwizzle.BlockLinear; + + int DstBlockHeight = 1 << ((DstBlkDim >> 4) & 0xf); + + long Tag = MakeInt64From2xInt32(NvGpuEngine2dReg.SrcAddress); + + TryGetCpuAddr(NvGpuEngine2dReg.SrcAddress, out long SrcAddress); + TryGetCpuAddr(NvGpuEngine2dReg.DstAddress, out long DstAddress); + + bool IsFbTexture = Gpu.Engine3d.IsFrameBufferPosition(Tag); + + if (IsFbTexture && DstLinear) + { + DstSwizzle = TextureSwizzle.BlockLinear; + } + + Texture DstTexture = new Texture( + DstAddress, + DstWidth, + DstHeight, + DstBlockHeight, + DstBlockHeight, + DstSwizzle, + GalTextureFormat.A8B8G8R8); + + if (IsFbTexture) + { + Gpu.Renderer.GetFrameBufferData(Tag, (byte[] Buffer) => + { + CopyTexture(Memory, DstTexture, Buffer); + }); + } + else + { + long Size = SrcWidth * SrcHeight * 4; + + byte[] Buffer = AMemoryHelper.ReadBytes(Memory, SrcAddress, Size); + + CopyTexture(Memory, DstTexture, Buffer); + } + } + + private void CopyTexture(AMemory Memory, Texture Texture, byte[] Buffer) + { + TextureWriter.Write(Memory, Texture, Buffer); + } + + private bool TryGetCpuAddr(NvGpuEngine2dReg Reg, out long Position) + { + Position = MakeInt64From2xInt32(Reg); + + Position = Gpu.GetCpuAddr(Position); + + return Position != -1; + } + + private long MakeInt64From2xInt32(NvGpuEngine2dReg Reg) + { + return + (long)Registers[(int)Reg + 0] << 32 | + (uint)Registers[(int)Reg + 1]; + } + + private void WriteRegister(NsGpuPBEntry PBEntry) + { + int ArgsCount = PBEntry.Arguments.Count; + + if (ArgsCount > 0) + { + Registers[PBEntry.Method] = PBEntry.Arguments[ArgsCount - 1]; + } + } + + private int ReadRegister(NvGpuEngine2dReg Reg) + { + return Registers[(int)Reg]; + } + + private void WriteRegister(NvGpuEngine2dReg Reg, int Value) + { + Registers[(int)Reg] = Value; + } + } +}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Gpu/NvGpuEngine2dReg.cs b/Ryujinx.Graphics/Gpu/NvGpuEngine2dReg.cs new file mode 100644 index 00000000..903baca8 --- /dev/null +++ b/Ryujinx.Graphics/Gpu/NvGpuEngine2dReg.cs @@ -0,0 +1,25 @@ +namespace Ryujinx.Graphics.Gpu +{ + enum NvGpuEngine2dReg + { + DstFormat = 0x80, + DstLinear = 0x81, + DstBlockDimensions = 0x82, + DstDepth = 0x83, + DstLayer = 0x84, + DstPitch = 0x85, + DstWidth = 0x86, + DstHeight = 0x87, + DstAddress = 0x88, + SrcFormat = 0x8c, + SrcLinear = 0x8d, + SrcBlockDimensions = 0x8e, + SrcDepth = 0x8f, + SrcLayer = 0x90, + SrcPitch = 0x91, + SrcWidth = 0x92, + SrcHeight = 0x93, + SrcAddress = 0x94, + CopyOperation = 0xab + } +}
\ No newline at end of file diff --git a/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs b/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs index 88ad7633..bf04db36 100644 --- a/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs +++ b/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs @@ -360,6 +360,9 @@ namespace Ryujinx.Graphics.Gpu for (int Index = 0; Index < 32; Index++) { + int VertexFirst = ReadRegister(NvGpuEngine3dReg.VertexArrayFirst); + int VertexCount = ReadRegister(NvGpuEngine3dReg.VertexArrayCount); + int Control = ReadRegister(NvGpuEngine3dReg.VertexArrayNControl + Index * 4); bool Enable = (Control & 0x1000) != 0; @@ -394,7 +397,7 @@ namespace Ryujinx.Graphics.Gpu } else { - Gpu.Renderer.DrawArrays(Index, PrimType); + Gpu.Renderer.DrawArrays(Index, VertexFirst, VertexCount, PrimType); } } } diff --git a/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs b/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs index 605ca9da..0d995619 100644 --- a/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs +++ b/Ryujinx.Graphics/Gpu/NvGpuEngine3dReg.cs @@ -12,6 +12,8 @@ namespace Ryujinx.Graphics.Gpu ViewportTranslateX = 0x283, ViewportTranslateY = 0x284, ViewportTranslateZ = 0x285, + VertexArrayFirst = 0x35d, + VertexArrayCount = 0x35e, VertexAttribNFormat = 0x458, IBlendEnable = 0x4b9, BlendSeparateAlpha = 0x4cf, diff --git a/Ryujinx.Graphics/Gpu/NvGpuFifo.cs b/Ryujinx.Graphics/Gpu/NvGpuFifo.cs index df765895..68c2902a 100644 --- a/Ryujinx.Graphics/Gpu/NvGpuFifo.cs +++ b/Ryujinx.Graphics/Gpu/NvGpuFifo.cs @@ -139,11 +139,17 @@ namespace Ryujinx.Graphics.Gpu { switch (SubChannels[PBEntry.SubChannel]) { + case NvGpuEngine._2d: Call2dMethod(Memory, PBEntry); break; case NvGpuEngine._3d: Call3dMethod(Memory, PBEntry); break; } } } + private void Call2dMethod(AMemory Memory, NsGpuPBEntry PBEntry) + { + Gpu.Engine2d.CallMethod(Memory, PBEntry); + } + private void Call3dMethod(AMemory Memory, NsGpuPBEntry PBEntry) { if (PBEntry.Method < 0xe00) diff --git a/Ryujinx.Graphics/Gpu/TextureHelper.cs b/Ryujinx.Graphics/Gpu/TextureHelper.cs new file mode 100644 index 00000000..d3c2ac14 --- /dev/null +++ b/Ryujinx.Graphics/Gpu/TextureHelper.cs @@ -0,0 +1,23 @@ +using System; + +namespace Ryujinx.Graphics.Gpu +{ + static class TextureHelper + { + public static ISwizzle GetSwizzle(Texture Texture, int Width, int Bpp) + { + switch (Texture.Swizzle) + { + case TextureSwizzle.Pitch: + case TextureSwizzle.PitchColorKey: + return new LinearSwizzle(Texture.Pitch, Bpp); + + case TextureSwizzle.BlockLinear: + case TextureSwizzle.BlockLinearColorKey: + return new BlockLinearSwizzle(Width, Bpp, Texture.BlockHeight); + } + + throw new NotImplementedException(Texture.Swizzle.ToString()); + } + } +} diff --git a/Ryujinx.Graphics/Gpu/TextureReader.cs b/Ryujinx.Graphics/Gpu/TextureReader.cs index 4c3b4fb1..17fd95c5 100644 --- a/Ryujinx.Graphics/Gpu/TextureReader.cs +++ b/Ryujinx.Graphics/Gpu/TextureReader.cs @@ -30,7 +30,7 @@ namespace Ryujinx.Graphics.Gpu byte[] Output = new byte[Width * Height * 2]; - ISwizzle Swizzle = GetSwizzle(Texture, Width, 2); + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 2); fixed (byte* BuffPtr = Output) { @@ -59,7 +59,7 @@ namespace Ryujinx.Graphics.Gpu byte[] Output = new byte[Width * Height * 4]; - ISwizzle Swizzle = GetSwizzle(Texture, Width, 4); + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 4); fixed (byte* BuffPtr = Output) { @@ -88,7 +88,7 @@ namespace Ryujinx.Graphics.Gpu byte[] Output = new byte[Width * Height * 8]; - ISwizzle Swizzle = GetSwizzle(Texture, Width, 8); + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 8); fixed (byte* BuffPtr = Output) { @@ -117,7 +117,7 @@ namespace Ryujinx.Graphics.Gpu byte[] Output = new byte[Width * Height * 16]; - ISwizzle Swizzle = GetSwizzle(Texture, Width, 16); + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 16); fixed (byte* BuffPtr = Output) { @@ -140,21 +140,5 @@ namespace Ryujinx.Graphics.Gpu return Output; } - - private static ISwizzle GetSwizzle(Texture Texture, int Width, int Bpp) - { - switch (Texture.Swizzle) - { - case TextureSwizzle.Pitch: - case TextureSwizzle.PitchColorKey: - return new LinearSwizzle(Texture.Pitch, Bpp); - - case TextureSwizzle.BlockLinear: - case TextureSwizzle.BlockLinearColorKey: - return new BlockLinearSwizzle(Width, Bpp, Texture.BlockHeight); - } - - throw new NotImplementedException(Texture.Swizzle.ToString()); - } } } diff --git a/Ryujinx.Graphics/Gpu/TextureWriter.cs b/Ryujinx.Graphics/Gpu/TextureWriter.cs new file mode 100644 index 00000000..2f25de73 --- /dev/null +++ b/Ryujinx.Graphics/Gpu/TextureWriter.cs @@ -0,0 +1,45 @@ +using ChocolArm64.Memory; +using Ryujinx.Graphics.Gal; +using System; + +namespace Ryujinx.Graphics.Gpu +{ + public static class TextureWriter + { + public static void Write(AMemory Memory, Texture Texture, byte[] Data) + { + switch (Texture.Format) + { + case GalTextureFormat.A8B8G8R8: Write4Bpp(Memory, Texture, Data); break; + + default: + throw new NotImplementedException(Texture.Format.ToString()); + } + } + + private unsafe static void Write4Bpp(AMemory Memory, Texture Texture, byte[] Data) + { + int Width = Texture.Width; + int Height = Texture.Height; + + ISwizzle Swizzle = TextureHelper.GetSwizzle(Texture, Width, 4); + + fixed (byte* BuffPtr = Data) + { + long InOffs = 0; + + for (int Y = 0; Y < Height; Y++) + for (int X = 0; X < Width; X++) + { + long Offset = (uint)Swizzle.GetSwizzleOffset(X, Y); + + int Pixel = *(int*)(BuffPtr + InOffs); + + Memory.WriteInt32Unchecked(Texture.Position + Offset, Pixel); + + InOffs += 4; + } + } + } + } +} |
