A cross-platform UI framework for .NET
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

107 lines
3.6 KiB

using System;
using Avalonia.Vulkan.UnmanagedInterop;
namespace Avalonia.Vulkan.Interop;
internal class VulkanCommandBuffer : IDisposable
{
private readonly VulkanCommandBufferPool _pool;
private VkCommandBuffer _handle;
private readonly IVulkanPlatformGraphicsContext _context;
private VulkanFence _fence;
private bool _hasEnded;
private bool _hasStarted;
public VkCommandBuffer Handle => _handle;
public VulkanCommandBuffer(VulkanCommandBufferPool pool, VkCommandBuffer handle, IVulkanPlatformGraphicsContext context)
{
_pool = pool;
_handle = handle;
_context = context;
_fence = new VulkanFence(context, VkFenceCreateFlags.VK_FENCE_CREATE_SIGNALED_BIT);
}
public unsafe void Dispose()
{
if (_fence.Handle.Handle != 0)
_fence.Wait();
_fence.Dispose();
if (_handle.Handle != IntPtr.Zero)
{
VkCommandBuffer buf = _handle;
_context.DeviceApi.FreeCommandBuffers(_context.DeviceHandle, _pool.Handle, 1, &buf);
_handle = default;
}
}
public bool IsFinished => _fence.IsSignaled;
public void BeginRecording()
{
if (_hasStarted)
return;
var beginInfo = new VkCommandBufferBeginInfo
{
sType = VkStructureType.VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,
flags = VkCommandBufferUsageFlags.VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT
};
_context.DeviceApi.BeginCommandBuffer(_handle, ref beginInfo).ThrowOnError("vkBeginCommandBuffer");
_hasStarted = true;
}
public void EndRecording()
{
if (_hasStarted && !_hasEnded)
{
_context.DeviceApi.EndCommandBuffer(_handle).ThrowOnError("vkEndCommandBuffer");
_hasEnded = true;
}
}
public void Submit()
{
Submit(null, null, null);
}
public unsafe void Submit(
ReadOnlySpan<VulkanSemaphore> waitSemaphores,
ReadOnlySpan<VkPipelineStageFlags> waitDstStageMask,
ReadOnlySpan<VulkanSemaphore> signalSemaphores,
VulkanFence? fence = null)
{
EndRecording();
VkFence fenceHandle = (fence ?? _fence).Handle;
_context.DeviceApi.ResetFences(_context.DeviceHandle, 1, &fenceHandle)
.ThrowOnError("vkResetFences");
var pWaitSempaphores = stackalloc VkSemaphore[waitSemaphores.Length];
for (var c = 0; c < waitSemaphores.Length; c++)
pWaitSempaphores[c] = waitSemaphores[c].Handle;
var pSignalSemaphores = stackalloc VkSemaphore[signalSemaphores.Length];
for (var c = 0; c < signalSemaphores.Length; c++)
pSignalSemaphores[c] = signalSemaphores[c].Handle;
VkCommandBuffer commandBuffer = _handle;
fixed (VkPipelineStageFlags* flags = waitDstStageMask)
{
var submitInfo = new VkSubmitInfo
{
sType = VkStructureType.VK_STRUCTURE_TYPE_SUBMIT_INFO,
waitSemaphoreCount = (uint)waitSemaphores.Length,
pWaitSemaphores = pWaitSempaphores,
signalSemaphoreCount = (uint)signalSemaphores.Length,
pSignalSemaphores = pSignalSemaphores,
commandBufferCount = 1,
pCommandBuffers = &commandBuffer,
pWaitDstStageMask = flags
};
_context.DeviceApi.QueueSubmit(_context.MainQueueHandle, 1, &submitInfo, fenceHandle)
.ThrowOnError("vkQueueSubmit");
}
_pool.AddSubmittedCommandBuffer(this);
}
}