Example #1
0
        public void Initialize(IVulkanAppHost host)
        {
            Host = host;
#if DEBUG
            const bool debug = true;
#else
            const bool debug = false;
#endif
            _initializingPermanent = true;
            // Calling ToDispose here registers the resource to be automatically disposed on exit.
            Instance                   = ToDispose(CreateInstance(debug));
            DebugReportCallback        = ToDispose(CreateDebugReportCallback(debug));
            Surface                    = ToDispose(CreateSurface());
            Context                    = ToDispose(new VulkanContext(Instance, Surface, Host.Platform));
            Content                    = ToDispose(new ContentManager(Host, Context, "Content"));
            ImageAvailableSemaphore    = ToDispose(Context.Device.CreateSemaphore());
            RenderingFinishedSemaphore = ToDispose(Context.Device.CreateSemaphore());

            if (host.Platform == Platform.MacOS)
            {
                //Setup MoltenVK specific device configuration.
                MVKDeviceConfiguration deviceConfig = Context.Device.GetMVKDeviceConfiguration();
                deviceConfig.DebugMode                    = debug;
                deviceConfig.PerformanceTracking          = debug;
                deviceConfig.PerformanceLoggingFrameCount = debug ? 300 : 0;
                Context.Device.SetMVKDeviceConfiguration(deviceConfig);
            }

            _initializingPermanent = false;
            // Calling ToDispose here registers the resource to be automatically disposed on events
            // such as window resize.
            Swapchain = ToDispose(CreateSwapchain());
            // Acquire underlying images of the freshly created swapchain.
            SwapchainImages = Swapchain.GetImages();
            // Create a command buffer for each swapchain image.
            CommandBuffers = Context.GraphicsCommandPool.AllocateBuffers(
                new CommandBufferAllocateInfo(CommandBufferLevel.Primary, SwapchainImages.Length));
            // Create a fence for each commandbuffer so that we can wait before using it again
            _initializingPermanent = true; //We need our fences to be there permanently
            SubmitFences           = new Fence[SwapchainImages.Length];
            for (int i = 0; i < SubmitFences.Length; i++)
            {
                ToDispose(SubmitFences[i] = Context.Device.CreateFence(new FenceCreateInfo(FenceCreateFlags.Signaled)));
            }

            // Allow concrete samples to initialize their resources.
            InitializePermanent();
            _initializingPermanent = false;
            InitializeFrame();

            // Record commands for execution by Vulkan.
            RecordCommandBuffers();
        }
Example #2
0
        private void CreateSwapChain()
        {
            SwapChainSupportDetails swapChainSupport = QuerySwapChainSupport(physicalDevice);

            uint imageCount = swapChainSupport.Capabilities.MinImageCount + 1;

            if (swapChainSupport.Capabilities.MaxImageCount > 0 && imageCount > swapChainSupport.Capabilities.MaxImageCount)
            {
                imageCount = swapChainSupport.Capabilities.MaxImageCount;
            }

            SurfaceFormat surfaceFormat = ChooseSwapSurfaceFormat(swapChainSupport.Formats);

            QueueFamilyIndices queueFamilies = FindQueueFamilies(physicalDevice);

            var indices = queueFamilies.Indices.ToArray();

            Extent2D extent = ChooseSwapExtent(swapChainSupport.Capabilities);

            swapChain = device.CreateSwapchain(
                surface,
                imageCount,
                surfaceFormat.Format,
                surfaceFormat.ColorSpace,
                extent,
                1,
                ImageUsageFlags.ColorAttachment | ImageUsageFlags.TransferSource,
                indices.Length == 1 ? SharingMode.Exclusive : SharingMode.Concurrent,
                indices,
                swapChainSupport.Capabilities.CurrentTransform,
                CompositeAlphaFlags.Opaque,
                ChooseSwapPresentMode(swapChainSupport.PresentModes),
                true,
                swapChain
                );

            swapChainImages = swapChain.GetImages();
            swapChainFormat = surfaceFormat.Format;
            swapChainExtent = extent;
        }
Example #3
0
        public void Resize()
        {
            Context.Device.WaitIdle();

            // Dispose all frame dependent resources.
            while (_toDisposeFrame.Count > 0)
            {
                _toDisposeFrame.Pop().Dispose();
            }

            // Reset all the command buffers allocated from the pools.
            Context.GraphicsCommandPool.Reset();
            Context.ComputeCommandPool.Reset();

            // Reinitialize frame dependent resources.
            Swapchain       = ToDispose(CreateSwapchain());
            SwapchainImages = Swapchain.GetImages();
            InitializeFrame();

            // Re-record command buffers.
            RecordCommandBuffers();
        }
Example #4
0
        public void Initialize(IVulkanAppHost host)
        {
            Host = host;
#if DEBUG
            const bool debug = true;
#else
            const bool debug = false;
#endif
            _initializingPermanent = true;
            // Calling ToDispose here registers the resource to be automatically disposed on exit.
            Instance                   = ToDispose(CreateInstance(debug));
            DebugReportCallback        = ToDispose(CreateDebugReportCallback(debug));
            Surface                    = ToDispose(CreateSurface());
            Context                    = ToDispose(new VulkanContext(Instance, Surface, Host.Platform));
            Content                    = ToDispose(new ContentManager(Host, Context, "Content"));
            ImageAvailableSemaphore    = ToDispose(Context.Device.CreateSemaphore());
            RenderingFinishedSemaphore = ToDispose(Context.Device.CreateSemaphore());

            _initializingPermanent = false;
            // Calling ToDispose here registers the resource to be automatically disposed on events
            // such as window resize.
            Swapchain = ToDispose(CreateSwapchain());
            // Acquire underlying images of the freshly created swapchain.
            SwapchainImages = Swapchain.GetImages();
            // Create a command buffer for each swapchain image.
            CommandBuffers = Context.GraphicsCommandPool.AllocateBuffers(
                new CommandBufferAllocateInfo(CommandBufferLevel.Primary, SwapchainImages.Length));

            // Allow concrete samples to initialize their resources.
            _initializingPermanent = true;
            InitializePermanent();
            _initializingPermanent = false;
            InitializeFrame();

            // Record commands for execution by Vulkan.
            RecordCommandBuffers();
        }
Example #5
0
 /// <summary>
 /// Construct a Graphics object belonging to a window
 /// </summary>
 /// <param name="window"></param>
 public Graphics(WyvernWindow window)
 {
     // Argument checks
     if (window is null)
     {
         throw new ArgumentNullException(nameof(window));
     }
     // Initialize the static part of Graphics if necessary
     InitializeStatic();
     // Store window
     Window = window;
     // Create window surface
     {
         AllocationCallbacks?allocationCallbacks = null;
         Surface = new SurfaceKhr(
             Instance,
             ref allocationCallbacks,
             VkGLFW3.VkGlfw.CreateWindowSurface(Instance.Handle, Window, IntPtr.Zero)
             );
         Surface.PrintDebug();
     }
     // Choose a physical device
     {
         PhysicalDevice = Instance.EnumeratePhysicalDevices()
                          .Where(e => GetDeviceMeetsRequirements(e, Surface))
                          .OrderByDescending(GetDeviceScore)
                          .FirstOrDefault();
         if (PhysicalDevice is null)
         {
             throw new InvalidOperationException("No physical device found that meets the requirements for the application");
         }
         MemoryProperties = PhysicalDevice.GetMemoryProperties();
     }
     // Create default queue families
     {
         ComputeQueueFamily = new QueueFamily(
             $"{Name}'s {nameof(ComputeQueueFamily)}", this, QueueFamily.QueueType.Compute, 2,
             true, ComputeCommandPoolFlags
             );
         GraphicsQueueFamily = new QueueFamily(
             $"{Name}'s {nameof(GraphicsQueueFamily)}", this, QueueFamily.QueueType.Graphics, 2,
             true, GraphicsCommandPoolFlags
             );
         TransferQueueFamily = new QueueFamily(
             $"{Name}'s {nameof(TransferQueueFamily)}", this, QueueFamily.QueueType.Transfer, 2,
             true, TransferCommandPoolFlags
             );
         PresentQueueFamily = new QueueFamily(
             $"{Name}'s {nameof(PresentQueueFamily)}", this, QueueFamily.QueueType.Present, 1,
             false
             );
     }
     // Create a logical device
     {
         // Generate queue create info structs
         var queueCreateInfos = QueueFamilies.Select(queueFamily =>
         {
             // Generate queue priorities
             var priorities = new float[queueFamily.Count];
             for (var i = 0; i < priorities.Length; i++)
             {
                 priorities[i] = 1f - (i / (float)(priorities.Length - 1));
             }
             // Create create info
             var createInfo = new DeviceQueueCreateInfo()
             {
                 QueueFamilyIndex = queueFamily.Index,
                 QueueCount       = queueFamily.Count,
                 QueuePriorities  = priorities
             };
             return(createInfo);
         });
         // Merge multiple queue families' queue create infos
         {
             var alreadyHave       = new List <int>();
             var uniqueCreateInfos = new List <DeviceQueueCreateInfo>();
             foreach (var createInfo in queueCreateInfos.OrderByDescending(e => e.QueueCount))
             {
                 if (!alreadyHave.Contains(createInfo.QueueFamilyIndex))
                 {
                     alreadyHave.Add(createInfo.QueueFamilyIndex);
                     uniqueCreateInfos.Add(createInfo);
                 }
             }
             queueCreateInfos = uniqueCreateInfos;
             foreach (var createInfo in queueCreateInfos)
             {
                 createInfo.PrintDebug();
             }
         }
         // Create device
         Device = PhysicalDevice.CreateDevice(new DeviceCreateInfo()
         {
             EnabledExtensionNames = EnabledDeviceExtensions.ToArray(),
             QueueCreateInfos      = queueCreateInfos.ToArray(),
             EnabledFeatures       = EnabledPhysicalDeviceFeatures
         });
         // Set the queues in the queue families, using those created with the device
         foreach (var family in QueueFamilies)
         {
             var queues = new Queue[family.Count];
             for (var i = 0; i < queues.Length; i++)
             {
                 queues[i] = Device.GetQueue(family.Index, i);
             }
             family.SetQueues(queues);
         }
         // Create and set the command pools in the queue families
         foreach (var family in QueueFamilies)
         {
             // Skip family that shouldn't have a command pool
             if (!family.HasCommandPool)
             {
                 continue;
             }
             // Create command pool
             var commandPool = Device.CreateCommandPool(new CommandPoolCreateInfo()
             {
                 QueueFamilyIndex = family.Index,
                 Flags            = family.CommandPoolFlags
             });
             family.SetCommandPool(commandPool);
         }
     }
     // Create swapchain
     {
         // Query supported capabilities and formats
         var surfaceCapabilities = SurfaceCapabilities;
         var surfaceFormats      = SurfaceFormats;
         var surfacePresentModes = SurfacePresentModes;
         surfaceCapabilities.PrintDebug();
         // Choose the best image format and color space
         {
             var imageFormat = Array.Find(
                 PreferredSwapchainFormats,
                 preferred => surfaceFormats.Any(available => available.Format == preferred)
                 );
             if (imageFormat == Format.Undefined)
             {
                 imageFormat = surfaceFormats.FirstOrDefault().Format;
             }
             if (imageFormat == Format.Undefined)
             {
                 throw new InvalidOperationException("Surface somehow does not support any known image formats");
             }
             SwapchainImageFormat = imageFormat;
             SwapchainColorSpace  = surfaceFormats.First(e => e.Format == SwapchainImageFormat).ColorSpace;
         }
         // Choose the best present mode
         {
             var presentMode = Array.Find(
                 PreferredPresentModes,
                 preferred => surfacePresentModes.Any(available => available == preferred)
                 );
             SwapchainPresentMode = presentMode;
         }
         // Create the swapchain
         SwapchainExtent = surfaceCapabilities.CurrentExtent;
         Swapchain       = Device.CreateSwapchainKhr(new SwapchainCreateInfoKhr(
                                                         surface: Surface,
                                                         imageFormat: SwapchainImageFormat,
                                                         imageExtent: SwapchainExtent,
                                                         preTransform: surfaceCapabilities.CurrentTransform,
                                                         presentMode: SwapchainPresentMode,
                                                         minImageCount: SurfaceCapabilities.MinImageCount,
                                                         imageArrayLayers: SurfaceCapabilities.MaxImageArrayLayers,
                                                         imageSharingMode: SharingMode.Exclusive,
                                                         imageColorSpace: SwapchainColorSpace
                                                         ));
         SwapchainAttachmentImages = Swapchain.GetImages().Select(
             e => new VKImage(
                 e, SwapchainImageFormat,
                 SwapchainExtent,
                 new ImageSubresourceRange(ImageAspects.Color, 0, 1, 0, 1)
                 )
             ).ToArray();
         Swapchain.PrintDebug();
     }
     // Create semaphores & fences
     {
         // Image available semaphore
         ImageAvailableSemaphore = Device.CreateSemaphore();
         ReadyToPresentSemaphore = Device.CreateSemaphore();
         // Swapchain image rendering fences
         RenderToImageFences = new Fence[SwapchainAttachmentImages.Length];
         for (var i = 0; i < RenderToImageFences.Length; i++)
         {
             RenderToImageFences[i] = Device.CreateFence(new FenceCreateInfo(flags: FenceCreateFlags.Signaled));
         }
     }
     // Create content collection
     {
         Content = new ContentCollection(this);
     }
     // Misc
     Stopwatch   = Stopwatch.StartNew();
     CurrentTime = 0.0;
 }
Example #6
0
        /// <summary>
        /// Initialize this swap chain on a specified surface.
        /// </summary>
        /// <param name="surface">Target video surface.</param>
        /// <param name="surfaceSize">Swap queue target size.</param>
        public void Initialize(Surface surface, Vector2i surfaceSize)
        {
            base.Initialize(surface, surfaceSize);

            VKSurface vkSurface = surface as VKSurface;

            // - Get capabilites and hardware information
            SurfaceCapabilities Capabilities = GraphicsCard.Handle.GetSurfaceCapabilities(vkSurface.Handle);

            formats      = GraphicsCard.Handle.GetSurfaceFormats(vkSurface.Handle);
            presentModes = GraphicsCard.Handle.GetSurfacePresentModes(vkSurface.Handle);

            uint imageCount = Capabilities.MinImageCount + 1;

            if (Capabilities.MaxImageCount > 0 && imageCount > Capabilities.MaxImageCount)
            {
                imageCount = Capabilities.MaxImageCount;
            }

            // - Default video format -> the first one
            surfaceFormat = formats[0];

            // - Checks for a BGRA32 video format
            foreach (var format in formats)
            {
                if (format.Format == Format.B8G8R8A8UNorm && format.ColorSpace == ColorSpace.SrgbNonlinear)
                {
                    surfaceFormat = format;
                    break;
                }
            }

            // - Checks if ther're no avaiable formats and we create a new one
            if (formats.Length == 1 && formats[0].Format == Format.Undefined)
            {
                surfaceFormat = new SharpVk.Khronos.SurfaceFormat
                {
                    Format     = Format.B8G8R8A8UNorm,
                    ColorSpace = ColorSpace.SrgbNonlinear
                };
            }

            // - Computes the swap chain drawing surface size
            Extent2D extent = Capabilities.CurrentExtent;

            if (extent.Width != uint.MaxValue)
            {
                long Width  = Math.Max(Capabilities.MinImageExtent.Width, Math.Min(Capabilities.MaxImageExtent.Width, surfaceSize.Width));
                long Height = Math.Max(Capabilities.MinImageExtent.Height, Math.Min(Capabilities.MaxImageExtent.Height, surfaceSize.Height));
                extent = new Extent2D((uint)Width, (uint)Height);
            }

            // - Shortcut (to avoid long parameters on the next call)
            var  queues    = new[] { RenderDevice.PresentQueueIndex, RenderDevice.GraphicQueueIndex };
            bool exclusive = RenderDevice.GraphicQueueIndex == RenderDevice.PresentQueueIndex;

            Handle = RenderDevice.Handle.CreateSwapchain
                     (
                vkSurface.Handle, imageCount,
                surfaceFormat.Format,
                surfaceFormat.ColorSpace,
                extent, 1, ImageUsageFlags.ColorAttachment,
                exclusive ? SharingMode.Exclusive : SharingMode.Concurrent, exclusive ? null : queues,
                Capabilities.CurrentTransform, CompositeAlphaFlags.Opaque,
                PresentModes.Contains(PresentMode.Mailbox) ? PresentMode.Mailbox : PresentMode.Fifo,
                true, Handle
                     );

            images      = Handle.GetImages();
            this.extent = extent;
        }