Use SupportBufferUpdater, add single layer flush

This commit is contained in:
riperiperi 2022-01-10 22:50:31 +00:00
parent db5ac3488a
commit d14dbb0cff
5 changed files with 64 additions and 36 deletions

View file

@ -320,7 +320,7 @@ namespace Ryujinx.Graphics.Vulkan
{ {
Offset = 0, Offset = 0,
Range = (ulong)SupportBuffer.RequiredSize, Range = (ulong)SupportBuffer.RequiredSize,
Buffer = _pipeline.RenderScaleBuffer.GetBuffer().Get(cbs, 0, SupportBuffer.RequiredSize).Value Buffer = _gd.BufferManager.GetBuffer(cbs.CommandBuffer, _pipeline.SupportBufferUpdater.Handle, false).Get(cbs, 0, SupportBuffer.RequiredSize).Value
}; };
dsc.UpdateBuffers(0, 0, uniformBuffer, DescriptorType.UniformBuffer); dsc.UpdateBuffers(0, 0, uniformBuffer, DescriptorType.UniformBuffer);

View file

@ -65,6 +65,22 @@ namespace Ryujinx.Graphics.Vulkan
return flushStorage.GetDataStorage(0, size); return flushStorage.GetDataStorage(0, size);
} }
public Span<byte> GetTextureData(CommandBufferPool cbp, TextureView view, int size, int layer, int level)
{
var flushStorage = ResizeIfNeeded(size);
using (var cbs = cbp.Rent())
{
var buffer = flushStorage.GetBuffer(cbs.CommandBuffer).Get(cbs).Value;
var image = view.GetImage().Get(cbs).Value;
view.CopyFromOrToBuffer(cbs.CommandBuffer, buffer, image, size, true, layer, level, 1, 1, singleSlice: true);
}
flushStorage.WaitForFences();
return flushStorage.GetDataStorage(0, size);
}
public void Dispose() public void Dispose()
{ {
_flushStorage.Dispose(); _flushStorage.Dispose();

View file

@ -41,16 +41,8 @@ namespace Ryujinx.Graphics.Vulkan
private ShaderCollection _program; private ShaderCollection _program;
private struct Vector4<T>
{
public T X;
public T Y;
public T Z;
public T W;
}
private Vector4<float>[] _renderScale = new Vector4<float>[65]; private Vector4<float>[] _renderScale = new Vector4<float>[65];
private Vector4<float>[] _cpRenderScale = new Vector4<float>[64]; private int _fragmentScaleCount;
protected FramebufferParams FramebufferParams; protected FramebufferParams FramebufferParams;
private Auto<DisposableFramebuffer> _framebuffer; private Auto<DisposableFramebuffer> _framebuffer;
@ -63,7 +55,7 @@ namespace Ryujinx.Graphics.Vulkan
private readonly BufferState[] _transformFeedbackBuffers; private readonly BufferState[] _transformFeedbackBuffers;
private readonly BufferState[] _vertexBuffers; private readonly BufferState[] _vertexBuffers;
public BufferHolder RenderScaleBuffer { get; } public SupportBufferUpdater SupportBufferUpdater;
private bool _needsIndexBufferRebind; private bool _needsIndexBufferRebind;
private bool _needsTransformFeedbackBuffersRebind; private bool _needsTransformFeedbackBuffersRebind;
@ -100,9 +92,8 @@ namespace Ryujinx.Graphics.Vulkan
var defaultScale = new Vector4<float> { X = 1f, Y = 0f, Z = 0f, W = 0f }; var defaultScale = new Vector4<float> { X = 1f, Y = 0f, Z = 0f, W = 0f };
new Span<Vector4<float>>(_renderScale).Fill(defaultScale); new Span<Vector4<float>>(_renderScale).Fill(defaultScale);
RenderScaleBuffer = gd.BufferManager.Create(gd, SupportBuffer.RequiredSize); SupportBufferUpdater = new SupportBufferUpdater(gd);
SupportBufferUpdater.UpdateRenderScale(_renderScale, 0, SupportBuffer.RenderScaleMaxCount);
SetSupportBufferDataCpu<Vector4<float>>(SupportBuffer.GraphicsRenderScaleOffset, _renderScale, SupportBuffer.RenderScaleMaxCount);
_newState.Initialize(); _newState.Initialize();
_newState.LineWidth = 1f; _newState.LineWidth = 1f;
@ -295,6 +286,8 @@ namespace Ryujinx.Graphics.Vulkan
{ {
if (texture is TextureView srcTexture) if (texture is TextureView srcTexture)
{ {
SupportBufferUpdater.Commit();
var oldCullMode = _newState.CullMode; var oldCullMode = _newState.CullMode;
var oldStencilTestEnable = _newState.StencilTestEnable; var oldStencilTestEnable = _newState.StencilTestEnable;
var oldDepthTestEnable = _newState.DepthTestEnable; var oldDepthTestEnable = _newState.DepthTestEnable;
@ -622,7 +615,7 @@ namespace Ryujinx.Graphics.Vulkan
public void SetRenderTargetScale(float scale) public void SetRenderTargetScale(float scale)
{ {
_renderScale[0].X = scale; _renderScale[0].X = scale;
SetSupportBufferData<Vector4<float>>(SupportBuffer.GraphicsRenderScaleOffset, _renderScale, 1); // Just the first element. SupportBufferUpdater.UpdateRenderScale(_renderScale, 0, 1); // Just the first element.
} }
public void SetScissors(ReadOnlySpan<Rectangle<int>> regions) public void SetScissors(ReadOnlySpan<Rectangle<int>> regions)
@ -875,11 +868,11 @@ namespace Ryujinx.Graphics.Vulkan
TextureBarrier(); TextureBarrier();
} }
public void UpdateRenderScale(ReadOnlySpan<float> scales, int textureCount, int imageCount) public void UpdateRenderScale(ReadOnlySpan<float> scales, int totalCount, int fragmentCount)
{ {
bool changed = false; bool changed = false;
for (int index = 0; index < textureCount + imageCount; index++) for (int index = 0; index < totalCount; index++)
{ {
if (_renderScale[1 + index].X != scales[index]) if (_renderScale[1 + index].X != scales[index])
{ {
@ -888,22 +881,19 @@ namespace Ryujinx.Graphics.Vulkan
} }
} }
// Only update fragment count if there are scales after it for the vertex stage.
if (fragmentCount != totalCount && fragmentCount != _fragmentScaleCount)
{
_fragmentScaleCount = fragmentCount;
SupportBufferUpdater.UpdateFragmentRenderScaleCount(_fragmentScaleCount);
}
if (changed) if (changed)
{ {
SetSupportBufferData<Vector4<float>>(SupportBuffer.GraphicsRenderScaleOffset, _renderScale, 1 + textureCount + imageCount); SupportBufferUpdater.UpdateRenderScale(_renderScale, 0, 1 + totalCount);
} }
} }
private void SetSupportBufferData<T>(int offset, ReadOnlySpan<T> data, int count) where T : unmanaged
{
RenderScaleBuffer.SetDataInline(Cbs, EndRenderPass, offset, MemoryMarshal.Cast<T, byte>(data.Slice(0, count)));
}
private void SetSupportBufferDataCpu<T>(int offset, ReadOnlySpan<T> data, int count) where T : unmanaged
{
RenderScaleBuffer.SetDataUnchecked(offset, MemoryMarshal.Cast<T, byte>(data.Slice(0, count)));
}
protected void SignalCommandBufferChange() protected void SignalCommandBufferChange()
{ {
_needsIndexBufferRebind = true; _needsIndexBufferRebind = true;
@ -1052,6 +1042,9 @@ namespace Ryujinx.Graphics.Vulkan
// Take the opportunity to process any pending work requested by other threads. // Take the opportunity to process any pending work requested by other threads.
_dynamicState.ReplayIfDirty(Gd.Api, CommandBuffer); _dynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
// Commit changes to the support buffer before drawing.
SupportBufferUpdater.Commit();
if (_stateDirty || Pbp != pbp) if (_stateDirty || Pbp != pbp)
{ {
CreatePipeline(pbp); CreatePipeline(pbp);
@ -1203,7 +1196,7 @@ namespace Ryujinx.Graphics.Vulkan
Gd.Api.DestroyPipelineCache(Device, _pipelineCache, null); Gd.Api.DestroyPipelineCache(Device, _pipelineCache, null);
} }
RenderScaleBuffer.Dispose(); SupportBufferUpdater.Dispose();
} }
} }

View file

@ -27,7 +27,7 @@ namespace Ryujinx.Graphics.Vulkan
Binding = 0, Binding = 0,
DescriptorType = DescriptorType.UniformBuffer, DescriptorType = DescriptorType.UniformBuffer,
DescriptorCount = 1, DescriptorCount = 1,
StageFlags = ShaderStageFlags.ShaderStageFragmentBit | ShaderStageFlags.ShaderStageComputeBit StageFlags = ShaderStageFlags.ShaderStageVertexBit | ShaderStageFlags.ShaderStageFragmentBit | ShaderStageFlags.ShaderStageComputeBit
}; };
int iter = 0; int iter = 0;

View file

@ -679,7 +679,18 @@ namespace Ryujinx.Graphics.Vulkan
public ReadOnlySpan<byte> GetData(int layer, int level) public ReadOnlySpan<byte> GetData(int layer, int level)
{ {
throw new NotImplementedException(); BackgroundResource resources = _gd.BackgroundResources.Get();
if (_gd.CommandBufferPool.OwnedByCurrentThread)
{
_gd.FlushAllCommands();
return GetData(_gd.CommandBufferPool, resources.GetFlushBuffer(), layer, level);
}
else
{
return GetData(resources.GetPool(), resources.GetFlushBuffer(), layer, level);
}
} }
private ReadOnlySpan<byte> GetData(CommandBufferPool cbp, PersistentFlushBuffer flushBuffer) private ReadOnlySpan<byte> GetData(CommandBufferPool cbp, PersistentFlushBuffer flushBuffer)
@ -697,6 +708,14 @@ namespace Ryujinx.Graphics.Vulkan
return GetDataFromBuffer(result, size, result); return GetDataFromBuffer(result, size, result);
} }
private ReadOnlySpan<byte> GetData(CommandBufferPool cbp, PersistentFlushBuffer flushBuffer, int layer, int level)
{
int size = GetBufferDataLength(Info.GetMipSize(level));
Span<byte> result = flushBuffer.GetTextureData(cbp, this, size, layer, level);
return GetDataFromBuffer(result, size, result);
}
public void SetData(ReadOnlySpan<byte> data) public void SetData(ReadOnlySpan<byte> data)
{ {
SetData(data, 0, 0, Info.GetLayers(), Info.Levels, singleSlice: false); SetData(data, 0, 0, Info.GetLayers(), Info.Levels, singleSlice: false);
@ -799,9 +818,9 @@ namespace Ryujinx.Graphics.Vulkan
bool singleSlice) bool singleSlice)
{ {
bool is3D = Info.Target == Target.Texture3D; bool is3D = Info.Target == Target.Texture3D;
int width = Info.Width; int width = Math.Max(1, Info.Width >> dstLevel);
int height = Info.Height; int height = Math.Max(1, Info.Height >> dstLevel);
int depth = is3D && !singleSlice ? Info.Depth : 1; int depth = is3D && !singleSlice ? Math.Max(1, Info.Depth >> dstLevel) : 1;
int layer = is3D ? 0 : dstLayer; int layer = is3D ? 0 : dstLayer;
int layers = dstLayers; int layers = dstLayers;
int levels = dstLevels; int levels = dstLevels;
@ -810,7 +829,7 @@ namespace Ryujinx.Graphics.Vulkan
for (int level = 0; level < levels; level++) for (int level = 0; level < levels; level++)
{ {
int mipSize = GetBufferDataLength(Info.GetMipSize(level)); int mipSize = GetBufferDataLength(Info.GetMipSize(dstLevel + level));
int endOffset = offset + mipSize; int endOffset = offset + mipSize;
@ -819,7 +838,7 @@ namespace Ryujinx.Graphics.Vulkan
break; break;
} }
int rowLength = (Info.GetMipStride(level) / Info.BytesPerPixel) * Info.BlockWidth; int rowLength = (Info.GetMipStride(dstLevel + level) / Info.BytesPerPixel) * Info.BlockWidth;
var aspectFlags = Info.Format.ConvertAspectFlags(); var aspectFlags = Info.Format.ConvertAspectFlags();