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,
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);

View file

@ -65,6 +65,22 @@ namespace Ryujinx.Graphics.Vulkan
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()
{
_flushStorage.Dispose();

View file

@ -41,16 +41,8 @@ namespace Ryujinx.Graphics.Vulkan
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>[] _cpRenderScale = new Vector4<float>[64];
private int _fragmentScaleCount;
protected FramebufferParams FramebufferParams;
private Auto<DisposableFramebuffer> _framebuffer;
@ -63,7 +55,7 @@ namespace Ryujinx.Graphics.Vulkan
private readonly BufferState[] _transformFeedbackBuffers;
private readonly BufferState[] _vertexBuffers;
public BufferHolder RenderScaleBuffer { get; }
public SupportBufferUpdater SupportBufferUpdater;
private bool _needsIndexBufferRebind;
private bool _needsTransformFeedbackBuffersRebind;
@ -100,9 +92,8 @@ namespace Ryujinx.Graphics.Vulkan
var defaultScale = new Vector4<float> { X = 1f, Y = 0f, Z = 0f, W = 0f };
new Span<Vector4<float>>(_renderScale).Fill(defaultScale);
RenderScaleBuffer = gd.BufferManager.Create(gd, SupportBuffer.RequiredSize);
SetSupportBufferDataCpu<Vector4<float>>(SupportBuffer.GraphicsRenderScaleOffset, _renderScale, SupportBuffer.RenderScaleMaxCount);
SupportBufferUpdater = new SupportBufferUpdater(gd);
SupportBufferUpdater.UpdateRenderScale(_renderScale, 0, SupportBuffer.RenderScaleMaxCount);
_newState.Initialize();
_newState.LineWidth = 1f;
@ -295,6 +286,8 @@ namespace Ryujinx.Graphics.Vulkan
{
if (texture is TextureView srcTexture)
{
SupportBufferUpdater.Commit();
var oldCullMode = _newState.CullMode;
var oldStencilTestEnable = _newState.StencilTestEnable;
var oldDepthTestEnable = _newState.DepthTestEnable;
@ -622,7 +615,7 @@ namespace Ryujinx.Graphics.Vulkan
public void SetRenderTargetScale(float 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)
@ -875,11 +868,11 @@ namespace Ryujinx.Graphics.Vulkan
TextureBarrier();
}
public void UpdateRenderScale(ReadOnlySpan<float> scales, int textureCount, int imageCount)
public void UpdateRenderScale(ReadOnlySpan<float> scales, int totalCount, int fragmentCount)
{
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])
{
@ -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)
{
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()
{
_needsIndexBufferRebind = true;
@ -1052,6 +1042,9 @@ namespace Ryujinx.Graphics.Vulkan
// Take the opportunity to process any pending work requested by other threads.
_dynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
// Commit changes to the support buffer before drawing.
SupportBufferUpdater.Commit();
if (_stateDirty || Pbp != pbp)
{
CreatePipeline(pbp);
@ -1203,7 +1196,7 @@ namespace Ryujinx.Graphics.Vulkan
Gd.Api.DestroyPipelineCache(Device, _pipelineCache, null);
}
RenderScaleBuffer.Dispose();
SupportBufferUpdater.Dispose();
}
}

View file

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

View file

@ -679,7 +679,18 @@ namespace Ryujinx.Graphics.Vulkan
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)
@ -697,6 +708,14 @@ namespace Ryujinx.Graphics.Vulkan
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)
{
SetData(data, 0, 0, Info.GetLayers(), Info.Levels, singleSlice: false);
@ -799,9 +818,9 @@ namespace Ryujinx.Graphics.Vulkan
bool singleSlice)
{
bool is3D = Info.Target == Target.Texture3D;
int width = Info.Width;
int height = Info.Height;
int depth = is3D && !singleSlice ? Info.Depth : 1;
int width = Math.Max(1, Info.Width >> dstLevel);
int height = Math.Max(1, Info.Height >> dstLevel);
int depth = is3D && !singleSlice ? Math.Max(1, Info.Depth >> dstLevel) : 1;
int layer = is3D ? 0 : dstLayer;
int layers = dstLayers;
int levels = dstLevels;
@ -810,7 +829,7 @@ namespace Ryujinx.Graphics.Vulkan
for (int level = 0; level < levels; level++)
{
int mipSize = GetBufferDataLength(Info.GetMipSize(level));
int mipSize = GetBufferDataLength(Info.GetMipSize(dstLevel + level));
int endOffset = offset + mipSize;
@ -819,7 +838,7 @@ namespace Ryujinx.Graphics.Vulkan
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();