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
This commit is contained in:
parent
12a7a2ead8
commit
a10b2c5ff2
24 changed files with 1745 additions and 1456 deletions
|
@ -30,12 +30,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
/// <summary>
|
||||
/// GPU buffer manager.
|
||||
/// </summary>
|
||||
public BufferManager BufferManager { get; }
|
||||
public BufferCache BufferCache { get; }
|
||||
|
||||
/// <summary>
|
||||
/// GPU texture manager.
|
||||
/// </summary>
|
||||
public TextureManager TextureManager { get; }
|
||||
public TextureCache TextureCache { get; }
|
||||
|
||||
private bool _isAnyVbInstanced;
|
||||
private bool _vsUsesInstanceId;
|
||||
|
@ -57,12 +57,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
|
||||
_currentProgramInfo = new ShaderProgramInfo[Constants.ShaderStages];
|
||||
|
||||
BufferManager = new BufferManager(context);
|
||||
TextureManager = new TextureManager(context);
|
||||
BufferCache = new BufferCache(context);
|
||||
TextureCache = new TextureCache(context);
|
||||
|
||||
context.MemoryManager.MemoryUnmapped += _counterCache.MemoryUnmappedHandler;
|
||||
context.MemoryManager.MemoryUnmapped += TextureManager.MemoryUnmappedHandler;
|
||||
context.MemoryManager.MemoryUnmapped += BufferManager.MemoryUnmappedHandler;
|
||||
context.MemoryManager.MemoryUnmapped += TextureCache.MemoryUnmappedHandler;
|
||||
context.MemoryManager.MemoryUnmapped += BufferCache.MemoryUnmappedHandler;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -280,7 +280,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
UpdateLogicOpState(state);
|
||||
}
|
||||
|
||||
CommitBindings();
|
||||
CommitBindings(state);
|
||||
|
||||
if (tfEnable && !_prevTfEnable)
|
||||
{
|
||||
|
@ -303,18 +303,20 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
/// Ensures that the bindings are visible to the host GPU.
|
||||
/// Note: this actually performs the binding using the host graphics API.
|
||||
/// </summary>
|
||||
private void CommitBindings()
|
||||
/// <param name="state">Current GPU state</param>
|
||||
private void CommitBindings(GpuState state)
|
||||
{
|
||||
UpdateStorageBuffers();
|
||||
UpdateStorageBuffers(state);
|
||||
|
||||
TextureManager.CommitGraphicsBindings();
|
||||
BufferManager.CommitGraphicsBindings();
|
||||
state.Channel.TextureManager.CommitGraphicsBindings();
|
||||
state.Channel.BufferManager.CommitGraphicsBindings();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates storage buffer bindings.
|
||||
/// </summary>
|
||||
private void UpdateStorageBuffers()
|
||||
/// <param name="state">Current GPU state</param>
|
||||
private void UpdateStorageBuffers(GpuState state)
|
||||
{
|
||||
for (int stage = 0; stage < _currentProgramInfo.Length; stage++)
|
||||
{
|
||||
|
@ -329,7 +331,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
{
|
||||
BufferDescriptor sb = info.SBuffers[index];
|
||||
|
||||
ulong sbDescAddress = BufferManager.GetGraphicsUniformBufferAddress(stage, 0);
|
||||
ulong sbDescAddress = state.Channel.BufferManager.GetGraphicsUniformBufferAddress(stage, 0);
|
||||
|
||||
int sbDescOffset = 0x110 + stage * 0x100 + sb.Slot * 0x10;
|
||||
|
||||
|
@ -337,7 +339,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
|
||||
SbDescriptor sbDescriptor = _context.PhysicalMemory.Read<SbDescriptor>(sbDescAddress);
|
||||
|
||||
BufferManager.SetGraphicsStorageBuffer(stage, sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size, sb.Flags);
|
||||
state.Channel.BufferManager.SetGraphicsStorageBuffer(stage, sb.Slot, sbDescriptor.PackAddress(), (uint)sbDescriptor.Size, sb.Flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -372,14 +374,14 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
|
||||
if (index >= count || !IsRtEnabled(colorState))
|
||||
{
|
||||
changedScale |= TextureManager.SetRenderTargetColor(index, null);
|
||||
changedScale |= state.Channel.TextureManager.SetRenderTargetColor(index, null);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
Texture color = TextureManager.FindOrCreateTexture(colorState, samplesInX, samplesInY, sizeHint);
|
||||
Texture color = TextureCache.FindOrCreateTexture(colorState, samplesInX, samplesInY, sizeHint);
|
||||
|
||||
changedScale |= TextureManager.SetRenderTargetColor(index, color);
|
||||
changedScale |= state.Channel.TextureManager.SetRenderTargetColor(index, color);
|
||||
}
|
||||
|
||||
bool dsEnable = state.Get<Boolean32>(MethodOffset.RtDepthStencilEnable);
|
||||
|
@ -391,15 +393,15 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
var dsState = state.Get<RtDepthStencilState>(MethodOffset.RtDepthStencilState);
|
||||
var dsSize = state.Get<Size3D>(MethodOffset.RtDepthStencilSize);
|
||||
|
||||
depthStencil = TextureManager.FindOrCreateTexture(dsState, dsSize, samplesInX, samplesInY, sizeHint);
|
||||
depthStencil = TextureCache.FindOrCreateTexture(dsState, dsSize, samplesInX, samplesInY, sizeHint);
|
||||
}
|
||||
|
||||
changedScale |= TextureManager.SetRenderTargetDepthStencil(depthStencil);
|
||||
changedScale |= state.Channel.TextureManager.SetRenderTargetDepthStencil(depthStencil);
|
||||
|
||||
if (changedScale)
|
||||
{
|
||||
TextureManager.UpdateRenderTargetScale(singleUse);
|
||||
_context.Renderer.Pipeline.SetRenderTargetScale(TextureManager.RenderTargetScale);
|
||||
state.Channel.TextureManager.UpdateRenderTargetScale(singleUse);
|
||||
_context.Renderer.Pipeline.SetRenderTargetScale(state.Channel.TextureManager.RenderTargetScale);
|
||||
|
||||
UpdateViewportTransform(state);
|
||||
UpdateScissorState(state);
|
||||
|
@ -436,7 +438,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
int width = scissor.X2 - x;
|
||||
int height = scissor.Y2 - y;
|
||||
|
||||
float scale = TextureManager.RenderTargetScale;
|
||||
float scale = state.Channel.TextureManager.RenderTargetScale;
|
||||
if (scale != 1f)
|
||||
{
|
||||
x = (int)(x * scale);
|
||||
|
@ -545,7 +547,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
float width = scaleX * 2;
|
||||
float height = scaleY * 2;
|
||||
|
||||
float scale = TextureManager.RenderTargetScale;
|
||||
float scale = state.Channel.TextureManager.RenderTargetScale;
|
||||
if (scale != 1f)
|
||||
{
|
||||
x *= scale;
|
||||
|
@ -670,7 +672,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
? texturePool.MaximumId
|
||||
: samplerPool.MaximumId;
|
||||
|
||||
TextureManager.SetGraphicsSamplerPool(samplerPool.Address.Pack(), maximumId, samplerIndex);
|
||||
state.Channel.TextureManager.SetGraphicsSamplerPool(samplerPool.Address.Pack(), maximumId, samplerIndex);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -681,9 +683,8 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
{
|
||||
var texturePool = state.Get<PoolState>(MethodOffset.TexturePoolState);
|
||||
|
||||
TextureManager.SetGraphicsTexturePool(texturePool.Address.Pack(), texturePool.MaximumId);
|
||||
|
||||
TextureManager.SetGraphicsTextureBufferIndex(state.Get<int>(MethodOffset.TextureBufferIndex));
|
||||
state.Channel.TextureManager.SetGraphicsTexturePool(texturePool.Address.Pack(), texturePool.MaximumId);
|
||||
state.Channel.TextureManager.SetGraphicsTextureBufferIndex(state.Get<int>(MethodOffset.TextureBufferIndex));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -771,7 +772,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
case IndexType.UInt: size *= 4; break;
|
||||
}
|
||||
|
||||
BufferManager.SetIndexBuffer(gpuVa, size, indexBuffer.Type);
|
||||
state.Channel.BufferManager.SetIndexBuffer(gpuVa, size, indexBuffer.Type);
|
||||
|
||||
// The index buffer affects the vertex buffer size calculation, we
|
||||
// need to ensure that they are updated.
|
||||
|
@ -792,7 +793,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
|
||||
if (!vertexBuffer.UnpackEnable())
|
||||
{
|
||||
BufferManager.SetVertexBuffer(index, 0, 0, 0, 0);
|
||||
state.Channel.BufferManager.SetVertexBuffer(index, 0, 0, 0, 0);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
@ -828,7 +829,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
size = (ulong)((firstInstance + drawState.First + drawState.Count) * stride);
|
||||
}
|
||||
|
||||
BufferManager.SetVertexBuffer(index, address, size, stride, divisor);
|
||||
state.Channel.BufferManager.SetVertexBuffer(index, address, size, stride, divisor);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1017,10 +1018,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
|
||||
if (info == null)
|
||||
{
|
||||
TextureManager.SetGraphicsTextures(stage, Array.Empty<TextureBindingInfo>());
|
||||
TextureManager.SetGraphicsImages(stage, Array.Empty<TextureBindingInfo>());
|
||||
BufferManager.SetGraphicsStorageBufferBindings(stage, null);
|
||||
BufferManager.SetGraphicsUniformBufferBindings(stage, null);
|
||||
state.Channel.TextureManager.SetGraphicsTextures(stage, Array.Empty<TextureBindingInfo>());
|
||||
state.Channel.TextureManager.SetGraphicsImages(stage, Array.Empty<TextureBindingInfo>());
|
||||
state.Channel.BufferManager.SetGraphicsStorageBufferBindings(stage, null);
|
||||
state.Channel.BufferManager.SetGraphicsUniformBufferBindings(stage, null);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -1040,7 +1041,7 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
descriptor.Flags);
|
||||
}
|
||||
|
||||
TextureManager.SetGraphicsTextures(stage, textureBindings);
|
||||
state.Channel.TextureManager.SetGraphicsTextures(stage, textureBindings);
|
||||
|
||||
var imageBindings = new TextureBindingInfo[info.Images.Count];
|
||||
|
||||
|
@ -1060,10 +1061,10 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
descriptor.Flags);
|
||||
}
|
||||
|
||||
TextureManager.SetGraphicsImages(stage, imageBindings);
|
||||
state.Channel.TextureManager.SetGraphicsImages(stage, imageBindings);
|
||||
|
||||
BufferManager.SetGraphicsStorageBufferBindings(stage, info.SBuffers);
|
||||
BufferManager.SetGraphicsUniformBufferBindings(stage, info.CBuffers);
|
||||
state.Channel.BufferManager.SetGraphicsStorageBufferBindings(stage, info.SBuffers);
|
||||
state.Channel.BufferManager.SetGraphicsUniformBufferBindings(stage, info.CBuffers);
|
||||
|
||||
if (info.SBuffers.Count != 0)
|
||||
{
|
||||
|
@ -1076,8 +1077,8 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
}
|
||||
}
|
||||
|
||||
BufferManager.SetGraphicsStorageBufferBindingsCount(storageBufferBindingsCount);
|
||||
BufferManager.SetGraphicsUniformBufferBindingsCount(uniformBufferBindingsCount);
|
||||
state.Channel.BufferManager.SetGraphicsStorageBufferBindingsCount(storageBufferBindingsCount);
|
||||
state.Channel.BufferManager.SetGraphicsUniformBufferBindingsCount(uniformBufferBindingsCount);
|
||||
|
||||
_context.Renderer.Pipeline.SetProgram(gs.HostProgram);
|
||||
}
|
||||
|
@ -1094,12 +1095,12 @@ namespace Ryujinx.Graphics.Gpu.Engine
|
|||
|
||||
if (!tfb.Enable)
|
||||
{
|
||||
BufferManager.SetTransformFeedbackBuffer(index, 0, 0);
|
||||
state.Channel.BufferManager.SetTransformFeedbackBuffer(index, 0, 0);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
BufferManager.SetTransformFeedbackBuffer(index, tfb.Address.Pack(), (uint)tfb.Size);
|
||||
state.Channel.BufferManager.SetTransformFeedbackBuffer(index, tfb.Address.Pack(), (uint)tfb.Size);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue