Ryujinx/Ryujinx.Graphics.Gpu/Engine/MethodUniformBufferUpdate.cs
gdkchan a10b2c5ff2
Initial support for GPU channels (#2372)
* Ground work for separate GPU channels

* Rename TextureManager to TextureCache

* Decouple texture bindings management from the texture cache

* Rename BufferManager to BufferCache

* Decouple buffer bindings management from the buffer cache

* More comments and proper disposal

* PR feedback

* Force host state update on channel switch

* Typo

* PR feedback

* Missing using
2021-06-24 01:51:41 +02:00

85 lines
2.9 KiB
C#

using Ryujinx.Graphics.Gpu.Memory;
using Ryujinx.Graphics.Gpu.State;
using System;
using System.Runtime.InteropServices;
namespace Ryujinx.Graphics.Gpu.Engine
{
partial class Methods
{
// State associated with direct uniform buffer updates.
// This state is used to attempt to batch together consecutive updates.
private ulong _ubBeginCpuAddress = 0;
private ulong _ubFollowUpAddress = 0;
private ulong _ubByteCount = 0;
/// <summary>
/// Flushes any queued ubo updates.
/// </summary>
private void FlushUboDirty()
{
if (_ubFollowUpAddress != 0)
{
BufferCache.ForceDirty(_ubFollowUpAddress - _ubByteCount, _ubByteCount);
_ubFollowUpAddress = 0;
}
}
/// <summary>
/// Updates the uniform buffer data with inline data.
/// </summary>
/// <param name="state">Current GPU state</param>
/// <param name="argument">New uniform buffer data word</param>
private void UniformBufferUpdate(GpuState state, int argument)
{
var uniformBuffer = state.Get<UniformBufferState>(MethodOffset.UniformBufferState);
ulong address = uniformBuffer.Address.Pack() + (uint)uniformBuffer.Offset;
if (_ubFollowUpAddress != address)
{
FlushUboDirty();
_ubByteCount = 0;
_ubBeginCpuAddress = _context.MemoryManager.Translate(address);
}
_context.PhysicalMemory.WriteUntracked(_ubBeginCpuAddress + _ubByteCount, MemoryMarshal.Cast<int, byte>(MemoryMarshal.CreateSpan(ref argument, 1)));
_ubFollowUpAddress = address + 4;
_ubByteCount += 4;
state.SetUniformBufferOffset(uniformBuffer.Offset + 4);
}
/// <summary>
/// Updates the uniform buffer data with inline data.
/// </summary>
/// <param name="state">Current GPU state</param>
/// <param name="data">Data to be written to the uniform buffer</param>
public void UniformBufferUpdate(GpuState state, ReadOnlySpan<int> data)
{
var uniformBuffer = state.Get<UniformBufferState>(MethodOffset.UniformBufferState);
ulong address = uniformBuffer.Address.Pack() + (uint)uniformBuffer.Offset;
ulong size = (ulong)data.Length * 4;
if (_ubFollowUpAddress != address)
{
FlushUboDirty();
_ubByteCount = 0;
_ubBeginCpuAddress = _context.MemoryManager.Translate(address);
}
_context.PhysicalMemory.WriteUntracked(_ubBeginCpuAddress + _ubByteCount, MemoryMarshal.Cast<int, byte>(data));
_ubFollowUpAddress = address + size;
_ubByteCount += size;
state.SetUniformBufferOffset(uniformBuffer.Offset + data.Length * 4);
}
}
}