diff options
Diffstat (limited to 'src/Ryujinx.Graphics.Vulkan/TextureView.cs')
-rw-r--r-- | src/Ryujinx.Graphics.Vulkan/TextureView.cs | 60 |
1 files changed, 56 insertions, 4 deletions
diff --git a/src/Ryujinx.Graphics.Vulkan/TextureView.cs b/src/Ryujinx.Graphics.Vulkan/TextureView.cs index cd280d5f..62d481eb 100644 --- a/src/Ryujinx.Graphics.Vulkan/TextureView.cs +++ b/src/Ryujinx.Graphics.Vulkan/TextureView.cs @@ -563,6 +563,34 @@ namespace Ryujinx.Graphics.Vulkan } } + public void CopyTo(BufferRange range, int layer, int level, int stride) + { + _gd.PipelineInternal.EndRenderPass(); + var cbs = _gd.PipelineInternal.CurrentCommandBuffer; + + int outSize = Info.GetMipSize(level); + int hostSize = GetBufferDataLength(outSize); + + var image = GetImage().Get(cbs).Value; + int offset = range.Offset; + + Auto<DisposableBuffer> autoBuffer = _gd.BufferManager.GetBuffer(cbs.CommandBuffer, range.Handle, true); + VkBuffer buffer = autoBuffer.Get(cbs, range.Offset, outSize).Value; + + if (PrepareOutputBuffer(cbs, hostSize, buffer, out VkBuffer copyToBuffer, out BufferHolder tempCopyHolder)) + { + offset = 0; + } + + CopyFromOrToBuffer(cbs.CommandBuffer, copyToBuffer, image, hostSize, true, layer, level, 1, 1, singleSlice: true, offset, stride); + + if (tempCopyHolder != null) + { + CopyDataToOutputBuffer(cbs, tempCopyHolder, autoBuffer, hostSize, range.Offset); + tempCopyHolder.Dispose(); + } + } + private ReadOnlySpan<byte> GetData(CommandBufferPool cbp, PersistentFlushBuffer flushBuffer) { int size = 0; @@ -693,6 +721,30 @@ namespace Ryujinx.Graphics.Vulkan return storage; } + private bool PrepareOutputBuffer(CommandBufferScoped cbs, int hostSize, VkBuffer target, out VkBuffer copyTarget, out BufferHolder copyTargetHolder) + { + if (NeedsD24S8Conversion()) + { + copyTargetHolder = _gd.BufferManager.Create(_gd, hostSize); + copyTarget = copyTargetHolder.GetBuffer().Get(cbs, 0, hostSize).Value; + + return true; + } + + copyTarget = target; + copyTargetHolder = null; + + return false; + } + + private void CopyDataToOutputBuffer(CommandBufferScoped cbs, BufferHolder hostData, Auto<DisposableBuffer> copyTarget, int hostSize, int dstOffset) + { + if (NeedsD24S8Conversion()) + { + _gd.HelperShader.ConvertD32S8ToD24S8(_gd, cbs, hostData, copyTarget, hostSize / (2 * sizeof(int)), dstOffset); + } + } + private bool NeedsD24S8Conversion() { return FormatCapabilities.IsD24S8(Info.Format) && VkFormat == VkFormat.D32SfloatS8Uint; @@ -708,7 +760,9 @@ namespace Ryujinx.Graphics.Vulkan int dstLevel, int dstLayers, int dstLevels, - bool singleSlice) + bool singleSlice, + int offset = 0, + int stride = 0) { bool is3D = Info.Target == Target.Texture3D; int width = Math.Max(1, Info.Width >> dstLevel); @@ -718,8 +772,6 @@ namespace Ryujinx.Graphics.Vulkan int layers = dstLayers; int levels = dstLevels; - int offset = 0; - for (int level = 0; level < levels; level++) { int mipSize = GetBufferDataLength(Info.GetMipSize2D(dstLevel + level) * dstLayers); @@ -731,7 +783,7 @@ namespace Ryujinx.Graphics.Vulkan break; } - int rowLength = (Info.GetMipStride(dstLevel + level) / Info.BytesPerPixel) * Info.BlockWidth; + int rowLength = ((stride == 0 ? Info.GetMipStride(dstLevel + level) : stride) / Info.BytesPerPixel) * Info.BlockWidth; var aspectFlags = Info.Format.ConvertAspectFlags(); |