mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-01-13 06:09:11 +00:00
Allow resources to be backed by different PhysicalMemory (still unused)
This commit is contained in:
parent
638be5f296
commit
640ea94cd8
27 changed files with 276 additions and 133 deletions
|
@ -106,6 +106,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||||
|
|
||||||
shaderGpuVa += (uint)qmd.ProgramOffset;
|
shaderGpuVa += (uint)qmd.ProgramOffset;
|
||||||
|
|
||||||
|
var shaderCache = memoryManager.GetBackingMemory(shaderGpuVa).ShaderCache;
|
||||||
|
|
||||||
int localMemorySize = qmd.ShaderLocalMemoryLowSize + qmd.ShaderLocalMemoryHighSize;
|
int localMemorySize = qmd.ShaderLocalMemoryLowSize + qmd.ShaderLocalMemoryHighSize;
|
||||||
|
|
||||||
int sharedMemorySize = Math.Min(qmd.SharedMemorySize, _context.Capabilities.MaximumComputeSharedMemorySize);
|
int sharedMemorySize = Math.Min(qmd.SharedMemorySize, _context.Capabilities.MaximumComputeSharedMemorySize);
|
||||||
|
@ -139,7 +141,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||||
sharedMemorySize,
|
sharedMemorySize,
|
||||||
_channel.BufferManager.HasUnalignedStorageBuffers);
|
_channel.BufferManager.HasUnalignedStorageBuffers);
|
||||||
|
|
||||||
CachedShaderProgram cs = memoryManager.Physical.ShaderCache.GetComputeShader(_channel, poolState, computeState, shaderGpuVa);
|
CachedShaderProgram cs = shaderCache.GetComputeShader(_channel, poolState, computeState, shaderGpuVa);
|
||||||
|
|
||||||
_context.Renderer.Pipeline.SetProgram(cs.HostProgram);
|
_context.Renderer.Pipeline.SetProgram(cs.HostProgram);
|
||||||
|
|
||||||
|
@ -153,10 +155,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||||
{
|
{
|
||||||
BufferDescriptor sb = info.SBuffers[index];
|
BufferDescriptor sb = info.SBuffers[index];
|
||||||
|
|
||||||
ulong sbDescAddress = _channel.BufferManager.GetComputeUniformBufferAddress(sb.SbCbSlot);
|
(var physical, ulong sbDescAddress) = _channel.BufferManager.GetComputeUniformBufferAddress(sb.SbCbSlot);
|
||||||
sbDescAddress += (ulong)sb.SbCbOffset * 4;
|
sbDescAddress += (ulong)sb.SbCbOffset * 4;
|
||||||
|
|
||||||
SbDescriptor sbDescriptor = _channel.MemoryManager.Physical.Read<SbDescriptor>(sbDescAddress);
|
SbDescriptor sbDescriptor = physical.Read<SbDescriptor>(sbDescAddress);
|
||||||
|
|
||||||
uint size;
|
uint size;
|
||||||
if (sb.SbCbSlot == Constants.DriverReservedUniformBuffer)
|
if (sb.SbCbSlot == Constants.DriverReservedUniformBuffer)
|
||||||
|
@ -184,7 +186,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Compute
|
||||||
sharedMemorySize,
|
sharedMemorySize,
|
||||||
_channel.BufferManager.HasUnalignedStorageBuffers);
|
_channel.BufferManager.HasUnalignedStorageBuffers);
|
||||||
|
|
||||||
cs = memoryManager.Physical.ShaderCache.GetComputeShader(_channel, poolState, computeState, shaderGpuVa);
|
cs = shaderCache.GetComputeShader(_channel, poolState, computeState, shaderGpuVa);
|
||||||
|
|
||||||
_context.Renderer.Pipeline.SetProgram(cs.HostProgram);
|
_context.Renderer.Pipeline.SetProgram(cs.HostProgram);
|
||||||
}
|
}
|
||||||
|
|
|
@ -281,7 +281,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||||
|
|
||||||
if (completeSource && completeDest)
|
if (completeSource && completeDest)
|
||||||
{
|
{
|
||||||
var target = memoryManager.Physical.TextureCache.FindTexture(
|
var target = memoryManager.GetBackingMemory(dstGpuVa).TextureCache.FindTexture(
|
||||||
memoryManager,
|
memoryManager,
|
||||||
dstGpuVa,
|
dstGpuVa,
|
||||||
dstBpp,
|
dstBpp,
|
||||||
|
@ -412,6 +412,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
var bufferCache = memoryManager.GetBackingMemory(dstGpuVa).BufferCache;
|
||||||
|
|
||||||
if (remap &&
|
if (remap &&
|
||||||
_state.State.SetRemapComponentsDstX == SetRemapComponentsDst.ConstA &&
|
_state.State.SetRemapComponentsDstX == SetRemapComponentsDst.ConstA &&
|
||||||
_state.State.SetRemapComponentsDstY == SetRemapComponentsDst.ConstA &&
|
_state.State.SetRemapComponentsDstY == SetRemapComponentsDst.ConstA &&
|
||||||
|
@ -422,7 +424,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||||
_state.State.SetRemapComponentsComponentSize == SetRemapComponentsComponentSize.Four)
|
_state.State.SetRemapComponentsComponentSize == SetRemapComponentsComponentSize.Four)
|
||||||
{
|
{
|
||||||
// Fast path for clears when remap is enabled.
|
// Fast path for clears when remap is enabled.
|
||||||
memoryManager.Physical.BufferCache.ClearBuffer(memoryManager, dstGpuVa, size * 4, _state.State.SetRemapConstA);
|
bufferCache.ClearBuffer(memoryManager, dstGpuVa, size * 4, _state.State.SetRemapConstA);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -442,7 +444,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Dma
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
memoryManager.Physical.BufferCache.CopyBuffer(memoryManager, srcGpuVa, dstGpuVa, size);
|
BufferCache.CopyBuffer(_context, memoryManager, srcGpuVa, dstGpuVa, size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -183,7 +183,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.InlineToMemory
|
||||||
// Right now the copy code at the bottom assumes that it is used on both which might be incorrect.
|
// Right now the copy code at the bottom assumes that it is used on both which might be incorrect.
|
||||||
if (!_isLinear)
|
if (!_isLinear)
|
||||||
{
|
{
|
||||||
var target = memoryManager.Physical.TextureCache.FindTexture(
|
var target = memoryManager.GetBackingMemory(_dstGpuVa).TextureCache.FindTexture(
|
||||||
memoryManager,
|
memoryManager,
|
||||||
_dstGpuVa,
|
_dstGpuVa,
|
||||||
1,
|
1,
|
||||||
|
|
|
@ -382,7 +382,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
||||||
|
|
||||||
ulong indirectBufferGpuVa = count.GpuVa;
|
ulong indirectBufferGpuVa = count.GpuVa;
|
||||||
|
|
||||||
var bufferCache = _processor.MemoryManager.Physical.BufferCache;
|
var bufferCache = _processor.MemoryManager.GetBackingMemory(indirectBufferGpuVa).BufferCache;
|
||||||
|
|
||||||
bool useBuffer = bufferCache.CheckModified(_processor.MemoryManager, indirectBufferGpuVa, IndirectIndexedDataEntrySize, out ulong indirectBufferAddress);
|
bool useBuffer = bufferCache.CheckModified(_processor.MemoryManager, indirectBufferGpuVa, IndirectIndexedDataEntrySize, out ulong indirectBufferAddress);
|
||||||
|
|
||||||
|
@ -392,6 +392,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
||||||
|
|
||||||
_processor.ThreedClass.DrawIndirect(
|
_processor.ThreedClass.DrawIndirect(
|
||||||
topology,
|
topology,
|
||||||
|
bufferCache,
|
||||||
|
null,
|
||||||
indirectBufferAddress,
|
indirectBufferAddress,
|
||||||
0,
|
0,
|
||||||
1,
|
1,
|
||||||
|
@ -490,15 +492,18 @@ namespace Ryujinx.Graphics.Gpu.Engine.MME
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var bufferCache = _processor.MemoryManager.Physical.BufferCache;
|
var indirectBufferCache = _processor.MemoryManager.GetBackingMemory(indirectBufferGpuVa).BufferCache;
|
||||||
|
var parameterBufferCache = _processor.MemoryManager.GetBackingMemory(parameterBufferGpuVa).BufferCache;
|
||||||
|
|
||||||
ulong indirectBufferSize = (ulong)maxDrawCount * (ulong)stride;
|
ulong indirectBufferSize = (ulong)maxDrawCount * (ulong)stride;
|
||||||
|
|
||||||
ulong indirectBufferAddress = bufferCache.TranslateAndCreateBuffer(_processor.MemoryManager, indirectBufferGpuVa, indirectBufferSize);
|
ulong indirectBufferAddress = indirectBufferCache.TranslateAndCreateBuffer(_processor.MemoryManager, indirectBufferGpuVa, indirectBufferSize);
|
||||||
ulong parameterBufferAddress = bufferCache.TranslateAndCreateBuffer(_processor.MemoryManager, parameterBufferGpuVa, 4);
|
ulong parameterBufferAddress = parameterBufferCache.TranslateAndCreateBuffer(_processor.MemoryManager, parameterBufferGpuVa, 4);
|
||||||
|
|
||||||
_processor.ThreedClass.DrawIndirect(
|
_processor.ThreedClass.DrawIndirect(
|
||||||
topology,
|
topology,
|
||||||
|
indirectBufferCache,
|
||||||
|
parameterBufferCache,
|
||||||
indirectBufferAddress,
|
indirectBufferAddress,
|
||||||
parameterBufferAddress,
|
parameterBufferAddress,
|
||||||
maxDrawCount,
|
maxDrawCount,
|
||||||
|
|
|
@ -371,7 +371,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
|
||||||
var memoryManager = _channel.MemoryManager;
|
var memoryManager = _channel.MemoryManager;
|
||||||
|
|
||||||
address = memoryManager.Translate(address);
|
address = memoryManager.Translate(address);
|
||||||
BufferRange range = memoryManager.Physical.BufferCache.GetBufferRange(address, size);
|
BufferRange range = memoryManager.GetBackingMemory(address).BufferCache.GetBufferRange(address, size);
|
||||||
|
|
||||||
ITexture bufferTexture = _vacContext.EnsureBufferTexture(index + 2, format);
|
ITexture bufferTexture = _vacContext.EnsureBufferTexture(index + 2, format);
|
||||||
bufferTexture.SetStorage(range);
|
bufferTexture.SetStorage(range);
|
||||||
|
@ -414,7 +414,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw
|
||||||
|
|
||||||
address = memoryManager.Translate(address + indexOffset);
|
address = memoryManager.Translate(address + indexOffset);
|
||||||
ulong misalign = address & ((ulong)_context.Capabilities.TextureBufferOffsetAlignment - 1);
|
ulong misalign = address & ((ulong)_context.Capabilities.TextureBufferOffsetAlignment - 1);
|
||||||
BufferRange range = memoryManager.Physical.BufferCache.GetBufferRange(address - misalign, size + misalign);
|
BufferRange range = memoryManager.GetBackingMemory(address).BufferCache.GetBufferRange(address - misalign, size + misalign);
|
||||||
misalignedOffset = (int)misalign >> shift;
|
misalignedOffset = (int)misalign >> shift;
|
||||||
|
|
||||||
SetIndexBufferTexture(reservations, range, format);
|
SetIndexBufferTexture(reservations, range, format);
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
|
|
||||||
// State associated with direct uniform buffer updates.
|
// State associated with direct uniform buffer updates.
|
||||||
// This state is used to attempt to batch together consecutive updates.
|
// This state is used to attempt to batch together consecutive updates.
|
||||||
|
private ulong _ubBeginGpuAddress = 0;
|
||||||
private ulong _ubBeginCpuAddress = 0;
|
private ulong _ubBeginCpuAddress = 0;
|
||||||
private ulong _ubFollowUpAddress = 0;
|
private ulong _ubFollowUpAddress = 0;
|
||||||
private ulong _ubByteCount = 0;
|
private ulong _ubByteCount = 0;
|
||||||
|
@ -112,12 +113,13 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
if (_ubFollowUpAddress != 0)
|
if (_ubFollowUpAddress != 0)
|
||||||
{
|
{
|
||||||
var memoryManager = _channel.MemoryManager;
|
var memoryManager = _channel.MemoryManager;
|
||||||
|
var physicalMemory = memoryManager.GetBackingMemory(_ubBeginGpuAddress);
|
||||||
|
|
||||||
Span<byte> data = MemoryMarshal.Cast<int, byte>(_ubData.AsSpan(0, (int)(_ubByteCount / 4)));
|
Span<byte> data = MemoryMarshal.Cast<int, byte>(_ubData.AsSpan(0, (int)(_ubByteCount / 4)));
|
||||||
|
|
||||||
if (memoryManager.Physical.WriteWithRedundancyCheck(_ubBeginCpuAddress, data))
|
if (physicalMemory.WriteWithRedundancyCheck(_ubBeginCpuAddress, data))
|
||||||
{
|
{
|
||||||
memoryManager.Physical.BufferCache.ForceDirty(memoryManager, _ubFollowUpAddress - _ubByteCount, _ubByteCount);
|
physicalMemory.BufferCache.ForceDirty(memoryManager, _ubFollowUpAddress - _ubByteCount, _ubByteCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
_ubFollowUpAddress = 0;
|
_ubFollowUpAddress = 0;
|
||||||
|
@ -140,6 +142,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
FlushUboDirty();
|
FlushUboDirty();
|
||||||
|
|
||||||
_ubByteCount = 0;
|
_ubByteCount = 0;
|
||||||
|
_ubBeginGpuAddress = address;
|
||||||
_ubBeginCpuAddress = _channel.MemoryManager.Translate(address);
|
_ubBeginCpuAddress = _channel.MemoryManager.Translate(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -168,6 +171,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
FlushUboDirty();
|
FlushUboDirty();
|
||||||
|
|
||||||
_ubByteCount = 0;
|
_ubByteCount = 0;
|
||||||
|
_ubBeginGpuAddress = address;
|
||||||
_ubBeginCpuAddress = _channel.MemoryManager.Translate(address);
|
_ubBeginCpuAddress = _channel.MemoryManager.Translate(address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -630,6 +630,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="engine">3D engine where this method is being called</param>
|
/// <param name="engine">3D engine where this method is being called</param>
|
||||||
/// <param name="topology">Primitive topology</param>
|
/// <param name="topology">Primitive topology</param>
|
||||||
|
/// <param name="indirectBufferCache">Buffer cache owning the buffer with the draw parameters</param>
|
||||||
|
/// <param name="parameterBufferCache">Buffer cache owning the buffer with the draw count</param>
|
||||||
/// <param name="indirectBufferAddress">Address of the buffer with the draw parameters, such as count, first index, etc</param>
|
/// <param name="indirectBufferAddress">Address of the buffer with the draw parameters, such as count, first index, etc</param>
|
||||||
/// <param name="parameterBufferAddress">Address of the buffer with the draw count</param>
|
/// <param name="parameterBufferAddress">Address of the buffer with the draw count</param>
|
||||||
/// <param name="maxDrawCount">Maximum number of draws that can be made</param>
|
/// <param name="maxDrawCount">Maximum number of draws that can be made</param>
|
||||||
|
@ -639,6 +641,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
public void DrawIndirect(
|
public void DrawIndirect(
|
||||||
ThreedClass engine,
|
ThreedClass engine,
|
||||||
PrimitiveTopology topology,
|
PrimitiveTopology topology,
|
||||||
|
BufferCache indirectBufferCache,
|
||||||
|
BufferCache parameterBufferCache,
|
||||||
ulong indirectBufferAddress,
|
ulong indirectBufferAddress,
|
||||||
ulong parameterBufferAddress,
|
ulong parameterBufferAddress,
|
||||||
int maxDrawCount,
|
int maxDrawCount,
|
||||||
|
@ -660,8 +664,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
PhysicalMemory memory = _channel.MemoryManager.Physical;
|
|
||||||
|
|
||||||
bool hasCount = (drawType & IndirectDrawType.Count) != 0;
|
bool hasCount = (drawType & IndirectDrawType.Count) != 0;
|
||||||
bool indexed = (drawType & IndirectDrawType.Indexed) != 0;
|
bool indexed = (drawType & IndirectDrawType.Indexed) != 0;
|
||||||
|
|
||||||
|
@ -681,8 +683,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
|
|
||||||
if (hasCount)
|
if (hasCount)
|
||||||
{
|
{
|
||||||
var indirectBuffer = memory.BufferCache.GetBufferRange(indirectBufferAddress, (ulong)maxDrawCount * (ulong)stride);
|
var indirectBuffer = indirectBufferCache.GetBufferRange(indirectBufferAddress, (ulong)maxDrawCount * (ulong)stride);
|
||||||
var parameterBuffer = memory.BufferCache.GetBufferRange(parameterBufferAddress, 4);
|
var parameterBuffer = parameterBufferCache.GetBufferRange(parameterBufferAddress, 4);
|
||||||
|
|
||||||
if (indexed)
|
if (indexed)
|
||||||
{
|
{
|
||||||
|
@ -695,7 +697,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
var indirectBuffer = memory.BufferCache.GetBufferRange(indirectBufferAddress, (ulong)stride);
|
var indirectBuffer = indirectBufferCache.GetBufferRange(indirectBufferAddress, (ulong)stride);
|
||||||
|
|
||||||
if (indexed)
|
if (indexed)
|
||||||
{
|
{
|
||||||
|
|
|
@ -361,10 +361,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
{
|
{
|
||||||
BufferDescriptor sb = info.SBuffers[index];
|
BufferDescriptor sb = info.SBuffers[index];
|
||||||
|
|
||||||
ulong sbDescAddress = _channel.BufferManager.GetGraphicsUniformBufferAddress(stage, sb.SbCbSlot);
|
(var physical, ulong sbDescAddress) = _channel.BufferManager.GetGraphicsUniformBufferAddress(stage, sb.SbCbSlot);
|
||||||
sbDescAddress += (ulong)sb.SbCbOffset * 4;
|
sbDescAddress += (ulong)sb.SbCbOffset * 4;
|
||||||
|
|
||||||
SbDescriptor sbDescriptor = _channel.MemoryManager.Physical.Read<SbDescriptor>(sbDescAddress);
|
SbDescriptor sbDescriptor = physical.Read<SbDescriptor>(sbDescAddress);
|
||||||
|
|
||||||
uint size;
|
uint size;
|
||||||
if (sb.SbCbSlot == Constants.DriverReservedUniformBuffer)
|
if (sb.SbCbSlot == Constants.DriverReservedUniformBuffer)
|
||||||
|
@ -485,7 +485,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
rtNoAlphaMask |= 1u << index;
|
rtNoAlphaMask |= 1u << index;
|
||||||
}
|
}
|
||||||
|
|
||||||
Image.Texture color = memoryManager.Physical.TextureCache.FindOrCreateTexture(
|
var colorTextureCache = memoryManager.GetBackingMemory(colorState.Address.Pack()).TextureCache;
|
||||||
|
|
||||||
|
Image.Texture color = colorTextureCache.FindOrCreateTexture(
|
||||||
memoryManager,
|
memoryManager,
|
||||||
colorState,
|
colorState,
|
||||||
_vtgWritesRtLayer || layered,
|
_vtgWritesRtLayer || layered,
|
||||||
|
@ -524,7 +526,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
var dsState = _state.State.RtDepthStencilState;
|
var dsState = _state.State.RtDepthStencilState;
|
||||||
var dsSize = _state.State.RtDepthStencilSize;
|
var dsSize = _state.State.RtDepthStencilSize;
|
||||||
|
|
||||||
depthStencil = memoryManager.Physical.TextureCache.FindOrCreateTexture(
|
var dsTextureCache = memoryManager.GetBackingMemory(dsState.Address.Pack()).TextureCache;
|
||||||
|
|
||||||
|
depthStencil = dsTextureCache.FindOrCreateTexture(
|
||||||
memoryManager,
|
memoryManager,
|
||||||
dsState,
|
dsState,
|
||||||
dsSize,
|
dsSize,
|
||||||
|
@ -1381,8 +1385,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
/// </summary>
|
/// </summary>
|
||||||
private void UpdateShaderState()
|
private void UpdateShaderState()
|
||||||
{
|
{
|
||||||
var shaderCache = _channel.MemoryManager.Physical.ShaderCache;
|
|
||||||
|
|
||||||
_vtgWritesRtLayer = false;
|
_vtgWritesRtLayer = false;
|
||||||
|
|
||||||
ShaderAddresses addresses = new();
|
ShaderAddresses addresses = new();
|
||||||
|
@ -1401,6 +1403,10 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
addressesSpan[index] = baseAddress + shader.Offset;
|
addressesSpan[index] = baseAddress + shader.Offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Shader stages on different address spaces are not supported right now,
|
||||||
|
// but it should never happen in practice anyway.
|
||||||
|
var shaderCache = _channel.MemoryManager.GetBackingMemory(addresses.VertexB).ShaderCache;
|
||||||
|
|
||||||
CachedShaderProgram gs = shaderCache.GetGraphicsShader(ref _state.State, ref _pipeline, _channel, ref _currentSpecState.GetPoolState(), ref _currentSpecState.GetGraphicsState(), addresses);
|
CachedShaderProgram gs = shaderCache.GetGraphicsShader(ref _state.State, ref _pipeline, _channel, ref _currentSpecState.GetPoolState(), ref _currentSpecState.GetGraphicsState(), addresses);
|
||||||
|
|
||||||
// Consume the modified flag for spec state so that it isn't checked again.
|
// Consume the modified flag for spec state so that it isn't checked again.
|
||||||
|
|
|
@ -6,6 +6,7 @@ using Ryujinx.Graphics.Gpu.Engine.InlineToMemory;
|
||||||
using Ryujinx.Graphics.Gpu.Engine.Threed.Blender;
|
using Ryujinx.Graphics.Gpu.Engine.Threed.Blender;
|
||||||
using Ryujinx.Graphics.Gpu.Engine.Types;
|
using Ryujinx.Graphics.Gpu.Engine.Types;
|
||||||
using Ryujinx.Graphics.Gpu.Synchronization;
|
using Ryujinx.Graphics.Gpu.Synchronization;
|
||||||
|
using Ryujinx.Graphics.Gpu.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Runtime.CompilerServices;
|
using System.Runtime.CompilerServices;
|
||||||
|
@ -803,6 +804,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
/// Performs a indirect draw, with parameters from a GPU buffer.
|
/// Performs a indirect draw, with parameters from a GPU buffer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="topology">Primitive topology</param>
|
/// <param name="topology">Primitive topology</param>
|
||||||
|
/// <param name="indirectBufferCache">Buffer cache owning the buffer with the draw parameters</param>
|
||||||
|
/// <param name="parameterBufferCache">Buffer cache owning the buffer with the draw count</param>
|
||||||
/// <param name="indirectBufferAddress">Address of the buffer with the draw parameters, such as count, first index, etc</param>
|
/// <param name="indirectBufferAddress">Address of the buffer with the draw parameters, such as count, first index, etc</param>
|
||||||
/// <param name="parameterBufferAddress">Address of the buffer with the draw count</param>
|
/// <param name="parameterBufferAddress">Address of the buffer with the draw count</param>
|
||||||
/// <param name="maxDrawCount">Maximum number of draws that can be made</param>
|
/// <param name="maxDrawCount">Maximum number of draws that can be made</param>
|
||||||
|
@ -811,6 +814,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
/// <param name="drawType">Type of the indirect draw, which can be indexed or non-indexed, with or without a draw count</param>
|
/// <param name="drawType">Type of the indirect draw, which can be indexed or non-indexed, with or without a draw count</param>
|
||||||
public void DrawIndirect(
|
public void DrawIndirect(
|
||||||
PrimitiveTopology topology,
|
PrimitiveTopology topology,
|
||||||
|
BufferCache indirectBufferCache,
|
||||||
|
BufferCache parameterBufferCache,
|
||||||
ulong indirectBufferAddress,
|
ulong indirectBufferAddress,
|
||||||
ulong parameterBufferAddress,
|
ulong parameterBufferAddress,
|
||||||
int maxDrawCount,
|
int maxDrawCount,
|
||||||
|
@ -818,7 +823,17 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
||||||
int indexCount,
|
int indexCount,
|
||||||
IndirectDrawType drawType)
|
IndirectDrawType drawType)
|
||||||
{
|
{
|
||||||
_drawManager.DrawIndirect(this, topology, indirectBufferAddress, parameterBufferAddress, maxDrawCount, stride, indexCount, drawType);
|
_drawManager.DrawIndirect(
|
||||||
|
this,
|
||||||
|
topology,
|
||||||
|
indirectBufferCache,
|
||||||
|
parameterBufferCache,
|
||||||
|
indirectBufferAddress,
|
||||||
|
parameterBufferAddress,
|
||||||
|
maxDrawCount,
|
||||||
|
stride,
|
||||||
|
indexCount,
|
||||||
|
drawType);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -233,6 +233,9 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
|
||||||
var dstCopyTexture = Unsafe.As<uint, TwodTexture>(ref _state.State.SetDstFormat);
|
var dstCopyTexture = Unsafe.As<uint, TwodTexture>(ref _state.State.SetDstFormat);
|
||||||
var srcCopyTexture = Unsafe.As<uint, TwodTexture>(ref _state.State.SetSrcFormat);
|
var srcCopyTexture = Unsafe.As<uint, TwodTexture>(ref _state.State.SetSrcFormat);
|
||||||
|
|
||||||
|
var srcTextureCache = memoryManager.GetBackingMemory(srcCopyTexture.Address.Pack()).TextureCache;
|
||||||
|
var dstTextureCache = memoryManager.GetBackingMemory(dstCopyTexture.Address.Pack()).TextureCache;
|
||||||
|
|
||||||
long srcX = ((long)_state.State.SetPixelsFromMemorySrcX0Int << 32) | (long)(ulong)_state.State.SetPixelsFromMemorySrcX0Frac;
|
long srcX = ((long)_state.State.SetPixelsFromMemorySrcX0Int << 32) | (long)(ulong)_state.State.SetPixelsFromMemorySrcX0Frac;
|
||||||
long srcY = ((long)_state.State.PixelsFromMemorySrcY0Int << 32) | (long)(ulong)_state.State.SetPixelsFromMemorySrcY0Frac;
|
long srcY = ((long)_state.State.PixelsFromMemorySrcY0Int << 32) | (long)(ulong)_state.State.SetPixelsFromMemorySrcY0Frac;
|
||||||
|
|
||||||
|
@ -304,7 +307,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
|
||||||
// are the same, as we can't blit between different depth formats.
|
// are the same, as we can't blit between different depth formats.
|
||||||
bool srcDepthAlias = srcCopyTexture.Format == dstCopyTexture.Format;
|
bool srcDepthAlias = srcCopyTexture.Format == dstCopyTexture.Format;
|
||||||
|
|
||||||
var srcTexture = memoryManager.Physical.TextureCache.FindOrCreateTexture(
|
var srcTexture = srcTextureCache.FindOrCreateTexture(
|
||||||
memoryManager,
|
memoryManager,
|
||||||
srcCopyTexture,
|
srcCopyTexture,
|
||||||
offset,
|
offset,
|
||||||
|
@ -325,7 +328,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
memoryManager.Physical.TextureCache.Lift(srcTexture);
|
srcTextureCache.Lift(srcTexture);
|
||||||
|
|
||||||
// When the source texture that was found has a depth format,
|
// When the source texture that was found has a depth format,
|
||||||
// we must enforce the target texture also has a depth format,
|
// we must enforce the target texture also has a depth format,
|
||||||
|
@ -341,7 +344,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Twod
|
||||||
dstCopyTextureFormat = dstCopyTexture.Format.Convert();
|
dstCopyTextureFormat = dstCopyTexture.Format.Convert();
|
||||||
}
|
}
|
||||||
|
|
||||||
var dstTexture = memoryManager.Physical.TextureCache.FindOrCreateTexture(
|
var dstTexture = dstTextureCache.FindOrCreateTexture(
|
||||||
memoryManager,
|
memoryManager,
|
||||||
dstCopyTexture,
|
dstCopyTexture,
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -58,22 +58,24 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
public void BindMemory(MemoryManager memoryManager)
|
public void BindMemory(MemoryManager memoryManager)
|
||||||
{
|
{
|
||||||
var oldMemoryManager = Interlocked.Exchange(ref _memoryManager, memoryManager ?? throw new ArgumentNullException(nameof(memoryManager)));
|
var oldMemoryManager = Interlocked.Exchange(ref _memoryManager, memoryManager ?? throw new ArgumentNullException(nameof(memoryManager)));
|
||||||
|
if (oldMemoryManager == memoryManager)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
memoryManager.Physical.IncrementReferenceCount();
|
memoryManager.AttachToChannel(BufferManager.Rebind);
|
||||||
|
|
||||||
if (oldMemoryManager != null)
|
if (oldMemoryManager != null)
|
||||||
{
|
{
|
||||||
oldMemoryManager.Physical.BufferCache.NotifyBuffersModified -= BufferManager.Rebind;
|
oldMemoryManager.DetachFromChannel(BufferManager.Rebind);
|
||||||
oldMemoryManager.Physical.DecrementReferenceCount();
|
|
||||||
oldMemoryManager.MemoryUnmapped -= MemoryUnmappedHandler;
|
oldMemoryManager.MemoryUnmapped -= MemoryUnmappedHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
memoryManager.Physical.BufferCache.NotifyBuffersModified += BufferManager.Rebind;
|
|
||||||
memoryManager.MemoryUnmapped += MemoryUnmappedHandler;
|
memoryManager.MemoryUnmapped += MemoryUnmappedHandler;
|
||||||
|
|
||||||
// Since the memory manager changed, make sure we will get pools from addresses of the new memory manager.
|
// Since the memory manager changed, make sure we will get pools from addresses of the new memory manager.
|
||||||
TextureManager.ReloadPools();
|
TextureManager.ReloadPools();
|
||||||
memoryManager.Physical.BufferCache.QueuePrune();
|
memoryManager.QueuePrune();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -86,7 +88,7 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
TextureManager.ReloadPools();
|
TextureManager.ReloadPools();
|
||||||
|
|
||||||
var memoryManager = Volatile.Read(ref _memoryManager);
|
var memoryManager = Volatile.Read(ref _memoryManager);
|
||||||
memoryManager?.Physical.BufferCache.QueuePrune();
|
memoryManager?.QueuePrune();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -141,8 +143,7 @@ namespace Ryujinx.Graphics.Gpu
|
||||||
var oldMemoryManager = Interlocked.Exchange(ref _memoryManager, null);
|
var oldMemoryManager = Interlocked.Exchange(ref _memoryManager, null);
|
||||||
if (oldMemoryManager != null)
|
if (oldMemoryManager != null)
|
||||||
{
|
{
|
||||||
oldMemoryManager.Physical.BufferCache.NotifyBuffersModified -= BufferManager.Rebind;
|
oldMemoryManager.DetachFromChannel(BufferManager.Rebind);
|
||||||
oldMemoryManager.Physical.DecrementReferenceCount();
|
|
||||||
oldMemoryManager.MemoryUnmapped -= MemoryUnmappedHandler;
|
oldMemoryManager.MemoryUnmapped -= MemoryUnmappedHandler;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
using Ryujinx.Graphics.Gpu.Memory;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
|
@ -60,10 +61,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// Finds a cache texture pool, or creates a new one if not found.
|
/// Finds a cache texture pool, or creates a new one if not found.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="channel">GPU channel that the texture pool cache belongs to</param>
|
/// <param name="channel">GPU channel that the texture pool cache belongs to</param>
|
||||||
|
/// <param name="physicalMemory">Backing memory of the pool</param>
|
||||||
/// <param name="address">Start address of the texture pool</param>
|
/// <param name="address">Start address of the texture pool</param>
|
||||||
/// <param name="maximumId">Maximum ID of the texture pool</param>
|
/// <param name="maximumId">Maximum ID of the texture pool</param>
|
||||||
/// <returns>The found or newly created texture pool</returns>
|
/// <returns>The found or newly created texture pool</returns>
|
||||||
public T FindOrCreate(GpuChannel channel, ulong address, int maximumId)
|
public T FindOrCreate(GpuChannel channel, PhysicalMemory physicalMemory, ulong address, int maximumId)
|
||||||
{
|
{
|
||||||
// Remove old entries from the cache, if possible.
|
// Remove old entries from the cache, if possible.
|
||||||
while (_pools.Count > MaxCapacity && (_currentTimestamp - _pools.First.Value.CacheTimestamp) >= MinDeltaForRemoval)
|
while (_pools.Count > MaxCapacity && (_currentTimestamp - _pools.First.Value.CacheTimestamp) >= MinDeltaForRemoval)
|
||||||
|
@ -98,7 +100,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not found, create a new one.
|
// If not found, create a new one.
|
||||||
pool = CreatePool(_context, channel, address, maximumId);
|
pool = CreatePool(_context, channel, physicalMemory, address, maximumId);
|
||||||
|
|
||||||
pool.CacheNode = _pools.AddLast(pool);
|
pool.CacheNode = _pools.AddLast(pool);
|
||||||
pool.CacheTimestamp = _currentTimestamp;
|
pool.CacheTimestamp = _currentTimestamp;
|
||||||
|
@ -111,9 +113,10 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">GPU context that the pool belongs to</param>
|
/// <param name="context">GPU context that the pool belongs to</param>
|
||||||
/// <param name="channel">GPU channel that the pool belongs to</param>
|
/// <param name="channel">GPU channel that the pool belongs to</param>
|
||||||
|
/// <param name="physicalMemory">Backing memory of the pool</param>
|
||||||
/// <param name="address">Address of the pool in guest memory</param>
|
/// <param name="address">Address of the pool in guest memory</param>
|
||||||
/// <param name="maximumId">Maximum ID of the pool (equal to maximum minus one)</param>
|
/// <param name="maximumId">Maximum ID of the pool (equal to maximum minus one)</param>
|
||||||
protected abstract T CreatePool(GpuContext context, GpuChannel channel, ulong address, int maximumId);
|
protected abstract T CreatePool(GpuContext context, GpuChannel channel, PhysicalMemory physicalMemory, ulong address, int maximumId);
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
using Ryujinx.Graphics.Gpu.Memory;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Image
|
namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -20,11 +22,17 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">GPU context that the sampler pool belongs to</param>
|
/// <param name="context">GPU context that the sampler pool belongs to</param>
|
||||||
/// <param name="channel">GPU channel that the texture pool belongs to</param>
|
/// <param name="channel">GPU channel that the texture pool belongs to</param>
|
||||||
|
/// <param name="physicalMemory">Backing memory of the pool</param>
|
||||||
/// <param name="address">Address of the sampler pool in guest memory</param>
|
/// <param name="address">Address of the sampler pool in guest memory</param>
|
||||||
/// <param name="maximumId">Maximum sampler ID of the sampler pool (equal to maximum samplers minus one)</param>
|
/// <param name="maximumId">Maximum sampler ID of the sampler pool (equal to maximum samplers minus one)</param>
|
||||||
protected override SamplerPool CreatePool(GpuContext context, GpuChannel channel, ulong address, int maximumId)
|
protected override SamplerPool CreatePool(
|
||||||
|
GpuContext context,
|
||||||
|
GpuChannel channel,
|
||||||
|
PhysicalMemory physicalMemory,
|
||||||
|
ulong address,
|
||||||
|
int maximumId)
|
||||||
{
|
{
|
||||||
return new SamplerPool(context, channel.MemoryManager.Physical, address, maximumId);
|
return new SamplerPool(context, physicalMemory, address, maximumId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -382,7 +382,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
ref BufferBounds bounds = ref _channel.BufferManager.GetUniformBufferBounds(_isCompute, stageIndex, textureBufferIndex);
|
ref BufferBounds bounds = ref _channel.BufferManager.GetUniformBufferBounds(_isCompute, stageIndex, textureBufferIndex);
|
||||||
|
|
||||||
cachedTextureBuffer = MemoryMarshal.Cast<byte, int>(_channel.MemoryManager.Physical.GetSpan(bounds.Address, (int)bounds.Size));
|
cachedTextureBuffer = MemoryMarshal.Cast<byte, int>(bounds.Physical.GetSpan(bounds.Address, (int)bounds.Size));
|
||||||
cachedTextureBufferIndex = textureBufferIndex;
|
cachedTextureBufferIndex = textureBufferIndex;
|
||||||
|
|
||||||
if (samplerBufferIndex == textureBufferIndex)
|
if (samplerBufferIndex == textureBufferIndex)
|
||||||
|
@ -396,7 +396,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
ref BufferBounds bounds = ref _channel.BufferManager.GetUniformBufferBounds(_isCompute, stageIndex, samplerBufferIndex);
|
ref BufferBounds bounds = ref _channel.BufferManager.GetUniformBufferBounds(_isCompute, stageIndex, samplerBufferIndex);
|
||||||
|
|
||||||
cachedSamplerBuffer = MemoryMarshal.Cast<byte, int>(_channel.MemoryManager.Physical.GetSpan(bounds.Address, (int)bounds.Size));
|
cachedSamplerBuffer = MemoryMarshal.Cast<byte, int>(bounds.Physical.GetSpan(bounds.Address, (int)bounds.Size));
|
||||||
cachedSamplerBufferIndex = samplerBufferIndex;
|
cachedSamplerBufferIndex = samplerBufferIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -524,7 +524,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
// Ensure that the buffer texture is using the correct buffer as storage.
|
// Ensure that the buffer texture is using the correct buffer as storage.
|
||||||
// Buffers are frequently re-created to accommodate larger data, so we need to re-bind
|
// Buffers are frequently re-created to accommodate larger data, so we need to re-bind
|
||||||
// to ensure we're not using a old buffer that was already deleted.
|
// to ensure we're not using a old buffer that was already deleted.
|
||||||
_channel.BufferManager.SetBufferTextureStorage(stage, hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, bindingInfo.Format, false);
|
var bufferCache = _channel.MemoryManager.GetBackingMemory(descriptor.UnpackAddress()).BufferCache;
|
||||||
|
_channel.BufferManager.SetBufferTextureStorage(stage, hostTexture, bufferCache, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, bindingInfo.Format, false);
|
||||||
|
|
||||||
// Cache is not used for buffer texture, it must always rebind.
|
// Cache is not used for buffer texture, it must always rebind.
|
||||||
state.CachedTexture = null;
|
state.CachedTexture = null;
|
||||||
|
@ -661,7 +662,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
format = texture.Format;
|
format = texture.Format;
|
||||||
}
|
}
|
||||||
|
|
||||||
_channel.BufferManager.SetBufferTextureStorage(stage, hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, format, true);
|
var bufferCache = _channel.MemoryManager.GetBackingMemory(descriptor.UnpackAddress()).BufferCache;
|
||||||
|
_channel.BufferManager.SetBufferTextureStorage(stage, hostTexture, bufferCache, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, format, true);
|
||||||
|
|
||||||
// Cache is not used for buffer texture, it must always rebind.
|
// Cache is not used for buffer texture, it must always rebind.
|
||||||
state.CachedTexture = null;
|
state.CachedTexture = null;
|
||||||
|
@ -726,9 +728,10 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
int packedId = ReadPackedId(stageIndex, handle, textureBufferIndex, samplerBufferIndex);
|
int packedId = ReadPackedId(stageIndex, handle, textureBufferIndex, samplerBufferIndex);
|
||||||
int textureId = TextureHandle.UnpackTextureId(packedId);
|
int textureId = TextureHandle.UnpackTextureId(packedId);
|
||||||
|
|
||||||
|
var physical = _channel.MemoryManager.GetBackingMemory(poolGpuVa);
|
||||||
ulong poolAddress = _channel.MemoryManager.Translate(poolGpuVa);
|
ulong poolAddress = _channel.MemoryManager.Translate(poolGpuVa);
|
||||||
|
|
||||||
TexturePool texturePool = _texturePoolCache.FindOrCreate(_channel, poolAddress, maximumId);
|
TexturePool texturePool = _texturePoolCache.FindOrCreate(_channel, physical, poolAddress, maximumId);
|
||||||
|
|
||||||
TextureDescriptor descriptor;
|
TextureDescriptor descriptor;
|
||||||
|
|
||||||
|
@ -762,12 +765,12 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
(int textureWordOffset, int samplerWordOffset, TextureHandleType handleType) = TextureHandle.UnpackOffsets(wordOffset);
|
(int textureWordOffset, int samplerWordOffset, TextureHandleType handleType) = TextureHandle.UnpackOffsets(wordOffset);
|
||||||
|
|
||||||
ulong textureBufferAddress = _isCompute
|
(var texturePhysicalMemory, ulong textureBufferAddress) = _isCompute
|
||||||
? _channel.BufferManager.GetComputeUniformBufferAddress(textureBufferIndex)
|
? _channel.BufferManager.GetComputeUniformBufferAddress(textureBufferIndex)
|
||||||
: _channel.BufferManager.GetGraphicsUniformBufferAddress(stageIndex, textureBufferIndex);
|
: _channel.BufferManager.GetGraphicsUniformBufferAddress(stageIndex, textureBufferIndex);
|
||||||
|
|
||||||
int handle = textureBufferAddress != 0
|
int handle = textureBufferAddress != 0
|
||||||
? _channel.MemoryManager.Physical.Read<int>(textureBufferAddress + (uint)textureWordOffset * 4)
|
? texturePhysicalMemory.Read<int>(textureBufferAddress + (uint)textureWordOffset * 4)
|
||||||
: 0;
|
: 0;
|
||||||
|
|
||||||
// The "wordOffset" (which is really the immediate value used on texture instructions on the shader)
|
// The "wordOffset" (which is really the immediate value used on texture instructions on the shader)
|
||||||
|
@ -782,12 +785,12 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
|
|
||||||
if (handleType != TextureHandleType.SeparateConstantSamplerHandle)
|
if (handleType != TextureHandleType.SeparateConstantSamplerHandle)
|
||||||
{
|
{
|
||||||
ulong samplerBufferAddress = _isCompute
|
(var samplerPhysicalMemory, ulong samplerBufferAddress) = _isCompute
|
||||||
? _channel.BufferManager.GetComputeUniformBufferAddress(samplerBufferIndex)
|
? _channel.BufferManager.GetComputeUniformBufferAddress(samplerBufferIndex)
|
||||||
: _channel.BufferManager.GetGraphicsUniformBufferAddress(stageIndex, samplerBufferIndex);
|
: _channel.BufferManager.GetGraphicsUniformBufferAddress(stageIndex, samplerBufferIndex);
|
||||||
|
|
||||||
samplerHandle = samplerBufferAddress != 0
|
samplerHandle = samplerBufferAddress != 0
|
||||||
? _channel.MemoryManager.Physical.Read<int>(samplerBufferAddress + (uint)samplerWordOffset * 4)
|
? samplerPhysicalMemory.Read<int>(samplerBufferAddress + (uint)samplerWordOffset * 4)
|
||||||
: 0;
|
: 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -824,7 +827,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
|
|
||||||
if (poolAddress != MemoryManager.PteUnmapped)
|
if (poolAddress != MemoryManager.PteUnmapped)
|
||||||
{
|
{
|
||||||
texturePool = _texturePoolCache.FindOrCreate(_channel, poolAddress, _texturePoolMaximumId);
|
var physical = _channel.MemoryManager.GetBackingMemory(_texturePoolGpuVa);
|
||||||
|
texturePool = _texturePoolCache.FindOrCreate(_channel, physical, poolAddress, _texturePoolMaximumId);
|
||||||
_texturePool = texturePool;
|
_texturePool = texturePool;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -835,7 +839,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
|
|
||||||
if (poolAddress != MemoryManager.PteUnmapped)
|
if (poolAddress != MemoryManager.PteUnmapped)
|
||||||
{
|
{
|
||||||
samplerPool = _samplerPoolCache.FindOrCreate(_channel, poolAddress, _samplerPoolMaximumId);
|
var physical = _channel.MemoryManager.GetBackingMemory(_samplerPoolGpuVa);
|
||||||
|
samplerPool = _samplerPoolCache.FindOrCreate(_channel, physical, poolAddress, _samplerPoolMaximumId);
|
||||||
_samplerPool = samplerPool;
|
_samplerPool = samplerPool;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -364,9 +364,10 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// <returns>The texture pool</returns>
|
/// <returns>The texture pool</returns>
|
||||||
public TexturePool GetTexturePool(ulong poolGpuVa, int maximumId)
|
public TexturePool GetTexturePool(ulong poolGpuVa, int maximumId)
|
||||||
{
|
{
|
||||||
|
var physical = _channel.MemoryManager.GetBackingMemory(poolGpuVa);
|
||||||
ulong poolAddress = _channel.MemoryManager.Translate(poolGpuVa);
|
ulong poolAddress = _channel.MemoryManager.Translate(poolGpuVa);
|
||||||
|
|
||||||
TexturePool texturePool = _texturePoolCache.FindOrCreate(_channel, poolAddress, maximumId);
|
TexturePool texturePool = _texturePoolCache.FindOrCreate(_channel, physical, poolAddress, maximumId);
|
||||||
|
|
||||||
return texturePool;
|
return texturePool;
|
||||||
}
|
}
|
||||||
|
|
|
@ -89,9 +89,10 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">GPU context that the texture pool belongs to</param>
|
/// <param name="context">GPU context that the texture pool belongs to</param>
|
||||||
/// <param name="channel">GPU channel that the texture pool belongs to</param>
|
/// <param name="channel">GPU channel that the texture pool belongs to</param>
|
||||||
|
/// <param name="physicalMemory">Backing memory of the pool</param>
|
||||||
/// <param name="address">Address of the texture pool in guest memory</param>
|
/// <param name="address">Address of the texture pool in guest memory</param>
|
||||||
/// <param name="maximumId">Maximum texture ID of the texture pool (equal to maximum textures minus one)</param>
|
/// <param name="maximumId">Maximum texture ID of the texture pool (equal to maximum textures minus one)</param>
|
||||||
public TexturePool(GpuContext context, GpuChannel channel, ulong address, int maximumId) : base(context, channel.MemoryManager.Physical, address, maximumId)
|
public TexturePool(GpuContext context, GpuChannel channel, PhysicalMemory physicalMemory, ulong address, int maximumId) : base(context, physicalMemory, address, maximumId)
|
||||||
{
|
{
|
||||||
_channel = channel;
|
_channel = channel;
|
||||||
}
|
}
|
||||||
|
@ -122,7 +123,9 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
return ref descriptor;
|
return ref descriptor;
|
||||||
}
|
}
|
||||||
|
|
||||||
texture = PhysicalMemory.TextureCache.FindOrCreateTexture(_channel.MemoryManager, TextureSearchFlags.ForSampler, info, layerSize);
|
MemoryManager memoryManager = _channel.MemoryManager;
|
||||||
|
TextureCache textureCache = memoryManager.GetBackingMemory(descriptor.UnpackAddress()).TextureCache;
|
||||||
|
texture = textureCache.FindOrCreateTexture(memoryManager, TextureSearchFlags.ForSampler, info, layerSize);
|
||||||
|
|
||||||
// If this happens, then the texture address is invalid, we can't add it to the cache.
|
// If this happens, then the texture address is invalid, we can't add it to the cache.
|
||||||
if (texture == null)
|
if (texture == null)
|
||||||
|
@ -280,7 +283,9 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
MultiRange range = _channel.MemoryManager.Physical.TextureCache.UpdatePartiallyMapped(_channel.MemoryManager, address, texture);
|
TextureCache textureCache = _channel.MemoryManager.GetBackingMemory(address).TextureCache;
|
||||||
|
|
||||||
|
MultiRange range = textureCache.UpdatePartiallyMapped(_channel.MemoryManager, address, texture);
|
||||||
|
|
||||||
// If the texture is not mapped at all, delete its reference.
|
// If the texture is not mapped at all, delete its reference.
|
||||||
|
|
||||||
|
@ -305,7 +310,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
if (!range.Equals(texture.Range))
|
if (!range.Equals(texture.Range))
|
||||||
{
|
{
|
||||||
// Part of the texture was mapped or unmapped. Replace the range and regenerate tracking handles.
|
// Part of the texture was mapped or unmapped. Replace the range and regenerate tracking handles.
|
||||||
if (!_channel.MemoryManager.Physical.TextureCache.UpdateMapping(texture, range))
|
if (!textureCache.UpdateMapping(texture, range))
|
||||||
{
|
{
|
||||||
// Texture could not be remapped due to a collision, just delete it.
|
// Texture could not be remapped due to a collision, just delete it.
|
||||||
if (Interlocked.Exchange(ref Items[request.ID], null) != null)
|
if (Interlocked.Exchange(ref Items[request.ID], null) != null)
|
||||||
|
@ -338,6 +343,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// <param name="size">Size of the range being invalidated</param>
|
/// <param name="size">Size of the range being invalidated</param>
|
||||||
protected override void InvalidateRangeImpl(ulong address, ulong size)
|
protected override void InvalidateRangeImpl(ulong address, ulong size)
|
||||||
{
|
{
|
||||||
|
MemoryManager memoryManager = _channel.MemoryManager;
|
||||||
|
|
||||||
ProcessDereferenceQueue();
|
ProcessDereferenceQueue();
|
||||||
|
|
||||||
ulong endAddress = address + size;
|
ulong endAddress = address + size;
|
||||||
|
@ -362,7 +369,8 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
|
|
||||||
if (texture.HasOneReference())
|
if (texture.HasOneReference())
|
||||||
{
|
{
|
||||||
_channel.MemoryManager.Physical.TextureCache.AddShortCache(texture, ref cachedDescriptor);
|
TextureCache textureCache = memoryManager.GetBackingMemory(descriptor.UnpackAddress()).TextureCache;
|
||||||
|
textureCache.AddShortCache(texture, ref cachedDescriptor);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Interlocked.Exchange(ref Items[id], null) != null)
|
if (Interlocked.Exchange(ref Items[id], null) != null)
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
using Ryujinx.Graphics.Gpu.Memory;
|
||||||
|
|
||||||
namespace Ryujinx.Graphics.Gpu.Image
|
namespace Ryujinx.Graphics.Gpu.Image
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -20,11 +22,17 @@ namespace Ryujinx.Graphics.Gpu.Image
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="context">GPU context that the texture pool belongs to</param>
|
/// <param name="context">GPU context that the texture pool belongs to</param>
|
||||||
/// <param name="channel">GPU channel that the texture pool belongs to</param>
|
/// <param name="channel">GPU channel that the texture pool belongs to</param>
|
||||||
|
/// <param name="physicalMemory">Backing memory of the pool</param>
|
||||||
/// <param name="address">Address of the texture pool in guest memory</param>
|
/// <param name="address">Address of the texture pool in guest memory</param>
|
||||||
/// <param name="maximumId">Maximum texture ID of the texture pool (equal to maximum textures minus one)</param>
|
/// <param name="maximumId">Maximum texture ID of the texture pool (equal to maximum textures minus one)</param>
|
||||||
protected override TexturePool CreatePool(GpuContext context, GpuChannel channel, ulong address, int maximumId)
|
protected override TexturePool CreatePool(
|
||||||
|
GpuContext context,
|
||||||
|
GpuChannel channel,
|
||||||
|
PhysicalMemory physicalMemory,
|
||||||
|
ulong address,
|
||||||
|
int maximumId)
|
||||||
{
|
{
|
||||||
return new TexturePool(context, channel, address, maximumId);
|
return new TexturePool(context, channel, physicalMemory, address, maximumId);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,16 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
readonly struct BufferBounds
|
readonly struct BufferBounds
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Physical memory backing the buffer.
|
||||||
|
/// </summary>
|
||||||
|
public PhysicalMemory Physical { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Buffer cache that owns the buffer.
|
||||||
|
/// </summary>
|
||||||
|
public BufferCache BufferCache => Physical.BufferCache;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Region virtual address.
|
/// Region virtual address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -25,11 +35,13 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Creates a new buffer region.
|
/// Creates a new buffer region.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="physical">Physical memory backing the buffer</param>
|
||||||
/// <param name="address">Region address</param>
|
/// <param name="address">Region address</param>
|
||||||
/// <param name="size">Region size</param>
|
/// <param name="size">Region size</param>
|
||||||
/// <param name="flags">Buffer usage flags</param>
|
/// <param name="flags">Buffer usage flags</param>
|
||||||
public BufferBounds(ulong address, ulong size, BufferUsageFlags flags = BufferUsageFlags.None)
|
public BufferBounds(PhysicalMemory physical, ulong address, ulong size, BufferUsageFlags flags = BufferUsageFlags.None)
|
||||||
{
|
{
|
||||||
|
Physical = physical;
|
||||||
Address = address;
|
Address = address;
|
||||||
Size = size;
|
Size = size;
|
||||||
Flags = flags;
|
Flags = flags;
|
||||||
|
|
|
@ -313,22 +313,26 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <remarks>
|
/// <remarks>
|
||||||
/// This does a GPU side copy.
|
/// This does a GPU side copy.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
|
/// <param name="context">GPU context</param>
|
||||||
/// <param name="memoryManager">GPU memory manager where the buffer is mapped</param>
|
/// <param name="memoryManager">GPU memory manager where the buffer is mapped</param>
|
||||||
/// <param name="srcVa">GPU virtual address of the copy source</param>
|
/// <param name="srcVa">GPU virtual address of the copy source</param>
|
||||||
/// <param name="dstVa">GPU virtual address of the copy destination</param>
|
/// <param name="dstVa">GPU virtual address of the copy destination</param>
|
||||||
/// <param name="size">Size in bytes of the copy</param>
|
/// <param name="size">Size in bytes of the copy</param>
|
||||||
public void CopyBuffer(MemoryManager memoryManager, ulong srcVa, ulong dstVa, ulong size)
|
public static void CopyBuffer(GpuContext context, MemoryManager memoryManager, ulong srcVa, ulong dstVa, ulong size)
|
||||||
{
|
{
|
||||||
ulong srcAddress = TranslateAndCreateBuffer(memoryManager, srcVa, size);
|
PhysicalMemory srcPhysical = memoryManager.GetBackingMemory(srcVa);
|
||||||
ulong dstAddress = TranslateAndCreateBuffer(memoryManager, dstVa, size);
|
PhysicalMemory dstPhysical = memoryManager.GetBackingMemory(dstVa);
|
||||||
|
|
||||||
Buffer srcBuffer = GetBuffer(srcAddress, size);
|
ulong srcAddress = srcPhysical.BufferCache.TranslateAndCreateBuffer(memoryManager, srcVa, size);
|
||||||
Buffer dstBuffer = GetBuffer(dstAddress, size);
|
ulong dstAddress = dstPhysical.BufferCache.TranslateAndCreateBuffer(memoryManager, dstVa, size);
|
||||||
|
|
||||||
|
Buffer srcBuffer = srcPhysical.BufferCache.GetBuffer(srcAddress, size);
|
||||||
|
Buffer dstBuffer = dstPhysical.BufferCache.GetBuffer(dstAddress, size);
|
||||||
|
|
||||||
int srcOffset = (int)(srcAddress - srcBuffer.Address);
|
int srcOffset = (int)(srcAddress - srcBuffer.Address);
|
||||||
int dstOffset = (int)(dstAddress - dstBuffer.Address);
|
int dstOffset = (int)(dstAddress - dstBuffer.Address);
|
||||||
|
|
||||||
_context.Renderer.Pipeline.CopyBuffer(
|
context.Renderer.Pipeline.CopyBuffer(
|
||||||
srcBuffer.Handle,
|
srcBuffer.Handle,
|
||||||
dstBuffer.Handle,
|
dstBuffer.Handle,
|
||||||
srcOffset,
|
srcOffset,
|
||||||
|
@ -344,7 +348,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
// Optimization: If the data being copied is already in memory, then copy it directly instead of flushing from GPU.
|
// Optimization: If the data being copied is already in memory, then copy it directly instead of flushing from GPU.
|
||||||
|
|
||||||
dstBuffer.ClearModified(dstAddress, size);
|
dstBuffer.ClearModified(dstAddress, size);
|
||||||
memoryManager.Physical.WriteTrackedResource(dstAddress, memoryManager.Physical.GetSpan(srcAddress, (int)size), ResourceKind.Buffer);
|
dstPhysical.WriteTrackedResource(dstAddress, srcPhysical.GetSpan(srcAddress, (int)size), ResourceKind.Buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -368,7 +372,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
_context.Renderer.Pipeline.ClearBuffer(buffer.Handle, offset, (int)size, value);
|
_context.Renderer.Pipeline.ClearBuffer(buffer.Handle, offset, (int)size, value);
|
||||||
|
|
||||||
memoryManager.Physical.FillTrackedResource(address, size, value, ResourceKind.Buffer);
|
memoryManager.GetBackingMemory(gpuVa).FillTrackedResource(address, size, value, ResourceKind.Buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -68,12 +68,13 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// Sets the region of a buffer at a given slot.
|
/// Sets the region of a buffer at a given slot.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">Buffer slot</param>
|
/// <param name="index">Buffer slot</param>
|
||||||
|
/// <param name="physical">Physical memory backing the buffer</param>
|
||||||
/// <param name="address">Region virtual address</param>
|
/// <param name="address">Region virtual address</param>
|
||||||
/// <param name="size">Region size in bytes</param>
|
/// <param name="size">Region size in bytes</param>
|
||||||
/// <param name="flags">Buffer usage flags</param>
|
/// <param name="flags">Buffer usage flags</param>
|
||||||
public void SetBounds(int index, ulong address, ulong size, BufferUsageFlags flags = BufferUsageFlags.None)
|
public void SetBounds(int index, PhysicalMemory physical, ulong address, ulong size, BufferUsageFlags flags = BufferUsageFlags.None)
|
||||||
{
|
{
|
||||||
Buffers[index] = new BufferBounds(address, size, flags);
|
Buffers[index] = new BufferBounds(physical, address, size, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -150,8 +151,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <param name="type">Type of each index buffer element</param>
|
/// <param name="type">Type of each index buffer element</param>
|
||||||
public void SetIndexBuffer(ulong gpuVa, ulong size, IndexType type)
|
public void SetIndexBuffer(ulong gpuVa, ulong size, IndexType type)
|
||||||
{
|
{
|
||||||
ulong address = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
var bufferCache = _channel.MemoryManager.GetBackingMemory(gpuVa).BufferCache;
|
||||||
|
ulong address = bufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
||||||
|
|
||||||
|
_indexBuffer.BufferCache = bufferCache;
|
||||||
_indexBuffer.Address = address;
|
_indexBuffer.Address = address;
|
||||||
_indexBuffer.Size = size;
|
_indexBuffer.Size = size;
|
||||||
_indexBuffer.Type = type;
|
_indexBuffer.Type = type;
|
||||||
|
@ -181,12 +184,16 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <param name="divisor">Vertex divisor of the buffer, for instanced draws</param>
|
/// <param name="divisor">Vertex divisor of the buffer, for instanced draws</param>
|
||||||
public void SetVertexBuffer(int index, ulong gpuVa, ulong size, int stride, int divisor)
|
public void SetVertexBuffer(int index, ulong gpuVa, ulong size, int stride, int divisor)
|
||||||
{
|
{
|
||||||
ulong address = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
var bufferCache = _channel.MemoryManager.GetBackingMemory(gpuVa).BufferCache;
|
||||||
|
ulong address = bufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
||||||
|
|
||||||
_vertexBuffers[index].Address = address;
|
ref VertexBuffer vb = ref _vertexBuffers[index];
|
||||||
_vertexBuffers[index].Size = size;
|
|
||||||
_vertexBuffers[index].Stride = stride;
|
vb.BufferCache = bufferCache;
|
||||||
_vertexBuffers[index].Divisor = divisor;
|
vb.Address = address;
|
||||||
|
vb.Size = size;
|
||||||
|
vb.Stride = stride;
|
||||||
|
vb.Divisor = divisor;
|
||||||
|
|
||||||
_vertexBuffersDirty = true;
|
_vertexBuffersDirty = true;
|
||||||
|
|
||||||
|
@ -209,9 +216,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <param name="size">Size in bytes of the transform feedback buffer</param>
|
/// <param name="size">Size in bytes of the transform feedback buffer</param>
|
||||||
public void SetTransformFeedbackBuffer(int index, ulong gpuVa, ulong size)
|
public void SetTransformFeedbackBuffer(int index, ulong gpuVa, ulong size)
|
||||||
{
|
{
|
||||||
ulong address = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
var physical = _channel.MemoryManager.GetBackingMemory(gpuVa);
|
||||||
|
ulong address = physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
||||||
|
|
||||||
_transformFeedbackBuffers[index] = new BufferBounds(address, size);
|
_transformFeedbackBuffers[index] = new BufferBounds(physical, address, size);
|
||||||
_transformFeedbackBuffersDirty = true;
|
_transformFeedbackBuffersDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -256,9 +264,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
gpuVa = BitUtils.AlignDown<ulong>(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment);
|
gpuVa = BitUtils.AlignDown<ulong>(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment);
|
||||||
|
|
||||||
ulong address = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
var physical = _channel.MemoryManager.GetBackingMemory(gpuVa);
|
||||||
|
ulong address = physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
||||||
|
|
||||||
_cpStorageBuffers.SetBounds(index, address, size, flags);
|
_cpStorageBuffers.SetBounds(index, physical, address, size, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -280,7 +289,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
gpuVa = BitUtils.AlignDown<ulong>(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment);
|
gpuVa = BitUtils.AlignDown<ulong>(gpuVa, (ulong)_context.Capabilities.StorageBufferOffsetAlignment);
|
||||||
|
|
||||||
ulong address = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
var physical = _channel.MemoryManager.GetBackingMemory(gpuVa);
|
||||||
|
ulong address = physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
||||||
|
|
||||||
if (buffers.Buffers[index].Address != address ||
|
if (buffers.Buffers[index].Address != address ||
|
||||||
buffers.Buffers[index].Size != size)
|
buffers.Buffers[index].Size != size)
|
||||||
|
@ -288,7 +298,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
_gpStorageBuffersDirty = true;
|
_gpStorageBuffersDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
buffers.SetBounds(index, address, size, flags);
|
buffers.SetBounds(index, physical, address, size, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -300,9 +310,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <param name="size">Size in bytes of the storage buffer</param>
|
/// <param name="size">Size in bytes of the storage buffer</param>
|
||||||
public void SetComputeUniformBuffer(int index, ulong gpuVa, ulong size)
|
public void SetComputeUniformBuffer(int index, ulong gpuVa, ulong size)
|
||||||
{
|
{
|
||||||
ulong address = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
var physical = _channel.MemoryManager.GetBackingMemory(gpuVa);
|
||||||
|
ulong address = physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
||||||
|
|
||||||
_cpUniformBuffers.SetBounds(index, address, size);
|
_cpUniformBuffers.SetBounds(index, physical, address, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -315,9 +326,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <param name="size">Size in bytes of the storage buffer</param>
|
/// <param name="size">Size in bytes of the storage buffer</param>
|
||||||
public void SetGraphicsUniformBuffer(int stage, int index, ulong gpuVa, ulong size)
|
public void SetGraphicsUniformBuffer(int stage, int index, ulong gpuVa, ulong size)
|
||||||
{
|
{
|
||||||
ulong address = _channel.MemoryManager.Physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
var physical = _channel.MemoryManager.GetBackingMemory(gpuVa);
|
||||||
|
ulong address = physical.BufferCache.TranslateAndCreateBuffer(_channel.MemoryManager, gpuVa, size);
|
||||||
|
|
||||||
_gpUniformBuffers[stage].SetBounds(index, address, size);
|
_gpUniformBuffers[stage].SetBounds(index, physical, address, size);
|
||||||
_gpUniformBuffersDirty = true;
|
_gpUniformBuffersDirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -413,9 +425,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="index">Index of the uniform buffer binding</param>
|
/// <param name="index">Index of the uniform buffer binding</param>
|
||||||
/// <returns>The uniform buffer address, or an undefined value if the buffer is not currently bound</returns>
|
/// <returns>The uniform buffer address, or an undefined value if the buffer is not currently bound</returns>
|
||||||
public ulong GetComputeUniformBufferAddress(int index)
|
public (PhysicalMemory, ulong) GetComputeUniformBufferAddress(int index)
|
||||||
{
|
{
|
||||||
return _cpUniformBuffers.Buffers[index].Address;
|
var buffer = _cpUniformBuffers.Buffers[index];
|
||||||
|
return (buffer.Physical, buffer.Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -424,9 +437,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <param name="stage">Index of the shader stage</param>
|
/// <param name="stage">Index of the shader stage</param>
|
||||||
/// <param name="index">Index of the uniform buffer binding</param>
|
/// <param name="index">Index of the uniform buffer binding</param>
|
||||||
/// <returns>The uniform buffer address, or an undefined value if the buffer is not currently bound</returns>
|
/// <returns>The uniform buffer address, or an undefined value if the buffer is not currently bound</returns>
|
||||||
public ulong GetGraphicsUniformBufferAddress(int stage, int index)
|
public (PhysicalMemory, ulong) GetGraphicsUniformBufferAddress(int stage, int index)
|
||||||
{
|
{
|
||||||
return _gpUniformBuffers[stage].Buffers[index].Address;
|
var buffer = _gpUniformBuffers[stage].Buffers[index];
|
||||||
|
return (buffer.Physical, buffer.Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -454,10 +468,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public void CommitComputeBindings()
|
public void CommitComputeBindings()
|
||||||
{
|
{
|
||||||
var bufferCache = _channel.MemoryManager.Physical.BufferCache;
|
BindBuffers(_cpStorageBuffers, isStorage: true);
|
||||||
|
BindBuffers(_cpUniformBuffers, isStorage: false);
|
||||||
BindBuffers(bufferCache, _cpStorageBuffers, isStorage: true);
|
|
||||||
BindBuffers(bufferCache, _cpUniformBuffers, isStorage: false);
|
|
||||||
|
|
||||||
CommitBufferTextureBindings();
|
CommitBufferTextureBindings();
|
||||||
|
|
||||||
|
@ -477,7 +489,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
foreach (var binding in _bufferTextures)
|
foreach (var binding in _bufferTextures)
|
||||||
{
|
{
|
||||||
var isStore = binding.BindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore);
|
var isStore = binding.BindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore);
|
||||||
var range = _channel.MemoryManager.Physical.BufferCache.GetBufferRange(binding.Address, binding.Size, isStore);
|
var range = binding.BufferCache.GetBufferRange(binding.Address, binding.Size, isStore);
|
||||||
binding.Texture.SetStorage(range);
|
binding.Texture.SetStorage(range);
|
||||||
|
|
||||||
// The texture must be rebound to use the new storage if it was updated.
|
// The texture must be rebound to use the new storage if it was updated.
|
||||||
|
@ -503,8 +515,6 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <param name="indexed">True if the index buffer is in use</param>
|
/// <param name="indexed">True if the index buffer is in use</param>
|
||||||
public void CommitGraphicsBindings(bool indexed)
|
public void CommitGraphicsBindings(bool indexed)
|
||||||
{
|
{
|
||||||
var bufferCache = _channel.MemoryManager.Physical.BufferCache;
|
|
||||||
|
|
||||||
if (indexed)
|
if (indexed)
|
||||||
{
|
{
|
||||||
if (_indexBufferDirty || _rebind)
|
if (_indexBufferDirty || _rebind)
|
||||||
|
@ -513,14 +523,14 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
if (_indexBuffer.Address != 0)
|
if (_indexBuffer.Address != 0)
|
||||||
{
|
{
|
||||||
BufferRange buffer = bufferCache.GetBufferRange(_indexBuffer.Address, _indexBuffer.Size);
|
BufferRange buffer = _indexBuffer.BufferCache.GetBufferRange(_indexBuffer.Address, _indexBuffer.Size);
|
||||||
|
|
||||||
_context.Renderer.Pipeline.SetIndexBuffer(buffer, _indexBuffer.Type);
|
_context.Renderer.Pipeline.SetIndexBuffer(buffer, _indexBuffer.Type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_indexBuffer.Address != 0)
|
else if (_indexBuffer.Address != 0)
|
||||||
{
|
{
|
||||||
bufferCache.SynchronizeBufferRange(_indexBuffer.Address, _indexBuffer.Size);
|
_indexBuffer.BufferCache.SynchronizeBufferRange(_indexBuffer.Address, _indexBuffer.Size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (_rebind)
|
else if (_rebind)
|
||||||
|
@ -545,7 +555,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
BufferRange buffer = bufferCache.GetBufferRange(vb.Address, vb.Size);
|
BufferRange buffer = vb.BufferCache.GetBufferRange(vb.Address, vb.Size);
|
||||||
|
|
||||||
vertexBuffers[index] = new VertexBufferDescriptor(buffer, vb.Stride, vb.Divisor);
|
vertexBuffers[index] = new VertexBufferDescriptor(buffer, vb.Stride, vb.Divisor);
|
||||||
}
|
}
|
||||||
|
@ -563,7 +573,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferCache.SynchronizeBufferRange(vb.Address, vb.Size);
|
vb.BufferCache.SynchronizeBufferRange(vb.Address, vb.Size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -585,7 +595,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
tfbs[index] = bufferCache.GetBufferRange(tfb.Address, tfb.Size, write: true);
|
tfbs[index] = tfb.BufferCache.GetBufferRange(tfb.Address, tfb.Size, write: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
_context.Renderer.Pipeline.SetTransformFeedbackBuffers(tfbs);
|
_context.Renderer.Pipeline.SetTransformFeedbackBuffers(tfbs);
|
||||||
|
@ -614,7 +624,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
|
|
||||||
_context.SupportBufferUpdater.SetTfeOffset(index, tfeOffset);
|
_context.SupportBufferUpdater.SetTfeOffset(index, tfeOffset);
|
||||||
|
|
||||||
buffers[index] = new BufferAssignment(index, bufferCache.GetBufferRange(address, size, write: true));
|
buffers[index] = new BufferAssignment(index, tfb.BufferCache.GetBufferRange(address, size, write: true));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -632,7 +642,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bufferCache.SynchronizeBufferRange(tfb.Address, tfb.Size);
|
tfb.BufferCache.SynchronizeBufferRange(tfb.Address, tfb.Size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -640,7 +650,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
_gpStorageBuffersDirty = false;
|
_gpStorageBuffersDirty = false;
|
||||||
|
|
||||||
BindBuffers(bufferCache, _gpStorageBuffers, isStorage: true);
|
BindBuffers(_gpStorageBuffers, isStorage: true);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -651,7 +661,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
_gpUniformBuffersDirty = false;
|
_gpUniformBuffersDirty = false;
|
||||||
|
|
||||||
BindBuffers(bufferCache, _gpUniformBuffers, isStorage: false);
|
BindBuffers(_gpUniformBuffers, isStorage: false);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -668,11 +678,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Bind respective buffer bindings on the host API.
|
/// Bind respective buffer bindings on the host API.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="bufferCache">Buffer cache holding the buffers for the specified ranges</param>
|
|
||||||
/// <param name="bindings">Buffer memory ranges to bind</param>
|
/// <param name="bindings">Buffer memory ranges to bind</param>
|
||||||
/// <param name="isStorage">True to bind as storage buffer, false to bind as uniform buffer</param>
|
/// <param name="isStorage">True to bind as storage buffer, false to bind as uniform buffer</param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void BindBuffers(BufferCache bufferCache, BuffersPerStage[] bindings, bool isStorage)
|
private void BindBuffers(BuffersPerStage[] bindings, bool isStorage)
|
||||||
{
|
{
|
||||||
int rangesCount = 0;
|
int rangesCount = 0;
|
||||||
|
|
||||||
|
@ -692,8 +701,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
var isWrite = bounds.Flags.HasFlag(BufferUsageFlags.Write);
|
var isWrite = bounds.Flags.HasFlag(BufferUsageFlags.Write);
|
||||||
var range = isStorage
|
var range = isStorage
|
||||||
? bufferCache.GetBufferRangeAligned(bounds.Address, bounds.Size, isWrite)
|
? bounds.BufferCache.GetBufferRangeAligned(bounds.Address, bounds.Size, isWrite)
|
||||||
: bufferCache.GetBufferRange(bounds.Address, bounds.Size);
|
: bounds.BufferCache.GetBufferRange(bounds.Address, bounds.Size);
|
||||||
|
|
||||||
ranges[rangesCount++] = new BufferAssignment(bindingInfo.Binding, range);
|
ranges[rangesCount++] = new BufferAssignment(bindingInfo.Binding, range);
|
||||||
}
|
}
|
||||||
|
@ -709,11 +718,10 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Bind respective buffer bindings on the host API.
|
/// Bind respective buffer bindings on the host API.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="bufferCache">Buffer cache holding the buffers for the specified ranges</param>
|
|
||||||
/// <param name="buffers">Buffer memory ranges to bind</param>
|
/// <param name="buffers">Buffer memory ranges to bind</param>
|
||||||
/// <param name="isStorage">True to bind as storage buffer, false to bind as uniform buffer</param>
|
/// <param name="isStorage">True to bind as storage buffer, false to bind as uniform buffer</param>
|
||||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
private void BindBuffers(BufferCache bufferCache, BuffersPerStage buffers, bool isStorage)
|
private void BindBuffers(BuffersPerStage buffers, bool isStorage)
|
||||||
{
|
{
|
||||||
int rangesCount = 0;
|
int rangesCount = 0;
|
||||||
|
|
||||||
|
@ -729,8 +737,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
var isWrite = bounds.Flags.HasFlag(BufferUsageFlags.Write);
|
var isWrite = bounds.Flags.HasFlag(BufferUsageFlags.Write);
|
||||||
var range = isStorage
|
var range = isStorage
|
||||||
? bufferCache.GetBufferRangeAligned(bounds.Address, bounds.Size, isWrite)
|
? bounds.BufferCache.GetBufferRangeAligned(bounds.Address, bounds.Size, isWrite)
|
||||||
: bufferCache.GetBufferRange(bounds.Address, bounds.Size);
|
: bounds.BufferCache.GetBufferRange(bounds.Address, bounds.Size);
|
||||||
|
|
||||||
ranges[rangesCount++] = new BufferAssignment(bindingInfo.Binding, range);
|
ranges[rangesCount++] = new BufferAssignment(bindingInfo.Binding, range);
|
||||||
}
|
}
|
||||||
|
@ -783,7 +791,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
_channel.MemoryManager.Physical.BufferCache.SynchronizeBufferRange(bounds.Address, bounds.Size);
|
bounds.BufferCache.SynchronizeBufferRange(bounds.Address, bounds.Size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -793,6 +801,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="stage">Shader stage accessing the texture</param>
|
/// <param name="stage">Shader stage accessing the texture</param>
|
||||||
/// <param name="texture">Buffer texture</param>
|
/// <param name="texture">Buffer texture</param>
|
||||||
|
/// <param name="bufferCache">Buffer cache that owns the buffer texture</param>
|
||||||
/// <param name="address">Address of the buffer in memory</param>
|
/// <param name="address">Address of the buffer in memory</param>
|
||||||
/// <param name="size">Size of the buffer in bytes</param>
|
/// <param name="size">Size of the buffer in bytes</param>
|
||||||
/// <param name="bindingInfo">Binding info for the buffer texture</param>
|
/// <param name="bindingInfo">Binding info for the buffer texture</param>
|
||||||
|
@ -801,15 +810,16 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
public void SetBufferTextureStorage(
|
public void SetBufferTextureStorage(
|
||||||
ShaderStage stage,
|
ShaderStage stage,
|
||||||
ITexture texture,
|
ITexture texture,
|
||||||
|
BufferCache bufferCache,
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
TextureBindingInfo bindingInfo,
|
TextureBindingInfo bindingInfo,
|
||||||
Format format,
|
Format format,
|
||||||
bool isImage)
|
bool isImage)
|
||||||
{
|
{
|
||||||
_channel.MemoryManager.Physical.BufferCache.CreateBuffer(address, size);
|
bufferCache.CreateBuffer(address, size);
|
||||||
|
|
||||||
_bufferTextures.Add(new BufferTextureBinding(stage, texture, address, size, bindingInfo, format, isImage));
|
_bufferTextures.Add(new BufferTextureBinding(stage, texture, bufferCache, address, size, bindingInfo, format, isImage));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -19,6 +19,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ITexture Texture { get; }
|
public ITexture Texture { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Buffer cache that owns the buffer.
|
||||||
|
/// </summary>
|
||||||
|
public BufferCache BufferCache { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The base address of the buffer binding.
|
/// The base address of the buffer binding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -49,6 +54,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="stage">Shader stage accessing the texture</param>
|
/// <param name="stage">Shader stage accessing the texture</param>
|
||||||
/// <param name="texture">Buffer texture</param>
|
/// <param name="texture">Buffer texture</param>
|
||||||
|
/// <param name="bufferCache">Buffer cache that owns the buffer</param>
|
||||||
/// <param name="address">Base address</param>
|
/// <param name="address">Base address</param>
|
||||||
/// <param name="size">Size in bytes</param>
|
/// <param name="size">Size in bytes</param>
|
||||||
/// <param name="bindingInfo">Binding info</param>
|
/// <param name="bindingInfo">Binding info</param>
|
||||||
|
@ -57,6 +63,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
public BufferTextureBinding(
|
public BufferTextureBinding(
|
||||||
ShaderStage stage,
|
ShaderStage stage,
|
||||||
ITexture texture,
|
ITexture texture,
|
||||||
|
BufferCache bufferCache,
|
||||||
ulong address,
|
ulong address,
|
||||||
ulong size,
|
ulong size,
|
||||||
TextureBindingInfo bindingInfo,
|
TextureBindingInfo bindingInfo,
|
||||||
|
@ -65,6 +72,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
{
|
{
|
||||||
Stage = stage;
|
Stage = stage;
|
||||||
Texture = texture;
|
Texture = texture;
|
||||||
|
BufferCache = bufferCache;
|
||||||
Address = address;
|
Address = address;
|
||||||
Size = size;
|
Size = size;
|
||||||
BindingInfo = bindingInfo;
|
BindingInfo = bindingInfo;
|
||||||
|
|
|
@ -7,6 +7,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
struct IndexBuffer
|
struct IndexBuffer
|
||||||
{
|
{
|
||||||
|
public BufferCache BufferCache;
|
||||||
public ulong Address;
|
public ulong Address;
|
||||||
public ulong Size;
|
public ulong Size;
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Physical memory where the virtual memory is mapped into.
|
/// Physical memory where the virtual memory is mapped into.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal PhysicalMemory Physical { get; }
|
private PhysicalMemory Physical { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Cache of GPU counters.
|
/// Cache of GPU counters.
|
||||||
|
@ -58,6 +58,35 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
MemoryUnmapped += CounterCache.MemoryUnmappedHandler;
|
MemoryUnmapped += CounterCache.MemoryUnmappedHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attaches the memory manager to a new GPU channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rebind">Action to be performed when the buffer cache changes</param>
|
||||||
|
internal void AttachToChannel(Action rebind)
|
||||||
|
{
|
||||||
|
Physical.IncrementReferenceCount();
|
||||||
|
Physical.BufferCache.NotifyBuffersModified += rebind;
|
||||||
|
Physical.BufferCache.QueuePrune();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Attaches the memory manager to a new GPU channel.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rebind">Action that was performed when the buffer cache changed</param>
|
||||||
|
internal void DetachFromChannel(Action rebind)
|
||||||
|
{
|
||||||
|
Physical.BufferCache.NotifyBuffersModified -= rebind;
|
||||||
|
Physical.DecrementReferenceCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Queues a prune of invalid entries on the buffer cache.
|
||||||
|
/// </summary>
|
||||||
|
internal void QueuePrune()
|
||||||
|
{
|
||||||
|
Physical.BufferCache.QueuePrune();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads data from GPU mapped memory.
|
/// Reads data from GPU mapped memory.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -563,6 +592,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal PhysicalMemory GetBackingMemory(ulong va)
|
||||||
|
{
|
||||||
|
return Physical;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Validates a GPU virtual address.
|
/// Validates a GPU virtual address.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -756,7 +790,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// <returns>Physical address</returns>
|
/// <returns>Physical address</returns>
|
||||||
private static ulong UnpackPaFromPte(ulong pte)
|
private static ulong UnpackPaFromPte(ulong pte)
|
||||||
{
|
{
|
||||||
return pte & 0xffffffffffffffUL;
|
return pte & 0xffffffffffffUL;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
||||||
/// </summary>
|
/// </summary>
|
||||||
struct VertexBuffer
|
struct VertexBuffer
|
||||||
{
|
{
|
||||||
|
public BufferCache BufferCache;
|
||||||
public ulong Address;
|
public ulong Address;
|
||||||
public ulong Size;
|
public ulong Size;
|
||||||
public int Stride;
|
public int Stride;
|
||||||
|
|
|
@ -55,11 +55,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public uint ConstantBuffer1Read(int offset)
|
public uint ConstantBuffer1Read(int offset)
|
||||||
{
|
{
|
||||||
ulong baseAddress = _compute
|
(var physical, ulong baseAddress) = _compute
|
||||||
? _channel.BufferManager.GetComputeUniformBufferAddress(1)
|
? _channel.BufferManager.GetComputeUniformBufferAddress(1)
|
||||||
: _channel.BufferManager.GetGraphicsUniformBufferAddress(_stageIndex, 1);
|
: _channel.BufferManager.GetGraphicsUniformBufferAddress(_stageIndex, 1);
|
||||||
|
|
||||||
return _channel.MemoryManager.Physical.Read<uint>(baseAddress + (ulong)offset);
|
return physical.Read<uint>(baseAddress + (ulong)offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
|
|
|
@ -724,14 +724,14 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
byte[] codeB,
|
byte[] codeB,
|
||||||
bool asCompute)
|
bool asCompute)
|
||||||
{
|
{
|
||||||
ulong cb1DataAddress = channel.BufferManager.GetGraphicsUniformBufferAddress(0, 1);
|
(var physical, ulong cb1DataAddress) = channel.BufferManager.GetGraphicsUniformBufferAddress(0, 1);
|
||||||
|
|
||||||
var memoryManager = channel.MemoryManager;
|
var memoryManager = channel.MemoryManager;
|
||||||
|
|
||||||
codeA ??= memoryManager.GetSpan(vertexA.Address, vertexA.Size).ToArray();
|
codeA ??= memoryManager.GetSpan(vertexA.Address, vertexA.Size).ToArray();
|
||||||
codeB ??= memoryManager.GetSpan(currentStage.Address, currentStage.Size).ToArray();
|
codeB ??= memoryManager.GetSpan(currentStage.Address, currentStage.Size).ToArray();
|
||||||
byte[] cb1DataA = memoryManager.Physical.GetSpan(cb1DataAddress, vertexA.Cb1DataSize).ToArray();
|
byte[] cb1DataA = physical.GetSpan(cb1DataAddress, vertexA.Cb1DataSize).ToArray();
|
||||||
byte[] cb1DataB = memoryManager.Physical.GetSpan(cb1DataAddress, currentStage.Cb1DataSize).ToArray();
|
byte[] cb1DataB = physical.GetSpan(cb1DataAddress, currentStage.Cb1DataSize).ToArray();
|
||||||
|
|
||||||
ShaderDumpPaths pathsA = default;
|
ShaderDumpPaths pathsA = default;
|
||||||
ShaderDumpPaths pathsB = default;
|
ShaderDumpPaths pathsB = default;
|
||||||
|
@ -766,11 +766,11 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
{
|
{
|
||||||
var memoryManager = channel.MemoryManager;
|
var memoryManager = channel.MemoryManager;
|
||||||
|
|
||||||
ulong cb1DataAddress = context.Stage == ShaderStage.Compute
|
(var physical, ulong cb1DataAddress) = context.Stage == ShaderStage.Compute
|
||||||
? channel.BufferManager.GetComputeUniformBufferAddress(1)
|
? channel.BufferManager.GetComputeUniformBufferAddress(1)
|
||||||
: channel.BufferManager.GetGraphicsUniformBufferAddress(StageToStageIndex(context.Stage), 1);
|
: channel.BufferManager.GetGraphicsUniformBufferAddress(StageToStageIndex(context.Stage), 1);
|
||||||
|
|
||||||
byte[] cb1Data = memoryManager.Physical.GetSpan(cb1DataAddress, context.Cb1DataSize).ToArray();
|
byte[] cb1Data = physical.GetSpan(cb1DataAddress, context.Cb1DataSize).ToArray();
|
||||||
code ??= memoryManager.GetSpan(context.Address, context.Size).ToArray();
|
code ??= memoryManager.GetSpan(context.Address, context.Size).ToArray();
|
||||||
|
|
||||||
ShaderDumpPaths paths = dumper?.Dump(code, context.Stage == ShaderStage.Compute) ?? default;
|
ShaderDumpPaths paths = dumper?.Dump(code, context.Stage == ShaderStage.Compute) ?? default;
|
||||||
|
|
|
@ -611,7 +611,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
{
|
{
|
||||||
ref BufferBounds bounds = ref channel.BufferManager.GetUniformBufferBounds(isCompute, stageIndex, textureBufferIndex);
|
ref BufferBounds bounds = ref channel.BufferManager.GetUniformBufferBounds(isCompute, stageIndex, textureBufferIndex);
|
||||||
|
|
||||||
cachedTextureBuffer = MemoryMarshal.Cast<byte, int>(channel.MemoryManager.Physical.GetSpan(bounds.Address, (int)bounds.Size));
|
cachedTextureBuffer = MemoryMarshal.Cast<byte, int>(bounds.Physical.GetSpan(bounds.Address, (int)bounds.Size));
|
||||||
cachedTextureBufferIndex = textureBufferIndex;
|
cachedTextureBufferIndex = textureBufferIndex;
|
||||||
|
|
||||||
if (samplerBufferIndex == textureBufferIndex)
|
if (samplerBufferIndex == textureBufferIndex)
|
||||||
|
@ -625,7 +625,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
|
||||||
{
|
{
|
||||||
ref BufferBounds bounds = ref channel.BufferManager.GetUniformBufferBounds(isCompute, stageIndex, samplerBufferIndex);
|
ref BufferBounds bounds = ref channel.BufferManager.GetUniformBufferBounds(isCompute, stageIndex, samplerBufferIndex);
|
||||||
|
|
||||||
cachedSamplerBuffer = MemoryMarshal.Cast<byte, int>(channel.MemoryManager.Physical.GetSpan(bounds.Address, (int)bounds.Size));
|
cachedSamplerBuffer = MemoryMarshal.Cast<byte, int>(bounds.Physical.GetSpan(bounds.Address, (int)bounds.Size));
|
||||||
cachedSamplerBufferIndex = samplerBufferIndex;
|
cachedSamplerBufferIndex = samplerBufferIndex;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue