forked from Mirror/Ryujinx
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:
parent
17f4ccf2d5
commit
f73a182b20
5 changed files with 133 additions and 46 deletions
|
@ -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();
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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))
|
||||||
|
|
Reference in a new issue