Properly support multiple vertex buffers, stub 2 ioctls, fix a shader issue, change the way how the vertex buffer size is calculated for the buffers with limit = 0

This commit is contained in:
gdkchan 2018-04-29 17:58:38 -03:00
parent 17f4ccf2d5
commit f73a182b20
5 changed files with 133 additions and 46 deletions

View file

@ -51,6 +51,8 @@ namespace Ryujinx.Core.OsHle.Services.Nv
{ ("/dev/nvhost-as-gpu", 0x4114), NvGpuAsIoctlRemap }, { ("/dev/nvhost-as-gpu", 0x4114), NvGpuAsIoctlRemap },
{ ("/dev/nvhost-ctrl", 0x001b), NvHostIoctlCtrlGetConfig }, { ("/dev/nvhost-ctrl", 0x001b), NvHostIoctlCtrlGetConfig },
{ ("/dev/nvhost-ctrl", 0x001d), NvHostIoctlCtrlEventWait }, { ("/dev/nvhost-ctrl", 0x001d), NvHostIoctlCtrlEventWait },
{ ("/dev/nvhost-ctrl", 0x001e), NvHostIoctlCtrlEventWaitAsync },
{ ("/dev/nvhost-ctrl", 0x001f), NvHostIoctlCtrlEventRegister },
{ ("/dev/nvhost-ctrl-gpu", 0x4701), NvGpuIoctlZcullGetCtxSize }, { ("/dev/nvhost-ctrl-gpu", 0x4701), NvGpuIoctlZcullGetCtxSize },
{ ("/dev/nvhost-ctrl-gpu", 0x4702), NvGpuIoctlZcullGetInfo }, { ("/dev/nvhost-ctrl-gpu", 0x4702), NvGpuIoctlZcullGetInfo },
{ ("/dev/nvhost-ctrl-gpu", 0x4703), NvGpuIoctlZbcSetTable }, { ("/dev/nvhost-ctrl-gpu", 0x4703), NvGpuIoctlZbcSetTable },
@ -384,6 +386,33 @@ namespace Ryujinx.Core.OsHle.Services.Nv
return 0; return 0;
} }
private long NvHostIoctlCtrlEventWaitAsync(ServiceCtx Context)
{
long Position = Context.Request.GetSendBuffPtr();
MemReader Reader = new MemReader(Context.Memory, Position);
int SyncPtId = Reader.ReadInt32();
int Threshold = Reader.ReadInt32();
int Timeout = Reader.ReadInt32();
int Value = Reader.ReadInt32();
Context.Memory.WriteInt32(Position + 0xc, 0xcafe);
return 0;
}
private long NvHostIoctlCtrlEventRegister(ServiceCtx Context)
{
long Position = Context.Request.GetSendBuffPtr();
MemReader Reader = new MemReader(Context.Memory, Position);
int UserEventId = Reader.ReadInt32();
return 0;
}
private long NvGpuIoctlZcullGetCtxSize(ServiceCtx Context) private long NvGpuIoctlZcullGetCtxSize(ServiceCtx Context)
{ {
long Position = Context.Request.GetSendBuffPtr(); long Position = Context.Request.GetSendBuffPtr();

View file

@ -2,6 +2,7 @@ namespace Ryujinx.Graphics.Gal
{ {
public struct GalVertexAttrib public struct GalVertexAttrib
{ {
public int Index { get; private set; }
public bool IsConst { get; private set; } public bool IsConst { get; private set; }
public int Offset { get; private set; } public int Offset { get; private set; }
@ -11,12 +12,14 @@ namespace Ryujinx.Graphics.Gal
public bool IsBgra { get; private set; } public bool IsBgra { get; private set; }
public GalVertexAttrib( public GalVertexAttrib(
int Index,
bool IsConst, bool IsConst,
int Offset, int Offset,
GalVertexAttribSize Size, GalVertexAttribSize Size,
GalVertexAttribType Type, GalVertexAttribType Type,
bool IsBgra) bool IsBgra)
{ {
this.Index = Index;
this.IsConst = IsConst; this.IsConst = IsConst;
this.Offset = Offset; this.Offset = Offset;
this.Size = Size; this.Size = Size;

View file

@ -44,12 +44,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ GalVertexAttribSize._11_11_10, VertexAttribPointerType.Int } //? { GalVertexAttribSize._11_11_10, VertexAttribPointerType.Int } //?
}; };
private struct VbInfo
{
public int VaoHandle;
public int VboHandle;
}
private struct IbInfo private struct IbInfo
{ {
public int IboHandle; public int IboHandle;
@ -58,13 +52,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public DrawElementsType Type; public DrawElementsType Type;
} }
private VbInfo[] VertexBuffers; private int VaoHandle;
private int[] VertexBuffers;
private IbInfo IndexBuffer; private IbInfo IndexBuffer;
public OGLRasterizer() public OGLRasterizer()
{ {
VertexBuffers = new VbInfo[32]; VertexBuffers = new int[32];
IndexBuffer = new IbInfo(); IndexBuffer = new IbInfo();
} }
@ -100,28 +96,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ {
EnsureVbInitialized(VbIndex); EnsureVbInitialized(VbIndex);
VbInfo Vb = VertexBuffers[VbIndex];
IntPtr Length = new IntPtr(Buffer.Length); IntPtr Length = new IntPtr(Buffer.Length);
GL.BindBuffer(BufferTarget.ArrayBuffer, Vb.VboHandle); GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBuffers[VbIndex]);
GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw); GL.BufferData(BufferTarget.ArrayBuffer, Length, Buffer, BufferUsageHint.StreamDraw);
GL.BindBuffer(BufferTarget.ArrayBuffer, 0); GL.BindBuffer(BufferTarget.ArrayBuffer, 0);
GL.BindVertexArray(Vb.VaoHandle); GL.BindVertexArray(VaoHandle);
for (int Attr = 0; Attr < 16; Attr++) foreach (GalVertexAttrib Attrib in Attribs)
{ {
GL.DisableVertexAttribArray(Attr); GL.EnableVertexAttribArray(Attrib.Index);
}
for (int Index = 0; Index < Attribs.Length; Index++) GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBuffers[VbIndex]);
{
GalVertexAttrib Attrib = Attribs[Index];
GL.EnableVertexAttribArray(Index);
GL.BindBuffer(BufferTarget.ArrayBuffer, Vb.VboHandle);
bool Unsigned = bool Unsigned =
Attrib.Type == GalVertexAttribType.Unorm || Attrib.Type == GalVertexAttribType.Unorm ||
@ -146,7 +133,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
int Size = AttribElements[Attrib.Size]; int Size = AttribElements[Attrib.Size];
int Offset = Attrib.Offset; int Offset = Attrib.Offset;
GL.VertexAttribPointer(Index, Size, Type, Normalize, Stride, Offset); GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Stride, Offset);
} }
GL.BindVertexArray(0); GL.BindVertexArray(0);
@ -174,20 +161,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL
return; return;
} }
VbInfo Vb = VertexBuffers[VbIndex]; GL.BindVertexArray(VaoHandle);
GL.BindVertexArray(Vb.VaoHandle);
GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount); GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount);
} }
public void DrawElements(int VbIndex, int First, GalPrimitiveType PrimType) public void DrawElements(int VbIndex, int First, GalPrimitiveType PrimType)
{ {
VbInfo Vb = VertexBuffers[VbIndex];
PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType); PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType);
GL.BindVertexArray(Vb.VaoHandle); GL.BindVertexArray(VaoHandle);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, IndexBuffer.IboHandle); GL.BindBuffer(BufferTarget.ElementArrayBuffer, IndexBuffer.IboHandle);
@ -196,19 +179,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private void EnsureVbInitialized(int VbIndex) private void EnsureVbInitialized(int VbIndex)
{ {
VbInfo Vb = VertexBuffers[VbIndex]; if (VaoHandle == 0)
if (Vb.VaoHandle == 0)
{ {
Vb.VaoHandle = GL.GenVertexArray(); VaoHandle = GL.GenVertexArray();
} }
if (Vb.VboHandle == 0) if (VertexBuffers[VbIndex] == 0)
{ {
Vb.VboHandle = GL.GenBuffer(); VertexBuffers[VbIndex] = GL.GenBuffer();
} }
VertexBuffers[VbIndex] = Vb;
} }
private void EnsureIbInitialized() private void EnsureIbInitialized()

View file

@ -261,7 +261,9 @@ namespace Ryujinx.Graphics.Gal.Shader
PrintBlockScope(SubScopeName, IdentationLevel + 1, Cond.Child); PrintBlockScope(SubScopeName, IdentationLevel + 1, Cond.Child);
} }
else if (Node is ShaderIrAsg Asg && IsValidOutOper(Asg.Dst)) else if (Node is ShaderIrAsg Asg)
{
if (IsValidOutOper(Asg.Dst))
{ {
string Expr = GetSrcExpr(Asg.Src, true); string Expr = GetSrcExpr(Asg.Src, true);
@ -269,6 +271,7 @@ namespace Ryujinx.Graphics.Gal.Shader
SB.AppendLine(Identation + GetDstOperName(Asg.Dst) + " = " + Expr + ";"); SB.AppendLine(Identation + GetDstOperName(Asg.Dst) + " = " + Expr + ";");
} }
}
else if (Node is ShaderIrOp Op) else if (Node is ShaderIrOp Op)
{ {
if (Op.Inst == ShaderIrInst.Exit) if (Op.Inst == ShaderIrInst.Exit)

View file

@ -351,6 +351,7 @@ namespace Ryujinx.Graphics.Gpu
} }
Attribs[ArrayIndex].Add(new GalVertexAttrib( Attribs[ArrayIndex].Add(new GalVertexAttrib(
Attr,
((Packed >> 6) & 0x1) != 0, ((Packed >> 6) & 0x1) != 0,
(Packed >> 7) & 0x3fff, (Packed >> 7) & 0x3fff,
(GalVertexAttribSize)((Packed >> 21) & 0x3f), (GalVertexAttribSize)((Packed >> 21) & 0x3f),
@ -367,18 +368,34 @@ namespace Ryujinx.Graphics.Gpu
bool Enable = (Control & 0x1000) != 0; bool Enable = (Control & 0x1000) != 0;
long VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4);
if (!Enable) if (!Enable)
{ {
continue; continue;
} }
long VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4);
long VertexEndPos = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNEndAddr + Index * 4);
long Size = (VertexEndPos - VertexPosition) + 1;
int Stride = Control & 0xfff; int Stride = Control & 0xfff;
long Size = 0;
if (IndexCount != 0)
{
Size = GetVertexCountFromIndexBuffer(
Memory,
IndexPosition,
IndexCount,
IndexSize);
}
else
{
Size = VertexCount;
}
//TODO: Support cases where the Stride is 0.
//In this case, we need to use the size of the attribute.
Size *= Stride;
VertexPosition = Gpu.GetCpuAddr(VertexPosition); VertexPosition = Gpu.GetCpuAddr(VertexPosition);
byte[] Data = AMemoryHelper.ReadBytes(Memory, VertexPosition, Size); byte[] Data = AMemoryHelper.ReadBytes(Memory, VertexPosition, Size);
@ -402,6 +419,62 @@ namespace Ryujinx.Graphics.Gpu
} }
} }
private int GetVertexCountFromIndexBuffer(
AMemory Memory,
long IndexPosition,
int IndexCount,
int IndexSize)
{
int MaxIndex = -1;
if (IndexSize == 2)
{
while (IndexCount -- > 0)
{
ushort Value = Memory.ReadUInt16(IndexPosition);
IndexPosition += 2;
if (MaxIndex < Value)
{
MaxIndex = Value;
}
}
}
else if (IndexSize == 1)
{
while (IndexCount -- > 0)
{
byte Value = Memory.ReadByte(IndexPosition++);
if (MaxIndex < Value)
{
MaxIndex = Value;
}
}
}
else if (IndexSize == 4)
{
while (IndexCount -- > 0)
{
uint Value = Memory.ReadUInt32(IndexPosition);
IndexPosition += 2;
if (MaxIndex < Value)
{
MaxIndex = (int)Value;
}
}
}
else
{
throw new ArgumentOutOfRangeException(nameof(IndexSize));
}
return MaxIndex + 1;
}
private void QueryControl(AMemory Memory, NsGpuPBEntry PBEntry) private void QueryControl(AMemory Memory, NsGpuPBEntry PBEntry)
{ {
if (TryGetCpuAddr(NvGpuEngine3dReg.QueryAddress, out long Position)) if (TryGetCpuAddr(NvGpuEngine3dReg.QueryAddress, out long Position))