summaryrefslogtreecommitdiffstats
path: root/Graphics/GraphicsEngineVulkan
diff options
context:
space:
mode:
authorEgor Yusov <egor.yusov@gmail.com>2018-03-18 00:03:31 +0000
committerEgor Yusov <egor.yusov@gmail.com>2018-03-18 00:03:31 +0000
commitcdf28f24b6943e90279ff0baa37ffbb6414c0419 (patch)
tree45f2e422d57c9fc3f46b163e934802bfcf67bd65 /Graphics/GraphicsEngineVulkan
parentAdded VulkanPhysiclDevice class (diff)
downloadDiligentCore-cdf28f24b6943e90279ff0baa37ffbb6414c0419.tar.gz
DiligentCore-cdf28f24b6943e90279ff0baa37ffbb6414c0419.zip
Added logical Vulkan device initialization
Diffstat (limited to 'Graphics/GraphicsEngineVulkan')
-rw-r--r--Graphics/GraphicsEngineVulkan/CMakeLists.txt5
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanErrors.h43
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.h3
-rw-r--r--Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.h3
-rw-r--r--Graphics/GraphicsEngineVulkan/include/pch.h31
-rw-r--r--Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp50
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp41
-rw-r--r--Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp35
8 files changed, 176 insertions, 35 deletions
diff --git a/Graphics/GraphicsEngineVulkan/CMakeLists.txt b/Graphics/GraphicsEngineVulkan/CMakeLists.txt
index 2ae05941..88dd3a11 100644
--- a/Graphics/GraphicsEngineVulkan/CMakeLists.txt
+++ b/Graphics/GraphicsEngineVulkan/CMakeLists.txt
@@ -30,6 +30,7 @@ set(INCLUDE
include/SwapChainVkImpl.h
include/TextureVkImpl.h
include/TextureViewVkImpl.h
+ include/VulkanErrors.h
)
set(VULKAN_UTILS_INCLUDE
@@ -183,7 +184,7 @@ set_common_target_properties(GraphicsEngineVk-shared)
set_common_target_properties(GraphicsEngineVk-static)
source_group("src" FILES ${SRC})
-source_group("src\\vulkan utils" FILES ${VULKAN_UTILS_SRC})
+source_group("src\\Vulkan Utilities" FILES ${VULKAN_UTILS_SRC})
source_group("dll" FILES
src/DLLMain.cpp
@@ -192,7 +193,7 @@ source_group("dll" FILES
source_group("include" FILES ${INCLUDE})
source_group("interface" FILES ${INTERFACE})
-source_group("include\\vulkan utils" FILES ${VULKAN_UTILS_INCLUDE})
+source_group("include\\Vulkan Utilities" FILES ${VULKAN_UTILS_INCLUDE})
#source_group("shaders" FILES
# ${SHADERS}
# shaders/GenerateMips/GenerateMipsCS.hlsli
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanErrors.h b/Graphics/GraphicsEngineVulkan/include/VulkanErrors.h
new file mode 100644
index 00000000..d93c930b
--- /dev/null
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanErrors.h
@@ -0,0 +1,43 @@
+/* Copyright 2015-2018 Egor Yusov
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF ANY PROPRIETARY RIGHTS.
+ *
+ * In no event and under no legal theory, whether in tort (including negligence),
+ * contract, or otherwise, unless required by applicable law (such as deliberate
+ * and grossly negligent acts) or agreed to in writing, shall any Contributor be
+ * liable for any damages, including any direct, indirect, special, incidental,
+ * or consequential damages of any character arising as a result of this License or
+ * out of the use or inability to use the software (including but not limited to damages
+ * for loss of goodwill, work stoppage, computer failure or malfunction, or any and
+ * all other commercial damages or losses), even if such Contributor has been advised
+ * of the possibility of such damages.
+ */
+
+#pragma once
+
+#include "Errors.h"
+#include "DebugUtilities.h"
+#include "VulkanUtilities/VulkanDebug.h"
+
+#define CHECK_VK_ERROR(err, ...)\
+{ \
+ if( err < 0 ) \
+ { \
+ LogError<false>(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__, "\nVK Error: ", VulkanUtilities::VkResultToString(err)); \
+ UNEXPECTED("Error"); \
+ } \
+}
+
+#define CHECK_VK_ERROR_AND_THROW(err, ...)\
+{ \
+ if( err < 0 ) \
+ LogError<true>(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__, "\nVK Error Code: ", VulkanUtilities::VkResultToString(err)); \
+}
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.h
index 9937d613..346afeee 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.h
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanInstance.h
@@ -40,7 +40,8 @@ namespace VulkanUtilities
bool IsLayerAvailable(const char *LayerName)const;
bool IsExtensionAvailable(const char *ExtensionName)const;
VkPhysicalDevice SelectPhysicalDevice();
-
+ VkAllocationCallbacks* GetVkAllocator()const{return m_pVkAllocator;}
+
private:
bool m_ValidationEnabled = false;
diff --git a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.h b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.h
index 76cd8bc8..2fb4d63a 100644
--- a/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.h
+++ b/Graphics/GraphicsEngineVulkan/include/VulkanUtilities/VulkanPhysicalDevice.h
@@ -32,6 +32,9 @@ namespace VulkanUtilities
{
public:
VulkanPhysicalDevice(VkPhysicalDevice vkDevice);
+ uint32_t FindQueueFamily(VkQueueFlags QueueFlags);
+ VkPhysicalDevice GetVkDeviceHandle()const{return m_VkDevice;}
+ bool IsExtensionSupported(const char *ExtensionName);
private:
const VkPhysicalDevice m_VkDevice;
diff --git a/Graphics/GraphicsEngineVulkan/include/pch.h b/Graphics/GraphicsEngineVulkan/include/pch.h
index ec0f4b00..7c623f11 100644
--- a/Graphics/GraphicsEngineVulkan/include/pch.h
+++ b/Graphics/GraphicsEngineVulkan/include/pch.h
@@ -28,8 +28,15 @@
#pragma once
-#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
-#define NOMINMAX
+#ifdef PLATFORM_WIN32
+# ifndef WIN32_LEAN_AND_MEAN
+# define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
+# endif
+
+# ifndef NOMINMAX
+# define NOMINMAX
+# endif
+#endif
#include <vector>
#include <exception>
@@ -40,23 +47,7 @@
#include "PlatformDefinitions.h"
#include "Errors.h"
#include "RefCntAutoPtr.h"
-#include "DebugUtilities.h"
-//#include "D3DErrors.h"
+#include "VulkanErrors.h"
#include "RenderDeviceBase.h"
#include "ValidatedCast.h"
-#include <atlcomcli.h>
-
-#define CHECK_VK_ERROR(err, ...)\
-{ \
- if( err < 0 ) \
- { \
- LogError<false>(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__, "\nVK Error: ", VulkanUtilities::VkResultToString(err)); \
- UNEXPECTED("Error"); \
- } \
-}
-
-#define CHECK_VK_ERROR_AND_THROW(err, ...)\
-{ \
- if( err < 0 ) \
- LogError<true>(__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__, "\nVK Error Code: ", VulkanUtilities::VkResultToString(err)); \
-}
+
diff --git a/Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp b/Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp
index c3b4c5ea..fcafced8 100644
--- a/Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/RenderDeviceFactoryVk.cpp
@@ -123,6 +123,11 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& Crea
if( !ppDevice || !ppContexts )
return;
+ SetRawAllocator(CreationAttribs.pRawMemAllocator);
+
+ *ppDevice = nullptr;
+ memset(ppContexts, 0, sizeof(*ppContexts) * (1 + NumDeferredContexts));
+
std::shared_ptr<VulkanUtilities::VulkanInstance> Instance;
try
{
@@ -131,14 +136,51 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& Crea
CreationAttribs.GlobalExtensionCount,
CreationAttribs.ppGlobalExtensionNames,
reinterpret_cast<VkAllocationCallbacks*>(CreationAttribs.pVkAllocator));
+
+ auto vkDevice = Instance->SelectPhysicalDevice();
+ std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice(new VulkanUtilities::VulkanPhysicalDevice(vkDevice));
+
+ // If an implementation exposes any queue family that supports graphics operations,
+ // at least one queue family of at least one physical device exposed by the implementation
+ // must support both graphics and compute operations.
+
+ VkDeviceQueueCreateInfo QueueInfo{};
+ QueueInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
+ // All commands that are allowed on a queue that supports transfer operations are also allowed on a
+ // queue that supports either graphics or compute operations.Thus, if the capabilities of a queue family
+ // include VK_QUEUE_GRAPHICS_BIT or VK_QUEUE_COMPUTE_BIT, then reporting the VK_QUEUE_TRANSFER_BIT
+ // capability separately for that queue family is optional.
+ QueueInfo.queueFamilyIndex = PhysicalDevice->FindQueueFamily(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT);
+ QueueInfo.queueCount = 1;
+ const float defaultQueuePriority = 1.0f; // Ask for highest priority for our queue. (range [0,1])
+ QueueInfo.pQueuePriorities = &defaultQueuePriority;
+
+ VkDeviceCreateInfo DeviceCreateInfo = {};
+ DeviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
+ DeviceCreateInfo.queueCreateInfoCount = 1;
+ DeviceCreateInfo.pQueueCreateInfos = &QueueInfo;
+ DeviceCreateInfo.pEnabledFeatures = nullptr;
+
+ std::vector<const char*> DeviceExtensions = { VK_KHR_SWAPCHAIN_EXTENSION_NAME };
+ if (PhysicalDevice->IsExtensionSupported(VK_EXT_DEBUG_MARKER_EXTENSION_NAME))
+ {
+ DeviceExtensions.push_back(VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
+ }
+
+ DeviceCreateInfo.ppEnabledExtensionNames = DeviceExtensions.empty() ? nullptr : DeviceExtensions.data();
+ DeviceCreateInfo.enabledExtensionCount = static_cast<uint32_t>(DeviceExtensions.size());
+
+ VkDevice VulkanDevice = VK_NULL_HANDLE;
+ auto res = vkCreateDevice(PhysicalDevice->GetVkDeviceHandle(), &DeviceCreateInfo, Instance->GetVkAllocator(), &VulkanDevice);
+ CHECK_VK_ERROR_AND_THROW(res, "Failed to create logical device");
+
+
}
catch(std::runtime_error& )
{
return;
}
- auto vkDevice = Instance->SelectPhysicalDevice();
- std::unique_ptr<VulkanUtilities::VulkanPhysicalDevice> PhysicalDevice(new VulkanUtilities::VulkanPhysicalDevice(vkDevice));
@@ -160,10 +202,6 @@ void EngineFactoryVkImpl::CreateDeviceAndContextsVk( const EngineVkAttribs& Crea
}
}
- SetRawAllocator(CreationAttribs.pRawMemAllocator);
-
- *ppDevice = nullptr;
- memset(ppContexts, 0, sizeof(*ppContexts) * (1+NumDeferredContexts));
RefCntAutoPtr<CommandQueueVkImpl> pCmdQueueVk;
CComPtr<IVkDevice> VkDevice;
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
index 561d990f..6ea5f13a 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanInstance.cpp
@@ -22,7 +22,7 @@
*/
#include <vector>
-#include "pch.h"
+#include "VulkanErrors.h"
#include "VulkanUtilities/VulkanInstance.h"
#include "VulkanUtilities/VulkanDebug.h"
@@ -193,20 +193,51 @@ namespace VulkanUtilities
VkPhysicalDevice VulkanInstance::SelectPhysicalDevice()
{
+ // Select a device that exposes a queue family that suppors both compute and graphics operations
+ // Prefer discrete GPU
for (auto Device : m_PhysicalDevices)
{
VkPhysicalDeviceProperties DeviceProps;
vkGetPhysicalDeviceProperties(Device, &DeviceProps);
- if (DeviceProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
+
+ uint32_t QueueFamilyCount = 0;
+ vkGetPhysicalDeviceQueueFamilyProperties(Device, &QueueFamilyCount, nullptr);
+ VERIFY_EXPR(QueueFamilyCount> 0);
+ std::vector<VkQueueFamilyProperties> QueueFamilyProperties(QueueFamilyCount);
+ vkGetPhysicalDeviceQueueFamilyProperties(Device, &QueueFamilyCount, QueueFamilyProperties.data());
+ VERIFY_EXPR(QueueFamilyCount == QueueFamilyProperties.size());
+
+ // If an implementation exposes any queue family that supports graphics operations,
+ // at least one queue family of at least one physical device exposed by the implementation
+ // must support both graphics and compute operations.
+ bool GraphicsAndComputeQueueSupported = false;
+ for(const auto &QueueFamilyProps : QueueFamilyProperties)
+ {
+ if( (QueueFamilyProps.queueFlags & VK_QUEUE_GRAPHICS_BIT) != 0 &&
+ (QueueFamilyProps.queueFlags & VK_QUEUE_COMPUTE_BIT) != 0)
+ {
+ GraphicsAndComputeQueueSupported = true;
+ break;
+ }
+ }
+ if(GraphicsAndComputeQueueSupported)
{
m_SelectedPhysicalDevice = Device;
- LOG_INFO_MESSAGE("Selected discrete GPU ", DeviceProps.deviceName);
- break;
+ if (DeviceProps.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU)
+ break;
}
}
- if(m_SelectedPhysicalDevice == VK_NULL_HANDLE)
+ if(m_SelectedPhysicalDevice != VK_NULL_HANDLE)
+ {
+ VkPhysicalDeviceProperties SelectedDeviceProps;
+ vkGetPhysicalDeviceProperties(m_SelectedPhysicalDevice, &SelectedDeviceProps);
+ LOG_INFO_MESSAGE("Using physical device ", SelectedDeviceProps.deviceName);
+ }
+ else
+ {
LOG_ERROR_MESSAGE("Failed to find suitable physical device");
+ }
return m_SelectedPhysicalDevice;
}
diff --git a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
index f75e24b5..745923ee 100644
--- a/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
+++ b/Graphics/GraphicsEngineVulkan/src/VulkanUtilities/VulkanPhysicalDevice.cpp
@@ -21,7 +21,7 @@
* of the possibility of such damages.
*/
-#include "pch.h"
+#include "VulkanErrors.h"
#include "VulkanUtilities/VulkanPhysicalDevice.h"
namespace VulkanUtilities
@@ -52,4 +52,37 @@ namespace VulkanUtilities
VERIFY_EXPR(ExtensionCount == m_SupportedExtensions.size());
}
}
+
+ uint32_t VulkanPhysicalDevice::FindQueueFamily(VkQueueFlags QueueFlags)
+ {
+ for(uint32_t i=0; i < m_QueueFamilyProperties.size(); ++i)
+ {
+ auto &Props = m_QueueFamilyProperties[i];
+ if( (Props.queueFlags & QueueFlags) == QueueFlags)
+ {
+ if(QueueFlags & (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT))
+ {
+ // Queues supporting graphics and/or compute operations must report (1,1,1)
+ // in minImageTransferGranularity, meaning that there are no additional restrictions
+ // on the granularity of image transfer operations for these queues.
+ VERIFY_EXPR(Props.minImageTransferGranularity.width == 1 &&
+ Props.minImageTransferGranularity.height == 1 &&
+ Props.minImageTransferGranularity.depth == 1);
+ return i;
+ }
+ }
+ }
+
+ LOG_ERROR_AND_THROW("Failed to find suitable queue family");
+ return 0;
+ }
+
+ bool VulkanPhysicalDevice::IsExtensionSupported(const char *ExtensionName)
+ {
+ for(const auto& Extension : m_SupportedExtensions)
+ if(strcmp(Extension.extensionName, ExtensionName) == 0)
+ return true;
+
+ return false;
+ }
}