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...

This commit is contained in:
gdkchan 2018-04-25 23:11:26 -03:00
parent 211f7f69db
commit a38a72b062
27 changed files with 816 additions and 199 deletions

View file

@ -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;

View file

@ -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)

View file

@ -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;
}
}
}

View file

@ -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
}
}

View file

@ -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);
}
}
}

View file

@ -12,6 +12,8 @@ namespace Ryujinx.Graphics.Gpu
ViewportTranslateX = 0x283,
ViewportTranslateY = 0x284,
ViewportTranslateZ = 0x285,
VertexArrayFirst = 0x35d,
VertexArrayCount = 0x35e,
VertexAttribNFormat = 0x458,
IBlendEnable = 0x4b9,
BlendSeparateAlpha = 0x4cf,

View file

@ -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)

View file

@ -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());
}
}
}

View file

@ -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());
}
}
}

View file

@ -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;
}
}
}
}
}