From 0216233a8378630fd6b04d11a881a9e854fefc9c Mon Sep 17 00:00:00 2001 From: Corentin Wallez Date: Tue, 21 Nov 2017 12:52:03 -0500 Subject: [PATCH] Vulkan: Create device and load all entry points --- src/backend/vulkan/VulkanBackend.cpp | 130 +++++++++++++++++---- src/backend/vulkan/VulkanBackend.h | 16 ++- src/backend/vulkan/VulkanFunctions.cpp | 155 ++++++++++++++++++++++++- src/backend/vulkan/VulkanFunctions.h | 152 +++++++++++++++++++++++- src/backend/vulkan/VulkanInfo.cpp | 106 +++++++++++++++-- src/backend/vulkan/VulkanInfo.h | 45 ++++--- 6 files changed, 546 insertions(+), 58 deletions(-) diff --git a/src/backend/vulkan/VulkanBackend.cpp b/src/backend/vulkan/VulkanBackend.cpp index 7500329fc7..251f6cd544 100644 --- a/src/backend/vulkan/VulkanBackend.cpp +++ b/src/backend/vulkan/VulkanBackend.cpp @@ -49,40 +49,68 @@ namespace vulkan { } VulkanFunctions* functions = GetMutableFunctions(); - VulkanInfo* vulkanInfo = GetMutableInfo(); if (!functions->LoadGlobalProcs(vulkanLib)) { ASSERT(false); return; } - if (!vulkanInfo->GatherGlobalInfo(*this)) { + if (!GatherGlobalInfo(*this, &globalInfo)) { ASSERT(false); return; } - KnownGlobalVulkanExtensions usedGlobals; - if (!CreateInstance(&usedGlobals)) { + VulkanGlobalKnobs usedGlobalKnobs = {}; + if (!CreateInstance(&usedGlobalKnobs)) { + ASSERT(false); + return; + } + *static_cast(&globalInfo) = usedGlobalKnobs; + + if (!functions->LoadInstanceProcs(instance, usedGlobalKnobs)) { ASSERT(false); return; } - if (!functions->LoadInstanceProcs(instance, usedGlobals)) { - ASSERT(false); - return; - } - - vulkanInfo->SetUsedGlobals(usedGlobals); - - if(usedGlobals.debugReport) { + if (usedGlobalKnobs.debugReport) { if (!RegisterDebugReport()) { ASSERT(false); return; } } + + std::vector physicalDevices; + if (!GetPhysicalDevices(*this, &physicalDevices) || physicalDevices.empty()) { + ASSERT(false); + return; + } + // TODO(cwallez@chromium.org): Choose the physical device based on ??? + physicalDevice = physicalDevices[0]; + + if (!GatherDeviceInfo(*this, physicalDevice, &deviceInfo)) { + ASSERT(false); + return; + } + + VulkanDeviceKnobs usedDeviceKnobs = {}; + if (!CreateDevice(&usedDeviceKnobs)) { + ASSERT(false); + return; + } + *static_cast(&deviceInfo) = usedDeviceKnobs; + + if (!functions->LoadDeviceProcs(vkDevice, usedDeviceKnobs)) { + ASSERT(false); + return; + } } Device::~Device() { + if (vkDevice != VK_NULL_HANDLE) { + fn.DestroyDevice(vkDevice, nullptr); + vkDevice = VK_NULL_HANDLE; + } + if (debugReportCallback != VK_NULL_HANDLE) { fn.DestroyDebugReportCallbackEXT(instance, debugReportCallback, nullptr); debugReportCallback = VK_NULL_HANDLE; @@ -160,18 +188,22 @@ namespace vulkan { void Device::TickImpl() { } - bool Device::CreateInstance(KnownGlobalVulkanExtensions* usedGlobals) { + VkInstance Device::GetInstance() const { + return instance; + } + + bool Device::CreateInstance(VulkanGlobalKnobs* usedKnobs) { std::vector layersToRequest; std::vector extensionsToRequest; #if defined(NXT_ENABLE_ASSERTS) - if (info.global.standardValidation) { + if (globalInfo.standardValidation) { layersToRequest.push_back(kLayerNameLunargStandardValidation); - usedGlobals->standardValidation = true; + usedKnobs->standardValidation = true; } - if (info.global.debugReport) { + if (globalInfo.debugReport) { extensionsToRequest.push_back(kExtensionNameExtDebugReport); - usedGlobals->debugReport = true; + usedKnobs->debugReport = true; } #endif @@ -201,6 +233,66 @@ namespace vulkan { return true; } + bool Device::CreateDevice(VulkanDeviceKnobs* usedKnobs) { + float zero = 0.0f; + std::vector layersToRequest; + std::vector extensionsToRequest; + std::vector queuesToRequest; + + if (deviceInfo.swapchain) { + extensionsToRequest.push_back(kExtensionNameKhrSwapchain); + usedKnobs->swapchain = true; + } + + // Find a universal queue family + { + constexpr uint32_t kUniversalFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT | VK_QUEUE_TRANSFER_BIT; + ssize_t universalQueueFamily = -1; + for (size_t i = 0; i < deviceInfo.queueFamilies.size(); ++i) { + if ((deviceInfo.queueFamilies[i].queueFlags & kUniversalFlags) == kUniversalFlags) { + universalQueueFamily = i; + break; + } + } + + if (universalQueueFamily == -1) { + return false; + } + queueFamily = static_cast(universalQueueFamily); + } + + // Choose to create a single universal queue + { + VkDeviceQueueCreateInfo queueCreateInfo; + queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; + queueCreateInfo.pNext = nullptr; + queueCreateInfo.flags = 0; + queueCreateInfo.queueFamilyIndex = static_cast(queueFamily); + queueCreateInfo.queueCount = 1; + queueCreateInfo.pQueuePriorities = &zero; + + queuesToRequest.push_back(queueCreateInfo); + } + + VkDeviceCreateInfo createInfo; + createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; + createInfo.pNext = nullptr; + createInfo.flags = 0; + createInfo.queueCreateInfoCount = static_cast(queuesToRequest.size()); + createInfo.pQueueCreateInfos = queuesToRequest.data(); + createInfo.enabledLayerCount = static_cast(layersToRequest.size()); + createInfo.ppEnabledLayerNames = layersToRequest.data(); + createInfo.enabledExtensionCount = static_cast(extensionsToRequest.size()); + createInfo.ppEnabledExtensionNames = extensionsToRequest.data(); + createInfo.pEnabledFeatures = &usedKnobs->features; + + if (fn.CreateDevice(physicalDevice, &createInfo, nullptr, &vkDevice) != VK_SUCCESS) { + return false; + } + + return true; + } + bool Device::RegisterDebugReport() { VkDebugReportCallbackCreateInfoEXT createInfo; createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT; @@ -234,10 +326,6 @@ namespace vulkan { return const_cast(&fn); } - VulkanInfo* Device::GetMutableInfo() { - return const_cast(&info); - } - // Buffer Buffer::Buffer(BufferBuilder* builder) diff --git a/src/backend/vulkan/VulkanBackend.h b/src/backend/vulkan/VulkanBackend.h index 9833e56c6a..e2bca1a0a1 100644 --- a/src/backend/vulkan/VulkanBackend.h +++ b/src/backend/vulkan/VulkanBackend.h @@ -121,13 +121,14 @@ namespace vulkan { // Contains all the Vulkan entry points, vkDoFoo is called via device->fn.DoFoo. const VulkanFunctions fn; - // All the information queried about this Vulkan system - const VulkanInfo info; + + VkInstance GetInstance() const; private: - bool CreateInstance(KnownGlobalVulkanExtensions* usedGlobals); - bool RegisterDebugReport(); + bool CreateInstance(VulkanGlobalKnobs* usedKnobs); + bool CreateDevice(VulkanDeviceKnobs* usedKnobs); + bool RegisterDebugReport(); static VkBool32 OnDebugReportCallback(VkDebugReportFlagsEXT flags, VkDebugReportObjectTypeEXT objectType, uint64_t object, @@ -140,11 +141,16 @@ namespace vulkan { // To make it easier to use fn it is a public const member. However // the Device is allowed to mutate them through these private methods. VulkanFunctions* GetMutableFunctions(); - VulkanInfo* GetMutableInfo(); + + VulkanGlobalInfo globalInfo; + VulkanDeviceInfo deviceInfo; DynamicLib vulkanLib; VkInstance instance = VK_NULL_HANDLE; + VkPhysicalDevice physicalDevice = VK_NULL_HANDLE; + VkDevice vkDevice = VK_NULL_HANDLE; + uint32_t queueFamily = 0; VkDebugReportCallbackEXT debugReportCallback = VK_NULL_HANDLE; }; diff --git a/src/backend/vulkan/VulkanFunctions.cpp b/src/backend/vulkan/VulkanFunctions.cpp index 62a8d8e812..be63afcef5 100644 --- a/src/backend/vulkan/VulkanFunctions.cpp +++ b/src/backend/vulkan/VulkanFunctions.cpp @@ -32,7 +32,6 @@ namespace vulkan { } GET_GLOBAL_PROC(CreateInstance); - GET_GLOBAL_PROC(DestroyInstance); GET_GLOBAL_PROC(EnumerateInstanceExtensionProperties); GET_GLOBAL_PROC(EnumerateInstanceLayerProperties); @@ -45,12 +44,16 @@ namespace vulkan { return false; \ } - bool VulkanFunctions::LoadInstanceProcs(VkInstance instance, const KnownGlobalVulkanExtensions& usedGlobals) { + bool VulkanFunctions::LoadInstanceProcs(VkInstance instance, const VulkanGlobalKnobs& usedKnobs) { + // Load this proc first so that we can destroy the instance even if some other GET_INSTANCE_PROC fails + GET_INSTANCE_PROC(DestroyInstance); + GET_INSTANCE_PROC(CreateDevice); GET_INSTANCE_PROC(DestroyDevice); GET_INSTANCE_PROC(EnumerateDeviceExtensionProperties); GET_INSTANCE_PROC(EnumerateDeviceLayerProperties); GET_INSTANCE_PROC(EnumeratePhysicalDevices); + GET_INSTANCE_PROC(GetDeviceProcAddr); GET_INSTANCE_PROC(GetPhysicalDeviceFeatures); GET_INSTANCE_PROC(GetPhysicalDeviceFormatProperties); GET_INSTANCE_PROC(GetPhysicalDeviceImageFormatProperties); @@ -59,12 +62,158 @@ namespace vulkan { GET_INSTANCE_PROC(GetPhysicalDeviceQueueFamilyProperties); GET_INSTANCE_PROC(GetPhysicalDeviceSparseImageFormatProperties); - if (usedGlobals.debugReport) { + if (usedKnobs.debugReport) { GET_INSTANCE_PROC(CreateDebugReportCallbackEXT); GET_INSTANCE_PROC(DebugReportMessageEXT); GET_INSTANCE_PROC(DestroyDebugReportCallbackEXT); } + if (usedKnobs.surface) { + GET_INSTANCE_PROC(DestroySurfaceKHR); + GET_INSTANCE_PROC(GetPhysicalDeviceSurfaceSupportKHR); + GET_INSTANCE_PROC(GetPhysicalDeviceSurfaceCapabilitiesKHR); + GET_INSTANCE_PROC(GetPhysicalDeviceSurfaceFormatsKHR); + GET_INSTANCE_PROC(GetPhysicalDeviceSurfacePresentModesKHR); + } + + return true; + } + + #define GET_DEVICE_PROC(name) \ + name = reinterpret_cast(GetDeviceProcAddr(device, "vk" #name)); \ + if (name == nullptr) { \ + return false; \ + } + + bool VulkanFunctions::LoadDeviceProcs(VkDevice device, const VulkanDeviceKnobs& usedKnobs) { + GET_DEVICE_PROC(AllocateCommandBuffers); + GET_DEVICE_PROC(AllocateDescriptorSets); + GET_DEVICE_PROC(AllocateMemory); + GET_DEVICE_PROC(BeginCommandBuffer); + GET_DEVICE_PROC(BindBufferMemory); + GET_DEVICE_PROC(BindImageMemory); + GET_DEVICE_PROC(CmdBeginQuery); + GET_DEVICE_PROC(CmdBeginRenderPass); + GET_DEVICE_PROC(CmdBindDescriptorSets); + GET_DEVICE_PROC(CmdBindIndexBuffer); + GET_DEVICE_PROC(CmdBindPipeline); + GET_DEVICE_PROC(CmdBindVertexBuffers); + GET_DEVICE_PROC(CmdBlitImage); + GET_DEVICE_PROC(CmdClearAttachments); + GET_DEVICE_PROC(CmdClearColorImage); + GET_DEVICE_PROC(CmdClearDepthStencilImage); + GET_DEVICE_PROC(CmdCopyBuffer); + GET_DEVICE_PROC(CmdCopyBufferToImage); + GET_DEVICE_PROC(CmdCopyImage); + GET_DEVICE_PROC(CmdCopyImageToBuffer); + GET_DEVICE_PROC(CmdCopyQueryPoolResults); + GET_DEVICE_PROC(CmdDispatch); + GET_DEVICE_PROC(CmdDispatchIndirect); + GET_DEVICE_PROC(CmdDraw); + GET_DEVICE_PROC(CmdDrawIndexed); + GET_DEVICE_PROC(CmdDrawIndexedIndirect); + GET_DEVICE_PROC(CmdDrawIndirect); + GET_DEVICE_PROC(CmdEndQuery); + GET_DEVICE_PROC(CmdEndRenderPass); + GET_DEVICE_PROC(CmdExecuteCommands); + GET_DEVICE_PROC(CmdFillBuffer); + GET_DEVICE_PROC(CmdNextSubpass); + GET_DEVICE_PROC(CmdPipelineBarrier); + GET_DEVICE_PROC(CmdPushConstants); + GET_DEVICE_PROC(CmdResetEvent); + GET_DEVICE_PROC(CmdResetQueryPool); + GET_DEVICE_PROC(CmdResolveImage); + GET_DEVICE_PROC(CmdSetBlendConstants); + GET_DEVICE_PROC(CmdSetDepthBias); + GET_DEVICE_PROC(CmdSetDepthBounds); + GET_DEVICE_PROC(CmdSetEvent); + GET_DEVICE_PROC(CmdSetLineWidth); + GET_DEVICE_PROC(CmdSetScissor); + GET_DEVICE_PROC(CmdSetStencilCompareMask); + GET_DEVICE_PROC(CmdSetStencilReference); + GET_DEVICE_PROC(CmdSetStencilWriteMask); + GET_DEVICE_PROC(CmdSetViewport); + GET_DEVICE_PROC(CmdUpdateBuffer); + GET_DEVICE_PROC(CmdWaitEvents); + GET_DEVICE_PROC(CmdWriteTimestamp); + GET_DEVICE_PROC(CreateBuffer); + GET_DEVICE_PROC(CreateBufferView); + GET_DEVICE_PROC(CreateCommandPool); + GET_DEVICE_PROC(CreateComputePipelines); + GET_DEVICE_PROC(CreateDescriptorPool); + GET_DEVICE_PROC(CreateDescriptorSetLayout); + GET_DEVICE_PROC(CreateEvent); + GET_DEVICE_PROC(CreateFence); + GET_DEVICE_PROC(CreateFramebuffer); + GET_DEVICE_PROC(CreateGraphicsPipelines); + GET_DEVICE_PROC(CreateImage); + GET_DEVICE_PROC(CreateImageView); + GET_DEVICE_PROC(CreatePipelineCache); + GET_DEVICE_PROC(CreatePipelineLayout); + GET_DEVICE_PROC(CreateQueryPool); + GET_DEVICE_PROC(CreateRenderPass); + GET_DEVICE_PROC(CreateSampler); + GET_DEVICE_PROC(CreateSemaphore); + GET_DEVICE_PROC(CreateShaderModule); + GET_DEVICE_PROC(DestroyBuffer); + GET_DEVICE_PROC(DestroyBufferView); + GET_DEVICE_PROC(DestroyCommandPool); + GET_DEVICE_PROC(DestroyDescriptorPool); + GET_DEVICE_PROC(DestroyDescriptorSetLayout); + GET_DEVICE_PROC(DestroyEvent); + GET_DEVICE_PROC(DestroyFence); + GET_DEVICE_PROC(DestroyFramebuffer); + GET_DEVICE_PROC(DestroyImage); + GET_DEVICE_PROC(DestroyImageView); + GET_DEVICE_PROC(DestroyPipeline); + GET_DEVICE_PROC(DestroyPipelineCache); + GET_DEVICE_PROC(DestroyPipelineLayout); + GET_DEVICE_PROC(DestroyQueryPool); + GET_DEVICE_PROC(DestroyRenderPass); + GET_DEVICE_PROC(DestroySampler); + GET_DEVICE_PROC(DestroySemaphore); + GET_DEVICE_PROC(DestroyShaderModule); + GET_DEVICE_PROC(DeviceWaitIdle); + GET_DEVICE_PROC(EndCommandBuffer); + GET_DEVICE_PROC(FlushMappedMemoryRanges); + GET_DEVICE_PROC(FreeCommandBuffers); + GET_DEVICE_PROC(FreeDescriptorSets); + GET_DEVICE_PROC(FreeMemory); + GET_DEVICE_PROC(GetBufferMemoryRequirements); + GET_DEVICE_PROC(GetDeviceMemoryCommitment); + GET_DEVICE_PROC(GetDeviceQueue); + GET_DEVICE_PROC(GetEventStatus); + GET_DEVICE_PROC(GetFenceStatus); + GET_DEVICE_PROC(GetImageMemoryRequirements); + GET_DEVICE_PROC(GetImageSparseMemoryRequirements); + GET_DEVICE_PROC(GetImageSubresourceLayout); + GET_DEVICE_PROC(GetPipelineCacheData); + GET_DEVICE_PROC(GetQueryPoolResults); + GET_DEVICE_PROC(GetRenderAreaGranularity); + GET_DEVICE_PROC(InvalidateMappedMemoryRanges); + GET_DEVICE_PROC(MapMemory); + GET_DEVICE_PROC(MergePipelineCaches); + GET_DEVICE_PROC(QueueBindSparse); + GET_DEVICE_PROC(QueueSubmit); + GET_DEVICE_PROC(QueueWaitIdle); + GET_DEVICE_PROC(ResetCommandBuffer); + GET_DEVICE_PROC(ResetCommandPool); + GET_DEVICE_PROC(ResetDescriptorPool); + GET_DEVICE_PROC(ResetEvent); + GET_DEVICE_PROC(ResetFences); + GET_DEVICE_PROC(SetEvent); + GET_DEVICE_PROC(UnmapMemory); + GET_DEVICE_PROC(UpdateDescriptorSets); + GET_DEVICE_PROC(WaitForFences); + + if (usedKnobs.swapchain) { + GET_DEVICE_PROC(CreateSwapchainKHR); + GET_DEVICE_PROC(DestroySwapchainKHR); + GET_DEVICE_PROC(GetSwapchainImagesKHR); + GET_DEVICE_PROC(AcquireNextImageKHR); + GET_DEVICE_PROC(QueuePresentKHR); + } + return true; } diff --git a/src/backend/vulkan/VulkanFunctions.h b/src/backend/vulkan/VulkanFunctions.h index 7ca10a5628..15aff7f86f 100644 --- a/src/backend/vulkan/VulkanFunctions.h +++ b/src/backend/vulkan/VulkanFunctions.h @@ -22,18 +22,21 @@ class DynamicLib; namespace backend { namespace vulkan { - struct KnownGlobalVulkanExtensions; + struct VulkanGlobalKnobs; + struct VulkanDeviceKnobs; // Stores the Vulkan entry points. Also loads them from the dynamic library // and the vkGet*ProcAddress entry points. struct VulkanFunctions { bool LoadGlobalProcs(const DynamicLib& vulkanLib); - bool LoadInstanceProcs(VkInstance instance, const KnownGlobalVulkanExtensions& usedGlobals); + bool LoadInstanceProcs(VkInstance instance, const VulkanGlobalKnobs& usedGlobals); + bool LoadDeviceProcs(VkDevice device, const VulkanDeviceKnobs& usedKnobs); + + // ---------- Global procs // Initial proc from which we can get all the others PFN_vkGetInstanceProcAddr GetInstanceProcAddr = nullptr; - // Global procs, can be used without an instance PFN_vkCreateInstance CreateInstance = nullptr; PFN_vkEnumerateInstanceExtensionProperties EnumerateInstanceExtensionProperties = nullptr; PFN_vkEnumerateInstanceLayerProperties EnumerateInstanceLayerProperties = nullptr; @@ -41,11 +44,14 @@ namespace vulkan { // before querying the instance procs in case we need to error out during initialization. PFN_vkDestroyInstance DestroyInstance = nullptr; - // Instance procs + // ---------- Instance procs + + // Core Vulkan 1.0 PFN_vkCreateDevice CreateDevice = nullptr; PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties = nullptr; PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties = nullptr; PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices = nullptr; + PFN_vkGetDeviceProcAddr GetDeviceProcAddr = nullptr; PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures = nullptr; PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties = nullptr; PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties = nullptr; @@ -61,8 +67,144 @@ namespace vulkan { PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT = nullptr; PFN_vkDebugReportMessageEXT DebugReportMessageEXT = nullptr; PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT = nullptr; - }; + // VK_KHR_surface + PFN_vkDestroySurfaceKHR DestroySurfaceKHR = nullptr; + PFN_vkGetPhysicalDeviceSurfaceSupportKHR GetPhysicalDeviceSurfaceSupportKHR = nullptr; + PFN_vkGetPhysicalDeviceSurfaceCapabilitiesKHR GetPhysicalDeviceSurfaceCapabilitiesKHR = nullptr; + PFN_vkGetPhysicalDeviceSurfaceFormatsKHR GetPhysicalDeviceSurfaceFormatsKHR = nullptr; + PFN_vkGetPhysicalDeviceSurfacePresentModesKHR GetPhysicalDeviceSurfacePresentModesKHR = nullptr; + + // ---------- Device procs + + // Core Vulkan 1.0 + PFN_vkAllocateCommandBuffers AllocateCommandBuffers = nullptr; + PFN_vkAllocateDescriptorSets AllocateDescriptorSets = nullptr; + PFN_vkAllocateMemory AllocateMemory = nullptr; + PFN_vkBeginCommandBuffer BeginCommandBuffer = nullptr; + PFN_vkBindBufferMemory BindBufferMemory = nullptr; + PFN_vkBindImageMemory BindImageMemory = nullptr; + PFN_vkCmdBeginQuery CmdBeginQuery = nullptr; + PFN_vkCmdBeginRenderPass CmdBeginRenderPass = nullptr; + PFN_vkCmdBindDescriptorSets CmdBindDescriptorSets = nullptr; + PFN_vkCmdBindIndexBuffer CmdBindIndexBuffer = nullptr; + PFN_vkCmdBindPipeline CmdBindPipeline = nullptr; + PFN_vkCmdBindVertexBuffers CmdBindVertexBuffers = nullptr; + PFN_vkCmdBlitImage CmdBlitImage = nullptr; + PFN_vkCmdClearAttachments CmdClearAttachments = nullptr; + PFN_vkCmdClearColorImage CmdClearColorImage = nullptr; + PFN_vkCmdClearDepthStencilImage CmdClearDepthStencilImage = nullptr; + PFN_vkCmdCopyBuffer CmdCopyBuffer = nullptr; + PFN_vkCmdCopyBufferToImage CmdCopyBufferToImage = nullptr; + PFN_vkCmdCopyImage CmdCopyImage = nullptr; + PFN_vkCmdCopyImageToBuffer CmdCopyImageToBuffer = nullptr; + PFN_vkCmdCopyQueryPoolResults CmdCopyQueryPoolResults = nullptr; + PFN_vkCmdDispatch CmdDispatch = nullptr; + PFN_vkCmdDispatchIndirect CmdDispatchIndirect = nullptr; + PFN_vkCmdDraw CmdDraw = nullptr; + PFN_vkCmdDrawIndexed CmdDrawIndexed = nullptr; + PFN_vkCmdDrawIndexedIndirect CmdDrawIndexedIndirect = nullptr; + PFN_vkCmdDrawIndirect CmdDrawIndirect = nullptr; + PFN_vkCmdEndQuery CmdEndQuery = nullptr; + PFN_vkCmdEndRenderPass CmdEndRenderPass = nullptr; + PFN_vkCmdExecuteCommands CmdExecuteCommands = nullptr; + PFN_vkCmdFillBuffer CmdFillBuffer = nullptr; + PFN_vkCmdNextSubpass CmdNextSubpass = nullptr; + PFN_vkCmdPipelineBarrier CmdPipelineBarrier = nullptr; + PFN_vkCmdPushConstants CmdPushConstants = nullptr; + PFN_vkCmdResetEvent CmdResetEvent = nullptr; + PFN_vkCmdResetQueryPool CmdResetQueryPool = nullptr; + PFN_vkCmdResolveImage CmdResolveImage = nullptr; + PFN_vkCmdSetBlendConstants CmdSetBlendConstants = nullptr; + PFN_vkCmdSetDepthBias CmdSetDepthBias = nullptr; + PFN_vkCmdSetDepthBounds CmdSetDepthBounds = nullptr; + PFN_vkCmdSetEvent CmdSetEvent = nullptr; + PFN_vkCmdSetLineWidth CmdSetLineWidth = nullptr; + PFN_vkCmdSetScissor CmdSetScissor = nullptr; + PFN_vkCmdSetStencilCompareMask CmdSetStencilCompareMask = nullptr; + PFN_vkCmdSetStencilReference CmdSetStencilReference = nullptr; + PFN_vkCmdSetStencilWriteMask CmdSetStencilWriteMask = nullptr; + PFN_vkCmdSetViewport CmdSetViewport = nullptr; + PFN_vkCmdUpdateBuffer CmdUpdateBuffer = nullptr; + PFN_vkCmdWaitEvents CmdWaitEvents = nullptr; + PFN_vkCmdWriteTimestamp CmdWriteTimestamp = nullptr; + PFN_vkCreateBuffer CreateBuffer = nullptr; + PFN_vkCreateBufferView CreateBufferView = nullptr; + PFN_vkCreateCommandPool CreateCommandPool = nullptr; + PFN_vkCreateComputePipelines CreateComputePipelines = nullptr; + PFN_vkCreateDescriptorPool CreateDescriptorPool = nullptr; + PFN_vkCreateDescriptorSetLayout CreateDescriptorSetLayout = nullptr; + PFN_vkCreateEvent CreateEvent = nullptr; + PFN_vkCreateFence CreateFence = nullptr; + PFN_vkCreateFramebuffer CreateFramebuffer = nullptr; + PFN_vkCreateGraphicsPipelines CreateGraphicsPipelines = nullptr; + PFN_vkCreateImage CreateImage = nullptr; + PFN_vkCreateImageView CreateImageView = nullptr; + PFN_vkCreatePipelineCache CreatePipelineCache = nullptr; + PFN_vkCreatePipelineLayout CreatePipelineLayout = nullptr; + PFN_vkCreateQueryPool CreateQueryPool = nullptr; + PFN_vkCreateRenderPass CreateRenderPass = nullptr; + PFN_vkCreateSampler CreateSampler = nullptr; + PFN_vkCreateSemaphore CreateSemaphore = nullptr; + PFN_vkCreateShaderModule CreateShaderModule = nullptr; + PFN_vkDestroyBuffer DestroyBuffer = nullptr; + PFN_vkDestroyBufferView DestroyBufferView = nullptr; + PFN_vkDestroyCommandPool DestroyCommandPool = nullptr; + PFN_vkDestroyDescriptorPool DestroyDescriptorPool = nullptr; + PFN_vkDestroyDescriptorSetLayout DestroyDescriptorSetLayout = nullptr; + PFN_vkDestroyEvent DestroyEvent = nullptr; + PFN_vkDestroyFence DestroyFence = nullptr; + PFN_vkDestroyFramebuffer DestroyFramebuffer = nullptr; + PFN_vkDestroyImage DestroyImage = nullptr; + PFN_vkDestroyImageView DestroyImageView = nullptr; + PFN_vkDestroyPipeline DestroyPipeline = nullptr; + PFN_vkDestroyPipelineCache DestroyPipelineCache = nullptr; + PFN_vkDestroyPipelineLayout DestroyPipelineLayout = nullptr; + PFN_vkDestroyQueryPool DestroyQueryPool = nullptr; + PFN_vkDestroyRenderPass DestroyRenderPass = nullptr; + PFN_vkDestroySampler DestroySampler = nullptr; + PFN_vkDestroySemaphore DestroySemaphore = nullptr; + PFN_vkDestroyShaderModule DestroyShaderModule = nullptr; + PFN_vkDeviceWaitIdle DeviceWaitIdle = nullptr; + PFN_vkEndCommandBuffer EndCommandBuffer = nullptr; + PFN_vkFlushMappedMemoryRanges FlushMappedMemoryRanges = nullptr; + PFN_vkFreeCommandBuffers FreeCommandBuffers = nullptr; + PFN_vkFreeDescriptorSets FreeDescriptorSets = nullptr; + PFN_vkFreeMemory FreeMemory = nullptr; + PFN_vkGetBufferMemoryRequirements GetBufferMemoryRequirements = nullptr; + PFN_vkGetDeviceMemoryCommitment GetDeviceMemoryCommitment = nullptr; + PFN_vkGetDeviceQueue GetDeviceQueue = nullptr; + PFN_vkGetEventStatus GetEventStatus = nullptr; + PFN_vkGetFenceStatus GetFenceStatus = nullptr; + PFN_vkGetImageMemoryRequirements GetImageMemoryRequirements = nullptr; + PFN_vkGetImageSparseMemoryRequirements GetImageSparseMemoryRequirements = nullptr; + PFN_vkGetImageSubresourceLayout GetImageSubresourceLayout = nullptr; + PFN_vkGetPipelineCacheData GetPipelineCacheData = nullptr; + PFN_vkGetQueryPoolResults GetQueryPoolResults = nullptr; + PFN_vkGetRenderAreaGranularity GetRenderAreaGranularity = nullptr; + PFN_vkInvalidateMappedMemoryRanges InvalidateMappedMemoryRanges = nullptr; + PFN_vkMapMemory MapMemory = nullptr; + PFN_vkMergePipelineCaches MergePipelineCaches = nullptr; + PFN_vkQueueBindSparse QueueBindSparse = nullptr; + PFN_vkQueueSubmit QueueSubmit = nullptr; + PFN_vkQueueWaitIdle QueueWaitIdle = nullptr; + PFN_vkResetCommandBuffer ResetCommandBuffer = nullptr; + PFN_vkResetCommandPool ResetCommandPool = nullptr; + PFN_vkResetDescriptorPool ResetDescriptorPool = nullptr; + PFN_vkResetEvent ResetEvent = nullptr; + PFN_vkResetFences ResetFences = nullptr; + PFN_vkSetEvent SetEvent = nullptr; + PFN_vkUnmapMemory UnmapMemory = nullptr; + PFN_vkUpdateDescriptorSets UpdateDescriptorSets = nullptr; + PFN_vkWaitForFences WaitForFences = nullptr; + + // VK_KHR_swapchain + PFN_vkCreateSwapchainKHR CreateSwapchainKHR = nullptr; + PFN_vkDestroySwapchainKHR DestroySwapchainKHR = nullptr; + PFN_vkGetSwapchainImagesKHR GetSwapchainImagesKHR = nullptr; + PFN_vkAcquireNextImageKHR AcquireNextImageKHR = nullptr; + PFN_vkQueuePresentKHR QueuePresentKHR = nullptr; + }; } } diff --git a/src/backend/vulkan/VulkanInfo.cpp b/src/backend/vulkan/VulkanInfo.cpp index 14ca081427..fce5b15d79 100644 --- a/src/backend/vulkan/VulkanInfo.cpp +++ b/src/backend/vulkan/VulkanInfo.cpp @@ -34,8 +34,10 @@ namespace vulkan { const char kLayerNameLunargStandardValidation[] = "VK_LAYER_LUNARG_standard_validation"; const char kExtensionNameExtDebugReport[] = "VK_EXT_debug_report"; + const char kExtensionNameKhrSurface[] = "VK_KHR_surface"; + const char kExtensionNameKhrSwapchain[] = "VK_KHR_swapchain"; - bool VulkanInfo::GatherGlobalInfo(const Device& device) { + bool GatherGlobalInfo(const Device& device, VulkanGlobalInfo* info) { // Gather the info about the instance layers { uint32_t count = 0; @@ -47,15 +49,15 @@ namespace vulkan { return false; } - global.layers.resize(count); - result = device.fn.EnumerateInstanceLayerProperties(&count, global.layers.data()); + info->layers.resize(count); + result = device.fn.EnumerateInstanceLayerProperties(&count, info->layers.data()); if (result != VK_SUCCESS) { return false; } - for (const auto& layer : global.layers) { + for (const auto& layer : info->layers) { if (IsLayerName(layer, kLayerNameLunargStandardValidation)) { - global.standardValidation = true; + info->standardValidation = true; } } } @@ -68,15 +70,18 @@ namespace vulkan { return false; } - global.extensions.resize(count); - result = device.fn.EnumerateInstanceExtensionProperties(nullptr, &count, global.extensions.data()); + info->extensions.resize(count); + result = device.fn.EnumerateInstanceExtensionProperties(nullptr, &count, info->extensions.data()); if (result != VK_SUCCESS) { return false; } - for (const auto& extension : global.extensions) { + for (const auto& extension : info->extensions) { if (IsExtensionName(extension, kExtensionNameExtDebugReport)) { - global.debugReport = true; + info->debugReport = true; + } + if (IsExtensionName(extension, kExtensionNameKhrSurface)) { + info->surface = true; } } } @@ -86,8 +91,87 @@ namespace vulkan { return true; } - void VulkanInfo::SetUsedGlobals(const KnownGlobalVulkanExtensions& usedGlobals) { - *static_cast(&global) = usedGlobals; + bool GetPhysicalDevices(const Device& device, std::vector* physicalDevices) { + VkInstance instance = device.GetInstance(); + + uint32_t count = 0; + VkResult result = device.fn.EnumeratePhysicalDevices(instance, &count, nullptr); + if (result != VK_SUCCESS && result != VK_INCOMPLETE) { + return false; + } + + physicalDevices->resize(count); + result = device.fn.EnumeratePhysicalDevices(instance, &count, physicalDevices->data()); + if (result != VK_SUCCESS) { + return false; + } + + return true; } + + bool GatherDeviceInfo(const Device& device, VkPhysicalDevice physicalDevice, VulkanDeviceInfo* info) { + // Gather general info about the device + device.fn.GetPhysicalDeviceProperties(physicalDevice, &info->properties); + device.fn.GetPhysicalDeviceFeatures(physicalDevice, &info->features); + + // Gather info about device memory. + { + VkPhysicalDeviceMemoryProperties memory; + device.fn.GetPhysicalDeviceMemoryProperties(physicalDevice, &memory); + + info->memoryTypes.assign(memory.memoryTypes, memory.memoryTypes + memory.memoryTypeCount); + info->memoryHeaps.assign(memory.memoryHeaps, memory.memoryHeaps + memory.memoryHeapCount); + } + + // Gather info about device queue families + { + uint32_t count = 0; + device.fn.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, nullptr); + + info->queueFamilies.resize(count); + device.fn.GetPhysicalDeviceQueueFamilyProperties(physicalDevice, &count, info->queueFamilies.data()); + } + + // Gather the info about the device layers + { + uint32_t count = 0; + VkResult result = device.fn.EnumerateDeviceLayerProperties(physicalDevice, &count, nullptr); + if (result != VK_SUCCESS && result != VK_INCOMPLETE) { + return false; + } + + info->layers.resize(count); + result = device.fn.EnumerateDeviceLayerProperties(physicalDevice, &count, info->layers.data()); + if (result != VK_SUCCESS) { + return false; + } + } + + // Gather the info about the device extensions + { + uint32_t count = 0; + VkResult result = device.fn.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &count, nullptr); + if (result != VK_SUCCESS && result != VK_INCOMPLETE) { + return false; + } + + info->extensions.resize(count); + result = device.fn.EnumerateDeviceExtensionProperties(physicalDevice, nullptr, &count, info->extensions.data()); + if (result != VK_SUCCESS) { + return false; + } + + for (const auto& extension : info->extensions) { + if (IsExtensionName(extension, kExtensionNameKhrSwapchain)) { + info->swapchain = true; + } + } + } + + // TODO(cwallez@chromium.org): gather info about formats + + return true; + } + } } diff --git a/src/backend/vulkan/VulkanInfo.h b/src/backend/vulkan/VulkanInfo.h index f15bf72b21..45a8c3cfa0 100644 --- a/src/backend/vulkan/VulkanInfo.h +++ b/src/backend/vulkan/VulkanInfo.h @@ -27,29 +27,48 @@ namespace vulkan { extern const char kLayerNameLunargStandardValidation[]; extern const char kExtensionNameExtDebugReport[]; + extern const char kExtensionNameKhrSurface[]; + extern const char kExtensionNameKhrSwapchain[]; - struct KnownGlobalVulkanExtensions { + // Global information - gathered before the instance is created + struct VulkanGlobalKnobs { // Layers bool standardValidation = false; // Extensions bool debugReport = false; + bool surface = false; }; - // Stores the information about the Vulkan system that are required to use Vulkan. - // Also does the querying of the information. - struct VulkanInfo { - // Global information - gathered before the instance is created - struct : KnownGlobalVulkanExtensions { - std::vector layers; - std::vector extensions; - // TODO(cwallez@chromium.org): layer instance extensions - } global; - - bool GatherGlobalInfo(const Device& device); - void SetUsedGlobals(const KnownGlobalVulkanExtensions& usedGlobals); + struct VulkanGlobalInfo : VulkanGlobalKnobs { + std::vector layers; + std::vector extensions; + // TODO(cwallez@chromium.org): layer instance extensions }; + // Device information - gathered before the device is created. + struct VulkanDeviceKnobs { + VkPhysicalDeviceFeatures features; + + // Extensions + bool swapchain = false; + }; + + struct VulkanDeviceInfo : VulkanDeviceKnobs { + VkPhysicalDeviceProperties properties; + std::vector queueFamilies; + + std::vector memoryTypes; + std::vector memoryHeaps; + + std::vector layers; + std::vector extensions; + // TODO(cwallez@chromium.org): layer instance extensions + }; + + bool GatherGlobalInfo(const Device& device, VulkanGlobalInfo* info); + bool GetPhysicalDevices(const Device& device, std::vector* physicalDevices); + bool GatherDeviceInfo(const Device& device, VkPhysicalDevice physicalDevice, VulkanDeviceInfo* info); } }