mirror of
https://git.naxdy.org/Mirror/Ryujinx.git
synced 2025-02-21 00:23:36 +00:00
Add barrier before use of some modified images
This commit is contained in:
parent
2852ddf510
commit
7838a45772
13 changed files with 151 additions and 20 deletions
|
@ -1,3 +1,4 @@
|
|||
using Ryujinx.Graphics.Shader;
|
||||
using System;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL
|
||||
|
@ -83,7 +84,7 @@ namespace Ryujinx.Graphics.GAL
|
|||
|
||||
void SetStorageBuffers(int first, ReadOnlySpan<BufferRange> buffers);
|
||||
|
||||
void SetTextureAndSampler(int binding, ITexture texture, ISampler sampler);
|
||||
void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler);
|
||||
|
||||
void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers);
|
||||
void SetUniformBuffers(int first, ReadOnlySpan<BufferRange> buffers);
|
||||
|
|
|
@ -1,17 +1,20 @@
|
|||
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Resources;
|
||||
using Ryujinx.Graphics.Shader;
|
||||
|
||||
namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
||||
{
|
||||
struct SetTextureAndSamplerCommand : IGALCommand
|
||||
{
|
||||
public CommandType CommandType => CommandType.SetTextureAndSampler;
|
||||
private ShaderStage _stage;
|
||||
private int _binding;
|
||||
private TableRef<ITexture> _texture;
|
||||
private TableRef<ISampler> _sampler;
|
||||
|
||||
public void Set(int binding, TableRef<ITexture> texture, TableRef<ISampler> sampler)
|
||||
public void Set(ShaderStage stage, int binding, TableRef<ITexture> texture, TableRef<ISampler> sampler)
|
||||
{
|
||||
_stage = stage;
|
||||
_binding = binding;
|
||||
_texture = texture;
|
||||
_sampler = sampler;
|
||||
|
@ -19,7 +22,7 @@ namespace Ryujinx.Graphics.GAL.Multithreading.Commands
|
|||
|
||||
public static void Run(ref SetTextureAndSamplerCommand command, ThreadedRenderer threaded, IRenderer renderer)
|
||||
{
|
||||
renderer.Pipeline.SetTextureAndSampler(command._binding, command._texture.GetAs<ThreadedTexture>(threaded)?.Base, command._sampler.GetAs<ThreadedSampler>(threaded)?.Base);
|
||||
renderer.Pipeline.SetTextureAndSampler(command._stage, command._binding, command._texture.GetAs<ThreadedTexture>(threaded)?.Base, command._sampler.GetAs<ThreadedSampler>(threaded)?.Base);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using Ryujinx.Graphics.GAL.Multithreading.Commands;
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Model;
|
||||
using Ryujinx.Graphics.GAL.Multithreading.Resources;
|
||||
using Ryujinx.Graphics.Shader;
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
|
@ -262,9 +263,9 @@ namespace Ryujinx.Graphics.GAL.Multithreading
|
|||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
public void SetTextureAndSampler(int binding, ITexture texture, ISampler sampler)
|
||||
public void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler)
|
||||
{
|
||||
_renderer.New<SetTextureAndSamplerCommand>().Set(binding, Ref(texture), Ref(sampler));
|
||||
_renderer.New<SetTextureAndSamplerCommand>().Set(stage, binding, Ref(texture), Ref(sampler));
|
||||
_renderer.QueueCommand();
|
||||
}
|
||||
|
||||
|
|
|
@ -559,7 +559,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
state.ScaleIndex = index;
|
||||
state.UsageFlags = usageFlags;
|
||||
|
||||
_context.Renderer.Pipeline.SetTextureAndSampler(bindingInfo.Binding, hostTextureRebind, state.Sampler);
|
||||
_context.Renderer.Pipeline.SetTextureAndSampler(stage, bindingInfo.Binding, hostTextureRebind, state.Sampler);
|
||||
}
|
||||
|
||||
continue;
|
||||
|
@ -582,7 +582,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
// Ensure that the buffer texture is using the correct buffer as storage.
|
||||
// Buffers are frequently re-created to accomodate larger data, so we need to re-bind
|
||||
// to ensure we're not using a old buffer that was already deleted.
|
||||
_channel.BufferManager.SetBufferTextureStorage(hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, bindingInfo.Format, false);
|
||||
_channel.BufferManager.SetBufferTextureStorage(stage, hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, bindingInfo.Format, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -599,7 +599,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
|
||||
state.Sampler = hostSampler;
|
||||
|
||||
_context.Renderer.Pipeline.SetTextureAndSampler(bindingInfo.Binding, hostTexture, hostSampler);
|
||||
_context.Renderer.Pipeline.SetTextureAndSampler(stage, bindingInfo.Binding, hostTexture, hostSampler);
|
||||
}
|
||||
|
||||
state.CachedTexture = texture;
|
||||
|
@ -715,7 +715,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
format = texture.Format;
|
||||
}
|
||||
|
||||
_channel.BufferManager.SetBufferTextureStorage(hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, format, true);
|
||||
_channel.BufferManager.SetBufferTextureStorage(stage, hostTexture, texture.Range.GetSubRange(0).Address, texture.Size, bindingInfo, format, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -435,7 +435,7 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
}
|
||||
else
|
||||
{
|
||||
_context.Renderer.Pipeline.SetTextureAndSampler(binding.BindingInfo.Binding, binding.Texture, null);
|
||||
_context.Renderer.Pipeline.SetTextureAndSampler(binding.Stage, binding.BindingInfo.Binding, binding.Texture, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -719,17 +719,25 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
/// <summary>
|
||||
/// Sets the buffer storage of a buffer texture. This will be bound when the buffer manager commits bindings.
|
||||
/// </summary>
|
||||
/// <param name="stage">Shader stage accessing the texture</param>
|
||||
/// <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="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)
|
||||
public void SetBufferTextureStorage(
|
||||
ShaderStage stage,
|
||||
ITexture texture,
|
||||
ulong address,
|
||||
ulong size,
|
||||
TextureBindingInfo bindingInfo,
|
||||
Format format,
|
||||
bool isImage)
|
||||
{
|
||||
_channel.MemoryManager.Physical.BufferCache.CreateBuffer(address, size);
|
||||
|
||||
_bufferTextures.Add(new BufferTextureBinding(texture, address, size, bindingInfo, format, isImage));
|
||||
_bufferTextures.Add(new BufferTextureBinding(stage, texture, address, size, bindingInfo, format, isImage));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Ryujinx.Graphics.GAL;
|
||||
using Ryujinx.Graphics.Gpu.Image;
|
||||
using Ryujinx.Graphics.Shader;
|
||||
|
||||
namespace Ryujinx.Graphics.Gpu.Memory
|
||||
{
|
||||
|
@ -8,6 +9,11 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
/// </summary>
|
||||
struct BufferTextureBinding
|
||||
{
|
||||
/// <summary>
|
||||
/// Shader stage accessing the texture.
|
||||
/// </summary>
|
||||
public ShaderStage Stage { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The buffer texture.
|
||||
/// </summary>
|
||||
|
@ -41,14 +47,23 @@ namespace Ryujinx.Graphics.Gpu.Memory
|
|||
/// <summary>
|
||||
/// Create a new buffer texture binding.
|
||||
/// </summary>
|
||||
/// <param name="stage">Shader stage accessing the texture</param>
|
||||
/// <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)
|
||||
public BufferTextureBinding(
|
||||
ShaderStage stage,
|
||||
ITexture texture,
|
||||
ulong address,
|
||||
ulong size,
|
||||
TextureBindingInfo bindingInfo,
|
||||
Format format,
|
||||
bool isImage)
|
||||
{
|
||||
Stage = stage;
|
||||
Texture = texture;
|
||||
Address = address;
|
||||
Size = size;
|
||||
|
|
|
@ -1195,7 +1195,7 @@ namespace Ryujinx.Graphics.OpenGL
|
|||
SetBuffers(first, buffers, isStorage: true);
|
||||
}
|
||||
|
||||
public void SetTextureAndSampler(int binding, ITexture texture, ISampler sampler)
|
||||
public void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler)
|
||||
{
|
||||
if (texture != null)
|
||||
{
|
||||
|
|
|
@ -167,7 +167,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
SignalDirty(DirtyFlags.Storage);
|
||||
}
|
||||
|
||||
public void SetTextureAndSampler(int binding, ITexture texture, ISampler sampler)
|
||||
public void SetTextureAndSampler(CommandBufferScoped cbs, ShaderStage stage, int binding, ITexture texture, ISampler sampler)
|
||||
{
|
||||
if (texture == null)
|
||||
{
|
||||
|
@ -195,7 +195,11 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
Array.Resize(ref _samplerRefs, binding + 1);
|
||||
}
|
||||
|
||||
_textureRefs[binding] = ((TextureView)texture).GetImageView();
|
||||
TextureView view = (TextureView)texture;
|
||||
|
||||
view.Storage.InsertBarrier(cbs, AccessFlags.AccessShaderReadBit, stage.ConvertToPipelineStageFlags());
|
||||
|
||||
_textureRefs[binding] = view.GetImageView();
|
||||
_samplerRefs[binding] = ((SamplerHolder)sampler)?.GetSampler();
|
||||
|
||||
_textures[binding] = new DescriptorImageInfo()
|
||||
|
|
|
@ -30,6 +30,29 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
return 0;
|
||||
}
|
||||
|
||||
public static PipelineStageFlags ConvertToPipelineStageFlags(this ShaderStage stage)
|
||||
{
|
||||
switch (stage)
|
||||
{
|
||||
case ShaderStage.Vertex:
|
||||
return PipelineStageFlags.PipelineStageVertexShaderBit;
|
||||
case ShaderStage.Geometry:
|
||||
return PipelineStageFlags.PipelineStageGeometryShaderBit;
|
||||
case ShaderStage.TessellationControl:
|
||||
return PipelineStageFlags.PipelineStageTessellationControlShaderBit;
|
||||
case ShaderStage.TessellationEvaluation:
|
||||
return PipelineStageFlags.PipelineStageTessellationEvaluationShaderBit;
|
||||
case ShaderStage.Fragment:
|
||||
return PipelineStageFlags.PipelineStageFragmentShaderBit;
|
||||
case ShaderStage.Compute:
|
||||
return PipelineStageFlags.PipelineStageComputeShaderBit;
|
||||
};
|
||||
|
||||
Logger.Debug?.Print(LogClass.Gpu, $"Invalid {nameof(ShaderStage)} enum value: {stage}.");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public static SamplerAddressMode Convert(this AddressMode mode)
|
||||
{
|
||||
switch (mode)
|
||||
|
|
|
@ -10,6 +10,8 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
{
|
||||
private readonly Device _device;
|
||||
private readonly Auto<DisposableImageView>[] _attachments;
|
||||
private readonly TextureView[] _colors;
|
||||
private readonly TextureView _depthStencil;
|
||||
private uint _validColorAttachments;
|
||||
|
||||
public uint Width { get; }
|
||||
|
@ -59,6 +61,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
int count = colorsCount + (IsValidTextureView(depthStencil) ? 1 : 0);
|
||||
|
||||
_attachments = new Auto<DisposableImageView>[count];
|
||||
_colors = new TextureView[colorsCount];
|
||||
|
||||
AttachmentSamples = new uint[count];
|
||||
AttachmentFormats = new VkFormat[count];
|
||||
|
@ -79,6 +82,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
var texture = (TextureView)color;
|
||||
|
||||
_attachments[index] = texture.GetImageViewForAttachment();
|
||||
_colors[index] = texture;
|
||||
_validColorAttachments |= 1u << bindIndex;
|
||||
|
||||
AttachmentSamples[index] = (uint)texture.Info.Samples;
|
||||
|
@ -101,6 +105,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
if (depthStencil is TextureView dsTexture && dsTexture.Valid)
|
||||
{
|
||||
_attachments[count - 1] = dsTexture.GetImageViewForAttachment();
|
||||
_depthStencil = dsTexture;
|
||||
|
||||
AttachmentSamples[count - 1] = (uint)dsTexture.Info.Samples;
|
||||
AttachmentFormats[count - 1] = dsTexture.VkFormat;
|
||||
|
@ -177,5 +182,22 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
api.CreateFramebuffer(_device, framebufferCreateInfo, null, out var framebuffer).ThrowOnError();
|
||||
return new Auto<DisposableFramebuffer>(new DisposableFramebuffer(api, _device, framebuffer), null, _attachments);
|
||||
}
|
||||
|
||||
public void UpdateModifications()
|
||||
{
|
||||
if (_colors != null)
|
||||
{
|
||||
for (int index = 0; index < _colors.Length; index++)
|
||||
{
|
||||
_colors[index].Storage.SetModification(
|
||||
AccessFlags.AccessColorAttachmentWriteBit,
|
||||
PipelineStageFlags.PipelineStageColorAttachmentOutputBit);
|
||||
}
|
||||
}
|
||||
|
||||
_depthStencil?.Storage.SetModification(
|
||||
AccessFlags.AccessDepthStencilAttachmentWriteBit,
|
||||
PipelineStageFlags.PipelineStageColorAttachmentOutputBit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -190,7 +190,7 @@ void main()
|
|||
|
||||
var sampler = linearFilter ? _samplerLinear : _samplerNearest;
|
||||
|
||||
_pipeline.SetTextureAndSampler(Constants.MaxTexturesPerStage, src, sampler);
|
||||
_pipeline.SetTextureAndSampler(ShaderStage.Fragment, Constants.MaxTexturesPerStage, src, sampler);
|
||||
|
||||
Span<float> region = stackalloc float[RegionBufferSize / sizeof(float)];
|
||||
|
||||
|
@ -327,7 +327,7 @@ void main()
|
|||
{
|
||||
const int RegionBufferSize = 16;
|
||||
|
||||
pipeline.SetTextureAndSampler(Constants.MaxTexturesPerStage, src, srcSampler);
|
||||
pipeline.SetTextureAndSampler(ShaderStage.Fragment, Constants.MaxTexturesPerStage, src, srcSampler);
|
||||
|
||||
Span<float> region = stackalloc float[RegionBufferSize / sizeof(float)];
|
||||
|
||||
|
|
|
@ -627,6 +627,7 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
public void SetRenderTargets(ITexture[] colors, ITexture depthStencil)
|
||||
{
|
||||
FramebufferParams?.UpdateModifications();
|
||||
CreateFramebuffer(colors, depthStencil);
|
||||
CreateRenderPass();
|
||||
SignalStateChange();
|
||||
|
@ -710,9 +711,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
_descriptorSetUpdater.SetStorageBuffers(CommandBuffer, first, buffers);
|
||||
}
|
||||
|
||||
public void SetTextureAndSampler(int binding, ITexture texture, ISampler sampler)
|
||||
public void SetTextureAndSampler(ShaderStage stage, int binding, ITexture texture, ISampler sampler)
|
||||
{
|
||||
_descriptorSetUpdater.SetTextureAndSampler(binding, texture, sampler);
|
||||
_descriptorSetUpdater.SetTextureAndSampler(Cbs, stage, binding, texture, sampler);
|
||||
}
|
||||
|
||||
public void SetTransformFeedbackBuffers(ReadOnlySpan<BufferRange> buffers)
|
||||
|
|
|
@ -43,6 +43,9 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
|
||||
private Dictionary<GAL.Format, TextureStorage> _aliasedStorages;
|
||||
|
||||
private AccessFlags _lastModificationAccess;
|
||||
private PipelineStageFlags _lastModificationStage;
|
||||
|
||||
public VkFormat VkFormat { get; }
|
||||
public float ScaleFactor { get; }
|
||||
|
||||
|
@ -399,6 +402,56 @@ namespace Ryujinx.Graphics.Vulkan
|
|||
return Info.Format == GAL.Format.D24UnormS8Uint && VkFormat == VkFormat.D32SfloatS8Uint;
|
||||
}
|
||||
|
||||
public void SetModification(AccessFlags accessFlags, PipelineStageFlags stage)
|
||||
{
|
||||
_lastModificationAccess = accessFlags;
|
||||
_lastModificationStage = stage;
|
||||
}
|
||||
|
||||
public void InsertBarrier(CommandBufferScoped cbs, AccessFlags dstAccessFlags, PipelineStageFlags dstStageFlags)
|
||||
{
|
||||
if (_lastModificationAccess != AccessFlags.AccessNoneKhr)
|
||||
{
|
||||
ImageAspectFlags aspectFlags;
|
||||
|
||||
if (_info.Format.IsDepthOrStencil())
|
||||
{
|
||||
if (_info.Format == GAL.Format.S8Uint)
|
||||
{
|
||||
aspectFlags = ImageAspectFlags.ImageAspectStencilBit;
|
||||
}
|
||||
else if (_info.Format == GAL.Format.D16Unorm || _info.Format == GAL.Format.D32Float)
|
||||
{
|
||||
aspectFlags = ImageAspectFlags.ImageAspectDepthBit;
|
||||
}
|
||||
else
|
||||
{
|
||||
aspectFlags = ImageAspectFlags.ImageAspectDepthBit | ImageAspectFlags.ImageAspectStencilBit;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
aspectFlags = ImageAspectFlags.ImageAspectColorBit;
|
||||
}
|
||||
|
||||
TextureView.InsertImageBarrier(
|
||||
_gd.Api,
|
||||
cbs.CommandBuffer,
|
||||
_imageAuto.Get(cbs).Value,
|
||||
_lastModificationAccess,
|
||||
dstAccessFlags,
|
||||
_lastModificationStage,
|
||||
dstStageFlags,
|
||||
aspectFlags,
|
||||
0,
|
||||
0,
|
||||
_info.GetLayers(),
|
||||
_info.Levels);
|
||||
|
||||
_lastModificationAccess = AccessFlags.AccessNoneKhr;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
if (_aliasedStorages != null)
|
||||
|
|
Loading…
Reference in a new issue