VulkanDevice class, setup debugging before creating the logical device
This commit is contained in:
parent
03fc9f66ea
commit
919a510549
2 changed files with 63 additions and 110 deletions
|
|
@ -115,7 +115,6 @@ namespace vk
|
||||||
*/
|
*/
|
||||||
uint32_t getQueueFamiliyIndex(VkQueueFlagBits queueFlags)
|
uint32_t getQueueFamiliyIndex(VkQueueFlagBits queueFlags)
|
||||||
{
|
{
|
||||||
uint32_t queueIndex;
|
|
||||||
uint32_t queueCount;
|
uint32_t queueCount;
|
||||||
|
|
||||||
// Get number of available queue families on this device
|
// Get number of available queue families on this device
|
||||||
|
|
@ -150,16 +149,53 @@ namespace vk
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create the logical device based on the assigned physical device
|
* Create the logical device based on the assigned physical device, also gets default queue family indices
|
||||||
*
|
*
|
||||||
* @param queueCreateInfos A vector containing queue create infos for all queues to be requested on the device
|
|
||||||
* @param enabledFeatures Can be used to enable certain features upon device creation
|
* @param enabledFeatures Can be used to enable certain features upon device creation
|
||||||
* @param useSwapChain Set to false for headless rendering to omit the swapchain device extensions
|
* @param useSwapChain Set to false for headless rendering to omit the swapchain device extensions
|
||||||
*
|
*
|
||||||
* @return VkResult of the device creation call
|
* @return VkResult of the device creation call
|
||||||
*/
|
*/
|
||||||
VkResult createLogicalDevice(std::vector<VkDeviceQueueCreateInfo> &queueCreateInfos, VkPhysicalDeviceFeatures enabledFeatures, bool useSwapChain = true)
|
VkResult createLogicalDevice(VkPhysicalDeviceFeatures enabledFeatures, bool useSwapChain = true)
|
||||||
{
|
{
|
||||||
|
// Get queue family indices for graphics and compute
|
||||||
|
// Note that the indices may overlap depending on the implementation
|
||||||
|
queueFamilyIndices.graphics = getQueueFamiliyIndex(VK_QUEUE_GRAPHICS_BIT);
|
||||||
|
queueFamilyIndices.compute = getQueueFamiliyIndex(VK_QUEUE_COMPUTE_BIT);
|
||||||
|
//todo: Transfer?
|
||||||
|
|
||||||
|
// Pass queue information for graphics and compute, so examples can later on request queues from both
|
||||||
|
std::vector<float> queuePriorities;
|
||||||
|
|
||||||
|
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos{};
|
||||||
|
// We need one queue create info per queue family index
|
||||||
|
// If graphics and compute share the same queue family index we only need one queue create info but
|
||||||
|
// with two queues to request
|
||||||
|
queueCreateInfos.resize(1);
|
||||||
|
// Graphics
|
||||||
|
queuePriorities.push_back(0.0f);
|
||||||
|
queueCreateInfos[0] = {};
|
||||||
|
queueCreateInfos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
|
queueCreateInfos[0].queueFamilyIndex = queueFamilyIndices.graphics;
|
||||||
|
queueCreateInfos[0].queueCount = 1;
|
||||||
|
// Compute
|
||||||
|
// If compute has a different queue family index, add another create info, else just add
|
||||||
|
if (queueFamilyIndices.graphics != queueFamilyIndices.compute)
|
||||||
|
{
|
||||||
|
queueCreateInfos.resize(2);
|
||||||
|
queueCreateInfos[1] = {};
|
||||||
|
queueCreateInfos[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
||||||
|
queueCreateInfos[1].queueFamilyIndex = queueFamilyIndices.compute;
|
||||||
|
queueCreateInfos[1].queueCount = 1;
|
||||||
|
queueCreateInfos[1].pQueuePriorities = queuePriorities.data();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
queueCreateInfos[0].queueCount++;
|
||||||
|
queuePriorities.push_back(0.0f);
|
||||||
|
}
|
||||||
|
queueCreateInfos[0].pQueuePriorities = queuePriorities.data();
|
||||||
|
|
||||||
// Create the logical device representation
|
// Create the logical device representation
|
||||||
std::vector<const char*> deviceExtensions;
|
std::vector<const char*> deviceExtensions;
|
||||||
if (useSwapChain)
|
if (useSwapChain)
|
||||||
|
|
@ -191,59 +227,6 @@ namespace vk
|
||||||
return vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &logicalDevice);
|
return vkCreateDevice(physicalDevice, &deviceCreateInfo, nullptr, &logicalDevice);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Create the logical device based on the assigned physical device
|
|
||||||
*
|
|
||||||
* @note Using this overload will implicitly get default queue family indices for graphics and compute
|
|
||||||
*
|
|
||||||
* @param enabledFeatures Can be used to enable certain features upon device creation
|
|
||||||
* @param useSwapChain Set to false for headless rendering to omit the swapchain device extensions
|
|
||||||
*
|
|
||||||
* @return VkResult of the device creation call
|
|
||||||
*/
|
|
||||||
VkResult createLogicalDevice(VkPhysicalDeviceFeatures enabledFeatures, bool useSwapChain = true)
|
|
||||||
{
|
|
||||||
// Get queue family indices for graphics and compute
|
|
||||||
// Note that the indices may overlap depending on the implementation
|
|
||||||
queueFamilyIndices.graphics = getQueueFamiliyIndex(VK_QUEUE_GRAPHICS_BIT);
|
|
||||||
queueFamilyIndices.compute = getQueueFamiliyIndex(VK_QUEUE_COMPUTE_BIT);
|
|
||||||
//todo: Transfer?
|
|
||||||
|
|
||||||
// Pass queue information for graphics and compute, so examples can later on request queues from both
|
|
||||||
std::vector<float> queuePriorities;
|
|
||||||
|
|
||||||
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos{};
|
|
||||||
// We need one queue create info per queue family index
|
|
||||||
// If graphics and compute share the same queue family index we only need one queue create info but
|
|
||||||
// with two queues to request
|
|
||||||
queueCreateInfos.resize(1);
|
|
||||||
queuePriorities.resize(1, 0.0f);
|
|
||||||
// Graphics
|
|
||||||
queueCreateInfos[0] = {};
|
|
||||||
queueCreateInfos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
|
||||||
queueCreateInfos[0].queueFamilyIndex = queueFamilyIndices.graphics;
|
|
||||||
queueCreateInfos[0].queueCount = 1;
|
|
||||||
queueCreateInfos[0].pQueuePriorities = queuePriorities.data();
|
|
||||||
// Compute
|
|
||||||
// If compute has a different queue family index, add another create info, else just add
|
|
||||||
if (queueFamilyIndices.graphics != queueFamilyIndices.compute)
|
|
||||||
{
|
|
||||||
queueCreateInfos.resize(2);
|
|
||||||
queueCreateInfos[1] = {};
|
|
||||||
queueCreateInfos[1].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
|
||||||
queueCreateInfos[1].queueFamilyIndex = queueFamilyIndices.compute;
|
|
||||||
queueCreateInfos[1].queueCount = 1;
|
|
||||||
queueCreateInfos[1].pQueuePriorities = queuePriorities.data();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
queueCreateInfos[0].queueCount++;
|
|
||||||
queuePriorities.push_back(0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
return createLogicalDevice(queueCreateInfos, enabledFeatures, useSwapChain);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a buffer on the device
|
* Create a buffer on the device
|
||||||
*
|
*
|
||||||
|
|
|
||||||
|
|
@ -208,14 +208,6 @@ void VulkanExampleBase::createPipelineCache()
|
||||||
|
|
||||||
void VulkanExampleBase::prepare()
|
void VulkanExampleBase::prepare()
|
||||||
{
|
{
|
||||||
if (enableValidation)
|
|
||||||
{
|
|
||||||
// The report flags determine what type of messages for the layers will be displayed
|
|
||||||
// For validating (debugging) an appplication the error and warning bits should suffice
|
|
||||||
VkDebugReportFlagsEXT debugReportFlags = VK_DEBUG_REPORT_ERROR_BIT_EXT; // VK_DEBUG_REPORT_WARNING_BIT_EXT (enable to also display warnings)
|
|
||||||
// Additional flags include performance info, loader and layer debug messages, etc.
|
|
||||||
vkDebug::setupDebugging(instance, debugReportFlags, VK_NULL_HANDLE);
|
|
||||||
}
|
|
||||||
if (enableDebugMarkers)
|
if (enableDebugMarkers)
|
||||||
{
|
{
|
||||||
vkDebug::DebugMarker::setup(device);
|
vkDebug::DebugMarker::setup(device);
|
||||||
|
|
@ -698,11 +690,6 @@ VulkanExampleBase::VulkanExampleBase(bool enableValidation, PFN_GetEnabledFeatur
|
||||||
this->enabledFeatures = enabledFeaturesFn();
|
this->enabledFeatures = enabledFeaturesFn();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !defined(__ANDROID__)
|
|
||||||
// Android Vulkan initialization is handled in APP_CMD_INIT_WINDOW event
|
|
||||||
initVulkan(enableValidation);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
// Enable console if validation is active
|
// Enable console if validation is active
|
||||||
// Debug message callback will output to it
|
// Debug message callback will output to it
|
||||||
|
|
@ -711,6 +698,11 @@ VulkanExampleBase::VulkanExampleBase(bool enableValidation, PFN_GetEnabledFeatur
|
||||||
setupConsole("VulkanExample");
|
setupConsole("VulkanExample");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if !defined(__ANDROID__)
|
||||||
|
// Android Vulkan initialization is handled in APP_CMD_INIT_WINDOW event
|
||||||
|
initVulkan(enableValidation);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanExampleBase::~VulkanExampleBase()
|
VulkanExampleBase::~VulkanExampleBase()
|
||||||
|
|
@ -793,6 +785,16 @@ void VulkanExampleBase::initVulkan(bool enableValidation)
|
||||||
loadVulkanFunctions(instance);
|
loadVulkanFunctions(instance);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// If requested, we enable the default validation layers for debugging
|
||||||
|
if (enableValidation)
|
||||||
|
{
|
||||||
|
// The report flags determine what type of messages for the layers will be displayed
|
||||||
|
// For validating (debugging) an appplication the error and warning bits should suffice
|
||||||
|
VkDebugReportFlagsEXT debugReportFlags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT | VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT;
|
||||||
|
// Additional flags include performance info, loader and layer debug messages, etc.
|
||||||
|
vkDebug::setupDebugging(instance, debugReportFlags, VK_NULL_HANDLE);
|
||||||
|
}
|
||||||
|
|
||||||
// Physical device
|
// Physical device
|
||||||
uint32_t gpuCount = 0;
|
uint32_t gpuCount = 0;
|
||||||
// Get number of available physical devices
|
// Get number of available physical devices
|
||||||
|
|
@ -812,42 +814,14 @@ void VulkanExampleBase::initVulkan(bool enableValidation)
|
||||||
// and want to use another one
|
// and want to use another one
|
||||||
physicalDevice = physicalDevices[0];
|
physicalDevice = physicalDevices[0];
|
||||||
|
|
||||||
vulkanDevice = new vk::VulkanDevice(physicalDevice);
|
|
||||||
|
|
||||||
// Find a queue that supports graphics operations
|
|
||||||
uint32_t graphicsQueueIndex = 0;
|
|
||||||
uint32_t queueCount;
|
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, NULL);
|
|
||||||
assert(queueCount >= 1);
|
|
||||||
|
|
||||||
std::vector<VkQueueFamilyProperties> queueProps;
|
|
||||||
queueProps.resize(queueCount);
|
|
||||||
vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice, &queueCount, queueProps.data());
|
|
||||||
|
|
||||||
for (graphicsQueueIndex = 0; graphicsQueueIndex < queueCount; graphicsQueueIndex++)
|
|
||||||
{
|
|
||||||
if (queueProps[graphicsQueueIndex].queueFlags & VK_QUEUE_GRAPHICS_BIT)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
assert(graphicsQueueIndex < queueCount);
|
|
||||||
|
|
||||||
// Vulkan device creation
|
// Vulkan device creation
|
||||||
|
// This is handled by a separate class that gets a logical device representation
|
||||||
// We will be requesting queues from one family only
|
// and encapsulates functions related to a device
|
||||||
// todo: Multiple queue families for transfer and async compute
|
vulkanDevice = new vk::VulkanDevice(physicalDevice);
|
||||||
std::vector<float> queuePriorities = { 0.0f };
|
VK_CHECK_RESULT(vulkanDevice->createLogicalDevice(enabledFeatures));
|
||||||
std::vector<VkDeviceQueueCreateInfo> queueCreateInfos = {};
|
|
||||||
queueCreateInfos.resize(1);
|
|
||||||
queueCreateInfos[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
|
|
||||||
queueCreateInfos[0].queueFamilyIndex = graphicsQueueIndex;
|
|
||||||
queueCreateInfos[0].queueCount = 1;
|
|
||||||
queueCreateInfos[0].pQueuePriorities = queuePriorities.data();
|
|
||||||
|
|
||||||
VK_CHECK_RESULT(vulkanDevice->createLogicalDevice(queueCreateInfos, enabledFeatures));
|
|
||||||
|
|
||||||
// Assign device to base class context
|
|
||||||
device = vulkanDevice->logicalDevice;
|
device = vulkanDevice->logicalDevice;
|
||||||
|
|
||||||
|
// todo: remove
|
||||||
// Store properties (including limits) and features of the phyiscal device
|
// Store properties (including limits) and features of the phyiscal device
|
||||||
// So examples can check against them and see if a feature is actually supported
|
// So examples can check against them and see if a feature is actually supported
|
||||||
vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
|
vkGetPhysicalDeviceProperties(physicalDevice, &deviceProperties);
|
||||||
|
|
@ -855,8 +829,8 @@ void VulkanExampleBase::initVulkan(bool enableValidation)
|
||||||
// Gather physical device memory properties
|
// Gather physical device memory properties
|
||||||
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties);
|
vkGetPhysicalDeviceMemoryProperties(physicalDevice, &deviceMemoryProperties);
|
||||||
|
|
||||||
// Get the graphics queue
|
// Get a graphics queue from the device
|
||||||
vkGetDeviceQueue(device, graphicsQueueIndex, 0, &queue);
|
vkGetDeviceQueue(device, vulkanDevice->queueFamilyIndices.graphics, 0, &queue);
|
||||||
|
|
||||||
// Find a suitable depth format
|
// Find a suitable depth format
|
||||||
VkBool32 validDepthFormat = vkTools::getSupportedDepthFormat(physicalDevice, &depthFormat);
|
VkBool32 validDepthFormat = vkTools::getSupportedDepthFormat(physicalDevice, &depthFormat);
|
||||||
|
|
@ -897,10 +871,6 @@ void VulkanExampleBase::setupConsole(std::string title)
|
||||||
FILE *stream;
|
FILE *stream;
|
||||||
freopen_s(&stream, "CONOUT$", "w+", stdout);
|
freopen_s(&stream, "CONOUT$", "w+", stdout);
|
||||||
SetConsoleTitle(TEXT(title.c_str()));
|
SetConsoleTitle(TEXT(title.c_str()));
|
||||||
if (enableValidation)
|
|
||||||
{
|
|
||||||
std::cout << "Validation enabled:\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HWND VulkanExampleBase::setupWindow(HINSTANCE hinstance, WNDPROC wndproc)
|
HWND VulkanExampleBase::setupWindow(HINSTANCE hinstance, WNDPROC wndproc)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue