diff options
| author | ReinUsesLisp <reinuseslisp@airmail.cc> | 2018-08-25 01:16:58 -0300 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-08-25 01:16:58 -0300 |
| commit | a42ab2e40cae5db96cc58634f1e70c4e31bb095d (patch) | |
| tree | f727a1f9685fa02a8e4f947e188f4b329135ad39 /Ryujinx.HLE | |
| parent | da7e7027518c40702536d4c51905ae7cb496cdb5 (diff) | |
Implement vertex instancing (#381)
Diffstat (limited to 'Ryujinx.HLE')
| -rw-r--r-- | Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs | 48 | ||||
| -rw-r--r-- | Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs | 2 |
2 files changed, 45 insertions, 5 deletions
diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs index be47b66c..2010e43b 100644 --- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs +++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3d.cs @@ -27,6 +27,8 @@ namespace Ryujinx.HLE.Gpu.Engines private List<long>[] UploadedKeys; + private int CurrentInstance = 0; + public NvGpuEngine3d(NvGpu Gpu) { this.Gpu = Gpu; @@ -654,10 +656,25 @@ namespace Ryujinx.HLE.Gpu.Engines long VertexPosition = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNAddress + Index * 4); long VertexEndPos = MakeInt64From2xInt32(NvGpuEngine3dReg.VertexArrayNEndAddr + Index * 2); - long VboKey = Vmm.GetPhysicalAddress(VertexPosition); + int VertexDivisor = ReadRegister(NvGpuEngine3dReg.VertexArrayNDivisor + Index * 4); + + bool Instanced = (ReadRegister(NvGpuEngine3dReg.VertexArrayNInstance + Index) & 1) != 0; int Stride = Control & 0xfff; + if (Instanced && VertexDivisor != 0) + { + VertexPosition += Stride * (CurrentInstance / VertexDivisor); + } + + if (VertexPosition > VertexEndPos) + { + //Instance is invalid, ignore the draw call + continue; + } + + long VboKey = Vmm.GetPhysicalAddress(VertexPosition); + long VbSize = (VertexEndPos - VertexPosition) + 1; bool VboCached = Gpu.Renderer.Rasterizer.IsVboCached(VboKey, VbSize); @@ -669,10 +686,12 @@ namespace Ryujinx.HLE.Gpu.Engines Gpu.Renderer.Rasterizer.CreateVbo(VboKey, (int)VbSize, DataAddress); } - State.VertexBindings[Index].Enabled = true; - State.VertexBindings[Index].Stride = Stride; - State.VertexBindings[Index].VboKey = VboKey; - State.VertexBindings[Index].Attribs = Attribs[Index].ToArray(); + State.VertexBindings[Index].Enabled = true; + State.VertexBindings[Index].Stride = Stride; + State.VertexBindings[Index].VboKey = VboKey; + State.VertexBindings[Index].Instanced = Instanced; + State.VertexBindings[Index].Divisor = VertexDivisor; + State.VertexBindings[Index].Attribs = Attribs[Index].ToArray(); } } @@ -683,6 +702,25 @@ namespace Ryujinx.HLE.Gpu.Engines GalPrimitiveType PrimType = (GalPrimitiveType)(PrimCtrl & 0xffff); + bool InstanceNext = ((PrimCtrl >> 26) & 1) != 0; + bool InstanceCont = ((PrimCtrl >> 27) & 1) != 0; + + if (InstanceNext && InstanceCont) + { + throw new InvalidOperationException("GPU tried to increase and reset instance count at the same time"); + } + + if (InstanceNext) + { + CurrentInstance++; + } + else if (!InstanceCont) + { + CurrentInstance = 0; + } + + State.Instance = CurrentInstance; + Gpu.Renderer.Pipeline.Bind(State); if (IndexCount != 0) diff --git a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs index 7eff13b5..ace324e9 100644 --- a/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs +++ b/Ryujinx.HLE/Gpu/Engines/NvGpuEngine3dReg.cs @@ -53,6 +53,7 @@ namespace Ryujinx.HLE.Gpu.Engines StencilFrontFuncMask = 0x4e6, StencilFrontMask = 0x4e7, VertexArrayElemBase = 0x50d, + VertexArrayInstBase = 0x50e, ZetaEnable = 0x54e, TexHeaderPoolOffset = 0x55d, TexSamplerPoolOffset = 0x557, @@ -70,6 +71,7 @@ namespace Ryujinx.HLE.Gpu.Engines IndexArrayFormat = 0x5f6, IndexBatchFirst = 0x5f7, IndexBatchCount = 0x5f8, + VertexArrayNInstance = 0x620, CullFaceEnable = 0x646, FrontFace = 0x647, CullFace = 0x648, |
