From e4f68592c3a6e51414e5f78eef096f21bf735eb1 Mon Sep 17 00:00:00 2001 From: riperiperi Date: Sun, 12 Feb 2023 09:30:26 +0000 Subject: [PATCH] Fix partial updates for textures. (#4401) I was forcing some types of texture to partially update when investigating performance with games that stream in data, and noticed that partially loading texture data was really broken on both backends. Fixes Vulkan texture set by getting the correct expected size for the texture. Fixes partial upload on both backends for both Texture 2D Array and Cubemap using the wrong offset and uploading to the first layer/level for a handle. 3D might also be affected. This might fix textures randomly having incorrect data in games that render to it - jumbled in the case of OpenGL, and outdated/black in the case of Vulkan. This case typically happens in UE4 games. --- Ryujinx.Graphics.Gpu/Image/TextureGroup.cs | 9 ++++----- Ryujinx.Graphics.Vulkan/TextureView.cs | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs b/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs index 942fa2f8..1040b394 100644 --- a/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs +++ b/Ryujinx.Graphics.Gpu/Image/TextureGroup.cs @@ -336,24 +336,23 @@ namespace Ryujinx.Graphics.Gpu.Image if (_loadNeeded[baseHandle + i]) { var info = GetHandleInformation(baseHandle + i); - int offsetIndex = info.Index; // Only one of these will be greater than 1, as partial sync is only called when there are sub-image views. for (int layer = 0; layer < info.Layers; layer++) { for (int level = 0; level < info.Levels; level++) { + int offsetIndex = GetOffsetIndex(info.BaseLayer + layer, info.BaseLevel + level); + int offset = _allOffsets[offsetIndex]; int endOffset = Math.Min(offset + _sliceSizes[info.BaseLevel + level], (int)Storage.Size); int size = endOffset - offset; ReadOnlySpan data = _physicalMemory.GetSpan(Storage.Range.GetSlice((ulong)offset, (ulong)size)); - SpanOrArray result = Storage.ConvertToHostCompatibleFormat(data, info.BaseLevel, true); + SpanOrArray result = Storage.ConvertToHostCompatibleFormat(data, info.BaseLevel + level, true); - Storage.SetData(result, info.BaseLayer, info.BaseLevel); - - offsetIndex++; + Storage.SetData(result, info.BaseLayer + layer, info.BaseLevel + level); } } } diff --git a/Ryujinx.Graphics.Vulkan/TextureView.cs b/Ryujinx.Graphics.Vulkan/TextureView.cs index d60ce39b..aa050c01 100644 --- a/Ryujinx.Graphics.Vulkan/TextureView.cs +++ b/Ryujinx.Graphics.Vulkan/TextureView.cs @@ -712,7 +712,7 @@ namespace Ryujinx.Graphics.Vulkan for (int level = 0; level < levels; level++) { - int mipSize = GetBufferDataLength(Info.GetMipSize(dstLevel + level)); + int mipSize = GetBufferDataLength(Info.GetMipSize2D(dstLevel + level) * dstLayers); int endOffset = offset + mipSize;