diff --git a/src/Ryujinx.Graphics.Vulkan/BarrierBatch.cs b/src/Ryujinx.Graphics.Vulkan/BarrierBatch.cs index 251f74319..927845fa0 100644 --- a/src/Ryujinx.Graphics.Vulkan/BarrierBatch.cs +++ b/src/Ryujinx.Graphics.Vulkan/BarrierBatch.cs @@ -46,7 +46,14 @@ namespace Ryujinx.Graphics.Vulkan public static (AccessFlags Access, PipelineStageFlags Stages) GetSubpassAccessSuperset(VulkanRenderer gd) { - AccessFlags access = BufferAccess; + AccessFlags access = BufferAccess | + AccessFlags.ShaderReadBit | + AccessFlags.ShaderWriteBit | + AccessFlags.ColorAttachmentReadBit | + AccessFlags.ColorAttachmentWriteBit | + AccessFlags.DepthStencilAttachmentReadBit | + AccessFlags.DepthStencilAttachmentWriteBit; + PipelineStageFlags stages = PipelineStageFlags.AllGraphicsBit; if (gd.TransformFeedbackApi != null) diff --git a/src/Ryujinx.Graphics.Vulkan/TextureCopy.cs b/src/Ryujinx.Graphics.Vulkan/TextureCopy.cs index aae3b0afb..0efb4dbb0 100644 --- a/src/Ryujinx.Graphics.Vulkan/TextureCopy.cs +++ b/src/Ryujinx.Graphics.Vulkan/TextureCopy.cs @@ -15,6 +15,8 @@ namespace Ryujinx.Graphics.Vulkan Image dstImage, TextureCreateInfo srcInfo, TextureCreateInfo dstInfo, + TextureCreateInfo srcStorageInfo, + TextureCreateInfo dstStorageInfo, Extents2D srcRegion, Extents2D dstRegion, int srcLayer, @@ -40,6 +42,13 @@ namespace Ryujinx.Graphics.Vulkan return (xy1, xy2); } + static (Offset3D, Offset3D) ClampOffsetsToMip(Offset3D xy1, Offset3D xy2, int mipW, int mipH) + { + return ( + new Offset3D(Math.Min(xy1.X, mipW), Math.Min(xy1.Y, mipH), xy1.Z), + new Offset3D(Math.Min(xy2.X, mipW), Math.Min(xy2.Y, mipH), xy2.Z)); + } + if (srcAspectFlags == 0) { srcAspectFlags = srcInfo.Format.ConvertAspectFlags(); @@ -80,6 +89,14 @@ namespace Ryujinx.Graphics.Vulkan (srcOffsets.Element0, srcOffsets.Element1) = ExtentsToOffset3D(srcRegion, srcInfo.Width, srcInfo.Height, level); (dstOffsets.Element0, dstOffsets.Element1) = ExtentsToOffset3D(dstRegion, dstInfo.Width, dstInfo.Height, level); + int srcMipW = Math.Max(1, srcStorageInfo.Width >> (int)copySrcLevel); + int srcMipH = Math.Max(1, srcStorageInfo.Height >> (int)copySrcLevel); + int dstMipW = Math.Max(1, dstStorageInfo.Width >> (int)copyDstLevel); + int dstMipH = Math.Max(1, dstStorageInfo.Height >> (int)copyDstLevel); + + (srcOffsets.Element0, srcOffsets.Element1) = ClampOffsetsToMip(srcOffsets.Element0, srcOffsets.Element1, srcMipW, srcMipH); + (dstOffsets.Element0, dstOffsets.Element1) = ClampOffsetsToMip(dstOffsets.Element0, dstOffsets.Element1, dstMipW, dstMipH); + ImageBlit region = new() { SrcSubresource = srcSl, @@ -121,6 +138,8 @@ namespace Ryujinx.Graphics.Vulkan Image dstImage, TextureCreateInfo srcInfo, TextureCreateInfo dstInfo, + TextureCreateInfo srcStorageInfo, + TextureCreateInfo dstStorageInfo, int srcViewLayer, int dstViewLayer, int srcViewLevel, @@ -151,6 +170,8 @@ namespace Ryujinx.Graphics.Vulkan dstImage, srcInfo, dstInfo, + srcStorageInfo, + dstStorageInfo, srcViewLayer, dstViewLayer, srcViewLevel, @@ -186,6 +207,8 @@ namespace Ryujinx.Graphics.Vulkan Image dstImage, TextureCreateInfo srcInfo, TextureCreateInfo dstInfo, + TextureCreateInfo srcStorageInfo, + TextureCreateInfo dstStorageInfo, int srcViewLayer, int dstViewLayer, int srcViewLevel, @@ -314,6 +337,14 @@ namespace Ryujinx.Graphics.Vulkan int copyWidth = sizeInBlocks ? BitUtils.DivRoundUp(width, blockWidth) : width; int copyHeight = sizeInBlocks ? BitUtils.DivRoundUp(height, blockHeight) : height; + int srcMipW = Math.Max(1, srcStorageInfo.Width >> (srcViewLevel + srcLevel + level)); + int srcMipH = Math.Max(1, srcStorageInfo.Height >> (srcViewLevel + srcLevel + level)); + int dstMipW = Math.Max(1, dstStorageInfo.Width >> (dstViewLevel + dstLevel + level)); + int dstMipH = Math.Max(1, dstStorageInfo.Height >> (dstViewLevel + dstLevel + level)); + + copyWidth = Math.Min(copyWidth, Math.Min(srcMipW, dstMipW)); + copyHeight = Math.Min(copyHeight, Math.Min(srcMipH, dstMipH)); + Extent3D extent = new((uint)copyWidth, (uint)copyHeight, (uint)srcDepth); if (srcInfo.Samples > 1 && srcInfo.Samples != dstInfo.Samples) diff --git a/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs b/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs index 46cd5b4be..b102efaf2 100644 --- a/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs +++ b/src/Ryujinx.Graphics.Vulkan/TextureStorage.cs @@ -67,6 +67,8 @@ namespace Ryujinx.Graphics.Vulkan public VkFormat VkFormat { get; } + public ImageUsageFlags UsageFlags { get; } + public unsafe TextureStorage( VulkanRenderer gd, Device device, @@ -93,7 +95,8 @@ namespace Ryujinx.Graphics.Vulkan SampleCountFlags sampleCountFlags = ConvertToSampleCountFlags(gd.Capabilities.SupportedSampleCounts, (uint)info.Samples); - ImageUsageFlags usage = GetImageUsage(info.Format, gd.Capabilities, isMsImageStorageSupported, true); + ImageUsageFlags usage = GetImageUsage(info.Format, gd.Capabilities, isMsImageStorageSupported); + UsageFlags = usage; ImageCreateFlags flags = ImageCreateFlags.CreateMutableFormatBit | ImageCreateFlags.CreateExtendedUsageBit; @@ -159,7 +162,7 @@ namespace Ryujinx.Graphics.Vulkan _imageAuto = new Auto(new DisposableImage(_gd.Api, device, _image)); - InitialTransition(ImageLayout.Preinitialized, ImageLayout.General); + InitialTransition(ImageLayout.Undefined, ImageLayout.General); } _slices = new TextureSliceInfo[levels * _depthOrLayers]; @@ -307,7 +310,7 @@ namespace Ryujinx.Graphics.Vulkan } } - public static ImageUsageFlags GetImageUsage(Format format, in HardwareCapabilities capabilities, bool isMsImageStorageSupported, bool extendedUsage) + public static ImageUsageFlags GetImageUsage(Format format, in HardwareCapabilities capabilities, bool isMsImageStorageSupported) { ImageUsageFlags usage = DefaultUsageFlags; @@ -320,7 +323,7 @@ namespace Ryujinx.Graphics.Vulkan usage |= ImageUsageFlags.ColorAttachmentBit; } - if ((format.IsImageCompatible && isMsImageStorageSupported) || extendedUsage) + if (format.IsImageCompatible && isMsImageStorageSupported) { usage |= ImageUsageFlags.StorageBit; } diff --git a/src/Ryujinx.Graphics.Vulkan/TextureView.cs b/src/Ryujinx.Graphics.Vulkan/TextureView.cs index 4513c804f..b6c0b8369 100644 --- a/src/Ryujinx.Graphics.Vulkan/TextureView.cs +++ b/src/Ryujinx.Graphics.Vulkan/TextureView.cs @@ -64,7 +64,7 @@ namespace Ryujinx.Graphics.Vulkan bool isMsImageStorageSupported = gd.Capabilities.SupportsShaderStorageImageMultisample || !info.Target.IsMultisample; VkFormat format = _gd.FormatCapabilities.ConvertToVkFormat(info.Format, isMsImageStorageSupported); - ImageUsageFlags usage = TextureStorage.GetImageUsage(info.Format, gd.Capabilities, isMsImageStorageSupported, false); + ImageUsageFlags usage = TextureStorage.GetImageUsage(info.Format, gd.Capabilities, isMsImageStorageSupported) & storage.UsageFlags; uint levels = (uint)info.Levels; uint layers = (uint)info.GetLayers(); @@ -133,6 +133,8 @@ namespace Ryujinx.Graphics.Vulkan shaderUsage |= ImageUsageFlags.StorageBit; } + shaderUsage &= storage.UsageFlags; + _imageView = CreateImageView(componentMapping, subresourceRange, type, shaderUsage); // Framebuffer attachments and storage images requires a identity component mapping. @@ -257,6 +259,8 @@ namespace Ryujinx.Graphics.Vulkan dstImage, src.Info, dst.Info, + src.Storage.Info, + dst.Storage.Info, src.FirstLayer, dst.FirstLayer, src.FirstLevel, @@ -310,6 +314,8 @@ namespace Ryujinx.Graphics.Vulkan dstImage, src.Info, dst.Info, + src.Storage.Info, + dst.Storage.Info, src.FirstLayer, dst.FirstLayer, src.FirstLevel, @@ -385,6 +391,8 @@ namespace Ryujinx.Graphics.Vulkan dst.GetImage().Get(cbs).Value, src.Info, dst.Info, + src.Storage.Info, + dst.Storage.Info, src.FirstLayer, dst.FirstLayer, src.FirstLevel, @@ -410,6 +418,8 @@ namespace Ryujinx.Graphics.Vulkan dst.GetImage().Get(cbs).Value, src.Info, dst.Info, + src.Storage.Info, + dst.Storage.Info, srcRegion, dstRegion, src.FirstLayer, @@ -463,6 +473,8 @@ namespace Ryujinx.Graphics.Vulkan dstImage.Get(cbs).Value, src.Info, dst.Info, + src.Storage.Info, + dst.Storage.Info, srcRegion, dstRegion, src.FirstLayer, diff --git a/src/Ryujinx.Graphics.Vulkan/VertexBufferState.cs b/src/Ryujinx.Graphics.Vulkan/VertexBufferState.cs index 236ab8721..da4edaa6a 100644 --- a/src/Ryujinx.Graphics.Vulkan/VertexBufferState.cs +++ b/src/Ryujinx.Graphics.Vulkan/VertexBufferState.cs @@ -68,9 +68,7 @@ namespace Ryujinx.Graphics.Vulkan int stride = (_stride + (alignment - 1)) & -alignment; int newSize = (_size / _stride) * stride; - Buffer buffer = autoBuffer.Get(cbs, 0, newSize).Value; - - updater.BindVertexBuffer(cbs, binding, buffer, 0, (ulong)newSize, (ulong)stride); + updater.BindVertexBuffer(cbs, binding, autoBuffer, 0, newSize, (ulong)stride); _buffer = autoBuffer; @@ -93,11 +91,7 @@ namespace Ryujinx.Graphics.Vulkan if (autoBuffer != null) { - int offset = _offset; - bool mirrorable = _size <= VertexBufferMaxMirrorable; - Buffer buffer = mirrorable ? autoBuffer.GetMirrorable(cbs, ref offset, _size, out _).Value : autoBuffer.Get(cbs, offset, _size).Value; - - updater.BindVertexBuffer(cbs, binding, buffer, (ulong)offset, (ulong)_size, (ulong)_stride); + updater.BindVertexBuffer(cbs, binding, autoBuffer, _offset, _size, (ulong)_stride); } } diff --git a/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs b/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs index 94269dd76..8927d2264 100644 --- a/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs +++ b/src/Ryujinx.Graphics.Vulkan/VertexBufferUpdater.cs @@ -15,6 +15,10 @@ namespace Ryujinx.Graphics.Vulkan private readonly NativeArray _sizes; private readonly NativeArray _strides; + private readonly Auto[] _bufferAutos; + private readonly int[] _bufferOffsetsForGet; + private readonly int[] _bufferSizesForGet; + public VertexBufferUpdater(VulkanRenderer gd) { _gd = gd; @@ -23,9 +27,13 @@ namespace Ryujinx.Graphics.Vulkan _offsets = new NativeArray(Constants.MaxVertexBuffers); _sizes = new NativeArray(Constants.MaxVertexBuffers); _strides = new NativeArray(Constants.MaxVertexBuffers); + + _bufferAutos = new Auto[Constants.MaxVertexBuffers]; + _bufferOffsetsForGet = new int[Constants.MaxVertexBuffers]; + _bufferSizesForGet = new int[Constants.MaxVertexBuffers]; } - public void BindVertexBuffer(CommandBufferScoped cbs, uint binding, VkBuffer buffer, ulong offset, ulong size, ulong stride) + public void BindVertexBuffer(CommandBufferScoped cbs, uint binding, Auto autoBuffer, int offset, int size, ulong stride) { if (_count == 0) { @@ -39,9 +47,11 @@ namespace Ryujinx.Graphics.Vulkan int index = (int)_count; - _buffers[index] = buffer; - _offsets[index] = offset; - _sizes[index] = size; + _bufferAutos[index] = autoBuffer; + _bufferOffsetsForGet[index] = offset; + _bufferSizesForGet[index] = size; + _offsets[index] = (ulong)offset; + _sizes[index] = (ulong)size; _strides[index] = stride; _count++; @@ -51,6 +61,12 @@ namespace Ryujinx.Graphics.Vulkan { if (_count != 0) { + for (int i = 0; i < _count; i++) + { + _buffers[i] = _bufferAutos[i].Get(cbs, _bufferOffsetsForGet[i], _bufferSizesForGet[i]).Value; + _bufferAutos[i] = null; + } + if (_gd.Capabilities.SupportsExtendedDynamicState) { _gd.ExtendedDynamicStateApi.CmdBindVertexBuffers2( diff --git a/src/Ryujinx.Graphics.Vulkan/Window.cs b/src/Ryujinx.Graphics.Vulkan/Window.cs index 0a0d970c1..eb8d433be 100644 --- a/src/Ryujinx.Graphics.Vulkan/Window.cs +++ b/src/Ryujinx.Graphics.Vulkan/Window.cs @@ -391,12 +391,12 @@ namespace Ryujinx.Graphics.Vulkan { if (_effect != null) { + _gd.FlushAllCommands(); _gd.CommandBufferPool.Return( cbs, null, [PipelineStageFlags.ColorAttachmentOutputBit], null); - _gd.FlushAllCommands(); cbs.GetFence().Wait(); cbs = _gd.CommandBufferPool.Rent(); } @@ -455,6 +455,8 @@ namespace Ryujinx.Graphics.Vulkan ImageLayout.General, ImageLayout.PresentSrcKhr); + _gd.FlushAllCommands(); + _gd.CommandBufferPool.Return( cbs, [_imageAvailableSemaphores[semaphoreIndex]],