From d14dbb0cffec5ff9c2ee620cae52982e512da38f Mon Sep 17 00:00:00 2001 From: riperiperi Date: Mon, 10 Jan 2022 22:50:31 +0000 Subject: [PATCH] Use SupportBufferUpdater, add single layer flush --- .../DescriptorSetUpdater.cs | 2 +- .../PersistentFlushBuffer.cs | 16 ++++++ Ryujinx.Graphics.Vulkan/PipelineBase.cs | 49 ++++++++----------- .../PipelineLayoutFactory.cs | 2 +- Ryujinx.Graphics.Vulkan/TextureView.cs | 31 +++++++++--- 5 files changed, 64 insertions(+), 36 deletions(-) diff --git a/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs b/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs index 3c3f69824..6b72dbb60 100644 --- a/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs +++ b/Ryujinx.Graphics.Vulkan/DescriptorSetUpdater.cs @@ -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); diff --git a/Ryujinx.Graphics.Vulkan/PersistentFlushBuffer.cs b/Ryujinx.Graphics.Vulkan/PersistentFlushBuffer.cs index 8e035aa32..c23d27b54 100644 --- a/Ryujinx.Graphics.Vulkan/PersistentFlushBuffer.cs +++ b/Ryujinx.Graphics.Vulkan/PersistentFlushBuffer.cs @@ -65,6 +65,22 @@ namespace Ryujinx.Graphics.Vulkan return flushStorage.GetDataStorage(0, size); } + public Span 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(); diff --git a/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/Ryujinx.Graphics.Vulkan/PipelineBase.cs index ce631c4a6..52790efcb 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineBase.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineBase.cs @@ -41,16 +41,8 @@ namespace Ryujinx.Graphics.Vulkan private ShaderCollection _program; - private struct Vector4 - { - public T X; - public T Y; - public T Z; - public T W; - } - private Vector4[] _renderScale = new Vector4[65]; - private Vector4[] _cpRenderScale = new Vector4[64]; + private int _fragmentScaleCount; protected FramebufferParams FramebufferParams; private Auto _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 { X = 1f, Y = 0f, Z = 0f, W = 0f }; new Span>(_renderScale).Fill(defaultScale); - RenderScaleBuffer = gd.BufferManager.Create(gd, SupportBuffer.RequiredSize); - - SetSupportBufferDataCpu>(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>(SupportBuffer.GraphicsRenderScaleOffset, _renderScale, 1); // Just the first element. + SupportBufferUpdater.UpdateRenderScale(_renderScale, 0, 1); // Just the first element. } public void SetScissors(ReadOnlySpan> regions) @@ -875,11 +868,11 @@ namespace Ryujinx.Graphics.Vulkan TextureBarrier(); } - public void UpdateRenderScale(ReadOnlySpan scales, int textureCount, int imageCount) + public void UpdateRenderScale(ReadOnlySpan 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>(SupportBuffer.GraphicsRenderScaleOffset, _renderScale, 1 + textureCount + imageCount); + SupportBufferUpdater.UpdateRenderScale(_renderScale, 0, 1 + totalCount); } } - private void SetSupportBufferData(int offset, ReadOnlySpan data, int count) where T : unmanaged - { - RenderScaleBuffer.SetDataInline(Cbs, EndRenderPass, offset, MemoryMarshal.Cast(data.Slice(0, count))); - } - - private void SetSupportBufferDataCpu(int offset, ReadOnlySpan data, int count) where T : unmanaged - { - RenderScaleBuffer.SetDataUnchecked(offset, MemoryMarshal.Cast(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(); } } diff --git a/Ryujinx.Graphics.Vulkan/PipelineLayoutFactory.cs b/Ryujinx.Graphics.Vulkan/PipelineLayoutFactory.cs index 3ceacfd0e..02b19c92b 100644 --- a/Ryujinx.Graphics.Vulkan/PipelineLayoutFactory.cs +++ b/Ryujinx.Graphics.Vulkan/PipelineLayoutFactory.cs @@ -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; diff --git a/Ryujinx.Graphics.Vulkan/TextureView.cs b/Ryujinx.Graphics.Vulkan/TextureView.cs index 38b334486..a8bad9537 100644 --- a/Ryujinx.Graphics.Vulkan/TextureView.cs +++ b/Ryujinx.Graphics.Vulkan/TextureView.cs @@ -679,7 +679,18 @@ namespace Ryujinx.Graphics.Vulkan public ReadOnlySpan 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 GetData(CommandBufferPool cbp, PersistentFlushBuffer flushBuffer) @@ -697,6 +708,14 @@ namespace Ryujinx.Graphics.Vulkan return GetDataFromBuffer(result, size, result); } + private ReadOnlySpan GetData(CommandBufferPool cbp, PersistentFlushBuffer flushBuffer, int layer, int level) + { + int size = GetBufferDataLength(Info.GetMipSize(level)); + + Span result = flushBuffer.GetTextureData(cbp, this, size, layer, level); + return GetDataFromBuffer(result, size, result); + } + public void SetData(ReadOnlySpan 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();