Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c52158b733 | ||
|
|
fd6d3ec88f | ||
|
|
0a0a95fd81 |
@@ -115,7 +115,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
|||||||
}
|
}
|
||||||
else /* if (type == LaunchDmaSemaphoreType.ReleaseFourWordSemaphore) */
|
else /* if (type == LaunchDmaSemaphoreType.ReleaseFourWordSemaphore) */
|
||||||
{
|
{
|
||||||
Logger.Warning?.Print(LogClass.Gpu, "DMA semaphore type ReleaseFourWordSemaphore was used, but is not currently implemented.");
|
_channel.MemoryManager.Write(address + 8, _context.GetTimestamp());
|
||||||
|
_channel.MemoryManager.Write(address, (ulong)_state.State.SetSemaphorePayload);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -75,6 +75,12 @@ namespace Ryujinx.Graphics.Gpu.Engine.GPFifo
|
|||||||
|
|
||||||
SemaphoredOperation operation = _state.State.SemaphoredOperation;
|
SemaphoredOperation operation = _state.State.SemaphoredOperation;
|
||||||
|
|
||||||
|
if (_state.State.SemaphoredReleaseSize == SemaphoredReleaseSize.SixteenBytes)
|
||||||
|
{
|
||||||
|
_parent.MemoryManager.Write(address + 4, 0);
|
||||||
|
_parent.MemoryManager.Write(address + 8, _context.GetTimestamp());
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: Acquire operations (Wait), interrupts for invalid combinations.
|
// TODO: Acquire operations (Wait), interrupts for invalid combinations.
|
||||||
if (operation == SemaphoredOperation.Release)
|
if (operation == SemaphoredOperation.Release)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using Ryujinx.Common;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.GAL;
|
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
{
|
{
|
||||||
@@ -9,9 +7,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
class SemaphoreUpdater
|
class SemaphoreUpdater
|
||||||
{
|
{
|
||||||
private const int NsToTicksFractionNumerator = 384;
|
|
||||||
private const int NsToTicksFractionDenominator = 625;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// GPU semaphore operation.
|
/// GPU semaphore operation.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -154,14 +149,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
{
|
{
|
||||||
ulong gpuVa = _state.State.SemaphoreAddress.Pack();
|
ulong gpuVa = _state.State.SemaphoreAddress.Pack();
|
||||||
|
|
||||||
ulong ticks = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds);
|
ulong ticks = _context.GetTimestamp();
|
||||||
|
|
||||||
if (GraphicsConfig.FastGpuTime)
|
|
||||||
{
|
|
||||||
// Divide by some amount to report time as if operations were performed faster than they really are.
|
|
||||||
// This can prevent some games from switching to a lower resolution because rendering is too slow.
|
|
||||||
ticks /= 256;
|
|
||||||
}
|
|
||||||
|
|
||||||
ICounterEvent counter = null;
|
ICounterEvent counter = null;
|
||||||
|
|
||||||
@@ -197,27 +185,5 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||||||
|
|
||||||
_channel.MemoryManager.CounterCache.AddOrUpdate(gpuVa, counter);
|
_channel.MemoryManager.CounterCache.AddOrUpdate(gpuVa, counter);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Converts a nanoseconds timestamp value to Maxwell time ticks.
|
|
||||||
/// </summary>
|
|
||||||
/// <remarks>
|
|
||||||
/// The frequency is 614400000 Hz.
|
|
||||||
/// </remarks>
|
|
||||||
/// <param name="nanoseconds">Timestamp in nanoseconds</param>
|
|
||||||
/// <returns>Maxwell ticks</returns>
|
|
||||||
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 / NsToTicksFractionDenominator;
|
|
||||||
|
|
||||||
ulong rounded = divided * NsToTicksFractionDenominator;
|
|
||||||
|
|
||||||
ulong errorBias = (nanoseconds - rounded) * NsToTicksFractionNumerator / NsToTicksFractionDenominator;
|
|
||||||
|
|
||||||
return divided * NsToTicksFractionNumerator + errorBias;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using Ryujinx.Common;
|
||||||
using Ryujinx.Graphics.GAL;
|
using Ryujinx.Graphics.GAL;
|
||||||
using Ryujinx.Graphics.Gpu.Engine.GPFifo;
|
using Ryujinx.Graphics.Gpu.Engine.GPFifo;
|
||||||
using Ryujinx.Graphics.Gpu.Memory;
|
using Ryujinx.Graphics.Gpu.Memory;
|
||||||
@@ -15,6 +16,9 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class GpuContext : IDisposable
|
public sealed class GpuContext : IDisposable
|
||||||
{
|
{
|
||||||
|
private const int NsToTicksFractionNumerator = 384;
|
||||||
|
private const int NsToTicksFractionDenominator = 625;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Event signaled when the host emulation context is ready to be used by the gpu context.
|
/// Event signaled when the host emulation context is ready to be used by the gpu context.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -180,6 +184,46 @@ namespace Ryujinx.Graphics.Gpu
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts a nanoseconds timestamp value to Maxwell time ticks.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// The frequency is 614400000 Hz.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="nanoseconds">Timestamp in nanoseconds</param>
|
||||||
|
/// <returns>Maxwell ticks</returns>
|
||||||
|
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 / NsToTicksFractionDenominator;
|
||||||
|
|
||||||
|
ulong rounded = divided * NsToTicksFractionDenominator;
|
||||||
|
|
||||||
|
ulong errorBias = (nanoseconds - rounded) * NsToTicksFractionNumerator / NsToTicksFractionDenominator;
|
||||||
|
|
||||||
|
return divided * NsToTicksFractionNumerator + errorBias;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the value of the GPU timer.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The current GPU timestamp</returns>
|
||||||
|
public ulong GetTimestamp()
|
||||||
|
{
|
||||||
|
ulong ticks = ConvertNanosecondsToTicks((ulong)PerformanceCounter.ElapsedNanoseconds);
|
||||||
|
|
||||||
|
if (GraphicsConfig.FastGpuTime)
|
||||||
|
{
|
||||||
|
// Divide by some amount to report time as if operations were performed faster than they really are.
|
||||||
|
// This can prevent some games from switching to a lower resolution because rendering is too slow.
|
||||||
|
ticks /= 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ticks;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Shader cache state update handler.
|
/// Shader cache state update handler.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
|
|
||||||
private readonly float[] _scales;
|
private readonly float[] _scales;
|
||||||
private bool _scaleChanged;
|
private bool _scaleChanged;
|
||||||
|
private int _lastFragmentTotal;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Constructs a new instance of the texture bindings manager.
|
/// Constructs a new instance of the texture bindings manager.
|
||||||
@@ -288,26 +289,30 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
private void CommitRenderScale()
|
private void CommitRenderScale()
|
||||||
{
|
{
|
||||||
|
// Stage 0 total: Compute or Vertex.
|
||||||
|
int total = _textureBindingsCount[0] + _imageBindingsCount[0];
|
||||||
|
|
||||||
|
int fragmentIndex = (int)ShaderStage.Fragment - 1;
|
||||||
|
int fragmentTotal = _isCompute ? 0 : (_textureBindingsCount[fragmentIndex] + _imageBindingsCount[fragmentIndex]);
|
||||||
|
|
||||||
|
if (total != 0 && fragmentTotal != _lastFragmentTotal)
|
||||||
|
{
|
||||||
|
// Must update scales in the support buffer if:
|
||||||
|
// - Vertex stage has bindings.
|
||||||
|
// - Fragment stage binding count has been updated since last render scale update.
|
||||||
|
|
||||||
|
_scaleChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
if (_scaleChanged)
|
if (_scaleChanged)
|
||||||
{
|
{
|
||||||
int fragmentTotal = 0;
|
|
||||||
int total;
|
|
||||||
|
|
||||||
if (!_isCompute)
|
if (!_isCompute)
|
||||||
{
|
{
|
||||||
int fragmentIndex = (int)ShaderStage.Fragment - 1;
|
total += fragmentTotal; // Add the fragment bindings to the total.
|
||||||
fragmentTotal = _textureBindingsCount[fragmentIndex] + _imageBindingsCount[fragmentIndex];
|
|
||||||
|
|
||||||
int vertexIndex = (int)ShaderStage.Vertex - 1;
|
|
||||||
int vertexTotal = _textureBindingsCount[vertexIndex] + _imageBindingsCount[vertexIndex];
|
|
||||||
|
|
||||||
total = fragmentTotal + vertexTotal;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
total = _textureBindingsCount[0] + _imageBindingsCount[0];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_lastFragmentTotal = fragmentTotal;
|
||||||
|
|
||||||
_context.Renderer.Pipeline.UpdateRenderScale(_scales, total, fragmentTotal);
|
_context.Renderer.Pipeline.UpdateRenderScale(_scales, total, fragmentTotal);
|
||||||
|
|
||||||
_scaleChanged = false;
|
_scaleChanged = false;
|
||||||
|
|||||||
@@ -396,7 +396,7 @@ namespace Ryujinx.Modules
|
|||||||
|
|
||||||
if (!OperatingSystem.IsWindows())
|
if (!OperatingSystem.IsWindows())
|
||||||
{
|
{
|
||||||
chmod(ryuBin, 0777);
|
chmod(ryuBin, 493);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user