// Initializes the various graphics resources found throughout the library internal void InitializeResources() { // Scratch command pool var pci = new Vk.CommandPoolCreateInfo(Queues.Graphics.FamilyIndex, Vk.CommandPoolCreateFlags.Transient | Vk.CommandPoolCreateFlags.ResetCommandBuffer); _scratchPool = VkDevice.CreateCommandPool(pci); _scratchAllocInfo = new Vk.CommandBufferAllocateInfo(Vk.CommandBufferLevel.Primary, 1); _scratchBeginInfo = new Vk.CommandBufferBeginInfo(Vk.CommandBufferUsages.OneTimeSubmit, null); _scratchFence = VkDevice.CreateFence(); // Resources throughout the library TransferBuffer.CreateResources(); }
// 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(); }
/// <summary> /// Wait for one or more fences to become signaled. /// <para> /// If the condition is satisfied when the command is called, then the command returns /// immediately. If the condition is not satisfied at the time the command is called, then /// the command will block and wait up to timeout nanoseconds for the condition to become satisfied. /// </para> /// </summary> /// <param name="fences">Fence handle.</param> /// <param name="waitAll"> /// The condition that must be satisfied to successfully unblock the wait. If <c>true</c> , /// then the condition is that all fences in <paramref name="fences"/> are signaled. /// Otherwise, the condition is that at least one fence in <paramref name="fences"/> is signaled. /// </param> /// <param name="timeout"> /// The timeout period in units of nanoseconds. Timeout is adjusted to the closest value /// allowed by the implementation-dependent timeout accuracy, which may be substantially /// longer than one nanosecond, and may be longer than the requested period. /// <para> /// If timeout is zero, then the command does not wait, but simply returns the current state /// of the fences. The result <see cref="Result.Timeout"/> will be thrown in this case if the /// condition is not satisfied, even though no actual wait was performed. /// </para> /// <para> /// If the specified timeout period expires before the condition is satisfied, the command /// throws with <see cref="Result.Timeout"/>. If the condition is satisfied before timeout /// nanoseconds has expired, the command returns successfully. /// </para> /// </param> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public void WaitFences(Fence[] fences, bool waitAll, long timeout = ~0) { Fence.Wait(this, fences, waitAll, timeout); }
/// <summary> /// Resets one or more fence objects. /// <para> /// Defines a fence unsignal operation for each fence, which resets the fence to the /// unsignaled state. /// </para> /// <para> /// If any member of <paramref name="fences"/> is already in the unsignaled state, then the /// command has no effect on that fence. /// </para> /// </summary> /// <param name="fences">Fence handles to reset.</param> /// <exception cref="VulkanException">Vulkan returns an error code.</exception> public void ResetFences(params Fence[] fences) { Fence.Reset(this, fences); }