internal RenderQueue() { // Allocate the pool _cmdPool = Device.VkDevice.CreateCommandPool(new Vk.CommandPoolCreateInfo( Device.Queues.Graphics.FamilyIndex, Vk.CommandPoolCreateFlags.ResetCommandBuffer | Vk.CommandPoolCreateFlags.Transient )); // Allocate the queue items var bufs = _cmdPool.AllocateBuffers(new Vk.CommandBufferAllocateInfo(Vk.CommandBufferLevel.Primary, (int)BUFFER_COUNT)); _queueItems = new RenderQueueItem[BUFFER_COUNT]; for (uint i = 0; i < BUFFER_COUNT; ++i) { _queueItems[i] = new RenderQueueItem { Buffer = bufs[i], Semaphore = Device.VkDevice.CreateSemaphore(), Fence = Device.VkDevice.CreateFence() }; } SubmitCount = 0; }
// Submits a one-time action that needs a graphics queue command buffer, will be synchronous // The command buffer will already have Begin() called when it is passed to the action, and will automatically call End() internal void SubmitScratchCommand(Action <Vk.CommandBuffer> action, Vk.Semaphore waitSem = null, Vk.PipelineStages waitStages = Vk.PipelineStages.AllGraphics, Vk.Fence waitFence = null) { // Record the command var cb = _scratchPool.AllocateBuffers(_scratchAllocInfo)[0]; cb.Begin(_scratchBeginInfo); action(cb); cb.End(); // Submit if (waitFence != null) { waitFence.Wait(); waitFence.Reset(); } Queues.Graphics.Submit(waitSem, waitStages, cb, null, _scratchFence); _scratchFence.Wait(); _scratchFence.Reset(); cb.Dispose(); }
public Swapchain(GraphicsDevice gdevice, Vk.Instance instance, Vk.PhysicalDevice pDevice, Vk.Device device) { Device = gdevice; _window = gdevice.Application.Window; _vkInstance = instance; _vkPhysicalDevice = pDevice; _vkDevice = device; // Create the surface long surfHandle = Glfw.CreateWindowSurface(instance, _window.Handle); Vk.AllocationCallbacks?acb = null; Surface = new VkKhr.SurfaceKhr(instance, ref acb, surfHandle); if (VkKhr.PhysicalDeviceExtensions.GetSurfaceSupportKhr(pDevice, gdevice.Queues.Graphics.FamilyIndex, Surface) == Vk.Constant.False) { LFATAL($"The physical device '{gdevice.Info.Name}' does not support surface presentation."); throw new PlatformNotSupportedException("Physical device does not support surface presentation."); } LINFO("Created Vulkan presentation surface."); // Check the surface for swapchain support levels var sFmts = VkKhr.PhysicalDeviceExtensions.GetSurfaceFormatsKhr(pDevice, Surface); var pModes = VkKhr.PhysicalDeviceExtensions.GetSurfacePresentModesKhr(pDevice, Surface); if (sFmts.Length == 0) { throw new PlatformNotSupportedException("The chosen device does not support any presentation formats."); } if (pModes.Length == 0) { throw new PlatformNotSupportedException("The chosen device does not support any presentation modes."); } // Choose the best available surface format if (sFmts.Length == 1 && sFmts[0].Format == Vk.Format.Undefined) // We are allowed to pick! { _surfaceFormat = PREFERRED_SURFACE_FORMATS[0]; } else // Check if one of the preferred formats is available, otherwise just use the first format given { var sfmt = PREFERRED_SURFACE_FORMATS.FirstOrDefault(fmt => sFmts.Contains(fmt)); if (sfmt.Format == 0 && sfmt.ColorSpace == 0) { _surfaceFormat = sFmts[0]; } else { _surfaceFormat = sfmt; } } // Choose the presentation mode (prefer mailbox -> fifo -> imm) _presentMode = pModes.Contains(VkKhr.PresentModeKhr.Mailbox) ? VkKhr.PresentModeKhr.Mailbox : pModes.Contains(VkKhr.PresentModeKhr.Fifo) ? VkKhr.PresentModeKhr.Fifo : VkKhr.PresentModeKhr.Immediate; // Prepare the synchronization objects _syncObjects.ImageAvailable = new Vk.Semaphore[MAX_INFLIGHT_FRAMES]; _syncObjects.BlitComplete = new Vk.Semaphore[MAX_INFLIGHT_FRAMES]; for (int i = 0; i < MAX_INFLIGHT_FRAMES; ++i) { _syncObjects.ImageAvailable[i] = device.CreateSemaphore(); _syncObjects.BlitComplete[i] = device.CreateSemaphore(); } // Setup the command buffers var cpci = new Vk.CommandPoolCreateInfo(_presentQueue.FamilyIndex, Vk.CommandPoolCreateFlags.Transient | Vk.CommandPoolCreateFlags.ResetCommandBuffer); _commandPool = device.CreateCommandPool(cpci); var cbai = new Vk.CommandBufferAllocateInfo(Vk.CommandBufferLevel.Primary, 1); _commandBuffer = _commandPool.AllocateBuffers(cbai)[0]; _blitFence = device.CreateFence(); // Do NOT start this signalled, as it is needed in rebuildSwapchain() below _rtTransferBarrier = new Vk.ImageMemoryBarrier( null, new Vk.ImageSubresourceRange(Vk.ImageAspects.Color, 0, 1, 0, 1), Vk.Accesses.ColorAttachmentWrite, Vk.Accesses.TransferRead, Vk.ImageLayout.ColorAttachmentOptimal, Vk.ImageLayout.TransferSrcOptimal ); _rtAttachBarrier = new Vk.ImageMemoryBarrier( null, new Vk.ImageSubresourceRange(Vk.ImageAspects.Color, 0, 1, 0, 1), Vk.Accesses.TransferRead, Vk.Accesses.ColorAttachmentWrite, Vk.ImageLayout.TransferSrcOptimal, Vk.ImageLayout.ColorAttachmentOptimal ); // Build the swapchain rebuildSwapchain(); }