Vulkan: Create VkInstance and register debug report
This commit is contained in:
parent
f2adf6d5bd
commit
6d9a3b82c6
|
@ -19,6 +19,8 @@
|
||||||
|
|
||||||
#include <spirv-cross/spirv_cross.hpp>
|
#include <spirv-cross/spirv_cross.hpp>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#if NXT_PLATFORM_LINUX
|
#if NXT_PLATFORM_LINUX
|
||||||
const char kVulkanLibName[] = "libvulkan.so.1";
|
const char kVulkanLibName[] = "libvulkan.so.1";
|
||||||
#elif NXT_PLATFORM_WINDOWS
|
#elif NXT_PLATFORM_WINDOWS
|
||||||
|
@ -58,9 +60,38 @@ namespace vulkan {
|
||||||
ASSERT(false);
|
ASSERT(false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
KnownGlobalVulkanExtensions usedGlobals;
|
||||||
|
if (!CreateInstance(&usedGlobals)) {
|
||||||
|
ASSERT(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!functions->LoadInstanceProcs(instance, usedGlobals)) {
|
||||||
|
ASSERT(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
vulkanInfo->SetUsedGlobals(usedGlobals);
|
||||||
|
|
||||||
|
if(usedGlobals.debugReport) {
|
||||||
|
if (!RegisterDebugReport()) {
|
||||||
|
ASSERT(false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Device::~Device() {
|
Device::~Device() {
|
||||||
|
if (debugReportCallback != VK_NULL_HANDLE) {
|
||||||
|
fn.DestroyDebugReportCallbackEXT(instance, debugReportCallback, nullptr);
|
||||||
|
debugReportCallback = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (instance != VK_NULL_HANDLE) {
|
||||||
|
fn.DestroyInstance(instance, nullptr);
|
||||||
|
instance = VK_NULL_HANDLE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) {
|
BindGroupBase* Device::CreateBindGroup(BindGroupBuilder* builder) {
|
||||||
|
@ -129,6 +160,76 @@ namespace vulkan {
|
||||||
void Device::TickImpl() {
|
void Device::TickImpl() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Device::CreateInstance(KnownGlobalVulkanExtensions* usedGlobals) {
|
||||||
|
std::vector<const char*> layersToRequest;
|
||||||
|
std::vector<const char*> extensionsToRequest;
|
||||||
|
|
||||||
|
#if defined(NXT_ENABLE_ASSERTS)
|
||||||
|
if (info.global.standardValidation) {
|
||||||
|
layersToRequest.push_back(kLayerNameLunargStandardValidation);
|
||||||
|
usedGlobals->standardValidation = true;
|
||||||
|
}
|
||||||
|
if (info.global.debugReport) {
|
||||||
|
extensionsToRequest.push_back(kExtensionNameExtDebugReport);
|
||||||
|
usedGlobals->debugReport = true;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
VkApplicationInfo appInfo;
|
||||||
|
appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO;
|
||||||
|
appInfo.pNext = nullptr;
|
||||||
|
appInfo.pApplicationName = nullptr;
|
||||||
|
appInfo.applicationVersion = 0;
|
||||||
|
appInfo.pEngineName = nullptr;
|
||||||
|
appInfo.engineVersion = 0;
|
||||||
|
appInfo.apiVersion = VK_API_VERSION_1_0;
|
||||||
|
|
||||||
|
VkInstanceCreateInfo createInfo;
|
||||||
|
createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
|
||||||
|
createInfo.pNext = nullptr;
|
||||||
|
createInfo.flags = 0;
|
||||||
|
createInfo.pApplicationInfo = &appInfo;
|
||||||
|
createInfo.enabledLayerCount = static_cast<uint32_t>(layersToRequest.size());
|
||||||
|
createInfo.ppEnabledLayerNames = layersToRequest.data();
|
||||||
|
createInfo.enabledExtensionCount = static_cast<uint32_t>(extensionsToRequest.size());
|
||||||
|
createInfo.ppEnabledExtensionNames = extensionsToRequest.data();
|
||||||
|
|
||||||
|
if (fn.CreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Device::RegisterDebugReport() {
|
||||||
|
VkDebugReportCallbackCreateInfoEXT createInfo;
|
||||||
|
createInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT;
|
||||||
|
createInfo.pNext = nullptr;
|
||||||
|
createInfo.flags = VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT;
|
||||||
|
createInfo.pfnCallback = Device::OnDebugReportCallback;
|
||||||
|
createInfo.pUserData = this;
|
||||||
|
|
||||||
|
if (fn.CreateDebugReportCallbackEXT(instance, &createInfo, nullptr, &debugReportCallback) != VK_SUCCESS) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
VkBool32 Device::OnDebugReportCallback(VkDebugReportFlagsEXT flags,
|
||||||
|
VkDebugReportObjectTypeEXT /*objectType*/,
|
||||||
|
uint64_t /*object*/,
|
||||||
|
size_t /*location*/,
|
||||||
|
int32_t /*messageCode*/,
|
||||||
|
const char* /*pLayerPrefix*/,
|
||||||
|
const char* pMessage,
|
||||||
|
void* /*pUserdata*/) {
|
||||||
|
std::cout << pMessage << std::endl;
|
||||||
|
ASSERT((flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) == 0);
|
||||||
|
|
||||||
|
return VK_FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
VulkanFunctions* Device::GetMutableFunctions() {
|
VulkanFunctions* Device::GetMutableFunctions() {
|
||||||
return const_cast<VulkanFunctions*>(&fn);
|
return const_cast<VulkanFunctions*>(&fn);
|
||||||
}
|
}
|
||||||
|
|
|
@ -125,12 +125,27 @@ namespace vulkan {
|
||||||
const VulkanInfo info;
|
const VulkanInfo info;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
bool CreateInstance(KnownGlobalVulkanExtensions* usedGlobals);
|
||||||
|
bool RegisterDebugReport();
|
||||||
|
|
||||||
|
static VkBool32 OnDebugReportCallback(VkDebugReportFlagsEXT flags,
|
||||||
|
VkDebugReportObjectTypeEXT objectType,
|
||||||
|
uint64_t object,
|
||||||
|
size_t location,
|
||||||
|
int32_t messageCode,
|
||||||
|
const char* pLayerPrefix,
|
||||||
|
const char* pMessage,
|
||||||
|
void* pUserdata);
|
||||||
|
|
||||||
// To make it easier to use fn it is a public const member. However
|
// 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.
|
// the Device is allowed to mutate them through these private methods.
|
||||||
VulkanFunctions* GetMutableFunctions();
|
VulkanFunctions* GetMutableFunctions();
|
||||||
VulkanInfo* GetMutableInfo();
|
VulkanInfo* GetMutableInfo();
|
||||||
|
|
||||||
DynamicLib vulkanLib;
|
DynamicLib vulkanLib;
|
||||||
|
|
||||||
|
VkInstance instance = VK_NULL_HANDLE;
|
||||||
|
VkDebugReportCallbackEXT debugReportCallback = VK_NULL_HANDLE;
|
||||||
};
|
};
|
||||||
|
|
||||||
class Buffer : public BufferBase {
|
class Buffer : public BufferBase {
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
|
|
||||||
#include "backend/vulkan/VulkanFunctions.h"
|
#include "backend/vulkan/VulkanFunctions.h"
|
||||||
|
|
||||||
|
#include "backend/vulkan/VulkanInfo.h"
|
||||||
#include "common/DynamicLib.h"
|
#include "common/DynamicLib.h"
|
||||||
|
|
||||||
namespace backend {
|
namespace backend {
|
||||||
|
@ -38,5 +39,34 @@ namespace vulkan {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define GET_INSTANCE_PROC(name) \
|
||||||
|
name = reinterpret_cast<decltype(name)>(GetInstanceProcAddr(instance, "vk" #name)); \
|
||||||
|
if (name == nullptr) { \
|
||||||
|
return false; \
|
||||||
|
}
|
||||||
|
|
||||||
|
bool VulkanFunctions::LoadInstanceProcs(VkInstance instance, const KnownGlobalVulkanExtensions& usedGlobals) {
|
||||||
|
GET_INSTANCE_PROC(CreateDevice);
|
||||||
|
GET_INSTANCE_PROC(DestroyDevice);
|
||||||
|
GET_INSTANCE_PROC(EnumerateDeviceExtensionProperties);
|
||||||
|
GET_INSTANCE_PROC(EnumerateDeviceLayerProperties);
|
||||||
|
GET_INSTANCE_PROC(EnumeratePhysicalDevices);
|
||||||
|
GET_INSTANCE_PROC(GetPhysicalDeviceFeatures);
|
||||||
|
GET_INSTANCE_PROC(GetPhysicalDeviceFormatProperties);
|
||||||
|
GET_INSTANCE_PROC(GetPhysicalDeviceImageFormatProperties);
|
||||||
|
GET_INSTANCE_PROC(GetPhysicalDeviceMemoryProperties);
|
||||||
|
GET_INSTANCE_PROC(GetPhysicalDeviceProperties);
|
||||||
|
GET_INSTANCE_PROC(GetPhysicalDeviceQueueFamilyProperties);
|
||||||
|
GET_INSTANCE_PROC(GetPhysicalDeviceSparseImageFormatProperties);
|
||||||
|
|
||||||
|
if (usedGlobals.debugReport) {
|
||||||
|
GET_INSTANCE_PROC(CreateDebugReportCallbackEXT);
|
||||||
|
GET_INSTANCE_PROC(DebugReportMessageEXT);
|
||||||
|
GET_INSTANCE_PROC(DestroyDebugReportCallbackEXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,10 +22,13 @@ class DynamicLib;
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace vulkan {
|
namespace vulkan {
|
||||||
|
|
||||||
|
struct KnownGlobalVulkanExtensions;
|
||||||
|
|
||||||
// Stores the Vulkan entry points. Also loads them from the dynamic library
|
// Stores the Vulkan entry points. Also loads them from the dynamic library
|
||||||
// and the vkGet*ProcAddress entry points.
|
// and the vkGet*ProcAddress entry points.
|
||||||
struct VulkanFunctions {
|
struct VulkanFunctions {
|
||||||
bool LoadGlobalProcs(const DynamicLib& vulkanLib);
|
bool LoadGlobalProcs(const DynamicLib& vulkanLib);
|
||||||
|
bool LoadInstanceProcs(VkInstance instance, const KnownGlobalVulkanExtensions& usedGlobals);
|
||||||
|
|
||||||
// Initial proc from which we can get all the others
|
// Initial proc from which we can get all the others
|
||||||
PFN_vkGetInstanceProcAddr GetInstanceProcAddr = nullptr;
|
PFN_vkGetInstanceProcAddr GetInstanceProcAddr = nullptr;
|
||||||
|
@ -37,7 +40,30 @@ namespace vulkan {
|
||||||
// DestroyInstance isn't technically a global proc but we want to be able to use it
|
// DestroyInstance isn't technically a global proc but we want to be able to use it
|
||||||
// before querying the instance procs in case we need to error out during initialization.
|
// before querying the instance procs in case we need to error out during initialization.
|
||||||
PFN_vkDestroyInstance DestroyInstance = nullptr;
|
PFN_vkDestroyInstance DestroyInstance = nullptr;
|
||||||
|
|
||||||
|
// Instance procs
|
||||||
|
PFN_vkCreateDevice CreateDevice = nullptr;
|
||||||
|
PFN_vkEnumerateDeviceExtensionProperties EnumerateDeviceExtensionProperties = nullptr;
|
||||||
|
PFN_vkEnumerateDeviceLayerProperties EnumerateDeviceLayerProperties = nullptr;
|
||||||
|
PFN_vkEnumeratePhysicalDevices EnumeratePhysicalDevices = nullptr;
|
||||||
|
PFN_vkGetPhysicalDeviceFeatures GetPhysicalDeviceFeatures = nullptr;
|
||||||
|
PFN_vkGetPhysicalDeviceFormatProperties GetPhysicalDeviceFormatProperties = nullptr;
|
||||||
|
PFN_vkGetPhysicalDeviceImageFormatProperties GetPhysicalDeviceImageFormatProperties = nullptr;
|
||||||
|
PFN_vkGetPhysicalDeviceMemoryProperties GetPhysicalDeviceMemoryProperties = nullptr;
|
||||||
|
PFN_vkGetPhysicalDeviceProperties GetPhysicalDeviceProperties = nullptr;
|
||||||
|
PFN_vkGetPhysicalDeviceQueueFamilyProperties GetPhysicalDeviceQueueFamilyProperties = nullptr;
|
||||||
|
PFN_vkGetPhysicalDeviceSparseImageFormatProperties GetPhysicalDeviceSparseImageFormatProperties = nullptr;
|
||||||
|
// Not technically an instance proc but we want to be able to use it as soon as the
|
||||||
|
// device is created.
|
||||||
|
PFN_vkDestroyDevice DestroyDevice = nullptr;
|
||||||
|
|
||||||
|
// VK_EXT_debug_report
|
||||||
|
PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallbackEXT = nullptr;
|
||||||
|
PFN_vkDebugReportMessageEXT DebugReportMessageEXT = nullptr;
|
||||||
|
PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallbackEXT = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,9 +16,25 @@
|
||||||
|
|
||||||
#include "backend/vulkan/VulkanBackend.h"
|
#include "backend/vulkan/VulkanBackend.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
bool IsLayerName(const VkLayerProperties& layer, const char* name) {
|
||||||
|
return strncmp(layer.layerName, name, VK_MAX_EXTENSION_NAME_SIZE) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IsExtensionName(const VkExtensionProperties& extension, const char* name) {
|
||||||
|
return strncmp(extension.extensionName, name, VK_MAX_EXTENSION_NAME_SIZE) == 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
namespace backend {
|
namespace backend {
|
||||||
namespace vulkan {
|
namespace vulkan {
|
||||||
|
|
||||||
|
const char kLayerNameLunargStandardValidation[] = "VK_LAYER_LUNARG_standard_validation";
|
||||||
|
|
||||||
|
const char kExtensionNameExtDebugReport[] = "VK_EXT_debug_report";
|
||||||
|
|
||||||
bool VulkanInfo::GatherGlobalInfo(const Device& device) {
|
bool VulkanInfo::GatherGlobalInfo(const Device& device) {
|
||||||
// Gather the info about the instance layers
|
// Gather the info about the instance layers
|
||||||
{
|
{
|
||||||
|
@ -36,6 +52,12 @@ namespace vulkan {
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const auto& layer : global.layers) {
|
||||||
|
if (IsLayerName(layer, kLayerNameLunargStandardValidation)) {
|
||||||
|
global.standardValidation = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Gather the info about the instance extensions
|
// Gather the info about the instance extensions
|
||||||
|
@ -51,11 +73,21 @@ namespace vulkan {
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (const auto& extension : global.extensions) {
|
||||||
|
if (IsExtensionName(extension, kExtensionNameExtDebugReport)) {
|
||||||
|
global.debugReport = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(cwallez@chromium:org): Each layer can expose additional extensions, query them?
|
// TODO(cwallez@chromium:org): Each layer can expose additional extensions, query them?
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void VulkanInfo::SetUsedGlobals(const KnownGlobalVulkanExtensions& usedGlobals) {
|
||||||
|
*static_cast<KnownGlobalVulkanExtensions*>(&global) = usedGlobals;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,18 +24,30 @@ namespace vulkan {
|
||||||
|
|
||||||
class Device;
|
class Device;
|
||||||
|
|
||||||
|
extern const char kLayerNameLunargStandardValidation[];
|
||||||
|
|
||||||
|
extern const char kExtensionNameExtDebugReport[];
|
||||||
|
|
||||||
|
struct KnownGlobalVulkanExtensions {
|
||||||
|
// Layers
|
||||||
|
bool standardValidation = false;
|
||||||
|
|
||||||
|
// Extensions
|
||||||
|
bool debugReport = false;
|
||||||
|
};
|
||||||
|
|
||||||
// Stores the information about the Vulkan system that are required to use Vulkan.
|
// Stores the information about the Vulkan system that are required to use Vulkan.
|
||||||
// Also does the querying of the information.
|
// Also does the querying of the information.
|
||||||
struct VulkanInfo {
|
struct VulkanInfo {
|
||||||
|
|
||||||
// Global information - gathered before the instance is created
|
// Global information - gathered before the instance is created
|
||||||
struct {
|
struct : KnownGlobalVulkanExtensions {
|
||||||
std::vector<VkLayerProperties> layers;
|
std::vector<VkLayerProperties> layers;
|
||||||
std::vector<VkExtensionProperties> extensions;
|
std::vector<VkExtensionProperties> extensions;
|
||||||
// TODO(cwallez@chromium.org): layer instance extensions
|
// TODO(cwallez@chromium.org): layer instance extensions
|
||||||
} global;
|
} global;
|
||||||
|
|
||||||
bool GatherGlobalInfo(const Device& device);
|
bool GatherGlobalInfo(const Device& device);
|
||||||
|
void SetUsedGlobals(const KnownGlobalVulkanExtensions& usedGlobals);
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue