// 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();
        }
Beispiel #3
0
        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();
        }
Beispiel #4
0
 /// <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);
 }
Beispiel #5
0
 /// <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);
 }