Compare commits
13 Commits
1016_part3
...
vk_version
| Author | SHA1 | Date |
|---|---|---|
|
|
05e971ce85 | |
|
|
5bda682821 | |
|
|
43a599b4f7 | |
|
|
c2d20af21c | |
|
|
a57a448291 | |
|
|
ae04202815 | |
|
|
945717b320 | |
|
|
ad849891b4 | |
|
|
e7c9dca969 | |
|
|
43315e9b7a | |
|
|
ed2d6f0f52 | |
|
|
f06d2aa1b1 | |
|
|
92704490a7 |
|
|
@ -5,6 +5,7 @@ using System.Runtime.InteropServices;
|
|||
using SharpEmu.HLE.GpuMemory;
|
||||
using SharpEmu.Libs.Gpu.Scheduling;
|
||||
using SharpEmu.ShaderCompiler.Vulkan;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using Silk.NET.Vulkan;
|
||||
|
||||
namespace SharpEmu.Libs.Gpu.Buffers;
|
||||
|
|
@ -191,11 +192,11 @@ public sealed unsafe class BdaFaultProcessor : IDisposable
|
|||
_downloadBuffer.Mapped.Slice((int)offset, (int)PageFaultAreaSize).Clear();
|
||||
_downloadBuffer.Flush(offset, PageFaultAreaSize);
|
||||
|
||||
var preBarrier = new BufferMemoryBarrier
|
||||
var preBarrier = new BufferMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.BufferMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.ShaderWriteBit,
|
||||
DstAccessMask = AccessFlags.ShaderReadBit,
|
||||
SType = StructureType.BufferMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.ShaderWriteBit,
|
||||
DstAccessMask = AccessFlags2.ShaderReadBit,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
Buffer = _faultBuffer.Handle,
|
||||
|
|
@ -203,12 +204,12 @@ public sealed unsafe class BdaFaultProcessor : IDisposable
|
|||
Size = _faultBufferSize,
|
||||
};
|
||||
var postBarrier = preBarrier;
|
||||
postBarrier.DstAccessMask = AccessFlags.ShaderWriteBit;
|
||||
postBarrier.DstAccessMask = AccessFlags2.ShaderWriteBit;
|
||||
|
||||
_scheduler.EndRendering();
|
||||
var vk = _device.Vk;
|
||||
var command = new CommandBuffer(_scheduler.Current.Handle);
|
||||
vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(vk,
|
||||
command, PipelineStageFlags.AllCommandsBit, PipelineStageFlags.ComputeShaderBit, DependencyFlags.ByRegionBit,
|
||||
0, null, 1, &preBarrier, 0, null);
|
||||
vk.CmdBindPipeline(command, PipelineBindPoint.Compute, _pipeline);
|
||||
|
|
@ -216,7 +217,7 @@ public sealed unsafe class BdaFaultProcessor : IDisposable
|
|||
vk.CmdBindDescriptorSets(command, PipelineBindPoint.Compute, _pipelineLayout, 0, 1, &set, 0, null);
|
||||
var threads = _pageCount / 32;
|
||||
vk.CmdDispatch(command, (uint)((threads + 63) / 64), 1, 1);
|
||||
vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(vk,
|
||||
command, PipelineStageFlags.ComputeShaderBit, PipelineStageFlags.AllCommandsBit, DependencyFlags.ByRegionBit,
|
||||
0, null, 1, &postBarrier, 0, null);
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System.Numerics;
|
||||
using SharpEmu.Libs.Gpu.Scheduling;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using Silk.NET.Vulkan;
|
||||
using VkBuffer = Silk.NET.Vulkan.Buffer;
|
||||
|
||||
|
|
@ -190,18 +191,18 @@ public unsafe class GpuBuffer : IDisposable
|
|||
command.EndRendering();
|
||||
var vk = _device.Vk;
|
||||
var native = new CommandBuffer(command.Handle);
|
||||
var before = stackalloc BufferMemoryBarrier[2];
|
||||
var before = stackalloc BufferMemoryBarrier2[2];
|
||||
before[0] = source.CreateBarrier(sourceOffset, size, sourceBefore, AccessFlags.TransferReadBit);
|
||||
before[1] = CreateBarrier(destinationOffset, size, destinationBefore, AccessFlags.TransferWriteBit);
|
||||
vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(vk,
|
||||
native, GetAccessStage(sourceBefore | destinationBefore), PipelineStageFlags.TransferBit, DependencyFlags.ByRegionBit,
|
||||
0, null, 2, before, 0, null);
|
||||
var copy = new BufferCopy(sourceOffset, destinationOffset, size);
|
||||
vk.CmdCopyBuffer(native, source.Handle, Handle, 1, ©);
|
||||
var after = stackalloc BufferMemoryBarrier[2];
|
||||
var after = stackalloc BufferMemoryBarrier2[2];
|
||||
after[0] = source.CreateBarrier(sourceOffset, size, AccessFlags.TransferReadBit, sourceAfter);
|
||||
after[1] = CreateBarrier(destinationOffset, size, AccessFlags.TransferWriteBit, destinationAfter);
|
||||
vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(vk,
|
||||
native, PipelineStageFlags.TransferBit, GetAccessStage(sourceAfter | destinationAfter), DependencyFlags.ByRegionBit,
|
||||
0, null, 2, after, 0, null);
|
||||
}
|
||||
|
|
@ -218,12 +219,12 @@ public unsafe class GpuBuffer : IDisposable
|
|||
var vk = _device.Vk;
|
||||
var native = new CommandBuffer(command.Handle);
|
||||
var before = CreateBarrier(offset, size, MemoryAccess, AccessFlags.TransferWriteBit);
|
||||
vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(vk,
|
||||
native, PipelineStageFlags.AllCommandsBit, PipelineStageFlags.TransferBit, DependencyFlags.ByRegionBit,
|
||||
0, null, 1, &before, 0, null);
|
||||
vk.CmdFillBuffer(native, Handle, offset, size, value);
|
||||
var after = CreateBarrier(offset, size, AccessFlags.TransferWriteBit, MemoryAccess);
|
||||
vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(vk,
|
||||
native, PipelineStageFlags.TransferBit, PipelineStageFlags.AllCommandsBit, DependencyFlags.ByRegionBit,
|
||||
0, null, 1, &after, 0, null);
|
||||
}
|
||||
|
|
@ -284,7 +285,7 @@ public unsafe class GpuBuffer : IDisposable
|
|||
};
|
||||
}
|
||||
|
||||
private BufferMemoryBarrier CreateBarrier(ulong offset, ulong size, AccessFlags source, AccessFlags destination)
|
||||
private BufferMemoryBarrier2 CreateBarrier(ulong offset, ulong size, AccessFlags source, AccessFlags destination)
|
||||
{
|
||||
if (Handle.Handle == 0 || size == 0 || offset > Size || size > Size - offset)
|
||||
{
|
||||
|
|
@ -292,11 +293,11 @@ public unsafe class GpuBuffer : IDisposable
|
|||
$"The DMA barrier range is invalid: handle=0x{Handle.Handle:X} offset=0x{offset:X16} size=0x{size:X16} capacity=0x{Size:X16}");
|
||||
}
|
||||
|
||||
return new BufferMemoryBarrier
|
||||
return new BufferMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.BufferMemoryBarrier,
|
||||
SrcAccessMask = source,
|
||||
DstAccessMask = destination,
|
||||
SType = StructureType.BufferMemoryBarrier2,
|
||||
SrcAccessMask = VulkanSynchronization.Access(source),
|
||||
DstAccessMask = VulkanSynchronization.Access(destination),
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
Buffer = Handle,
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using SharpEmu.HLE.GuestMemory;
|
|||
using SharpEmu.Libs.Gpu.Scheduling;
|
||||
using SharpEmu.Libs.Kernel;
|
||||
using SharpEmu.Libs.VideoOut;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using Silk.NET.Vulkan;
|
||||
|
||||
namespace SharpEmu.Libs.Gpu.Buffers;
|
||||
|
|
@ -1014,18 +1015,18 @@ public sealed unsafe class GuestBufferCache : IGuestBufferStore, IDisposable
|
|||
command.EndRendering();
|
||||
var native = new CommandBuffer(command.Handle);
|
||||
var vk = _device.Vk;
|
||||
var before = new BufferMemoryBarrier
|
||||
var before = new BufferMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.BufferMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit | AccessFlags.TransferReadBit | AccessFlags.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags.TransferWriteBit,
|
||||
SType = StructureType.BufferMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.MemoryReadBit | AccessFlags2.MemoryWriteBit | AccessFlags2.TransferReadBit | AccessFlags2.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags2.TransferWriteBit,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
Buffer = buffer.Handle,
|
||||
Offset = 0,
|
||||
Size = buffer.Size,
|
||||
};
|
||||
vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(vk,
|
||||
native, PipelineStageFlags.AllCommandsBit, PipelineStageFlags.TransferBit, DependencyFlags.ByRegionBit,
|
||||
0, null, 1, &before, 0, null);
|
||||
var regions = CollectionsMarshal.AsSpan(copies);
|
||||
|
|
@ -1035,9 +1036,9 @@ public sealed unsafe class GuestBufferCache : IGuestBufferStore, IDisposable
|
|||
}
|
||||
|
||||
var after = before;
|
||||
after.SrcAccessMask = AccessFlags.TransferWriteBit;
|
||||
after.DstAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit;
|
||||
vk.CmdPipelineBarrier(
|
||||
after.SrcAccessMask = AccessFlags2.TransferWriteBit;
|
||||
after.DstAccessMask = AccessFlags2.MemoryReadBit | AccessFlags2.MemoryWriteBit;
|
||||
VulkanSynchronization.PipelineBarrier(vk,
|
||||
native, PipelineStageFlags.TransferBit, PipelineStageFlags.AllCommandsBit, DependencyFlags.ByRegionBit,
|
||||
0, null, 1, &after, 0, null);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using SharpEmu.Libs.Gpu.Buffers;
|
||||
using SharpEmu.Libs.Gpu.Scheduling;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using Silk.NET.Vulkan;
|
||||
using VkBuffer = Silk.NET.Vulkan.Buffer;
|
||||
|
||||
|
|
@ -17,11 +18,11 @@ public sealed unsafe partial class CachedImage
|
|||
private const ImageLayout ReadyLayout = ImageLayout.General;
|
||||
private const AccessFlags ReadyAccess = AccessFlags.ShaderReadBit | AccessFlags.TransferReadBit;
|
||||
|
||||
private ImageMemoryBarrier MakeBarrier(in ImageAccessState from, ImageLayout layout, AccessFlags access, uint baseLevel, uint levelCount, uint baseLayer, uint layerCount) => new()
|
||||
private ImageMemoryBarrier2 MakeBarrier(in ImageAccessState from, ImageLayout layout, AccessFlags access, uint baseLevel, uint levelCount, uint baseLayer, uint layerCount) => new()
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SrcAccessMask = from.Access,
|
||||
DstAccessMask = access,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = VulkanSynchronization.Access(from.Access),
|
||||
DstAccessMask = VulkanSynchronization.Access(access),
|
||||
OldLayout = from.Layout,
|
||||
NewLayout = layout,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -31,9 +32,9 @@ public sealed unsafe partial class CachedImage
|
|||
};
|
||||
|
||||
// Barriers for the requested state; a repeated write always gets a barrier.
|
||||
public (List<ImageMemoryBarrier> Barriers, PipelineStageFlags SourceStages) GetBarriers(ImageLayout layout, AccessFlags access, PipelineStageFlags stage, SubresourceRange? range)
|
||||
public (List<ImageMemoryBarrier2> Barriers, PipelineStageFlags SourceStages) GetBarriers(ImageLayout layout, AccessFlags access, PipelineStageFlags stage, SubresourceRange? range)
|
||||
{
|
||||
var barriers = new List<ImageMemoryBarrier>();
|
||||
var barriers = new List<ImageMemoryBarrier2>();
|
||||
PipelineStageFlags sourceStages = 0;
|
||||
if (range is { } && Description.IsVolume)
|
||||
{
|
||||
|
|
@ -128,22 +129,22 @@ public sealed unsafe partial class CachedImage
|
|||
RecordBarriers(command, sourceStages, stage, null, barriers);
|
||||
}
|
||||
|
||||
private void RecordBarriers(CommandBuffer command, PipelineStageFlags sourceStages, PipelineStageFlags destinationStages, BufferMemoryBarrier* bufferBarrier, List<ImageMemoryBarrier> imageBarriers)
|
||||
private void RecordBarriers(CommandBuffer command, PipelineStageFlags sourceStages, PipelineStageFlags destinationStages, BufferMemoryBarrier2* bufferBarrier, List<ImageMemoryBarrier2> imageBarriers)
|
||||
{
|
||||
var images = imageBarriers.ToArray();
|
||||
fixed (ImageMemoryBarrier* imagePointer = images)
|
||||
fixed (ImageMemoryBarrier2* imagePointer = images)
|
||||
{
|
||||
_device.Vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_device.Vk,
|
||||
command, sourceStages == 0 ? PipelineStageFlags.TopOfPipeBit : sourceStages, destinationStages, DependencyFlags.ByRegionBit,
|
||||
0, null, bufferBarrier == null ? 0u : 1u, bufferBarrier, (uint)images.Length, imagePointer);
|
||||
}
|
||||
}
|
||||
|
||||
private static BufferMemoryBarrier BufferBarrier(VkBuffer buffer, ulong offset, ulong size, AccessFlags source, AccessFlags destination) => new()
|
||||
private static BufferMemoryBarrier2 BufferBarrier(VkBuffer buffer, ulong offset, ulong size, AccessFlags source, AccessFlags destination) => new()
|
||||
{
|
||||
SType = StructureType.BufferMemoryBarrier,
|
||||
SrcAccessMask = source,
|
||||
DstAccessMask = destination,
|
||||
SType = StructureType.BufferMemoryBarrier2,
|
||||
SrcAccessMask = VulkanSynchronization.Access(source),
|
||||
DstAccessMask = VulkanSynchronization.Access(destination),
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
Buffer = buffer,
|
||||
|
|
@ -218,7 +219,7 @@ public sealed unsafe partial class CachedImage
|
|||
}
|
||||
|
||||
bufferBarrier = BufferBarrier(buffer, offset, size, AccessFlags.TransferReadBit, MemoryAccess);
|
||||
_device.Vk.CmdPipelineBarrier(command, PipelineStageFlags.TransferBit, PipelineStageFlags.AllCommandsBit, DependencyFlags.ByRegionBit, 0, null, 1, &bufferBarrier, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(_device.Vk,command, PipelineStageFlags.TransferBit, PipelineStageFlags.AllCommandsBit, DependencyFlags.ByRegionBit, 0, null, 1, &bufferBarrier, 0, null);
|
||||
Transition(ReadyLayout, ReadyAccess, null, command);
|
||||
}
|
||||
|
||||
|
|
@ -234,7 +235,7 @@ public sealed unsafe partial class CachedImage
|
|||
}
|
||||
|
||||
bufferBarrier = BufferBarrier(buffer, offset, size, AccessFlags.TransferWriteBit, MemoryAccess);
|
||||
_device.Vk.CmdPipelineBarrier(command, PipelineStageFlags.TransferBit, PipelineStageFlags.AllCommandsBit, DependencyFlags.ByRegionBit, 0, null, 1, &bufferBarrier, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(_device.Vk,command, PipelineStageFlags.TransferBit, PipelineStageFlags.AllCommandsBit, DependencyFlags.ByRegionBit, 0, null, 1, &bufferBarrier, 0, null);
|
||||
}
|
||||
|
||||
private static (uint SourceLayers, uint DestinationLayers) SanitizeCopyLayers(CachedImage source, CachedImage destination, uint depth)
|
||||
|
|
@ -528,10 +529,10 @@ public sealed unsafe partial class CachedImage
|
|||
destinationCopy.ImageSubresource = new ImageSubresourceLayers(destinationAspect, level, Backing.ImageType == ImageType.Type3D ? 0 : slice, 1);
|
||||
destinationCopy.ImageOffset.Z = Backing.ImageType == ImageType.Type3D ? (int)slice : 0;
|
||||
var barrier = BufferBarrier(buffer.Handle, 0, copySize, AccessFlags.TransferReadBit, AccessFlags.TransferWriteBit);
|
||||
_device.Vk.CmdPipelineBarrier(command, PipelineStageFlags.TransferBit, PipelineStageFlags.TransferBit, DependencyFlags.ByRegionBit, 0, null, 1, &barrier, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(_device.Vk,command, PipelineStageFlags.TransferBit, PipelineStageFlags.TransferBit, DependencyFlags.ByRegionBit, 0, null, 1, &barrier, 0, null);
|
||||
_device.Vk.CmdCopyImageToBuffer(command, source.Backing.Handle, ImageLayout.TransferSrcOptimal, buffer.Handle, 1, &sourceCopy);
|
||||
barrier = BufferBarrier(buffer.Handle, 0, copySize, AccessFlags.TransferWriteBit, AccessFlags.TransferReadBit);
|
||||
_device.Vk.CmdPipelineBarrier(command, PipelineStageFlags.TransferBit, PipelineStageFlags.TransferBit, DependencyFlags.ByRegionBit, 0, null, 1, &barrier, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(_device.Vk,command, PipelineStageFlags.TransferBit, PipelineStageFlags.TransferBit, DependencyFlags.ByRegionBit, 0, null, 1, &barrier, 0, null);
|
||||
_device.Vk.CmdCopyBufferToImage(command, buffer.Handle, Backing.Handle, ImageLayout.TransferDstOptimal, 1, &destinationCopy);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System.Runtime.InteropServices;
|
|||
using SharpEmu.Libs.Gpu.Buffers;
|
||||
using SharpEmu.Libs.Gpu.Scheduling;
|
||||
using SharpEmu.ShaderCompiler.Vulkan;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using Silk.NET.Vulkan;
|
||||
using VkBuffer = Silk.NET.Vulkan.Buffer;
|
||||
|
||||
|
|
@ -437,11 +438,11 @@ public sealed unsafe class GpuTiler : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
private static BufferMemoryBarrier Barrier(VkBuffer buffer, ulong offset, ulong size, AccessFlags source, AccessFlags destination) => new()
|
||||
private static BufferMemoryBarrier2 Barrier(VkBuffer buffer, ulong offset, ulong size, AccessFlags source, AccessFlags destination) => new()
|
||||
{
|
||||
SType = StructureType.BufferMemoryBarrier,
|
||||
SrcAccessMask = source,
|
||||
DstAccessMask = destination,
|
||||
SType = StructureType.BufferMemoryBarrier2,
|
||||
SrcAccessMask = VulkanSynchronization.Access(source),
|
||||
DstAccessMask = VulkanSynchronization.Access(destination),
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
Buffer = buffer,
|
||||
|
|
@ -496,21 +497,21 @@ public sealed unsafe class GpuTiler : IDisposable
|
|||
|
||||
_scheduler.EndRendering();
|
||||
var command = new CommandBuffer(_scheduler.Current.Handle);
|
||||
var barriers = stackalloc BufferMemoryBarrier[3];
|
||||
var barriers = stackalloc BufferMemoryBarrier2[3];
|
||||
barriers[0] = Barrier(source, sourceOffset, sourceCapacity, AccessFlags.MemoryWriteBit | AccessFlags.HostWriteBit, AccessFlags.ShaderReadBit);
|
||||
barriers[1] = Barrier(target, targetOffset, targetCapacity, AccessFlags.MemoryWriteBit | AccessFlags.HostWriteBit,
|
||||
clearTarget ? AccessFlags.TransferWriteBit : AccessFlags.ShaderReadBit | AccessFlags.ShaderWriteBit);
|
||||
var first = dispatches[0].ArgumentsOffset;
|
||||
var last = dispatches[^1].ArgumentsOffset;
|
||||
barriers[2] = Barrier(dispatches[0].ArgumentsBuffer, first, last - first + TileTransferArguments.Size, AccessFlags.HostWriteBit, AccessFlags.UniformReadBit);
|
||||
vk.CmdPipelineBarrier(command, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit,
|
||||
VulkanSynchronization.PipelineBarrier(vk,command, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit,
|
||||
PipelineStageFlags.ComputeShaderBit | PipelineStageFlags.TransferBit, 0, 0, null, 3, barriers, 0, null);
|
||||
if (clearTarget)
|
||||
{
|
||||
vk.CmdFillBuffer(command, target, targetOffset, targetCapacity, 0);
|
||||
barriers[1].SrcAccessMask = AccessFlags.TransferWriteBit;
|
||||
barriers[1].DstAccessMask = AccessFlags.ShaderReadBit | AccessFlags.ShaderWriteBit;
|
||||
vk.CmdPipelineBarrier(command, PipelineStageFlags.TransferBit, PipelineStageFlags.ComputeShaderBit, 0, 0, null, 1, barriers + 1, 0, null);
|
||||
barriers[1].SrcAccessMask = AccessFlags2.TransferWriteBit;
|
||||
barriers[1].DstAccessMask = AccessFlags2.ShaderReadBit | AccessFlags2.ShaderWriteBit;
|
||||
VulkanSynchronization.PipelineBarrier(vk,command, PipelineStageFlags.TransferBit, PipelineStageFlags.ComputeShaderBit, 0, 0, null, 1, barriers + 1, 0, null);
|
||||
}
|
||||
|
||||
Span<DescriptorBufferInfo> infos = stackalloc DescriptorBufferInfo[3];
|
||||
|
|
@ -524,9 +525,9 @@ public sealed unsafe class GpuTiler : IDisposable
|
|||
vk.CmdDispatch(command, (dispatch.Arguments.Width + 7) / 8, (dispatch.Arguments.Height + 7) / 8, dispatch.Arguments.Depth);
|
||||
}
|
||||
|
||||
barriers[1].SrcAccessMask = AccessFlags.ShaderWriteBit;
|
||||
barriers[1].DstAccessMask = AccessFlags.TransferReadBit | AccessFlags.MemoryReadBit;
|
||||
vk.CmdPipelineBarrier(command, PipelineStageFlags.ComputeShaderBit, PipelineStageFlags.AllCommandsBit, 0, 0, null, 1, barriers + 1, 0, null);
|
||||
barriers[1].SrcAccessMask = AccessFlags2.ShaderWriteBit;
|
||||
barriers[1].DstAccessMask = AccessFlags2.TransferReadBit | AccessFlags2.MemoryReadBit;
|
||||
VulkanSynchronization.PipelineBarrier(vk,command, PipelineStageFlags.ComputeShaderBit, PipelineStageFlags.AllCommandsBit, 0, 0, null, 1, barriers + 1, 0, null);
|
||||
}
|
||||
|
||||
// Detiles into a scratch buffer that lives through the current tick.
|
||||
|
|
@ -673,13 +674,13 @@ public sealed unsafe class GpuTiler : IDisposable
|
|||
var vk = _device.Vk;
|
||||
_scheduler.EndRendering();
|
||||
var command = new CommandBuffer(_scheduler.Current.Handle);
|
||||
var barriers = stackalloc BufferMemoryBarrier[2];
|
||||
var barriers = stackalloc BufferMemoryBarrier2[2];
|
||||
barriers[0] = Barrier(source.Buffer, source.Offset, sourceBarrierSize,
|
||||
AccessFlags.MemoryWriteBit | AccessFlags.HostWriteBit | AccessFlags.TransferWriteBit | AccessFlags.ShaderWriteBit, AccessFlags.ShaderReadBit);
|
||||
barriers[1] = Barrier(target.Buffer, target.Offset, targetBarrierSize,
|
||||
AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit | AccessFlags.HostWriteBit | AccessFlags.TransferWriteBit | AccessFlags.ShaderWriteBit,
|
||||
AccessFlags.ShaderReadBit | AccessFlags.ShaderWriteBit);
|
||||
vk.CmdPipelineBarrier(command, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit, PipelineStageFlags.ComputeShaderBit, 0, 0, null, 2, barriers, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(vk,command, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit, PipelineStageFlags.ComputeShaderBit, 0, 0, null, 2, barriers, 0, null);
|
||||
vk.CmdBindPipeline(command, PipelineBindPoint.Compute, pipeline);
|
||||
|
||||
var descriptorAlignment = StorageAlignment;
|
||||
|
|
@ -737,9 +738,9 @@ public sealed unsafe class GpuTiler : IDisposable
|
|||
}
|
||||
}
|
||||
|
||||
barriers[1].SrcAccessMask = AccessFlags.ShaderWriteBit;
|
||||
barriers[1].DstAccessMask = AccessFlags.TransferReadBit | AccessFlags.MemoryReadBit;
|
||||
vk.CmdPipelineBarrier(command, PipelineStageFlags.ComputeShaderBit, PipelineStageFlags.AllCommandsBit, 0, 0, null, 1, barriers + 1, 0, null);
|
||||
barriers[1].SrcAccessMask = AccessFlags2.ShaderWriteBit;
|
||||
barriers[1].DstAccessMask = AccessFlags2.TransferReadBit | AccessFlags2.MemoryReadBit;
|
||||
VulkanSynchronization.PipelineBarrier(vk,command, PipelineStageFlags.ComputeShaderBit, PipelineStageFlags.AllCommandsBit, 0, 0, null, 1, barriers + 1, 0, null);
|
||||
}
|
||||
|
||||
private void SwapBgra16(TilerBufferSpan input, TilerBufferSpan output, uint pixels)
|
||||
|
|
@ -760,20 +761,20 @@ public sealed unsafe class GpuTiler : IDisposable
|
|||
Span<DescriptorBufferInfo> infos = stackalloc DescriptorBufferInfo[2];
|
||||
infos[0] = inputBinding.Info;
|
||||
infos[1] = outputBinding.Info;
|
||||
var barriers = stackalloc BufferMemoryBarrier[2];
|
||||
var barriers = stackalloc BufferMemoryBarrier2[2];
|
||||
barriers[0] = Barrier(infos[0].Buffer, infos[0].Offset, infos[0].Range, AccessFlags.MemoryWriteBit | AccessFlags.HostWriteBit | AccessFlags.ShaderWriteBit, AccessFlags.ShaderReadBit);
|
||||
barriers[1] = Barrier(infos[1].Buffer, infos[1].Offset, infos[1].Range, AccessFlags.MemoryReadBit, AccessFlags.ShaderWriteBit);
|
||||
var vk = _device.Vk;
|
||||
_scheduler.EndRendering();
|
||||
var command = new CommandBuffer(_scheduler.Current.Handle);
|
||||
vk.CmdPipelineBarrier(command, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit, PipelineStageFlags.ComputeShaderBit, 0, 0, null, 2, barriers, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(vk,command, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit, PipelineStageFlags.ComputeShaderBit, 0, 0, null, 2, barriers, 0, null);
|
||||
vk.CmdBindPipeline(command, PipelineBindPoint.Compute, _swapBgra16);
|
||||
BindDescriptorSet(command, WriteDescriptorSet(infos, -1));
|
||||
PushArguments(command, new TileTransferArguments { SourceBase = inputBinding.Base, DestinationBase = outputBinding.Base, Width = pixels });
|
||||
vk.CmdDispatch(command, (pixels + 63) / 64, 1, 1);
|
||||
barriers[1].SrcAccessMask = AccessFlags.ShaderWriteBit;
|
||||
barriers[1].DstAccessMask = AccessFlags.TransferReadBit;
|
||||
vk.CmdPipelineBarrier(command, PipelineStageFlags.ComputeShaderBit, PipelineStageFlags.TransferBit, 0, 0, null, 1, barriers + 1, 0, null);
|
||||
barriers[1].SrcAccessMask = AccessFlags2.ShaderWriteBit;
|
||||
barriers[1].DstAccessMask = AccessFlags2.TransferReadBit;
|
||||
VulkanSynchronization.PipelineBarrier(vk,command, PipelineStageFlags.ComputeShaderBit, PipelineStageFlags.TransferBit, 0, 0, null, 1, barriers + 1, 0, null);
|
||||
}
|
||||
|
||||
public TilerBufferSpan SwapBgra16(TilerBufferSpan input)
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using SharpEmu.Libs.Gpu.Buffers;
|
||||
using SharpEmu.Libs.Gpu.Scheduling;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using Silk.NET.Vulkan;
|
||||
|
||||
using SharpEmu.Libs.VideoOut;
|
||||
|
|
@ -686,11 +687,11 @@ public sealed unsafe partial class GuestImageCache
|
|||
|
||||
download.Flush(offset, range.Size);
|
||||
DownloadToBuffer(image, download, offset, range.Size, plan);
|
||||
var barrier = new BufferMemoryBarrier
|
||||
var barrier = new BufferMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.BufferMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.MemoryWriteBit | AccessFlags.TransferWriteBit | AccessFlags.ShaderWriteBit,
|
||||
DstAccessMask = AccessFlags.HostReadBit,
|
||||
SType = StructureType.BufferMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.MemoryWriteBit | AccessFlags2.TransferWriteBit | AccessFlags2.ShaderWriteBit,
|
||||
DstAccessMask = AccessFlags2.HostReadBit,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
Buffer = download.Handle,
|
||||
|
|
@ -698,7 +699,7 @@ public sealed unsafe partial class GuestImageCache
|
|||
Size = range.Size,
|
||||
};
|
||||
_scheduler.EndRendering();
|
||||
_device.Vk.CmdPipelineBarrier(new CommandBuffer(_scheduler.Current.Handle), PipelineStageFlags.AllCommandsBit, PipelineStageFlags.HostBit, 0, 0, null, 1, &barrier, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(_device.Vk,new CommandBuffer(_scheduler.Current.Handle), PipelineStageFlags.AllCommandsBit, PipelineStageFlags.HostBit, 0, 0, null, 1, &barrier, 0, null);
|
||||
var backing = _backing;
|
||||
_scheduler.QueuePriorityCompletionAction(() =>
|
||||
{
|
||||
|
|
|
|||
|
|
@ -13,18 +13,18 @@ public static class GlobalDataShareBarrier
|
|||
public const PipelineStageFlags SourceStages =
|
||||
PipelineStageFlags.HostBit | PipelineStageFlags.TransferBit | PipelineStageFlags.AllGraphicsBit | PipelineStageFlags.ComputeShaderBit;
|
||||
|
||||
public static BufferMemoryBarrier Make(VkBuffer buffer)
|
||||
public static BufferMemoryBarrier2 Make(VkBuffer buffer)
|
||||
{
|
||||
if (buffer.Handle == 0)
|
||||
{
|
||||
throw SubmissionScheduler.Fatal("The global data share buffer is missing.");
|
||||
}
|
||||
|
||||
return new BufferMemoryBarrier
|
||||
return new BufferMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.BufferMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.HostWriteBit | AccessFlags.TransferWriteBit | AccessFlags.ShaderWriteBit,
|
||||
DstAccessMask = AccessFlags.ShaderReadBit | AccessFlags.ShaderWriteBit,
|
||||
SType = StructureType.BufferMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.HostWriteBit | AccessFlags2.TransferWriteBit | AccessFlags2.ShaderWriteBit,
|
||||
DstAccessMask = AccessFlags2.ShaderReadBit | AccessFlags2.ShaderWriteBit,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
Buffer = buffer,
|
||||
|
|
|
|||
|
|
@ -89,7 +89,7 @@ internal sealed unsafe class VulkanCommandProfile : IDisposable
|
|||
queries.Count = 1;
|
||||
queries.Submitted = false;
|
||||
_vulkan.CmdResetQueryPool(command, queries.Pool, 0, QueryCapacity);
|
||||
_vulkan.CmdWriteTimestamp(command, PipelineStageFlags.TopOfPipeBit, queries.Pool, 0);
|
||||
_vulkan.CmdWriteTimestamp2(command, PipelineStageFlags2.TopOfPipeBit, queries.Pool, 0);
|
||||
}
|
||||
|
||||
public void WriteMarker(CommandBuffer command, IntervalKind kind, ulong pipeline = 0, uint first = 0, uint second = 0, uint third = 0)
|
||||
|
|
@ -108,7 +108,7 @@ internal sealed unsafe class VulkanCommandProfile : IDisposable
|
|||
var index = queries.Count++;
|
||||
queries.Markers[index] = new Marker(new IntervalKey(kind, pipeline), first, second, third);
|
||||
// Completion intervals do not isolate shader stages or eliminate overlap with later work.
|
||||
_vulkan.CmdWriteTimestamp(command, PipelineStageFlags.BottomOfPipeBit, queries.Pool, (uint)index);
|
||||
_vulkan.CmdWriteTimestamp2(command, PipelineStageFlags2.BottomOfPipeBit, queries.Pool, (uint)index);
|
||||
}
|
||||
|
||||
public void MarkSubmitted(nint command)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,56 @@
|
|||
// Copyright (C) 2026 SharpEmu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
using Silk.NET.Vulkan;
|
||||
|
||||
namespace SharpEmu.Libs.Gpu.Vulkan;
|
||||
|
||||
internal static unsafe class VulkanSynchronization
|
||||
{
|
||||
public static AccessFlags2 Access(AccessFlags access) => (AccessFlags2)(ulong)access;
|
||||
|
||||
public static void PipelineBarrier(
|
||||
Vk vk,
|
||||
CommandBuffer command,
|
||||
PipelineStageFlags sourceStages,
|
||||
PipelineStageFlags destinationStages,
|
||||
DependencyFlags dependencyFlags,
|
||||
uint memoryBarrierCount,
|
||||
MemoryBarrier2* memoryBarriers,
|
||||
uint bufferMemoryBarrierCount,
|
||||
BufferMemoryBarrier2* bufferMemoryBarriers,
|
||||
uint imageMemoryBarrierCount,
|
||||
ImageMemoryBarrier2* imageMemoryBarriers)
|
||||
{
|
||||
var sourceStages2 = (PipelineStageFlags2)(ulong)sourceStages;
|
||||
var destinationStages2 = (PipelineStageFlags2)(ulong)destinationStages;
|
||||
for (var index = 0u; index < memoryBarrierCount; index++)
|
||||
{
|
||||
memoryBarriers[index].SrcStageMask = sourceStages2;
|
||||
memoryBarriers[index].DstStageMask = destinationStages2;
|
||||
}
|
||||
for (var index = 0u; index < bufferMemoryBarrierCount; index++)
|
||||
{
|
||||
bufferMemoryBarriers[index].SrcStageMask = sourceStages2;
|
||||
bufferMemoryBarriers[index].DstStageMask = destinationStages2;
|
||||
}
|
||||
for (var index = 0u; index < imageMemoryBarrierCount; index++)
|
||||
{
|
||||
imageMemoryBarriers[index].SrcStageMask = sourceStages2;
|
||||
imageMemoryBarriers[index].DstStageMask = destinationStages2;
|
||||
}
|
||||
|
||||
var dependencyInfo = new DependencyInfo
|
||||
{
|
||||
SType = StructureType.DependencyInfo,
|
||||
DependencyFlags = dependencyFlags,
|
||||
MemoryBarrierCount = memoryBarrierCount,
|
||||
PMemoryBarriers = memoryBarriers,
|
||||
BufferMemoryBarrierCount = bufferMemoryBarrierCount,
|
||||
PBufferMemoryBarriers = bufferMemoryBarriers,
|
||||
ImageMemoryBarrierCount = imageMemoryBarrierCount,
|
||||
PImageMemoryBarriers = imageMemoryBarriers,
|
||||
};
|
||||
vk.CmdPipelineBarrier2(command, &dependencyInfo);
|
||||
}
|
||||
}
|
||||
|
|
@ -128,27 +128,47 @@ internal sealed unsafe class VulkanTickDevice : IGpuTickDevice
|
|||
fixed (ulong* signalSemaphores = bundle.SignalSemaphores)
|
||||
fixed (ulong* signalTicks = bundle.SignalTicks)
|
||||
{
|
||||
var timelineInfo = new TimelineSemaphoreSubmitInfo
|
||||
var waitInfos = stackalloc SemaphoreSubmitInfo[bundle.WaitCount];
|
||||
for (var index = 0; index < bundle.WaitCount; index++)
|
||||
{
|
||||
SType = StructureType.TimelineSemaphoreSubmitInfo,
|
||||
WaitSemaphoreValueCount = (uint)bundle.WaitCount,
|
||||
PWaitSemaphoreValues = waitTicks,
|
||||
SignalSemaphoreValueCount = (uint)bundle.SignalCount,
|
||||
PSignalSemaphoreValues = signalTicks,
|
||||
};
|
||||
var submitInfo = new SubmitInfo
|
||||
waitInfos[index] = new SemaphoreSubmitInfo
|
||||
{
|
||||
SType = StructureType.SemaphoreSubmitInfo,
|
||||
Semaphore = new VkSemaphore(waitSemaphores[index]),
|
||||
Value = waitTicks[index],
|
||||
StageMask = (PipelineStageFlags2)waitStages[index],
|
||||
};
|
||||
}
|
||||
|
||||
var signalInfos = stackalloc SemaphoreSubmitInfo[bundle.SignalCount];
|
||||
for (var index = 0; index < bundle.SignalCount; index++)
|
||||
{
|
||||
SType = StructureType.SubmitInfo,
|
||||
PNext = &timelineInfo,
|
||||
WaitSemaphoreCount = (uint)bundle.WaitCount,
|
||||
PWaitSemaphores = (VkSemaphore*)waitSemaphores,
|
||||
PWaitDstStageMask = (PipelineStageFlags*)waitStages,
|
||||
CommandBufferCount = 1,
|
||||
PCommandBuffers = &commandBuffer,
|
||||
SignalSemaphoreCount = (uint)bundle.SignalCount,
|
||||
PSignalSemaphores = (VkSemaphore*)signalSemaphores,
|
||||
signalInfos[index] = new SemaphoreSubmitInfo
|
||||
{
|
||||
SType = StructureType.SemaphoreSubmitInfo,
|
||||
Semaphore = new VkSemaphore(signalSemaphores[index]),
|
||||
Value = signalTicks[index],
|
||||
StageMask = PipelineStageFlags2.AllCommandsBit,
|
||||
};
|
||||
}
|
||||
|
||||
var commandInfo = new CommandBufferSubmitInfo
|
||||
{
|
||||
SType = StructureType.CommandBufferSubmitInfo,
|
||||
CommandBuffer = commandBuffer,
|
||||
DeviceMask = 1,
|
||||
};
|
||||
var result = _vk.QueueSubmit(_queue, 1, &submitInfo, default);
|
||||
var submitInfo = new SubmitInfo2
|
||||
{
|
||||
SType = StructureType.SubmitInfo2,
|
||||
WaitSemaphoreInfoCount = (uint)bundle.WaitCount,
|
||||
PWaitSemaphoreInfos = waitInfos,
|
||||
CommandBufferInfoCount = 1,
|
||||
PCommandBufferInfos = &commandInfo,
|
||||
SignalSemaphoreInfoCount = (uint)bundle.SignalCount,
|
||||
PSignalSemaphoreInfos = signalInfos,
|
||||
};
|
||||
var result = _vk.QueueSubmit2(_queue, 1, &submitInfo, default);
|
||||
if (result == Result.Success)
|
||||
CommandProfile?.MarkSubmitted(buffer);
|
||||
failure = result.ToString();
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ using SharpEmu.Libs.Gpu;
|
|||
using SharpEmu.Libs.Gpu.Buffers;
|
||||
using SharpEmu.Libs.Gpu.Images;
|
||||
using SharpEmu.Libs.Gpu.Scheduling;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using Silk.NET.Vulkan;
|
||||
using VkBuffer = Silk.NET.Vulkan.Buffer;
|
||||
|
||||
|
|
@ -751,11 +752,11 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
}
|
||||
|
||||
var initialized = texture.HostMoviePlane == 0 ? _hostMovieImageInitialized : _hostMovieChromaImageInitialized;
|
||||
var toTransfer = new ImageMemoryBarrier
|
||||
var toTransfer = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SrcAccessMask = initialized ? AccessFlags.ShaderReadBit : 0,
|
||||
DstAccessMask = AccessFlags.TransferWriteBit,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = initialized ? AccessFlags2.ShaderReadBit : 0,
|
||||
DstAccessMask = AccessFlags2.TransferWriteBit,
|
||||
OldLayout = initialized ? ImageLayout.ShaderReadOnlyOptimal : ImageLayout.Undefined,
|
||||
NewLayout = ImageLayout.TransferDstOptimal,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -763,7 +764,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = texture.Image,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
_vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
_commandBuffer, initialized ? PipelineStageFlags.AllCommandsBit : PipelineStageFlags.TopOfPipeBit, PipelineStageFlags.TransferBit,
|
||||
0, 0, null, 0, null, 1, &toTransfer);
|
||||
var copyRegion = new BufferImageCopy
|
||||
|
|
@ -773,11 +774,11 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
ImageExtent = new Extent3D(texture.Width, texture.Height, 1),
|
||||
};
|
||||
_vk.CmdCopyBufferToImage(_commandBuffer, texture.StagingBuffer, texture.Image, ImageLayout.TransferDstOptimal, 1, ©Region);
|
||||
var toShaderRead = new ImageMemoryBarrier
|
||||
var toShaderRead = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags.ShaderReadBit,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags2.ShaderReadBit,
|
||||
OldLayout = ImageLayout.TransferDstOptimal,
|
||||
NewLayout = ImageLayout.ShaderReadOnlyOptimal,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -785,7 +786,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = texture.Image,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
_vk.CmdPipelineBarrier(_commandBuffer, PipelineStageFlags.TransferBit, shaderStage, 0, 0, null, 0, null, 1, &toShaderRead);
|
||||
VulkanSynchronization.PipelineBarrier(_vk,_commandBuffer, PipelineStageFlags.TransferBit, shaderStage, 0, 0, null, 0, null, 1, &toShaderRead);
|
||||
if (texture.HostMoviePlane == 0)
|
||||
{
|
||||
_hostMovieImageInitialized = true;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ using SharpEmu.Libs.Gpu.GpuCommands;
|
|||
using SharpEmu.Libs.Gpu.Images;
|
||||
using SharpEmu.Libs.Gpu.Scheduling;
|
||||
using SharpEmu.ShaderCompiler;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using Silk.NET.Vulkan;
|
||||
|
||||
internal static unsafe partial class VulkanVideoPresenter
|
||||
|
|
@ -311,13 +312,13 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
EndRendering();
|
||||
EndRendering();
|
||||
var commandBuffer = BeginBatchedGuestCommands();
|
||||
var barrier = new MemoryBarrier
|
||||
var barrier = new MemoryBarrier2
|
||||
{
|
||||
SType = StructureType.MemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.MemoryWriteBit,
|
||||
DstAccessMask = AccessFlags.MemoryReadBit | AccessFlags.MemoryWriteBit,
|
||||
SType = StructureType.MemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.MemoryWriteBit,
|
||||
DstAccessMask = AccessFlags2.MemoryReadBit | AccessFlags2.MemoryWriteBit,
|
||||
};
|
||||
_vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
commandBuffer,
|
||||
PipelineStageFlags.AllCommandsBit,
|
||||
PipelineStageFlags.AllCommandsBit,
|
||||
|
|
@ -547,11 +548,11 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
snapshot = CreateGuestFlipSnapshot(GetPresentationSnapshotFormat(source.Backing.Format),
|
||||
extent.Width, extent.Height, displayBuffer.Address, version);
|
||||
source.Transition(ImageLayout.TransferSrcOptimal, AccessFlags.TransferReadBit, null, commandBuffer);
|
||||
var toTransferDst = new ImageMemoryBarrier
|
||||
var toTransferDst = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = 0,
|
||||
DstAccessMask = AccessFlags.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags2.TransferWriteBit,
|
||||
OldLayout = ImageLayout.Undefined,
|
||||
NewLayout = ImageLayout.TransferDstOptimal,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -559,7 +560,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = snapshot.Image,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
_vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
commandBuffer, PipelineStageFlags.TopOfPipeBit, PipelineStageFlags.TransferBit, 0, 0, null, 0, null, 1, &toTransferDst);
|
||||
var copy = new ImageCopy
|
||||
{
|
||||
|
|
@ -569,11 +570,11 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
};
|
||||
_vk.CmdCopyImage(
|
||||
commandBuffer, source.Backing.Handle, ImageLayout.TransferSrcOptimal, snapshot.Image, ImageLayout.TransferDstOptimal, 1, ©);
|
||||
var toShaderRead = new ImageMemoryBarrier
|
||||
var toShaderRead = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags.ShaderReadBit | AccessFlags.TransferReadBit,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags2.ShaderReadBit | AccessFlags2.TransferReadBit,
|
||||
OldLayout = ImageLayout.TransferDstOptimal,
|
||||
NewLayout = ImageLayout.ShaderReadOnlyOptimal,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -581,7 +582,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = snapshot.Image,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
_vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
commandBuffer, PipelineStageFlags.TransferBit, PipelineStageFlags.AllCommandsBit, 0, 0, null, 0, null, 1, &toShaderRead);
|
||||
|
||||
FlushBatchedGuestCommands();
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ using SharpEmu.Libs.Gpu.Rendering;
|
|||
using SharpEmu.Libs.Gpu.Scheduling;
|
||||
using SharpEmu.ShaderCompiler;
|
||||
using SharpEmu.ShaderCompiler.Resources;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using Silk.NET.Vulkan;
|
||||
using VkBuffer = Silk.NET.Vulkan.Buffer;
|
||||
|
||||
|
|
@ -678,7 +679,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
EndRendering();
|
||||
command = BeginBatchedGuestCommands();
|
||||
var barrier = GlobalDataShareBarrier.Make(descriptors.GlobalDataShare.Buffer);
|
||||
_vk.CmdPipelineBarrier(command, GlobalDataShareBarrier.SourceStages, DescriptorWriter.PipelineStageFlag(stageFlag), 0, 0, null, 1, &barrier, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(_vk,command, GlobalDataShareBarrier.SourceStages, DescriptorWriter.PipelineStageFlag(stageFlag), 0, 0, null, 1, &barrier, 0, null);
|
||||
}
|
||||
|
||||
RecordStageTextureTransitions(stage.Textures);
|
||||
|
|
|
|||
|
|
@ -63,6 +63,14 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
_relay.BindCurrentThread();
|
||||
WaitForRenderDocAttachIfRequested();
|
||||
_vk = Vk.GetApi();
|
||||
uint loaderVersion = Vk.Version10;
|
||||
Check(_vk.EnumerateInstanceVersion(ref loaderVersion), "vkEnumerateInstanceVersion");
|
||||
if (loaderVersion < Vk.Version13)
|
||||
{
|
||||
throw new InvalidOperationException(
|
||||
$"SharpEmu requires Vulkan 1.3; loader exposes {loaderVersion >> 22}.{(loaderVersion >> 12) & 0x3ff}.");
|
||||
}
|
||||
|
||||
CreateInstance();
|
||||
CreateSurface();
|
||||
SelectPhysicalDevice();
|
||||
|
|
@ -253,7 +261,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
ApplicationVersion = Vk.MakeVersion(0, 0, 1),
|
||||
PEngineName = applicationName,
|
||||
EngineVersion = Vk.MakeVersion(0, 0, 1),
|
||||
ApiVersion = Vk.Version12,
|
||||
ApiVersion = Vk.Version13,
|
||||
};
|
||||
|
||||
var extensions = _window.GetRequiredVulkanInstanceExtensions(out var extensionCount);
|
||||
|
|
@ -515,6 +523,14 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
}
|
||||
|
||||
_vk.GetPhysicalDeviceProperties(device, out var properties);
|
||||
if (properties.ApiVersion < Vk.Version13)
|
||||
{
|
||||
var unsupportedName = SilkMarshal.PtrToString((nint)properties.DeviceName) ?? string.Empty;
|
||||
Console.Error.WriteLine(
|
||||
$"[LOADER][INFO] Vulkan candidate skipped: {unsupportedName} api={properties.ApiVersion >> 22}.{(properties.ApiVersion >> 12) & 0x3ff} requires=1.3");
|
||||
break;
|
||||
}
|
||||
|
||||
var name = SilkMarshal.PtrToString((nint)properties.DeviceName) ?? string.Empty;
|
||||
var score = ScorePhysicalDevice(properties, name, deviceOverride);
|
||||
Console.Error.WriteLine(
|
||||
|
|
@ -740,25 +756,15 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
SType = StructureType.PhysicalDeviceColorWriteEnableFeaturesExt,
|
||||
PNext = &depthClipControlFeatures,
|
||||
};
|
||||
var extendedDynamicState2Features = new PhysicalDeviceExtendedDynamicState2FeaturesEXT
|
||||
var vulkan13Features = new PhysicalDeviceVulkan13Features
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt,
|
||||
SType = StructureType.PhysicalDeviceVulkan13Features,
|
||||
PNext = &colorWriteEnableFeatures,
|
||||
};
|
||||
var extendedDynamicStateFeatures = new PhysicalDeviceExtendedDynamicStateFeaturesEXT
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceExtendedDynamicStateFeaturesExt,
|
||||
PNext = &extendedDynamicState2Features,
|
||||
};
|
||||
var dynamicRenderingFeatures = new PhysicalDeviceDynamicRenderingFeaturesKHR
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceDynamicRenderingFeaturesKhr,
|
||||
PNext = &extendedDynamicStateFeatures,
|
||||
};
|
||||
var maintenance8Features = new PhysicalDeviceMaintenance8FeaturesKHR
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceMaintenance8FeaturesKhr,
|
||||
PNext = &dynamicRenderingFeatures,
|
||||
PNext = &vulkan13Features,
|
||||
};
|
||||
var robustness2Features = new PhysicalDeviceRobustness2FeaturesEXT
|
||||
{
|
||||
|
|
@ -790,10 +796,8 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
var supportsRobustness2 = supportsRobustImageAccess2 || supportsNullDescriptor;
|
||||
_vk.GetPhysicalDeviceProperties(_physicalDevice, out var deviceProperties);
|
||||
var deviceName = SilkMarshal.PtrToString((nint)deviceProperties.DeviceName) ?? "unknown";
|
||||
RequireRenderingFeature(dynamicRenderingFeatures.DynamicRendering, DynamicRenderingExtensionName, deviceName);
|
||||
RequireRenderingFeature(extendedDynamicStateFeatures.ExtendedDynamicState, ExtendedDynamicStateExtensionName, deviceName);
|
||||
RequireRenderingFeature(
|
||||
extendedDynamicState2Features.ExtendedDynamicState2, ExtendedDynamicState2ExtensionName, deviceName);
|
||||
RequireRenderingFeature(vulkan13Features.DynamicRendering, "Vulkan 1.3 dynamicRendering", deviceName);
|
||||
RequireRenderingFeature(vulkan13Features.Synchronization2, "Vulkan 1.3 synchronization2", deviceName);
|
||||
var supportsColorWriteEnable = colorWriteEnableFeatures.ColorWriteEnable;
|
||||
_supportsDepthClipControl = depthClipControlFeatures.DepthClipControl;
|
||||
_supportsDepthClipEnable = depthClipEnableFeatures.DepthClipEnable;
|
||||
|
|
@ -821,9 +825,6 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
var maintenance8Extension = (byte*)SilkMarshal.StringToPtr("VK_KHR_maintenance8");
|
||||
var robustness2Extension = (byte*)SilkMarshal.StringToPtr("VK_EXT_robustness2");
|
||||
var portabilitySubsetExtension = (byte*)SilkMarshal.StringToPtr(PortabilitySubsetExtensionName);
|
||||
var dynamicRenderingExtension = (byte*)SilkMarshal.StringToPtr(DynamicRenderingExtensionName);
|
||||
var extendedDynamicStateExtension = (byte*)SilkMarshal.StringToPtr(ExtendedDynamicStateExtensionName);
|
||||
var extendedDynamicState2Extension = (byte*)SilkMarshal.StringToPtr(ExtendedDynamicState2ExtensionName);
|
||||
var colorWriteEnableExtension = (byte*)SilkMarshal.StringToPtr(ColorWriteEnableExtensionName);
|
||||
var depthClipControlExtension = (byte*)SilkMarshal.StringToPtr(DepthClipControlExtensionName);
|
||||
var depthClipEnableExtension = (byte*)SilkMarshal.StringToPtr(DepthClipEnableExtensionName);
|
||||
|
|
@ -834,9 +835,6 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
var extensionCount = 0u;
|
||||
extensions[extensionCount++] = swapchainExtension;
|
||||
extensions[extensionCount++] = pushDescriptorExtension;
|
||||
extensions[extensionCount++] = dynamicRenderingExtension;
|
||||
extensions[extensionCount++] = extendedDynamicStateExtension;
|
||||
extensions[extensionCount++] = extendedDynamicState2Extension;
|
||||
if (_supportsFragmentShaderBarycentric)
|
||||
{
|
||||
extensions[extensionCount++] = barycentricExtension;
|
||||
|
|
@ -941,28 +939,17 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
renderingChain = &colorWriteEnableFeatures;
|
||||
}
|
||||
|
||||
extendedDynamicState2Features = new PhysicalDeviceExtendedDynamicState2FeaturesEXT
|
||||
vulkan13Features = new PhysicalDeviceVulkan13Features
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt,
|
||||
ExtendedDynamicState2 = true,
|
||||
PNext = renderingChain,
|
||||
};
|
||||
extendedDynamicStateFeatures = new PhysicalDeviceExtendedDynamicStateFeaturesEXT
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceExtendedDynamicStateFeaturesExt,
|
||||
ExtendedDynamicState = true,
|
||||
PNext = &extendedDynamicState2Features,
|
||||
};
|
||||
dynamicRenderingFeatures = new PhysicalDeviceDynamicRenderingFeaturesKHR
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceDynamicRenderingFeaturesKhr,
|
||||
SType = StructureType.PhysicalDeviceVulkan13Features,
|
||||
DynamicRendering = true,
|
||||
PNext = &extendedDynamicStateFeatures,
|
||||
Synchronization2 = true,
|
||||
PNext = renderingChain,
|
||||
};
|
||||
var features2 = new PhysicalDeviceFeatures2
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceFeatures2,
|
||||
PNext = &dynamicRenderingFeatures,
|
||||
PNext = &vulkan13Features,
|
||||
Features = enabledFeatures,
|
||||
};
|
||||
var createInfo = new DeviceCreateInfo
|
||||
|
|
@ -983,9 +970,6 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
SilkMarshal.Free((nint)maintenance8Extension);
|
||||
SilkMarshal.Free((nint)robustness2Extension);
|
||||
SilkMarshal.Free((nint)portabilitySubsetExtension);
|
||||
SilkMarshal.Free((nint)dynamicRenderingExtension);
|
||||
SilkMarshal.Free((nint)extendedDynamicStateExtension);
|
||||
SilkMarshal.Free((nint)extendedDynamicState2Extension);
|
||||
SilkMarshal.Free((nint)colorWriteEnableExtension);
|
||||
SilkMarshal.Free((nint)depthClipControlExtension);
|
||||
SilkMarshal.Free((nint)depthClipEnableExtension);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ namespace SharpEmu.Libs.VideoOut;
|
|||
using SharpEmu.Libs.Gpu;
|
||||
using SharpEmu.ShaderCompiler;
|
||||
using SharpEmu.Libs.Gpu.Images;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using Silk.NET.Vulkan;
|
||||
using VkBuffer = Silk.NET.Vulkan.Buffer;
|
||||
|
||||
|
|
@ -66,12 +67,12 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
var oldLayout = _imageInitialized[imageIndex]
|
||||
? PresentationTargetFinalLayout
|
||||
: ImageLayout.Undefined;
|
||||
var toTransfer = new ImageMemoryBarrier
|
||||
var toTransfer = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = _hdrOutputActive && _imageInitialized[imageIndex]
|
||||
? AccessFlags.ShaderReadBit : 0,
|
||||
DstAccessMask = AccessFlags.TransferWriteBit,
|
||||
? AccessFlags2.ShaderReadBit : 0,
|
||||
DstAccessMask = AccessFlags2.TransferWriteBit,
|
||||
OldLayout = oldLayout,
|
||||
NewLayout = ImageLayout.TransferDstOptimal,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -79,7 +80,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = presentationTarget,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
_vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
_commandBuffer,
|
||||
GetPresentationUploadSourceStage(_hdrOutputActive, _imageInitialized[imageIndex]),
|
||||
PipelineStageFlags.TransferBit,
|
||||
|
|
@ -108,13 +109,13 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
1,
|
||||
©Region);
|
||||
|
||||
var toFinalLayout = new ImageMemoryBarrier
|
||||
var toFinalLayout = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.TransferWriteBit,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.TransferWriteBit,
|
||||
DstAccessMask = _hdrOutputActive
|
||||
? AccessFlags.ShaderReadBit
|
||||
: AccessFlags.MemoryReadBit,
|
||||
? AccessFlags2.ShaderReadBit
|
||||
: AccessFlags2.MemoryReadBit,
|
||||
OldLayout = ImageLayout.TransferDstOptimal,
|
||||
NewLayout = PresentationTargetFinalLayout,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -122,7 +123,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = presentationTarget,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
_vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
_commandBuffer,
|
||||
PipelineStageFlags.TransferBit,
|
||||
_hdrOutputActive
|
||||
|
|
@ -246,9 +247,9 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
_commandBuffer,
|
||||
$"SharpEmu present image 0x{source.Address:X16}");
|
||||
|
||||
var sourceToTransfer = new ImageMemoryBarrier
|
||||
var sourceToTransfer = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
// An offscreen target is last written as a color attachment,
|
||||
// then put in ShaderReadOnlyOptimal for later sampling. A
|
||||
// layout-only handoff to ShaderRead does not make that write
|
||||
|
|
@ -257,8 +258,8 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
// (usually black) image while Windows drivers happened to
|
||||
// tolerate it. Include all preceding writes before blitting
|
||||
// the image into the swapchain.
|
||||
SrcAccessMask = AccessFlags.MemoryWriteBit | AccessFlags.ShaderReadBit,
|
||||
DstAccessMask = AccessFlags.TransferReadBit,
|
||||
SrcAccessMask = AccessFlags2.MemoryWriteBit | AccessFlags2.ShaderReadBit,
|
||||
DstAccessMask = AccessFlags2.TransferReadBit,
|
||||
OldLayout = ImageLayout.ShaderReadOnlyOptimal,
|
||||
NewLayout = ImageLayout.TransferSrcOptimal,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -266,15 +267,15 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = source.Image,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
var destinationToTransfer = new ImageMemoryBarrier
|
||||
var destinationToTransfer = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = _imageInitialized[imageIndex]
|
||||
? _hdrOutputActive
|
||||
? AccessFlags.ShaderReadBit
|
||||
: AccessFlags.MemoryReadBit
|
||||
? AccessFlags2.ShaderReadBit
|
||||
: AccessFlags2.MemoryReadBit
|
||||
: 0,
|
||||
DstAccessMask = AccessFlags.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags2.TransferWriteBit,
|
||||
OldLayout = _imageInitialized[imageIndex]
|
||||
? PresentationTargetFinalLayout
|
||||
: ImageLayout.Undefined,
|
||||
|
|
@ -293,11 +294,11 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
encodeForPresent = TryGetPresentEncodeImage(out encodeImage);
|
||||
}
|
||||
|
||||
var encodeToTransferDst = new ImageMemoryBarrier
|
||||
var encodeToTransferDst = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.TransferReadBit,
|
||||
DstAccessMask = AccessFlags.TransferWriteBit,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.TransferReadBit,
|
||||
DstAccessMask = AccessFlags2.TransferWriteBit,
|
||||
OldLayout = ImageLayout.Undefined,
|
||||
NewLayout = ImageLayout.TransferDstOptimal,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -305,11 +306,11 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = _presentEncodeImage,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
var barriers = stackalloc ImageMemoryBarrier[3];
|
||||
var barriers = stackalloc ImageMemoryBarrier2[3];
|
||||
barriers[0] = sourceToTransfer;
|
||||
barriers[1] = destinationToTransfer;
|
||||
barriers[2] = encodeToTransferDst;
|
||||
_vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
_commandBuffer,
|
||||
PipelineStageFlags.AllCommandsBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
|
|
@ -382,13 +383,13 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
&clearColor,
|
||||
1,
|
||||
&clearRange);
|
||||
var clearComplete = new MemoryBarrier
|
||||
var clearComplete = new MemoryBarrier2
|
||||
{
|
||||
SType = StructureType.MemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags.TransferWriteBit,
|
||||
SType = StructureType.MemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags2.TransferWriteBit,
|
||||
};
|
||||
_vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
_commandBuffer, PipelineStageFlags.TransferBit, PipelineStageFlags.TransferBit,
|
||||
0, 1, &clearComplete, 0, null, 0, null);
|
||||
}
|
||||
|
|
@ -479,11 +480,11 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
|
||||
if (encodeForPresent)
|
||||
{
|
||||
var encodeToTransferSrc = new ImageMemoryBarrier
|
||||
var encodeToTransferSrc = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags.TransferReadBit,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags2.TransferReadBit,
|
||||
OldLayout = ImageLayout.TransferDstOptimal,
|
||||
NewLayout = ImageLayout.TransferSrcOptimal,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -491,7 +492,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = encodeImage,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
_vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
_commandBuffer,
|
||||
PipelineStageFlags.TransferBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
|
|
@ -525,11 +526,11 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
|
||||
if (traceDestination)
|
||||
{
|
||||
var destinationToReadback = new ImageMemoryBarrier
|
||||
var destinationToReadback = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags.TransferReadBit,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags2.TransferReadBit,
|
||||
OldLayout = ImageLayout.TransferDstOptimal,
|
||||
NewLayout = ImageLayout.TransferSrcOptimal,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -537,7 +538,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = presentationTarget,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
_vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
_commandBuffer,
|
||||
PipelineStageFlags.TransferBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
|
|
@ -568,11 +569,11 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
_swapchainReadbackPending = true;
|
||||
}
|
||||
|
||||
var sourceToShaderRead = new ImageMemoryBarrier
|
||||
var sourceToShaderRead = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.TransferReadBit,
|
||||
DstAccessMask = AccessFlags.ShaderReadBit,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.TransferReadBit,
|
||||
DstAccessMask = AccessFlags2.ShaderReadBit,
|
||||
OldLayout = ImageLayout.TransferSrcOptimal,
|
||||
NewLayout = ImageLayout.ShaderReadOnlyOptimal,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -580,15 +581,15 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = source.Image,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
var destinationToFinalLayout = new ImageMemoryBarrier
|
||||
var destinationToFinalLayout = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = traceDestination
|
||||
? AccessFlags.TransferReadBit
|
||||
: AccessFlags.TransferWriteBit,
|
||||
? AccessFlags2.TransferReadBit
|
||||
: AccessFlags2.TransferWriteBit,
|
||||
DstAccessMask = _hdrOutputActive
|
||||
? AccessFlags.ShaderReadBit
|
||||
: AccessFlags.MemoryReadBit,
|
||||
? AccessFlags2.ShaderReadBit
|
||||
: AccessFlags2.MemoryReadBit,
|
||||
OldLayout = traceDestination
|
||||
? ImageLayout.TransferSrcOptimal
|
||||
: ImageLayout.TransferDstOptimal,
|
||||
|
|
@ -600,7 +601,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
};
|
||||
barriers[0] = sourceToShaderRead;
|
||||
barriers[1] = destinationToFinalLayout;
|
||||
_vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
_commandBuffer,
|
||||
PipelineStageFlags.TransferBit,
|
||||
_hdrOutputActive
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ namespace SharpEmu.Libs.VideoOut;
|
|||
|
||||
using SharpEmu.ShaderCompiler.Vulkan;
|
||||
using Silk.NET.Core.Native;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using Silk.NET.Vulkan;
|
||||
|
||||
internal static unsafe partial class VulkanVideoPresenter
|
||||
|
|
@ -309,13 +310,13 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
|
||||
private void RecordHdrPresentation(uint imageIndex, bool isHdr)
|
||||
{
|
||||
var sourceBarrier = new ImageMemoryBarrier
|
||||
var sourceBarrier = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.MemoryWriteBit |
|
||||
AccessFlags.TransferWriteBit |
|
||||
AccessFlags.ColorAttachmentWriteBit,
|
||||
DstAccessMask = AccessFlags.ShaderReadBit,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.MemoryWriteBit |
|
||||
AccessFlags2.TransferWriteBit |
|
||||
AccessFlags2.ColorAttachmentWriteBit,
|
||||
DstAccessMask = AccessFlags2.ShaderReadBit,
|
||||
OldLayout = ImageLayout.ShaderReadOnlyOptimal,
|
||||
NewLayout = ImageLayout.ShaderReadOnlyOptimal,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -323,7 +324,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = _presentationImages[imageIndex],
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
_vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
_commandBuffer,
|
||||
PipelineStageFlags.AllCommandsBit,
|
||||
PipelineStageFlags.FragmentShaderBit,
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
namespace SharpEmu.Libs.VideoOut;
|
||||
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using Silk.NET.Vulkan;
|
||||
using VkBuffer = Silk.NET.Vulkan.Buffer;
|
||||
|
||||
|
|
@ -91,11 +92,11 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
PerfOverlay.Fill(pixels, pendingWork, _pendingGuestSubmissions.Count);
|
||||
var presentationTarget = PresentationTargetImage(imageIndex);
|
||||
|
||||
var toTransferDst = new ImageMemoryBarrier
|
||||
var toTransferDst = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SrcAccessMask = _overlayImageInitialized ? AccessFlags.TransferReadBit : 0,
|
||||
DstAccessMask = AccessFlags.TransferWriteBit,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = _overlayImageInitialized ? AccessFlags2.TransferReadBit : 0,
|
||||
DstAccessMask = AccessFlags2.TransferWriteBit,
|
||||
OldLayout = _overlayImageInitialized
|
||||
? ImageLayout.TransferSrcOptimal
|
||||
: ImageLayout.Undefined,
|
||||
|
|
@ -105,7 +106,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = _overlayImage,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
_vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
_commandBuffer,
|
||||
PipelineStageFlags.TransferBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
|
|
@ -124,11 +125,11 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
1,
|
||||
©Region);
|
||||
|
||||
var toTransferSrc = new ImageMemoryBarrier
|
||||
var toTransferSrc = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags.TransferReadBit,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags2.TransferReadBit,
|
||||
OldLayout = ImageLayout.TransferDstOptimal,
|
||||
NewLayout = ImageLayout.TransferSrcOptimal,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -136,11 +137,11 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = _overlayImage,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
var swapchainToDst = new ImageMemoryBarrier
|
||||
var swapchainToDst = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = 0,
|
||||
DstAccessMask = AccessFlags.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags2.TransferWriteBit,
|
||||
OldLayout = PresentationTargetFinalLayout,
|
||||
NewLayout = ImageLayout.TransferDstOptimal,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -148,8 +149,8 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = presentationTarget,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
var preBlitBarriers = stackalloc ImageMemoryBarrier[2] { toTransferSrc, swapchainToDst };
|
||||
_vk.CmdPipelineBarrier(
|
||||
var preBlitBarriers = stackalloc ImageMemoryBarrier2[2] { toTransferSrc, swapchainToDst };
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
_commandBuffer,
|
||||
PipelineStageFlags.TransferBit | PipelineStageFlags.ColorAttachmentOutputBit,
|
||||
PipelineStageFlags.TransferBit,
|
||||
|
|
@ -180,11 +181,11 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
1,
|
||||
©);
|
||||
|
||||
var presentationTargetToFinal = new ImageMemoryBarrier
|
||||
var presentationTargetToFinal = new ImageMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.ImageMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.TransferWriteBit,
|
||||
DstAccessMask = _hdrOutputActive ? AccessFlags.ShaderReadBit : 0,
|
||||
SType = StructureType.ImageMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.TransferWriteBit,
|
||||
DstAccessMask = _hdrOutputActive ? AccessFlags2.ShaderReadBit : 0,
|
||||
OldLayout = ImageLayout.TransferDstOptimal,
|
||||
NewLayout = PresentationTargetFinalLayout,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
|
|
@ -192,7 +193,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
Image = presentationTarget,
|
||||
SubresourceRange = ColorSubresourceRange(),
|
||||
};
|
||||
_vk.CmdPipelineBarrier(
|
||||
VulkanSynchronization.PipelineBarrier(_vk,
|
||||
_commandBuffer,
|
||||
PipelineStageFlags.TransferBit,
|
||||
_hdrOutputActive
|
||||
|
|
|
|||
|
|
@ -24,20 +24,17 @@ using VkBuffer = Silk.NET.Vulkan.Buffer;
|
|||
// This partial is the render host: it records what the executor resolved with dynamic rendering.
|
||||
internal static unsafe partial class VulkanVideoPresenter
|
||||
{
|
||||
private const string DynamicRenderingExtensionName = "VK_KHR_dynamic_rendering";
|
||||
private const string ExtendedDynamicStateExtensionName = "VK_EXT_extended_dynamic_state";
|
||||
private const string ExtendedDynamicState2ExtensionName = "VK_EXT_extended_dynamic_state2";
|
||||
private const string ColorWriteEnableExtensionName = "VK_EXT_color_write_enable";
|
||||
private const string DepthClipControlExtensionName = "VK_EXT_depth_clip_control";
|
||||
private const string DepthClipEnableExtensionName = "VK_EXT_depth_clip_enable";
|
||||
private const int DrawsPerBatch = 64;
|
||||
private const uint SingleRectangleVertexCount = 4;
|
||||
|
||||
private static void RequireRenderingFeature(bool supported, string extension, string deviceName)
|
||||
private static void RequireRenderingFeature(bool supported, string feature, string deviceName)
|
||||
{
|
||||
if (!supported)
|
||||
{
|
||||
throw SubmissionScheduler.Fatal($"The device lacks a required rendering feature: device={deviceName} extension={extension}.");
|
||||
throw SubmissionScheduler.Fatal($"The device lacks a required rendering feature: device={deviceName} feature={feature}.");
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -99,9 +96,6 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
}
|
||||
}
|
||||
|
||||
private KhrDynamicRendering _dynamicRenderingApi = null!;
|
||||
private ExtExtendedDynamicState _extendedDynamicStateApi = null!;
|
||||
private ExtExtendedDynamicState2 _extendedDynamicState2Api = null!;
|
||||
private ExtColorWriteEnable? _colorWriteEnableApi;
|
||||
private bool _supportsDepthClipControl;
|
||||
private bool _supportsDepthClipEnable;
|
||||
|
|
@ -127,21 +121,6 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
|
||||
private void LoadRenderingCommands(bool supportsColorWriteEnable, string deviceName)
|
||||
{
|
||||
if (!_vk.TryGetDeviceExtension(_instance, _device, out _dynamicRenderingApi))
|
||||
{
|
||||
throw SubmissionScheduler.Fatal($"The device extension commands are unavailable: device={deviceName} extension={DynamicRenderingExtensionName}.");
|
||||
}
|
||||
|
||||
if (!_vk.TryGetDeviceExtension(_instance, _device, out _extendedDynamicStateApi))
|
||||
{
|
||||
throw SubmissionScheduler.Fatal($"The device extension commands are unavailable: device={deviceName} extension={ExtendedDynamicStateExtensionName}.");
|
||||
}
|
||||
|
||||
if (!_vk.TryGetDeviceExtension(_instance, _device, out _extendedDynamicState2Api))
|
||||
{
|
||||
throw SubmissionScheduler.Fatal($"The device extension commands are unavailable: device={deviceName} extension={ExtendedDynamicState2ExtensionName}.");
|
||||
}
|
||||
|
||||
if (!_vk.TryGetDeviceExtension(_instance, _device, out _pushDescriptorApi))
|
||||
{
|
||||
throw SubmissionScheduler.Fatal($"The device extension commands are unavailable: device={deviceName} extension={PushDescriptorExtensionName}.");
|
||||
|
|
@ -525,10 +504,10 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
_vk.CmdSetLineWidth(command, state.LineWidth);
|
||||
var blendConstants = stackalloc float[4] { state.BlendRed, state.BlendGreen, state.BlendBlue, state.BlendAlpha };
|
||||
_vk.CmdSetBlendConstants(command, blendConstants);
|
||||
_extendedDynamicStateApi.CmdSetDepthTestEnable(command, state.DepthTestEnabled);
|
||||
_extendedDynamicStateApi.CmdSetDepthWriteEnable(command, state.DepthWriteEnabled);
|
||||
_extendedDynamicStateApi.CmdSetDepthCompareOp(command, state.DepthCompare);
|
||||
_extendedDynamicState2Api.CmdSetDepthBiasEnable(command, state.DepthBiasEnabled);
|
||||
_vk.CmdSetDepthTestEnable(command, state.DepthTestEnabled);
|
||||
_vk.CmdSetDepthWriteEnable(command, state.DepthWriteEnabled);
|
||||
_vk.CmdSetDepthCompareOp(command, state.DepthCompare);
|
||||
_vk.CmdSetDepthBiasEnable(command, state.DepthBiasEnabled);
|
||||
if (state.DepthBiasEnabled)
|
||||
{
|
||||
_vk.CmdSetDepthBias(command, state.DepthBiasConstantFactor, _supportsDepthBiasClamp ? state.DepthBiasClamp : 0f, state.DepthBiasSlopeFactor);
|
||||
|
|
@ -718,7 +697,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
PDepthAttachment = depthStencil.HasDepth ? &depth : null,
|
||||
PStencilAttachment = depthStencil.HasStencil ? &stencil : null,
|
||||
};
|
||||
_dynamicRenderingApi.CmdBeginRendering(command, &rendering);
|
||||
_vk.CmdBeginRendering(command, &rendering);
|
||||
_renderingScopesBegun++;
|
||||
_renderingActive = true;
|
||||
_renderingState = state;
|
||||
|
|
@ -733,7 +712,7 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
|
||||
_renderingActive = false;
|
||||
_renderingState = default;
|
||||
_dynamicRenderingApi.CmdEndRendering(new CommandBuffer(_scheduler.Current.Handle));
|
||||
_vk.CmdEndRendering(new CommandBuffer(_scheduler.Current.Handle));
|
||||
}
|
||||
|
||||
public void BindPipeline(PipelineBindPoint bindPoint, in PipelineHandle pipeline)
|
||||
|
|
@ -832,18 +811,18 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
using var profileScope = RenderPhaseProfile.MeasureDetail(RenderPhaseProfile.Phase.DrawRecording);
|
||||
var (buffer, offset) = _bufferCache.ObtainBuffer(argumentsAddress, 3u * sizeof(uint), false);
|
||||
var command = BeginBatchedGuestCommands();
|
||||
var barrier = new BufferMemoryBarrier
|
||||
var barrier = new BufferMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.BufferMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.ShaderWriteBit | AccessFlags.TransferWriteBit | AccessFlags.MemoryWriteBit,
|
||||
DstAccessMask = AccessFlags.IndirectCommandReadBit,
|
||||
SType = StructureType.BufferMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.ShaderWriteBit | AccessFlags2.TransferWriteBit | AccessFlags2.MemoryWriteBit,
|
||||
DstAccessMask = AccessFlags2.IndirectCommandReadBit,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
Buffer = buffer.Handle,
|
||||
Offset = offset,
|
||||
Size = 3u * sizeof(uint),
|
||||
};
|
||||
_vk.CmdPipelineBarrier(command, PipelineStageFlags.AllCommandsBit, PipelineStageFlags.DrawIndirectBit, 0, 0, null, 1, &barrier, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(_vk,command, PipelineStageFlags.AllCommandsBit, PipelineStageFlags.DrawIndirectBit, 0, 0, null, 1, &barrier, 0, null);
|
||||
_vk.CmdDispatchIndirect(command, buffer.Handle, offset);
|
||||
CountDraw();
|
||||
return true;
|
||||
|
|
@ -853,13 +832,13 @@ internal static unsafe partial class VulkanVideoPresenter
|
|||
{
|
||||
EndRendering();
|
||||
var command = BeginBatchedGuestCommands();
|
||||
var barrier = new MemoryBarrier
|
||||
var barrier = new MemoryBarrier2
|
||||
{
|
||||
SType = StructureType.MemoryBarrier,
|
||||
SrcAccessMask = sourceAccess,
|
||||
DstAccessMask = destinationAccess,
|
||||
SType = StructureType.MemoryBarrier2,
|
||||
SrcAccessMask = VulkanSynchronization.Access(sourceAccess),
|
||||
DstAccessMask = VulkanSynchronization.Access(destinationAccess),
|
||||
};
|
||||
_vk.CmdPipelineBarrier(command, sourceStages, destinationStages, 0, 1, &barrier, 0, null, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(_vk,command, sourceStages, destinationStages, 0, 1, &barrier, 0, null, 0, null);
|
||||
}
|
||||
|
||||
public void ShaderWriteBarrier(PipelineStageFlags sourceStages) =>
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ using System.Runtime.InteropServices;
|
|||
using SharpEmu.Libs.Gpu.Buffers;
|
||||
using SharpEmu.Libs.Gpu.Images;
|
||||
using SharpEmu.Libs.Gpu.Scheduling;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using SharpEmu.Libs.Tests.Gpu.Scheduling;
|
||||
using SharpEmu.Libs.Tests.Gpu.Vulkan;
|
||||
using SharpEmu.ShaderCompiler.Vulkan;
|
||||
|
|
@ -122,18 +123,18 @@ internal sealed unsafe class MultisampleDepthSampleReader : IDisposable
|
|||
var count = samples;
|
||||
vk.CmdPushConstants(command, _pipelineLayout, ShaderStageFlags.ComputeBit, 0, 4, &count);
|
||||
vk.CmdDispatch(command, 1, 1, 1);
|
||||
var barrier = new BufferMemoryBarrier
|
||||
var barrier = new BufferMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.BufferMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.ShaderWriteBit,
|
||||
DstAccessMask = AccessFlags.HostReadBit,
|
||||
SType = StructureType.BufferMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.ShaderWriteBit,
|
||||
DstAccessMask = AccessFlags2.HostReadBit,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
Buffer = output.Handle,
|
||||
Offset = 0,
|
||||
Size = output.Size,
|
||||
};
|
||||
vk.CmdPipelineBarrier(command, PipelineStageFlags.ComputeShaderBit, PipelineStageFlags.HostBit, 0, 0, null, 1, &barrier, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(vk, command, PipelineStageFlags.ComputeShaderBit, PipelineStageFlags.HostBit, 0, 0, null, 1, &barrier, 0, null);
|
||||
_scheduler.Finish();
|
||||
output.Invalidate(0, output.Size);
|
||||
bytes = output.Mapped[..(int)(samples * 4)].ToArray();
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ using SharpEmu.HLE.GpuMemory;
|
|||
using SharpEmu.HLE.Host;
|
||||
using SharpEmu.Libs.Gpu.Buffers;
|
||||
using SharpEmu.Libs.Gpu.Images;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using SharpEmu.Libs.Tests.Gpu.Buffers;
|
||||
using Silk.NET.Vulkan;
|
||||
using Xunit;
|
||||
|
|
@ -176,22 +177,22 @@ internal static class ImageCacheTestSupport
|
|||
var aligned = (size + 3) & ~3UL;
|
||||
using var download = new GpuBuffer(harness.Vulkan.DeviceInfo, harness.Scheduler, GpuBufferUsage.Download, 0, GpuBuffer.AllFlags, aligned);
|
||||
var command = new CommandBuffer(harness.Scheduler.Current.Handle);
|
||||
var before = new BufferMemoryBarrier
|
||||
var before = new BufferMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.BufferMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.MemoryWriteBit | AccessFlags.ShaderWriteBit | AccessFlags.TransferWriteBit | AccessFlags.HostWriteBit,
|
||||
DstAccessMask = AccessFlags.TransferReadBit,
|
||||
SType = StructureType.BufferMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.MemoryWriteBit | AccessFlags2.ShaderWriteBit | AccessFlags2.TransferWriteBit | AccessFlags2.HostWriteBit,
|
||||
DstAccessMask = AccessFlags2.TransferReadBit,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
Buffer = source,
|
||||
Offset = offset,
|
||||
Size = aligned,
|
||||
};
|
||||
vk.CmdPipelineBarrier(command, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit, PipelineStageFlags.TransferBit, 0, 0, null, 1, &before, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(vk, command, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit, PipelineStageFlags.TransferBit, 0, 0, null, 1, &before, 0, null);
|
||||
var region = new BufferCopy(offset, 0, aligned);
|
||||
vk.CmdCopyBuffer(command, source, download.Handle, 1, ®ion);
|
||||
var after = before with { Buffer = download.Handle, Offset = 0, SrcAccessMask = AccessFlags.TransferWriteBit, DstAccessMask = AccessFlags.HostReadBit };
|
||||
vk.CmdPipelineBarrier(command, PipelineStageFlags.TransferBit, PipelineStageFlags.HostBit, 0, 0, null, 1, &after, 0, null);
|
||||
var after = before with { Buffer = download.Handle, Offset = 0, SrcAccessMask = AccessFlags2.TransferWriteBit, DstAccessMask = AccessFlags2.HostReadBit };
|
||||
VulkanSynchronization.PipelineBarrier(vk, command, PipelineStageFlags.TransferBit, PipelineStageFlags.HostBit, 0, 0, null, 1, &after, 0, null);
|
||||
harness.Scheduler.Finish();
|
||||
download.Invalidate(0, aligned);
|
||||
return download.Mapped[..(int)size].ToArray();
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ using SharpEmu.HLE.Host;
|
|||
using SharpEmu.Libs.Gpu.Buffers;
|
||||
using SharpEmu.Libs.Gpu.Images;
|
||||
using SharpEmu.Libs.Gpu.Scheduling;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using SharpEmu.Libs.Tests.Gpu.Buffers;
|
||||
using SharpEmu.Libs.Tests.Gpu.Vulkan;
|
||||
using Silk.NET.Vulkan;
|
||||
|
|
@ -231,22 +232,22 @@ internal sealed unsafe class ImageTestHarness : IDisposable
|
|||
var aligned = (size + 3) & ~3UL;
|
||||
using var download = new GpuBuffer(Device, Scheduler, GpuBufferUsage.Download, 0, GpuBuffer.AllFlags, aligned);
|
||||
var command = new CommandBuffer(Scheduler.Current.Handle);
|
||||
var before = new BufferMemoryBarrier
|
||||
var before = new BufferMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.BufferMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.MemoryWriteBit | AccessFlags.ShaderWriteBit | AccessFlags.TransferWriteBit | AccessFlags.HostWriteBit,
|
||||
DstAccessMask = AccessFlags.TransferReadBit,
|
||||
SType = StructureType.BufferMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.MemoryWriteBit | AccessFlags2.ShaderWriteBit | AccessFlags2.TransferWriteBit | AccessFlags2.HostWriteBit,
|
||||
DstAccessMask = AccessFlags2.TransferReadBit,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
Buffer = source,
|
||||
Offset = offset,
|
||||
Size = aligned,
|
||||
};
|
||||
Vk.CmdPipelineBarrier(command, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit, PipelineStageFlags.TransferBit, 0, 0, null, 1, &before, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(Vk, command, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit, PipelineStageFlags.TransferBit, 0, 0, null, 1, &before, 0, null);
|
||||
var region = new BufferCopy(offset, 0, aligned);
|
||||
Vk.CmdCopyBuffer(command, source, download.Handle, 1, ®ion);
|
||||
var after = before with { Buffer = download.Handle, Offset = 0, SrcAccessMask = AccessFlags.TransferWriteBit, DstAccessMask = AccessFlags.HostReadBit };
|
||||
Vk.CmdPipelineBarrier(command, PipelineStageFlags.TransferBit, PipelineStageFlags.HostBit, 0, 0, null, 1, &after, 0, null);
|
||||
var after = before with { Buffer = download.Handle, Offset = 0, SrcAccessMask = AccessFlags2.TransferWriteBit, DstAccessMask = AccessFlags2.HostReadBit };
|
||||
VulkanSynchronization.PipelineBarrier(Vk, command, PipelineStageFlags.TransferBit, PipelineStageFlags.HostBit, 0, 0, null, 1, &after, 0, null);
|
||||
Scheduler.Finish();
|
||||
download.Invalidate(0, aligned);
|
||||
return download.Mapped[..(int)size].ToArray();
|
||||
|
|
@ -499,14 +500,14 @@ internal sealed unsafe class TilerComputeRunner : IDisposable
|
|||
|
||||
vk.UpdateDescriptorSets(device, 3, writes, 0, null);
|
||||
var command = new CommandBuffer(_harness.Scheduler.Current.Handle);
|
||||
var barriers = stackalloc BufferMemoryBarrier[3];
|
||||
var barriers = stackalloc BufferMemoryBarrier2[3];
|
||||
for (var index = 0; index < 3; index++)
|
||||
{
|
||||
barriers[index] = new BufferMemoryBarrier
|
||||
barriers[index] = new BufferMemoryBarrier2
|
||||
{
|
||||
SType = StructureType.BufferMemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.HostWriteBit | AccessFlags.MemoryWriteBit,
|
||||
DstAccessMask = index == 1 ? AccessFlags.ShaderReadBit | AccessFlags.ShaderWriteBit : index == 2 ? AccessFlags.UniformReadBit : AccessFlags.ShaderReadBit,
|
||||
SType = StructureType.BufferMemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.HostWriteBit | AccessFlags2.MemoryWriteBit,
|
||||
DstAccessMask = index == 1 ? AccessFlags2.ShaderReadBit | AccessFlags2.ShaderWriteBit : index == 2 ? AccessFlags2.UniformReadBit : AccessFlags2.ShaderReadBit,
|
||||
SrcQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
DstQueueFamilyIndex = Vk.QueueFamilyIgnored,
|
||||
Buffer = infos[index].Buffer,
|
||||
|
|
@ -515,7 +516,7 @@ internal sealed unsafe class TilerComputeRunner : IDisposable
|
|||
};
|
||||
}
|
||||
|
||||
vk.CmdPipelineBarrier(command, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit, PipelineStageFlags.ComputeShaderBit, 0, 0, null, 3, barriers, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(vk, command, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit, PipelineStageFlags.ComputeShaderBit, 0, 0, null, 3, barriers, 0, null);
|
||||
vk.CmdBindPipeline(command, PipelineBindPoint.Compute, pipeline);
|
||||
vk.CmdBindDescriptorSets(command, PipelineBindPoint.Compute, _pipelineLayout, 0, 1, &set, 0, null);
|
||||
fixed (TileTransferArguments* pointer = &push)
|
||||
|
|
@ -524,8 +525,8 @@ internal sealed unsafe class TilerComputeRunner : IDisposable
|
|||
}
|
||||
|
||||
vk.CmdDispatch(command, groupsX, groupsY, groupsZ);
|
||||
var after = barriers[1] with { SrcAccessMask = AccessFlags.ShaderWriteBit, DstAccessMask = AccessFlags.TransferReadBit | AccessFlags.MemoryReadBit };
|
||||
vk.CmdPipelineBarrier(command, PipelineStageFlags.ComputeShaderBit, PipelineStageFlags.AllCommandsBit, 0, 0, null, 1, &after, 0, null);
|
||||
var after = barriers[1] with { SrcAccessMask = AccessFlags2.ShaderWriteBit, DstAccessMask = AccessFlags2.TransferReadBit | AccessFlags2.MemoryReadBit };
|
||||
VulkanSynchronization.PipelineBarrier(vk, command, PipelineStageFlags.ComputeShaderBit, PipelineStageFlags.AllCommandsBit, 0, 0, null, 1, &after, 0, null);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using SharpEmu.Libs.Tests.Gpu.Scheduling;
|
||||
using SharpEmu.Libs.Tests.Gpu.Vulkan;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using SharpEmu.Libs.VideoOut;
|
||||
using Silk.NET.Vulkan;
|
||||
using Xunit;
|
||||
|
|
@ -64,13 +65,13 @@ public sealed unsafe class PresentationColorTests : IClassFixture<HeadlessVulkan
|
|||
var range = new ImageSubresourceRange(ImageAspectFlags.ColorBit, 0, 1, 0, 1);
|
||||
harness.Vk.CmdClearColorImage(command, target.Backing.Handle,
|
||||
ImageLayout.TransferDstOptimal, &black, 1, &range);
|
||||
var clearComplete = new MemoryBarrier
|
||||
var clearComplete = new MemoryBarrier2
|
||||
{
|
||||
SType = StructureType.MemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags.TransferWriteBit,
|
||||
SType = StructureType.MemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.TransferWriteBit,
|
||||
DstAccessMask = AccessFlags2.TransferWriteBit,
|
||||
};
|
||||
harness.Vk.CmdPipelineBarrier(command, PipelineStageFlags.TransferBit, PipelineStageFlags.TransferBit,
|
||||
VulkanSynchronization.PipelineBarrier(harness.Vk, command, PipelineStageFlags.TransferBit, PipelineStageFlags.TransferBit,
|
||||
0, 1, &clearComplete, 0, null, 0, null);
|
||||
var blit = new ImageBlit
|
||||
{
|
||||
|
|
|
|||
|
|
@ -40,15 +40,12 @@ internal sealed unsafe class HeadlessVulkan : IDisposable
|
|||
SupportsDynamicRendering = dynamicRendering;
|
||||
}
|
||||
|
||||
// Dynamic rendering with the two extended dynamic state extensions, as the presenter's render host needs.
|
||||
// Dynamic rendering support required by the presenter's render host.
|
||||
public bool SupportsDynamicRendering { get; }
|
||||
public bool SupportsFragmentShaderBarycentric { get; private init; }
|
||||
|
||||
private static readonly string[] RenderingExtensionNames =
|
||||
[
|
||||
"VK_KHR_dynamic_rendering",
|
||||
"VK_EXT_extended_dynamic_state",
|
||||
"VK_EXT_extended_dynamic_state2",
|
||||
"VK_KHR_push_descriptor",
|
||||
];
|
||||
|
||||
|
|
@ -78,7 +75,7 @@ internal sealed unsafe class HeadlessVulkan : IDisposable
|
|||
|
||||
public object QueueGate { get; } = new();
|
||||
|
||||
// The device API version: 1.3 when the loader and the device support it, else 1.2.
|
||||
// The device API version. The production renderer requires Vulkan 1.3.
|
||||
public uint ApiVersion { get; }
|
||||
|
||||
// SPIR-V 1.6 modules (the compiled reference blobs) need a Vulkan 1.3 device.
|
||||
|
|
@ -209,7 +206,11 @@ internal sealed unsafe class HeadlessVulkan : IDisposable
|
|||
var vk = Vk.GetApi();
|
||||
uint instanceVersion = Vk.Version10;
|
||||
vk.EnumerateInstanceVersion(ref instanceVersion);
|
||||
var apiVersion = instanceVersion >= Vk.Version13 ? Vk.Version13 : Vk.Version12;
|
||||
if (instanceVersion < Vk.Version13)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var apiVersion = Vk.Version13;
|
||||
var appInfo = new ApplicationInfo { SType = StructureType.ApplicationInfo, ApiVersion = apiVersion };
|
||||
var validation = Environment.GetEnvironmentVariable(ValidationVariable) == "1";
|
||||
var layers = validation ? SilkMarshal.StringArrayToPtr(new[] { "VK_LAYER_KHRONOS_validation" }) : 0;
|
||||
|
|
@ -261,9 +262,10 @@ internal sealed unsafe class HeadlessVulkan : IDisposable
|
|||
}
|
||||
|
||||
vk.GetPhysicalDeviceProperties(physical, out var physicalProperties);
|
||||
if (physicalProperties.ApiVersion < apiVersion)
|
||||
if (physicalProperties.ApiVersion < Vk.Version13)
|
||||
{
|
||||
apiVersion = Vk.Version12;
|
||||
vk.DestroyInstance(instance, null);
|
||||
return null;
|
||||
}
|
||||
|
||||
uint familyCount = 0;
|
||||
|
|
@ -301,24 +303,14 @@ internal sealed unsafe class HeadlessVulkan : IDisposable
|
|||
}
|
||||
var barycentric = (bool)barycentricFeatures.FragmentShaderBarycentric;
|
||||
|
||||
var extendedDynamicState2Features = new PhysicalDeviceExtendedDynamicState2FeaturesEXT
|
||||
var vulkan13Features = new PhysicalDeviceVulkan13Features
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt,
|
||||
};
|
||||
var extendedDynamicStateFeatures = new PhysicalDeviceExtendedDynamicStateFeaturesEXT
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceExtendedDynamicStateFeaturesExt,
|
||||
PNext = &extendedDynamicState2Features,
|
||||
};
|
||||
var dynamicRenderingFeatures = new PhysicalDeviceDynamicRenderingFeaturesKHR
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceDynamicRenderingFeaturesKhr,
|
||||
PNext = &extendedDynamicStateFeatures,
|
||||
SType = StructureType.PhysicalDeviceVulkan13Features,
|
||||
};
|
||||
var addressFeatures = new PhysicalDeviceBufferDeviceAddressFeatures
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceBufferDeviceAddressFeatures,
|
||||
PNext = &dynamicRenderingFeatures,
|
||||
PNext = &vulkan13Features,
|
||||
};
|
||||
var timelineFeatures = new PhysicalDeviceTimelineSemaphoreFeatures
|
||||
{
|
||||
|
|
@ -327,9 +319,10 @@ internal sealed unsafe class HeadlessVulkan : IDisposable
|
|||
};
|
||||
var features = new PhysicalDeviceFeatures2 { SType = StructureType.PhysicalDeviceFeatures2, PNext = &timelineFeatures };
|
||||
vk.GetPhysicalDeviceFeatures2(physical, &features);
|
||||
var dynamicRendering = dynamicRenderingFeatures.DynamicRendering && extendedDynamicStateFeatures.ExtendedDynamicState &&
|
||||
extendedDynamicState2Features.ExtendedDynamicState2 && HasDeviceExtensions(vk, physical, RenderingExtensionNames);
|
||||
if (family == uint.MaxValue || !timelineFeatures.TimelineSemaphore || !addressFeatures.BufferDeviceAddress)
|
||||
var dynamicRendering = vulkan13Features.DynamicRendering && vulkan13Features.Synchronization2 &&
|
||||
HasDeviceExtensions(vk, physical, RenderingExtensionNames);
|
||||
if (family == uint.MaxValue || !timelineFeatures.TimelineSemaphore || !addressFeatures.BufferDeviceAddress ||
|
||||
!vulkan13Features.Synchronization2)
|
||||
{
|
||||
vk.DestroyInstance(instance, null);
|
||||
return null;
|
||||
|
|
@ -352,34 +345,23 @@ internal sealed unsafe class HeadlessVulkan : IDisposable
|
|||
PQueuePriorities = &priority,
|
||||
};
|
||||
timelineFeatures.TimelineSemaphore = true;
|
||||
extendedDynamicState2Features = new PhysicalDeviceExtendedDynamicState2FeaturesEXT
|
||||
vulkan13Features = new PhysicalDeviceVulkan13Features
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceExtendedDynamicState2FeaturesExt,
|
||||
ExtendedDynamicState2 = true,
|
||||
};
|
||||
extendedDynamicStateFeatures = new PhysicalDeviceExtendedDynamicStateFeaturesEXT
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceExtendedDynamicStateFeaturesExt,
|
||||
ExtendedDynamicState = true,
|
||||
PNext = &extendedDynamicState2Features,
|
||||
};
|
||||
dynamicRenderingFeatures = new PhysicalDeviceDynamicRenderingFeaturesKHR
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceDynamicRenderingFeaturesKhr,
|
||||
DynamicRendering = true,
|
||||
PNext = &extendedDynamicStateFeatures,
|
||||
SType = StructureType.PhysicalDeviceVulkan13Features,
|
||||
DynamicRendering = dynamicRendering,
|
||||
Synchronization2 = true,
|
||||
};
|
||||
addressFeatures = new PhysicalDeviceBufferDeviceAddressFeatures
|
||||
{
|
||||
SType = StructureType.PhysicalDeviceBufferDeviceAddressFeatures,
|
||||
BufferDeviceAddress = true,
|
||||
PNext = dynamicRendering ? &dynamicRenderingFeatures : null,
|
||||
PNext = &vulkan13Features,
|
||||
};
|
||||
timelineFeatures.PNext = &addressFeatures;
|
||||
if (barycentric)
|
||||
{
|
||||
barycentricFeatures.PNext = addressFeatures.PNext;
|
||||
addressFeatures.PNext = &barycentricFeatures;
|
||||
barycentricFeatures.PNext = vulkan13Features.PNext;
|
||||
vulkan13Features.PNext = &barycentricFeatures;
|
||||
}
|
||||
var extensionNames = new List<string>();
|
||||
if (dynamicRendering) extensionNames.AddRange(RenderingExtensionNames);
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
using System.Runtime.InteropServices;
|
||||
using SharpEmu.Libs.Gpu.Buffers;
|
||||
using SharpEmu.Libs.Gpu.Vulkan;
|
||||
using SharpEmu.Libs.Tests.Gpu.Images;
|
||||
using SharpEmu.ShaderCompiler;
|
||||
using SharpEmu.ShaderCompiler.Resources;
|
||||
|
|
@ -288,13 +289,13 @@ internal sealed unsafe class LayoutComputeRunner : IDisposable
|
|||
}
|
||||
|
||||
var command = new CommandBuffer(_harness.Scheduler.Current.Handle);
|
||||
var barrier = new MemoryBarrier
|
||||
var barrier = new MemoryBarrier2
|
||||
{
|
||||
SType = StructureType.MemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.HostWriteBit | AccessFlags.MemoryWriteBit,
|
||||
DstAccessMask = AccessFlags.ShaderReadBit | AccessFlags.ShaderWriteBit,
|
||||
SType = StructureType.MemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.HostWriteBit | AccessFlags2.MemoryWriteBit,
|
||||
DstAccessMask = AccessFlags2.ShaderReadBit | AccessFlags2.ShaderWriteBit,
|
||||
};
|
||||
vk.CmdPipelineBarrier(command, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit, PipelineStageFlags.ComputeShaderBit, 0, 1, &barrier, 0, null, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(vk, command, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit, PipelineStageFlags.ComputeShaderBit, 0, 1, &barrier, 0, null, 0, null);
|
||||
vk.CmdBindPipeline(command, PipelineBindPoint.Compute, _pipeline);
|
||||
vk.CmdBindDescriptorSets(command, PipelineBindPoint.Compute, _pipelineLayout, 0, 1, &set, 0, null);
|
||||
if (layout.UsesPushData)
|
||||
|
|
@ -306,13 +307,13 @@ internal sealed unsafe class LayoutComputeRunner : IDisposable
|
|||
}
|
||||
|
||||
vk.CmdDispatch(command, groupsX, groupsY, groupsZ);
|
||||
var after = new MemoryBarrier
|
||||
var after = new MemoryBarrier2
|
||||
{
|
||||
SType = StructureType.MemoryBarrier,
|
||||
SrcAccessMask = AccessFlags.ShaderWriteBit,
|
||||
DstAccessMask = AccessFlags.TransferReadBit | AccessFlags.MemoryReadBit | AccessFlags.HostReadBit,
|
||||
SType = StructureType.MemoryBarrier2,
|
||||
SrcAccessMask = AccessFlags2.ShaderWriteBit,
|
||||
DstAccessMask = AccessFlags2.TransferReadBit | AccessFlags2.MemoryReadBit | AccessFlags2.HostReadBit,
|
||||
};
|
||||
vk.CmdPipelineBarrier(command, PipelineStageFlags.ComputeShaderBit, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit, 0, 1, &after, 0, null, 0, null);
|
||||
VulkanSynchronization.PipelineBarrier(vk, command, PipelineStageFlags.ComputeShaderBit, PipelineStageFlags.AllCommandsBit | PipelineStageFlags.HostBit, 0, 1, &after, 0, null, 0, null);
|
||||
}
|
||||
|
||||
public byte[] ReadBack(GpuBuffer buffer, ulong offset, ulong size) => _harness.ReadBack(buffer.Handle, offset, size);
|
||||
|
|
|
|||
Loading…
Reference in New Issue