aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2018-04-29 17:58:38 -0300
committergdkchan <gab.dark.100@gmail.com>2018-04-29 17:58:38 -0300
commitf73a182b20970f993abc1f1329dfab1e5d3b3354 (patch)
treead46e02d29560b013713291f236b953a601e2d5f
parent17f4ccf2d552b9646097282818d82525a3d902cf (diff)
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
-rw-r--r--Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs29
-rw-r--r--Ryujinx.Graphics/Gal/GalVertexAttrib.cs3
-rw-r--r--Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs53
-rw-r--r--Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs11
-rw-r--r--Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs81
5 files changed, 132 insertions, 45 deletions
diff --git a/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs b/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs
index f41a98d0..2652724d 100644
--- a/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs
+++ b/Ryujinx.Core/OsHle/Services/Nv/INvDrvServices.cs
@@ -51,6 +51,8 @@ namespace Ryujinx.Core.OsHle.Services.Nv
{ ("/dev/nvhost-as-gpu", 0x4114), NvGpuAsIoctlRemap },
{ ("/dev/nvhost-ctrl", 0x001b), NvHostIoctlCtrlGetConfig },
{ ("/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", 0x4702), NvGpuIoctlZcullGetInfo },
{ ("/dev/nvhost-ctrl-gpu", 0x4703), NvGpuIoctlZbcSetTable },
@@ -384,6 +386,33 @@ namespace Ryujinx.Core.OsHle.Services.Nv
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)
{
long Position = Context.Request.GetSendBuffPtr();
diff --git a/Ryujinx.Graphics/Gal/GalVertexAttrib.cs b/Ryujinx.Graphics/Gal/GalVertexAttrib.cs
index 563e624d..dd040060 100644
--- a/Ryujinx.Graphics/Gal/GalVertexAttrib.cs
+++ b/Ryujinx.Graphics/Gal/GalVertexAttrib.cs
@@ -2,6 +2,7 @@ namespace Ryujinx.Graphics.Gal
{
public struct GalVertexAttrib
{
+ public int Index { get; private set; }
public bool IsConst { get; private set; }
public int Offset { get; private set; }
@@ -11,12 +12,14 @@ namespace Ryujinx.Graphics.Gal
public bool IsBgra { get; private set; }
public GalVertexAttrib(
+ int Index,
bool IsConst,
int Offset,
GalVertexAttribSize Size,
GalVertexAttribType Type,
bool IsBgra)
{
+ this.Index = Index;
this.IsConst = IsConst;
this.Offset = Offset;
this.Size = Size;
diff --git a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
index b1504563..5b115446 100644
--- a/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
+++ b/Ryujinx.Graphics/Gal/OpenGL/OGLRasterizer.cs
@@ -44,12 +44,6 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{ GalVertexAttribSize._11_11_10, VertexAttribPointerType.Int } //?
};
- private struct VbInfo
- {
- public int VaoHandle;
- public int VboHandle;
- }
-
private struct IbInfo
{
public int IboHandle;
@@ -58,13 +52,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL
public DrawElementsType Type;
}
- private VbInfo[] VertexBuffers;
+ private int VaoHandle;
+
+ private int[] VertexBuffers;
private IbInfo IndexBuffer;
public OGLRasterizer()
{
- VertexBuffers = new VbInfo[32];
+ VertexBuffers = new int[32];
IndexBuffer = new IbInfo();
}
@@ -100,28 +96,19 @@ namespace Ryujinx.Graphics.Gal.OpenGL
{
EnsureVbInitialized(VbIndex);
- VbInfo Vb = VertexBuffers[VbIndex];
-
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.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++)
- {
- GalVertexAttrib Attrib = Attribs[Index];
-
- GL.EnableVertexAttribArray(Index);
-
- GL.BindBuffer(BufferTarget.ArrayBuffer, Vb.VboHandle);
+ GL.BindBuffer(BufferTarget.ArrayBuffer, VertexBuffers[VbIndex]);
bool Unsigned =
Attrib.Type == GalVertexAttribType.Unorm ||
@@ -146,7 +133,7 @@ namespace Ryujinx.Graphics.Gal.OpenGL
int Size = AttribElements[Attrib.Size];
int Offset = Attrib.Offset;
- GL.VertexAttribPointer(Index, Size, Type, Normalize, Stride, Offset);
+ GL.VertexAttribPointer(Attrib.Index, Size, Type, Normalize, Stride, Offset);
}
GL.BindVertexArray(0);
@@ -174,20 +161,16 @@ namespace Ryujinx.Graphics.Gal.OpenGL
return;
}
- VbInfo Vb = VertexBuffers[VbIndex];
-
- GL.BindVertexArray(Vb.VaoHandle);
+ GL.BindVertexArray(VaoHandle);
GL.DrawArrays(OGLEnumConverter.GetPrimitiveType(PrimType), First, PrimCount);
}
public void DrawElements(int VbIndex, int First, GalPrimitiveType PrimType)
{
- VbInfo Vb = VertexBuffers[VbIndex];
-
PrimitiveType Mode = OGLEnumConverter.GetPrimitiveType(PrimType);
- GL.BindVertexArray(Vb.VaoHandle);
+ GL.BindVertexArray(VaoHandle);
GL.BindBuffer(BufferTarget.ElementArrayBuffer, IndexBuffer.IboHandle);
@@ -196,19 +179,15 @@ namespace Ryujinx.Graphics.Gal.OpenGL
private void EnsureVbInitialized(int VbIndex)
{
- VbInfo Vb = VertexBuffers[VbIndex];
-
- if (Vb.VaoHandle == 0)
+ if (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()
diff --git a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
index c22f5926..1e0824d2 100644
--- a/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
+++ b/Ryujinx.Graphics/Gal/Shader/GlslDecompiler.cs
@@ -261,13 +261,16 @@ namespace Ryujinx.Graphics.Gal.Shader
PrintBlockScope(SubScopeName, IdentationLevel + 1, Cond.Child);
}
- else if (Node is ShaderIrAsg Asg && IsValidOutOper(Asg.Dst))
+ else if (Node is ShaderIrAsg Asg)
{
- string Expr = GetSrcExpr(Asg.Src, true);
+ if (IsValidOutOper(Asg.Dst))
+ {
+ string Expr = GetSrcExpr(Asg.Src, true);
- Expr = GetExprWithCast(Asg.Dst, Asg.Src, Expr);
+ Expr = GetExprWithCast(Asg.Dst, Asg.Src, Expr);
- SB.AppendLine(Identation + GetDstOperName(Asg.Dst) + " = " + Expr + ";");
+ SB.AppendLine(Identation + GetDstOperName(Asg.Dst) + " = " + Expr + ";");
+ }
}
else if (Node is ShaderIrOp Op)
{
diff --git a/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs b/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs
index bf04db36..a6696650 100644
--- a/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs
+++ b/Ryujinx.Graphics/Gpu/NvGpuEngine3d.cs
@@ -351,6 +351,7 @@ namespace Ryujinx.Graphics.Gpu
}
Attribs[ArrayIndex].Add(new GalVertexAttrib(
+ Attr,
((Packed >> 6) & 0x1) != 0,
(Packed >> 7) & 0x3fff,
(GalVertexAttribSize)((Packed >> 21) & 0x3f),
@@ -367,17 +368,33 @@ namespace Ryujinx.Graphics.Gpu
bool Enable = (Control & 0x1000) != 0;
+ long VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4);
+
if (!Enable)
{
continue;
}
- long VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4);
- long VertexEndPos = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNEndAddr + Index * 4);
+ int Stride = Control & 0xfff;
- long Size = (VertexEndPos - VertexPosition) + 1;
+ long Size = 0;
- int Stride = Control & 0xfff;
+ 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);
@@ -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)
{
if (TryGetCpuAddr(NvGpuEngine3dReg.QueryAddress, out long Position))