diff options
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Engine/MethodReport.cs')
-rw-r--r-- | Ryujinx.Graphics.Gpu/Engine/MethodReport.cs | 100 |
1 files changed, 100 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs b/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs new file mode 100644 index 00000000..fd0a31a1 --- /dev/null +++ b/Ryujinx.Graphics.Gpu/Engine/MethodReport.cs @@ -0,0 +1,100 @@ +using Ryujinx.Common; +using Ryujinx.Graphics.GAL; +using Ryujinx.Graphics.Gpu.State; +using System; +using System.Runtime.InteropServices; + +namespace Ryujinx.Graphics.Gpu.Engine +{ + partial class Methods + { + private ulong _runningCounter; + + private void Report(int argument) + { + ReportMode mode = (ReportMode)(argument & 3); + + ReportCounterType type = (ReportCounterType)((argument >> 23) & 0x1f); + + switch (mode) + { + case ReportMode.Semaphore: ReportSemaphore(); break; + case ReportMode.Counter: ReportCounter(type); break; + } + } + + private void ReportSemaphore() + { + ReportState state = _context.State.GetReportState(); + + _context.MemoryAccessor.Write(state.Address.Pack(), state.Payload); + + _context.AdvanceSequence(); + } + + private struct CounterData + { + public ulong Counter; + public ulong Timestamp; + } + + private void ReportCounter(ReportCounterType type) + { + CounterData counterData = new CounterData(); + + ulong counter = 0; + + switch (type) + { + case ReportCounterType.Zero: + counter = 0; + break; + case ReportCounterType.SamplesPassed: + counter = _context.Renderer.GetCounter(CounterType.SamplesPassed); + break; + case ReportCounterType.PrimitivesGenerated: + counter = _context.Renderer.GetCounter(CounterType.PrimitivesGenerated); + break; + case ReportCounterType.TransformFeedbackPrimitivesWritten: + counter = _context.Renderer.GetCounter(CounterType.TransformFeedbackPrimitivesWritten); + break; + } + + ulong ticks; + + if (GraphicsConfig.FastGpuTime) + { + ticks = _runningCounter++; + } + else + { + ticks = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds); + } + + counterData.Counter = counter; + counterData.Timestamp = ticks; + + Span<CounterData> counterDataSpan = MemoryMarshal.CreateSpan(ref counterData, 1); + + Span<byte> data = MemoryMarshal.Cast<CounterData, byte>(counterDataSpan); + + ReportState state = _context.State.GetReportState(); + + _context.MemoryAccessor.Write(state.Address.Pack(), data); + } + + private static ulong ConvertNanosecondsToTicks(ulong nanoseconds) + { + // We need to divide first to avoid overflows. + // We fix up the result later by calculating the difference and adding + // that to the result. + ulong divided = nanoseconds / 625; + + ulong rounded = divided * 625; + + ulong errorBias = ((nanoseconds - rounded) * 384) / 625; + + return divided * 384 + errorBias; + } + } +}
\ No newline at end of file |