aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Memory
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2021-03-08 21:43:39 +0000
committerGitHub <noreply@github.com>2021-03-08 18:43:39 -0300
commit1623ab524f54901e154c8b644e2315985d5bd0a0 (patch)
treeccfc6473f380e30a596e97742d2fd0995ecf2dd1 /Ryujinx.Graphics.Gpu/Memory
parentda283ff3c37629769324926e24a7b203f9901890 (diff)
Improve Buffer Textures and flush Image Stores (#2088)
* Improve Buffer Textures and flush Image Stores Fixes a number of issues with buffer textures: - Reworked Buffer Textures to create their buffers in the TextureManager, then bind them with the BufferManager later. - Fixes an issue where a buffer texture's buffer could be invalidated after it is bound, but before use. - Fixed width unpacking for large buffer textures. The width is now 32-bit rather than 16. - Force buffer textures to be rebound whenever any buffer is created, as using the handle id wasn't reliable, and the cost of binding isn't too high. Fixes vertex explosions and flickering animations in UE4 games. * Set ImageStore flag... for ImageStore. * Check the offset and size.
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Memory')
-rw-r--r--Ryujinx.Graphics.Gpu/Memory/BufferManager.cs60
-rw-r--r--Ryujinx.Graphics.Gpu/Memory/BufferTextureBinding.cs60
2 files changed, 102 insertions, 18 deletions
diff --git a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
index 08d52faa..b2cd1ced 100644
--- a/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
+++ b/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
@@ -1,9 +1,11 @@
using Ryujinx.Common;
using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.Gpu.Image;
using Ryujinx.Graphics.Gpu.State;
using Ryujinx.Graphics.Shader;
using Ryujinx.Memory.Range;
using System;
+using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
@@ -31,6 +33,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
private IndexBuffer _indexBuffer;
private VertexBuffer[] _vertexBuffers;
private BufferBounds[] _transformFeedbackBuffers;
+ private List<BufferTextureBinding> _bufferTextures;
/// <summary>
/// Holds shader stage buffer state and binding information.
@@ -138,6 +141,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
_gpStorageBuffers[index] = new BuffersPerStage(Constants.TotalGpStorageBuffers);
_gpUniformBuffers[index] = new BuffersPerStage(Constants.TotalGpUniformBuffers);
}
+
+ _bufferTextures = new List<BufferTextureBinding>();
}
/// <summary>
@@ -620,11 +625,40 @@ namespace Ryujinx.Graphics.Gpu.Memory
_context.Renderer.Pipeline.SetUniformBuffers(uRanges);
+ CommitBufferTextureBindings();
+
// Force rebind after doing compute work.
_rebind = true;
}
/// <summary>
+ /// Commit any queued buffer texture bindings.
+ /// </summary>
+ private void CommitBufferTextureBindings()
+ {
+ if (_bufferTextures.Count > 0)
+ {
+ foreach (var binding in _bufferTextures)
+ {
+ binding.Texture.SetStorage(GetBufferRange(binding.Address, binding.Size, binding.BindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore)));
+
+ // The texture must be rebound to use the new storage if it was updated.
+
+ if (binding.IsImage)
+ {
+ _context.Renderer.Pipeline.SetImage(binding.BindingInfo.Binding, binding.Texture, binding.Format);
+ }
+ else
+ {
+ _context.Renderer.Pipeline.SetTexture(binding.BindingInfo.Binding, binding.Texture);
+ }
+ }
+
+ _bufferTextures.Clear();
+ }
+ }
+
+ /// <summary>
/// Ensures that the graphics engine bindings are visible to the host GPU.
/// Note: this actually performs the binding using the host graphics API.
/// </summary>
@@ -743,6 +777,8 @@ namespace Ryujinx.Graphics.Gpu.Memory
UpdateBuffers(_gpUniformBuffers);
}
+ CommitBufferTextureBindings();
+
_rebind = false;
}
@@ -813,31 +849,19 @@ namespace Ryujinx.Graphics.Gpu.Memory
}
/// <summary>
- /// Sets the buffer storage of a buffer texture.
+ /// Sets the buffer storage of a buffer texture. This will be bound when the buffer manager commits bindings.
/// </summary>
/// <param name="texture">Buffer texture</param>
/// <param name="address">Address of the buffer in memory</param>
/// <param name="size">Size of the buffer in bytes</param>
- /// <param name="compute">Indicates if the buffer texture belongs to the compute or graphics pipeline</param>
- public void SetBufferTextureStorage(ITexture texture, ulong address, ulong size, bool compute)
+ /// <param name="bindingInfo">Binding info for the buffer texture</param>
+ /// <param name="format">Format of the buffer texture</param>
+ /// <param name="isImage">Whether the binding is for an image or a sampler</param>
+ public void SetBufferTextureStorage(ITexture texture, ulong address, ulong size, TextureBindingInfo bindingInfo, Format format, bool isImage)
{
CreateBuffer(address, size);
- if (_rebind)
- {
- // We probably had to modify existing buffers to create the texture buffer,
- // so rebind everything to ensure we're using the new buffers for all bound resources.
- if (compute)
- {
- CommitComputeBindings();
- }
- else
- {
- CommitGraphicsBindings();
- }
- }
-
- texture.SetStorage(GetBufferRange(address, size));
+ _bufferTextures.Add(new BufferTextureBinding(texture, address, size, bindingInfo, format, isImage));
}
/// <summary>
diff --git a/Ryujinx.Graphics.Gpu/Memory/BufferTextureBinding.cs b/Ryujinx.Graphics.Gpu/Memory/BufferTextureBinding.cs
new file mode 100644
index 00000000..cf0d225e
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/Memory/BufferTextureBinding.cs
@@ -0,0 +1,60 @@
+using Ryujinx.Graphics.GAL;
+using Ryujinx.Graphics.Gpu.Image;
+
+namespace Ryujinx.Graphics.Gpu.Memory
+{
+ /// <summary>
+ /// A buffer binding to apply to a buffer texture.
+ /// </summary>
+ struct BufferTextureBinding
+ {
+ /// <summary>
+ /// The buffer texture.
+ /// </summary>
+ public ITexture Texture { get; }
+
+ /// <summary>
+ /// The base address of the buffer binding.
+ /// </summary>
+ public ulong Address { get; }
+
+ /// <summary>
+ /// The size of the buffer binding in bytes.
+ /// </summary>
+ public ulong Size { get; }
+
+ /// <summary>
+ /// The image or sampler binding info for the buffer texture.
+ /// </summary>
+ public TextureBindingInfo BindingInfo { get; }
+
+ /// <summary>
+ /// The image format for the binding.
+ /// </summary>
+ public Format Format { get; }
+
+ /// <summary>
+ /// Whether the binding is for an image or a sampler.
+ /// </summary>
+ public bool IsImage { get; }
+
+ /// <summary>
+ /// Create a new buffer texture binding.
+ /// </summary>
+ /// <param name="texture">Buffer texture</param>
+ /// <param name="address">Base address</param>
+ /// <param name="size">Size in bytes</param>
+ /// <param name="bindingInfo">Binding info</param>
+ /// <param name="format">Binding format</param>
+ /// <param name="isImage">Whether the binding is for an image or a sampler</param>
+ public BufferTextureBinding(ITexture texture, ulong address, ulong size, TextureBindingInfo bindingInfo, Format format, bool isImage)
+ {
+ Texture = texture;
+ Address = address;
+ Size = size;
+ BindingInfo = bindingInfo;
+ Format = format;
+ IsImage = isImage;
+ }
+ }
+}