aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Vulkan/TextureView.cs
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2023-05-01 20:05:12 +0100
committerGitHub <noreply@github.com>2023-05-01 16:05:12 -0300
commite18d258fa09379f31ca4310fbbe9e1869581d49f (patch)
treec8427df586f4385feef9b8d201a648aeb2afec1b /src/Ryujinx.Graphics.Vulkan/TextureView.cs
parent36f10df775cf0c678548b97346432095823dfd8a (diff)
GPU: Pre-emptively flush textures that are flushed often (to imported memory when available) (#4711)
* WIP texture pre-flush Improve performance of TextureView GetData to buffer Fix copy/sync ordering Fix minor bug Make this actually work WIP host mapping stuff * Fix usage flags * message * Cleanup 1 * Fix rebase * Fix * Improve pre-flush rules * Fix pre-flush * A lot of cleanup * Use the host memory bits * Select the correct memory type * Cleanup TextureGroupHandle * Missing comment * Remove debugging logs * Revert BufferHandle _value access modifier * One interrupt action at a time. * Support D32S8 to D24S8 conversion, safeguards * Interrupt cannot happen in sync handle's lock Waitable needs to be checked twice now, but this should stop it from deadlocking. * Remove unused using * Address some feedback * Address feedback * Address more feedback * Address more feedback * Improve sync rules Should allow for faster sync in some cases.
Diffstat (limited to 'src/Ryujinx.Graphics.Vulkan/TextureView.cs')
-rw-r--r--src/Ryujinx.Graphics.Vulkan/TextureView.cs60
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();