public void InitVulkan() { VkResult err; err = CreateInstance(true); if (err != VkResult.Success) { throw new InvalidOperationException("Could not create Vulkan instance."); } if (Settings.Validation) { } // Physical Device uint gpuCount = 0; Util.CheckResult(vkEnumeratePhysicalDevices(Instance, &gpuCount, null)); Debug.Assert(gpuCount > 0); // Enumerate devices IntPtr *physicalDevices = stackalloc IntPtr[(int)gpuCount]; err = vkEnumeratePhysicalDevices(Instance, &gpuCount, (VkPhysicalDevice *)physicalDevices); if (err != VkResult.Success) { throw new InvalidOperationException("Could not enumerate physical devices."); } // GPU selection // Select physical Device to be used for the Vulkan example // Defaults to the first Device unless specified by command line uint selectedDevice = 0; // TODO: Implement arg parsing, etc. PhysicalDevice = ((VkPhysicalDevice *)physicalDevices)[selectedDevice]; // Store properties (including limits) and features of the phyiscal Device // So examples can check against them and see if a feature is actually supported VkPhysicalDeviceProperties deviceProperties; vkGetPhysicalDeviceProperties(PhysicalDevice, &deviceProperties); DeviceProperties = deviceProperties; VkPhysicalDeviceFeatures deviceFeatures; vkGetPhysicalDeviceFeatures(PhysicalDevice, &deviceFeatures); DeviceFeatures = deviceFeatures; // Gather physical Device memory properties VkPhysicalDeviceMemoryProperties deviceMemoryProperties; vkGetPhysicalDeviceMemoryProperties(PhysicalDevice, &deviceMemoryProperties); DeviceMemoryProperties = deviceMemoryProperties; // Derived examples can override this to set actual features (based on above readings) to enable for logical device creation getEnabledFeatures(); // Vulkan Device creation // This is handled by a separate class that gets a logical Device representation // and encapsulates functions related to a Device VulkanDevice = new vksVulkanDevice(PhysicalDevice); VkResult res = VulkanDevice.CreateLogicalDevice(EnabledFeatures, EnabledExtensions); if (res != VkResult.Success) { throw new InvalidOperationException("Could not create Vulkan Device."); } Device = VulkanDevice.LogicalDevice; // Get a graphics queue from the Device VkQueue queue; vkGetDeviceQueue(Device, VulkanDevice.QFIndices.Graphics, 0, &queue); Queue = queue; // Find a suitable depth format VkFormat depthFormat; uint validDepthFormat = Tools.getSupportedDepthFormat(PhysicalDevice, &depthFormat); Debug.Assert(validDepthFormat == True); DepthFormat = depthFormat; Swapchain.Connect(Instance, PhysicalDevice, Device); // Create synchronization objects VkSemaphoreCreateInfo semaphoreCreateInfo = Initializers.SemaphoreCreateInfo(); // Create a semaphore used to synchronize image presentation // Ensures that the image is displayed before we start submitting new commands to the queu Util.CheckResult(vkCreateSemaphore(Device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->PresentComplete)); // Create a semaphore used to synchronize command submission // Ensures that the image is not presented until all commands have been sumbitted and executed Util.CheckResult(vkCreateSemaphore(Device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->RenderComplete)); // Create a semaphore used to synchronize command submission // Ensures that the image is not presented until all commands for the text overlay have been sumbitted and executed // Will be inserted after the render complete semaphore if the text overlay is enabled Util.CheckResult(vkCreateSemaphore(Device, &semaphoreCreateInfo, null, &GetSemaphoresPtr()->TextOverlayComplete)); // Set up submit info structure // Semaphores will stay the same during application lifetime // Command buffer submission info is set by each example SubmitInfo = Initializers.SubmitInfo(); SubmitInfo.pWaitDstStageMask = (VkPipelineStageFlags *)submitPipelineStages.Data; SubmitInfo.waitSemaphoreCount = 1; SubmitInfo.pWaitSemaphores = &GetSemaphoresPtr()->PresentComplete; SubmitInfo.signalSemaphoreCount = 1; SubmitInfo.pSignalSemaphores = &GetSemaphoresPtr()->RenderComplete; }