Implement GPU syncpoints (#980)
* Implement GPU syncpoints This adds support for GPU syncpoints on the GPU backend & nvservices. Everything that was implemented here is based on my researches, hardware testing of the GM20B and reversing of nvservices (8.1.0). Thanks to @fincs for the informations about some behaviours of the pusher and for the initial informations about syncpoints. * syncpoint: address gdkchan's comments * Add some missing logic to handle SubmitGpfifo correctly * Handle the NV event API correctly * evnt => hostEvent * Finish addressing gdkchan's comments * nvservices: write the output buffer even when an error is returned * dma pusher: Implemnet prefetch barrier lso fix when the commands should be prefetch. * Partially fix prefetch barrier * Add a missing syncpoint check in QueryEvent of NvHostSyncPt * Address Ac_K's comments and fix GetSyncpoint for ChannelResourcePolicy == Channel * fix SyncptWait & SyncptWaitEx cmds logic * Address ripinperi's comments * Address gdkchan's comments * Move user event management to the control channel * Fix mm implementation, nvdec works again * Address ripinperi's comments * Address gdkchan's comments * Implement nvhost-ctrl close accurately + make nvservices dispose channels when stopping the emulator * Fix typo in MultiMediaOperationType
This commit is contained in:
parent
4960ab85f8
commit
644de99e86
37 changed files with 1576 additions and 386 deletions
|
@ -1,3 +1,4 @@
|
|||
using Ryujinx.Common;
|
||||
using Ryujinx.Common.Logging;
|
||||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Gpu;
|
||||
|
@ -5,7 +6,9 @@ using Ryujinx.HLE.HOS.Kernel.Threading;
|
|||
using Ryujinx.HLE.HOS.Services.Nv.NvDrvServices.NvMap;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
|
@ -117,15 +120,37 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
private ResultCode GbpDequeueBuffer(ServiceCtx context, BinaryReader parcelReader)
|
||||
{
|
||||
// TODO: Errors.
|
||||
int format = parcelReader.ReadInt32();
|
||||
int width = parcelReader.ReadInt32();
|
||||
int height = parcelReader.ReadInt32();
|
||||
int getTimestamps = parcelReader.ReadInt32();
|
||||
int usage = parcelReader.ReadInt32();
|
||||
int async = parcelReader.ReadInt32();
|
||||
int width = parcelReader.ReadInt32();
|
||||
int height = parcelReader.ReadInt32();
|
||||
int format = parcelReader.ReadInt32();
|
||||
int usage = parcelReader.ReadInt32();
|
||||
|
||||
int slot = GetFreeSlotBlocking(width, height);
|
||||
|
||||
return MakeReplyParcel(context, slot, 1, 0x24, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0);
|
||||
MultiFence multiFence = MultiFence.NoFence;
|
||||
|
||||
using (MemoryStream ms = new MemoryStream())
|
||||
{
|
||||
BinaryWriter writer = new BinaryWriter(ms);
|
||||
|
||||
// Allocated slot
|
||||
writer.Write(slot);
|
||||
|
||||
// Has multi fence
|
||||
writer.Write(1);
|
||||
|
||||
// Write the multi fnece
|
||||
WriteFlattenedObject(writer, multiFence);
|
||||
|
||||
// Padding
|
||||
writer.Write(0);
|
||||
|
||||
// Status
|
||||
writer.Write(0);
|
||||
|
||||
return MakeReplyParcel(context, ms.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
private ResultCode GbpQueueBuffer(ServiceCtx context, BinaryReader parcelReader)
|
||||
|
@ -142,9 +167,9 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
parcelReader.BaseStream.Position = Position;
|
||||
|
||||
_bufferQueue[slot].Transform = queueBufferObject.Transform;
|
||||
_bufferQueue[slot].Fence = queueBufferObject.Fence;
|
||||
_bufferQueue[slot].Crop = queueBufferObject.Crop;
|
||||
|
||||
_bufferQueue[slot].State = BufferState.Queued;
|
||||
_bufferQueue[slot].State = BufferState.Queued;
|
||||
|
||||
SendFrameBuffer(context, slot);
|
||||
|
||||
|
@ -219,14 +244,19 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
return reader.ReadBytes((int)flattenedObjectSize);
|
||||
}
|
||||
|
||||
private unsafe T ReadFlattenedObject<T>(BinaryReader reader) where T: struct
|
||||
private T ReadFlattenedObject<T>(BinaryReader reader) where T: struct
|
||||
{
|
||||
byte[] data = ReadFlattenedObject(reader);
|
||||
long flattenedObjectSize = reader.ReadInt64();
|
||||
|
||||
fixed (byte* ptr = data)
|
||||
{
|
||||
return Marshal.PtrToStructure<T>((IntPtr)ptr);
|
||||
}
|
||||
Debug.Assert(flattenedObjectSize == Unsafe.SizeOf<T>());
|
||||
|
||||
return reader.ReadStruct<T>();
|
||||
}
|
||||
|
||||
private unsafe void WriteFlattenedObject<T>(BinaryWriter writer, T value) where T : struct
|
||||
{
|
||||
writer.Write(Unsafe.SizeOf<T>());
|
||||
writer.WriteStruct(value);
|
||||
}
|
||||
|
||||
private ResultCode MakeReplyParcel(ServiceCtx context, params int[] ints)
|
||||
|
@ -328,10 +358,21 @@ namespace Ryujinx.HLE.HOS.Services.SurfaceFlinger
|
|||
format,
|
||||
bytesPerPixel,
|
||||
crop,
|
||||
AcquireBuffer,
|
||||
ReleaseBuffer,
|
||||
slot);
|
||||
}
|
||||
|
||||
private void AcquireBuffer(GpuContext context, object slot)
|
||||
{
|
||||
AcquireBuffer(context, (int)slot);
|
||||
}
|
||||
|
||||
private void AcquireBuffer(GpuContext context, int slot)
|
||||
{
|
||||
_bufferQueue[slot].Fence.WaitForever(context);
|
||||
}
|
||||
|
||||
private void ReleaseBuffer(object slot)
|
||||
{
|
||||
ReleaseBuffer((int)slot);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue