using Ryujinx.Common.Logging; using Ryujinx.Graphics.Gpu.State; namespace Ryujinx.Graphics.Gpu.Engine { partial class Methods { /// /// Checks if draws and clears should be performed, according /// to currently set conditional rendering conditions. /// /// GPU state /// True if rendering is enabled, false otherwise private bool GetRenderEnable(GpuState state) { ConditionState condState = state.Get(MethodOffset.ConditionState); switch (condState.Condition) { case Condition.Always: return true; case Condition.Never: return false; case Condition.ResultNonZero: return CounterNonZero(condState.Address.Pack()); case Condition.Equal: return CounterCompare(condState.Address.Pack(), true); case Condition.NotEqual: return CounterCompare(condState.Address.Pack(), false); } Logger.PrintWarning(LogClass.Gpu, $"Invalid conditional render condition \"{condState.Condition}\"."); return true; } /// /// Checks if the counter value at a given GPU memory address is non-zero. /// /// GPU virtual address of the counter value /// True if the value is not zero, false otherwise private bool CounterNonZero(ulong gpuVa) { if (!FindAndFlush(gpuVa)) { return false; } return _context.MemoryAccessor.ReadUInt64(gpuVa) != 0; } /// /// Checks if the counter at a given GPU memory address passes a specified equality comparison. /// /// GPU virtual address /// True to check if the values are equal, false to check if they are not equal /// True if the condition is met, false otherwise private bool CounterCompare(ulong gpuVa, bool isEqual) { if (!FindAndFlush(gpuVa) && !FindAndFlush(gpuVa + 16)) { return false; } ulong x = _context.MemoryAccessor.ReadUInt64(gpuVa); ulong y = _context.MemoryAccessor.ReadUInt64(gpuVa + 16); return isEqual ? x == y : x != y; } /// /// Tries to find a counter that is supposed to be written at the specified address, /// flushing if necessary. /// /// GPU virtual address where the counter is supposed to be written /// True if a counter value is found at the specified address, false otherwise private bool FindAndFlush(ulong gpuVa) { return _counterCache.Contains(gpuVa); } } }