diff --git a/Editor/Editor.vcxproj b/Editor/Editor.vcxproj index 33c056d79..2da0966b6 100644 --- a/Editor/Editor.vcxproj +++ b/Editor/Editor.vcxproj @@ -103,7 +103,7 @@ Windows true - ../$(Platform)/$(Configuration) + ../$(Platform)/$(Configuration);$(VULKAN_SDK)/Lib32 @@ -117,7 +117,7 @@ Windows true - ../$(Platform)/$(Configuration) + ../$(Platform)/$(Configuration);$(VULKAN_SDK)/Lib @@ -141,7 +141,7 @@ true true true - ../$(Platform)/$(Configuration) + ../$(Platform)/$(Configuration);$(VULKAN_SDK)/Lib32 @@ -161,7 +161,7 @@ true true true - ../$(Platform)/$(Configuration) + ../$(Platform)/$(Configuration);$(VULKAN_SDK)/Lib diff --git a/Template_Windows/Template_Windows.vcxproj b/Template_Windows/Template_Windows.vcxproj index 4c096050f..67de2a88e 100644 --- a/Template_Windows/Template_Windows.vcxproj +++ b/Template_Windows/Template_Windows.vcxproj @@ -105,7 +105,7 @@ true true true - ../$(Platform)/$(Configuration) + ../$(Platform)/$(Configuration);$(VULKAN_SDK)/Lib @@ -120,7 +120,7 @@ Windows true - ../$(Platform)/$(Configuration) + ../$(Platform)/$(Configuration);$(VULKAN_SDK)/Lib32 @@ -135,7 +135,7 @@ Windows true - ../$(Platform)/$(Configuration) + ../$(Platform)/$(Configuration);$(VULKAN_SDK)/Lib @@ -155,7 +155,7 @@ true true true - ../$(Platform)/$(Configuration) + ../$(Platform)/$(Configuration);$(VULKAN_SDK)/Lib32 diff --git a/Tests/Tests.vcxproj b/Tests/Tests.vcxproj index 9dd27ff72..4bc6a8d6a 100644 --- a/Tests/Tests.vcxproj +++ b/Tests/Tests.vcxproj @@ -110,7 +110,7 @@ true true true - ../$(Platform)/$(Configuration) + ../$(Platform)/$(Configuration);$(VULKAN_SDK)/Lib @@ -126,7 +126,7 @@ Windows true - ../$(Platform)/$(Configuration) + ../$(Platform)/$(Configuration);$(VULKAN_SDK)/Lib32 @@ -142,7 +142,7 @@ Windows true - ../$(Platform)/$(Configuration) + ../$(Platform)/$(Configuration);$(VULKAN_SDK)/Lib @@ -162,7 +162,7 @@ true true true - ../$(Platform)/$(Configuration) + ../$(Platform)/$(Configuration);$(VULKAN_SDK)/Lib32 diff --git a/WickedEngine.sln b/WickedEngine.sln index c93b82ddc..9754c6b1c 100644 --- a/WickedEngine.sln +++ b/WickedEngine.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 -VisualStudioVersion = 15.0.26730.16 +VisualStudioVersion = 15.0.27130.2036 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "WickedEngine_SHARED", "WickedEngine\WickedEngine_SHARED.vcxitems", "{45D41ACC-2C3C-43D2-BC10-02AA73FFC7C7}" EndProject @@ -42,8 +42,8 @@ Global {06163DCB-B183-4ED9-9C62-13EF1658E049}.Release|Win32.Build.0 = Release|Win32 {06163DCB-B183-4ED9-9C62-13EF1658E049}.Release|x64.ActiveCfg = Release|x64 {06163DCB-B183-4ED9-9C62-13EF1658E049}.Release|x64.Build.0 = Release|x64 - {60DA258F-E95F-4CF4-A46B-17D80644464B}.Debug|ARM.ActiveCfg = Debug|x64 - {60DA258F-E95F-4CF4-A46B-17D80644464B}.Debug|ARM.Build.0 = Debug|x64 + {60DA258F-E95F-4CF4-A46B-17D80644464B}.Debug|ARM.ActiveCfg = Debug|ARM + {60DA258F-E95F-4CF4-A46B-17D80644464B}.Debug|ARM.Build.0 = Debug|ARM {60DA258F-E95F-4CF4-A46B-17D80644464B}.Debug|Win32.ActiveCfg = Debug|Win32 {60DA258F-E95F-4CF4-A46B-17D80644464B}.Debug|Win32.Build.0 = Debug|Win32 {60DA258F-E95F-4CF4-A46B-17D80644464B}.Debug|x64.ActiveCfg = Debug|x64 diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.cpp b/WickedEngine/wiGraphicsDevice_Vulkan.cpp index 237364688..fd0189a2d 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.cpp +++ b/WickedEngine/wiGraphicsDevice_Vulkan.cpp @@ -1,3 +1,4 @@ +#define _CRT_SECURE_NO_WARNINGS #include "wiGraphicsDevice_Vulkan.h" #include "wiHelper.h" #include "ResourceMapping.h" @@ -11,11 +12,622 @@ using namespace std; #ifdef WICKEDENGINE_BUILD_VULKAN #pragma comment(lib,"vulkan-1.lib") +bool in_callback = false; +#define ERR_EXIT(err_msg, err_class) \ + do { \ + if (!this->suppress_popups) MessageBoxA(NULL, err_msg, err_class, MB_OK); \ + exit(1); \ + } while (0) +void DbgMsg(char *fmt, ...) { + va_list va; + va_start(va, fmt); + printf(fmt, va); + fflush(stdout); + va_end(va); +} +VKAPI_ATTR VkBool32 VKAPI_CALL BreakCallback(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, + size_t location, int32_t msgCode, const char *pLayerPrefix, const char *pMsg, + void *pUserData) { +#ifndef WIN32 + raise(SIGTRAP); +#else + DebugBreak(); +#endif + + return false; +} + +static int validation_error = 0; +VKAPI_ATTR VkBool32 VKAPI_CALL dbgFunc(VkFlags msgFlags, VkDebugReportObjectTypeEXT objType, uint64_t srcObject, size_t location, + int32_t msgCode, const char *pLayerPrefix, const char *pMsg, void *pUserData) { + // clang-format off + char *message = (char *)malloc(strlen(pMsg) + 100); + + assert(message); + + if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) { + sprintf(message, "INFORMATION: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); + validation_error = 1; + } + else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { + sprintf(message, "WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); + validation_error = 1; + } + else if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) { + sprintf(message, "PERFORMANCE WARNING: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); + validation_error = 1; + } + else if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { + sprintf(message, "ERROR: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); + validation_error = 1; + } + else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) { + sprintf(message, "DEBUG: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); + validation_error = 1; + } + else { + sprintf(message, "INFORMATION: [%s] Code %d : %s", pLayerPrefix, msgCode, pMsg); + validation_error = 1; + } + +#ifdef _WIN32 + + in_callback = true; + struct demo *demo = (struct demo*) pUserData; + MessageBoxA(NULL, message, "Alert", MB_OK); + in_callback = false; + +#elif defined(ANDROID) + + if (msgFlags & VK_DEBUG_REPORT_INFORMATION_BIT_EXT) { + __android_log_print(ANDROID_LOG_INFO, APP_SHORT_NAME, "%s", message); + } + else if (msgFlags & VK_DEBUG_REPORT_WARNING_BIT_EXT) { + __android_log_print(ANDROID_LOG_WARN, APP_SHORT_NAME, "%s", message); + } + else if (msgFlags & VK_DEBUG_REPORT_PERFORMANCE_WARNING_BIT_EXT) { + __android_log_print(ANDROID_LOG_WARN, APP_SHORT_NAME, "%s", message); + } + else if (msgFlags & VK_DEBUG_REPORT_ERROR_BIT_EXT) { + __android_log_print(ANDROID_LOG_ERROR, APP_SHORT_NAME, "%s", message); + } + else if (msgFlags & VK_DEBUG_REPORT_DEBUG_BIT_EXT) { + __android_log_print(ANDROID_LOG_DEBUG, APP_SHORT_NAME, "%s", message); + } + else { + __android_log_print(ANDROID_LOG_INFO, APP_SHORT_NAME, "%s", message); + } + +#else + + printf("%s\n", message); + fflush(stdout); + +#endif + + free(message); + + // clang-format on + + /* + * false indicates that layer should not bail-out of an + * API call that had validation failures. This may mean that the + * app dies inside the driver due to invalid parameter(s). + * That's what would happen without validation layers, so we'll + * keep that behavior here. + */ + return false; +} + + +static VkBool32 demo_check_layers(uint32_t check_count, char **check_names, + uint32_t layer_count, + VkLayerProperties *layers) { + for (uint32_t i = 0; i < check_count; i++) { + VkBool32 found = 0; + for (uint32_t j = 0; j < layer_count; j++) { + if (!strcmp(check_names[i], layers[j].layerName)) { + found = 1; + break; + } + } + if (!found) { + fprintf(stderr, "Cannot find layer: %s\n", check_names[i]); + return 0; + } + } + return 1; +} + namespace wiGraphicsTypes { // Engine functions GraphicsDevice_Vulkan::GraphicsDevice_Vulkan(wiWindowRegistration::window_type window, bool fullscreen) : GraphicsDevice() { + FULLSCREEN = fullscreen; + + RECT rect = RECT(); + GetClientRect(window, &rect); + SCREENWIDTH = rect.right - rect.left; + SCREENHEIGHT = rect.bottom - rect.top; + + VkResult err; + uint32_t instance_extension_count = 0; + uint32_t instance_layer_count = 0; + uint32_t validation_layer_count = 0; + char **instance_validation_layers = NULL; + + this->enabled_extension_count = 0; + this->enabled_layer_count = 0; + this->validate = true; + + char *instance_validation_layers_alt1[] = { + "VK_LAYER_LUNARG_standard_validation" + }; + + char *instance_validation_layers_alt2[] = { + "VK_LAYER_GOOGLE_threading", "VK_LAYER_LUNARG_parameter_validation", + "VK_LAYER_LUNARG_object_tracker", "VK_LAYER_LUNARG_core_validation", + "VK_LAYER_GOOGLE_unique_objects" + }; + + /* Look for validation layers */ + VkBool32 validation_found = 0; + if (validate) { + + err = vkEnumerateInstanceLayerProperties(&instance_layer_count, NULL); + assert(!err); + + instance_validation_layers = instance_validation_layers_alt1; + if (instance_layer_count > 0) { + VkLayerProperties *instance_layers = + (VkLayerProperties*)malloc(sizeof(VkLayerProperties) * instance_layer_count); + err = vkEnumerateInstanceLayerProperties(&instance_layer_count, + instance_layers); + assert(!err); + + + validation_found = demo_check_layers( + ARRAYSIZE(instance_validation_layers_alt1), + instance_validation_layers, instance_layer_count, + instance_layers); + if (validation_found) { + this->enabled_layer_count = ARRAYSIZE(instance_validation_layers_alt1); + this->enabled_layers[0] = "VK_LAYER_LUNARG_standard_validation"; + validation_layer_count = 1; + } + else { + // use alternative set of validation layers + instance_validation_layers = instance_validation_layers_alt2; + this->enabled_layer_count = ARRAYSIZE(instance_validation_layers_alt2); + validation_found = demo_check_layers( + ARRAYSIZE(instance_validation_layers_alt2), + instance_validation_layers, instance_layer_count, + instance_layers); + validation_layer_count = + ARRAYSIZE(instance_validation_layers_alt2); + for (uint32_t i = 0; i < validation_layer_count; i++) { + this->enabled_layers[i] = instance_validation_layers[i]; + } + } + free(instance_layers); + } + + if (!validation_found) { + ERR_EXIT("vkEnumerateInstanceLayerProperties failed to find " + "required validation layer.\n\n" + "Please look at the Getting Started guide for additional " + "information.\n", + "vkCreateInstance Failure"); + } + } + + /* Look for instance extensions */ + VkBool32 surfaceExtFound = 0; + VkBool32 platformSurfaceExtFound = 0; + memset(this->extension_names, 0, sizeof(this->extension_names)); + + err = vkEnumerateInstanceExtensionProperties( + NULL, &instance_extension_count, NULL); + assert(!err); + + if (instance_extension_count > 0) { + VkExtensionProperties *instance_extensions = + (VkExtensionProperties*)malloc(sizeof(VkExtensionProperties) * instance_extension_count); + err = vkEnumerateInstanceExtensionProperties( + NULL, &instance_extension_count, instance_extensions); + assert(!err); + for (uint32_t i = 0; i < instance_extension_count; i++) { + if (!strcmp(VK_KHR_SURFACE_EXTENSION_NAME, + instance_extensions[i].extensionName)) { + surfaceExtFound = 1; + this->extension_names[this->enabled_extension_count++] = + VK_KHR_SURFACE_EXTENSION_NAME; + } +#if defined(VK_USE_PLATFORM_WIN32_KHR) + if (!strcmp(VK_KHR_WIN32_SURFACE_EXTENSION_NAME, + instance_extensions[i].extensionName)) { + platformSurfaceExtFound = 1; + this->extension_names[this->enabled_extension_count++] = + VK_KHR_WIN32_SURFACE_EXTENSION_NAME; + } +#elif defined(VK_USE_PLATFORM_XLIB_KHR) + if (!strcmp(VK_KHR_XLIB_SURFACE_EXTENSION_NAME, + instance_extensions[i].extensionName)) { + platformSurfaceExtFound = 1; + this->extension_names[this->enabled_extension_count++] = + VK_KHR_XLIB_SURFACE_EXTENSION_NAME; + } +#elif defined(VK_USE_PLATFORM_XCB_KHR) + if (!strcmp(VK_KHR_XCB_SURFACE_EXTENSION_NAME, + instance_extensions[i].extensionName)) { + platformSurfaceExtFound = 1; + this->extension_names[this->enabled_extension_count++] = + VK_KHR_XCB_SURFACE_EXTENSION_NAME; + } +#elif defined(VK_USE_PLATFORM_WAYLAND_KHR) + if (!strcmp(VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME, + instance_extensions[i].extensionName)) { + platformSurfaceExtFound = 1; + this->extension_names[this->enabled_extension_count++] = + VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME; + } +#elif defined(VK_USE_PLATFORM_MIR_KHR) +#elif defined(VK_USE_PLATFORM_DISPLAY_KHR) + if (!strcmp(VK_KHR_DISPLAY_EXTENSION_NAME, + instance_extensions[i].extensionName)) { + platformSurfaceExtFound = 1; + this->extension_names[this->enabled_extension_count++] = + VK_KHR_DISPLAY_EXTENSION_NAME; + } +#elif defined(VK_USE_PLATFORM_ANDROID_KHR) + if (!strcmp(VK_KHR_ANDROID_SURFACE_EXTENSION_NAME, + instance_extensions[i].extensionName)) { + platformSurfaceExtFound = 1; + this->extension_names[this->enabled_extension_count++] = + VK_KHR_ANDROID_SURFACE_EXTENSION_NAME; + } +#elif defined(VK_USE_PLATFORM_IOS_MVK) + if (!strcmp(VK_MVK_IOS_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) { + platformSurfaceExtFound = 1; + this->extension_names[this->enabled_extension_count++] = VK_MVK_IOS_SURFACE_EXTENSION_NAME; + } +#elif defined(VK_USE_PLATFORM_MACOS_MVK) + if (!strcmp(VK_MVK_MACOS_SURFACE_EXTENSION_NAME, instance_extensions[i].extensionName)) { + platformSurfaceExtFound = 1; + this->extension_names[this->enabled_extension_count++] = VK_MVK_MACOS_SURFACE_EXTENSION_NAME; + } +#endif + if (!strcmp(VK_EXT_DEBUG_REPORT_EXTENSION_NAME, + instance_extensions[i].extensionName)) { + if (this->validate) { + this->extension_names[this->enabled_extension_count++] = + VK_EXT_DEBUG_REPORT_EXTENSION_NAME; + } + } + assert(this->enabled_extension_count < 64); + } + + free(instance_extensions); + } + + if (!surfaceExtFound) { + ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find " + "the " VK_KHR_SURFACE_EXTENSION_NAME + " extension.\n\nDo you have a compatible " + "Vulkan installable client driver (ICD) installed?\nPlease " + "look at the Getting Started guide for additional " + "information.\n", + "vkCreateInstance Failure"); + } + if (!platformSurfaceExtFound) { +#if defined(VK_USE_PLATFORM_WIN32_KHR) + ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find " + "the " VK_KHR_WIN32_SURFACE_EXTENSION_NAME + " extension.\n\nDo you have a compatible " + "Vulkan installable client driver (ICD) installed?\nPlease " + "look at the Getting Started guide for additional " + "information.\n", + "vkCreateInstance Failure"); +#elif defined(VK_USE_PLATFORM_IOS_MVK) + ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find the " + VK_MVK_IOS_SURFACE_EXTENSION_NAME" extension.\n\nDo you have a compatible " + "Vulkan installable client driver (ICD) installed?\nPlease " + "look at the Getting Started guide for additional " + "information.\n", + "vkCreateInstance Failure"); +#elif defined(VK_USE_PLATFORM_MACOS_MVK) + ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find the " + VK_MVK_MACOS_SURFACE_EXTENSION_NAME" extension.\n\nDo you have a compatible " + "Vulkan installable client driver (ICD) installed?\nPlease " + "look at the Getting Started guide for additional " + "information.\n", + "vkCreateInstance Failure"); +#elif defined(VK_USE_PLATFORM_XCB_KHR) + ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find " + "the " VK_KHR_XCB_SURFACE_EXTENSION_NAME + " extension.\n\nDo you have a compatible " + "Vulkan installable client driver (ICD) installed?\nPlease " + "look at the Getting Started guide for additional " + "information.\n", + "vkCreateInstance Failure"); +#elif defined(VK_USE_PLATFORM_WAYLAND_KHR) + ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find " + "the " VK_KHR_WAYLAND_SURFACE_EXTENSION_NAME + " extension.\n\nDo you have a compatible " + "Vulkan installable client driver (ICD) installed?\nPlease " + "look at the Getting Started guide for additional " + "information.\n", + "vkCreateInstance Failure"); +#elif defined(VK_USE_PLATFORM_MIR_KHR) +#elif defined(VK_USE_PLATFORM_DISPLAY_KHR) + ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find " + "the " VK_KHR_DISPLAY_EXTENSION_NAME + " extension.\n\nDo you have a compatible " + "Vulkan installable client driver (ICD) installed?\nPlease " + "look at the Getting Started guide for additional " + "information.\n", + "vkCreateInstance Failure"); +#elif defined(VK_USE_PLATFORM_ANDROID_KHR) + ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find " + "the " VK_KHR_ANDROID_SURFACE_EXTENSION_NAME + " extension.\n\nDo you have a compatible " + "Vulkan installable client driver (ICD) installed?\nPlease " + "look at the Getting Started guide for additional " + "information.\n", + "vkCreateInstance Failure"); +#elif defined(VK_USE_PLATFORM_XLIB_KHR) + ERR_EXIT("vkEnumerateInstanceExtensionProperties failed to find " + "the " VK_KHR_XLIB_SURFACE_EXTENSION_NAME + " extension.\n\nDo you have a compatible " + "Vulkan installable client driver (ICD) installed?\nPlease " + "look at the Getting Started guide for additional " + "information.\n", + "vkCreateInstance Failure"); +#endif + } + VkApplicationInfo app; + app.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; + app.pNext = NULL; + app.pApplicationName = "WickedEngine"; + app.applicationVersion = 0; + app.pEngineName = "Wickedengine"; + app.engineVersion = 0; + app.apiVersion = VK_API_VERSION_1_0; + + VkInstanceCreateInfo inst_info; + inst_info.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + inst_info.pNext = NULL; + inst_info.pApplicationInfo = &app; + inst_info.enabledLayerCount = this->enabled_layer_count; + inst_info.ppEnabledLayerNames = (const char *const *)instance_validation_layers; + inst_info.enabledExtensionCount = this->enabled_extension_count; + inst_info.ppEnabledExtensionNames = (const char *const *)this->extension_names; + + /* + * This is info for a temp callback to use during CreateInstance. + * After the instance is created, we use the instance-based + * function to register the final callback. + */ + VkDebugReportCallbackCreateInfoEXT dbgCreateInfoTemp; + VkValidationFlagsEXT val_flags; + if (this->validate) { + dbgCreateInfoTemp.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; + dbgCreateInfoTemp.pNext = NULL; + dbgCreateInfoTemp.pfnCallback = this->use_break ? BreakCallback : dbgFunc; + dbgCreateInfoTemp.pUserData = this; + dbgCreateInfoTemp.flags = + VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; + if (this->validate_checks_disabled) { + val_flags.sType = VK_STRUCTURE_TYPE_VALIDATION_FLAGS_EXT; + val_flags.pNext = NULL; + val_flags.disabledValidationCheckCount = 1; + VkValidationCheckEXT disabled_check = VK_VALIDATION_CHECK_ALL_EXT; + val_flags.pDisabledValidationChecks = &disabled_check; + dbgCreateInfoTemp.pNext = (void*)&val_flags; + } + inst_info.pNext = &dbgCreateInfoTemp; + } + + uint32_t gpu_count; + + err = vkCreateInstance(&inst_info, NULL, &this->inst); + if (err == VK_ERROR_INCOMPATIBLE_DRIVER) { + ERR_EXIT("Cannot find a compatible Vulkan installable client driver " + "(ICD).\n\nPlease look at the Getting Started guide for " + "additional information.\n", + "vkCreateInstance Failure"); + } + else if (err == VK_ERROR_EXTENSION_NOT_PRESENT) { + ERR_EXIT("Cannot find a specified extension library" + ".\nMake sure your layers path is set appropriately.\n", + "vkCreateInstance Failure"); + } + else if (err) { + ERR_EXIT("vkCreateInstance failed.\n\nDo you have a compatible Vulkan " + "installable client driver (ICD) installed?\nPlease look at " + "the Getting Started guide for additional information.\n", + "vkCreateInstance Failure"); + } + + /* Make initial call to query gpu_count, then second call for gpu info*/ + err = vkEnumeratePhysicalDevices(this->inst, &gpu_count, NULL); + assert(!err && gpu_count > 0); + + if (gpu_count > 0) { + VkPhysicalDevice *physical_devices = (VkPhysicalDevice*)malloc(sizeof(VkPhysicalDevice) * gpu_count); + err = vkEnumeratePhysicalDevices(this->inst, &gpu_count, physical_devices); + assert(!err); + /* For cube demo we just grab the first physical device */ + this->gpu = physical_devices[0]; + free(physical_devices); + } + else { + ERR_EXIT("vkEnumeratePhysicalDevices reported zero accessible devices.\n\n" + "Do you have a compatible Vulkan installable client driver (ICD) " + "installed?\nPlease look at the Getting Started guide for " + "additional information.\n", + "vkEnumeratePhysicalDevices Failure"); + } + + /* Look for device extensions */ + uint32_t device_extension_count = 0; + VkBool32 swapchainExtFound = 0; + this->enabled_extension_count = 0; + memset(this->extension_names, 0, sizeof(this->extension_names)); + + err = vkEnumerateDeviceExtensionProperties(this->gpu, NULL, + &device_extension_count, NULL); + assert(!err); + + if (device_extension_count > 0) { + VkExtensionProperties *device_extensions = + (VkExtensionProperties*)malloc(sizeof(VkExtensionProperties) * device_extension_count); + err = vkEnumerateDeviceExtensionProperties( + this->gpu, NULL, &device_extension_count, device_extensions); + assert(!err); + + for (uint32_t i = 0; i < device_extension_count; i++) { + if (!strcmp(VK_KHR_SWAPCHAIN_EXTENSION_NAME, + device_extensions[i].extensionName)) { + swapchainExtFound = 1; + this->extension_names[this->enabled_extension_count++] = + VK_KHR_SWAPCHAIN_EXTENSION_NAME; + } + assert(this->enabled_extension_count < 64); + } + + if (this->VK_KHR_incremental_present_enabled) { + // Even though the user "enabled" the extension via the command + // line, we must make sure that it's enumerated for use with the + // device. Therefore, disable it here, and re-enable it again if + // enumerated. + this->VK_KHR_incremental_present_enabled = false; + for (uint32_t i = 0; i < device_extension_count; i++) { + if (!strcmp(VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME, + device_extensions[i].extensionName)) { + this->extension_names[this->enabled_extension_count++] = + VK_KHR_INCREMENTAL_PRESENT_EXTENSION_NAME; + this->VK_KHR_incremental_present_enabled = true; + DbgMsg("VK_KHR_incremental_present extension enabled\n"); + } + assert(this->enabled_extension_count < 64); + } + if (!this->VK_KHR_incremental_present_enabled) { + DbgMsg("VK_KHR_incremental_present extension NOT AVAILABLE\n"); + } + } + + if (this->VK_GOOGLE_display_timing_enabled) { + // Even though the user "enabled" the extension via the command + // line, we must make sure that it's enumerated for use with the + // device. Therefore, disable it here, and re-enable it again if + // enumerated. + this->VK_GOOGLE_display_timing_enabled = false; + for (uint32_t i = 0; i < device_extension_count; i++) { + if (!strcmp(VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME, + device_extensions[i].extensionName)) { + this->extension_names[this->enabled_extension_count++] = + VK_GOOGLE_DISPLAY_TIMING_EXTENSION_NAME; + this->VK_GOOGLE_display_timing_enabled = true; + DbgMsg("VK_GOOGLE_display_timing extension enabled\n"); + } + assert(this->enabled_extension_count < 64); + } + if (!this->VK_GOOGLE_display_timing_enabled) { + DbgMsg("VK_GOOGLE_display_timing extension NOT AVAILABLE\n"); + } + } + + free(device_extensions); + } + + if (!swapchainExtFound) { + ERR_EXIT("vkEnumerateDeviceExtensionProperties failed to find " + "the " VK_KHR_SWAPCHAIN_EXTENSION_NAME + " extension.\n\nDo you have a compatible " + "Vulkan installable client driver (ICD) installed?\nPlease " + "look at the Getting Started guide for additional " + "information.\n", + "vkCreateInstance Failure"); + } + + if (this->validate) { + this->CreateDebugReportCallback = + (PFN_vkCreateDebugReportCallbackEXT)vkGetInstanceProcAddr( + this->inst, "vkCreateDebugReportCallbackEXT"); + this->DestroyDebugReportCallback = + (PFN_vkDestroyDebugReportCallbackEXT)vkGetInstanceProcAddr( + this->inst, "vkDestroyDebugReportCallbackEXT"); + if (!this->CreateDebugReportCallback) { + ERR_EXIT( + "GetProcAddr: Unable to find vkCreateDebugReportCallbackEXT\n", + "vkGetProcAddr Failure"); + } + if (!this->DestroyDebugReportCallback) { + ERR_EXIT( + "GetProcAddr: Unable to find vkDestroyDebugReportCallbackEXT\n", + "vkGetProcAddr Failure"); + } + this->DebugReportMessage = + (PFN_vkDebugReportMessageEXT)vkGetInstanceProcAddr( + this->inst, "vkDebugReportMessageEXT"); + if (!this->DebugReportMessage) { + ERR_EXIT("GetProcAddr: Unable to find vkDebugReportMessageEXT\n", + "vkGetProcAddr Failure"); + } + + VkDebugReportCallbackCreateInfoEXT dbgCreateInfo; + PFN_vkDebugReportCallbackEXT callback; + callback = this->use_break ? BreakCallback : dbgFunc; + dbgCreateInfo.sType = VK_STRUCTURE_TYPE_DEBUG_REPORT_CREATE_INFO_EXT; + dbgCreateInfo.pNext = NULL; + dbgCreateInfo.pfnCallback = callback; + dbgCreateInfo.pUserData = this; + dbgCreateInfo.flags = + VK_DEBUG_REPORT_ERROR_BIT_EXT | VK_DEBUG_REPORT_WARNING_BIT_EXT; + err = this->CreateDebugReportCallback(this->inst, &dbgCreateInfo, NULL, + &this->msg_callback); + switch (err) { + case VK_SUCCESS: + break; + case VK_ERROR_OUT_OF_HOST_MEMORY: + ERR_EXIT("CreateDebugReportCallback: out of host memory\n", + "CreateDebugReportCallback Failure"); + break; + default: + ERR_EXIT("CreateDebugReportCallback: unknown failure\n", + "CreateDebugReportCallback Failure"); + break; + } + } + vkGetPhysicalDeviceProperties(this->gpu, &this->gpu_props); + + /* Call with NULL data to get count */ + vkGetPhysicalDeviceQueueFamilyProperties(this->gpu, + &this->queue_family_count, NULL); + assert(this->queue_family_count >= 1); + + this->queue_props = (VkQueueFamilyProperties *)malloc( + this->queue_family_count * sizeof(VkQueueFamilyProperties)); + vkGetPhysicalDeviceQueueFamilyProperties( + this->gpu, &this->queue_family_count, this->queue_props); + + // Query fine-grained feature support for this device. + // If app has specific feature requirements it should check supported + // features based on this query + VkPhysicalDeviceFeatures physDevFeatures; + vkGetPhysicalDeviceFeatures(this->gpu, &physDevFeatures); + + //GET_INSTANCE_PROC_ADDR(this->inst, GetPhysicalDeviceSurfaceSupportKHR); + //GET_INSTANCE_PROC_ADDR(this->inst, GetPhysicalDeviceSurfaceCapabilitiesKHR); + //GET_INSTANCE_PROC_ADDR(this->inst, GetPhysicalDeviceSurfaceFormatsKHR); + //GET_INSTANCE_PROC_ADDR(this->inst, GetPhysicalDeviceSurfacePresentModesKHR); + //GET_INSTANCE_PROC_ADDR(this->inst, GetSwapchainImagesKHR); + + + + } GraphicsDevice_Vulkan::~GraphicsDevice_Vulkan() { @@ -41,6 +653,10 @@ namespace wiGraphicsTypes { return E_FAIL; } + HRESULT GraphicsDevice_Vulkan::CreateTexture1D(const Texture1DDesc* pDesc, const SubresourceData *pInitialData, Texture1D **ppTexture1D) + { + return E_FAIL; + } HRESULT GraphicsDevice_Vulkan::CreateTexture2D(const Texture2DDesc* pDesc, const SubresourceData *pInitialData, Texture2D **ppTexture2D) { return E_FAIL; @@ -125,6 +741,18 @@ namespace wiGraphicsTypes void GraphicsDevice_Vulkan::BindViewports(UINT NumViewports, const ViewPort *pViewports, GRAPHICSTHREAD threadID) { + assert(NumViewports <= 6); + VkViewport viewports[6]; + for (UINT i = 0; i < NumViewports; ++i) + { + viewports[i].x = pViewports[i].TopLeftX; + viewports[i].y = pViewports[i].TopLeftY; + viewports[i].width = pViewports[i].Width; + viewports[i].height = pViewports[i].Height; + viewports[i].minDepth = pViewports[i].MinDepth; + viewports[i].maxDepth = pViewports[i].MaxDepth; + } + vkCmdSetViewport(commandBuffers[threadID], 0, NumViewports, viewports); } void GraphicsDevice_Vulkan::BindRenderTargetsUAVs(UINT NumViews, Texture* const *ppRenderTargets, Texture2D* depthStencilTexture, GPUResource* const *ppUAVs, int slotUAV, int countUAV, GRAPHICSTHREAD threadID, int arrayIndex) @@ -243,6 +871,17 @@ namespace wiGraphicsTypes } void GraphicsDevice_Vulkan::SetScissorRects(UINT numRects, const Rect* rects, GRAPHICSTHREAD threadID) { + assert(rects != nullptr); + assert(numRects <= 8); + VkRect2D scissors[8]; + for (UINT i = 0; i < numRects; ++i) + { + scissors[i].extent.width = abs(rects[i].right - rects[i].left); + scissors[i].extent.height = abs(rects[i].bottom - rects[i].top); + scissors[i].offset.x = rects[i].left; + scissors[i].offset.y = rects[i].bottom; + } + vkCmdSetScissor(commandBuffers[threadID], 0, numRects, scissors); } void GraphicsDevice_Vulkan::QueryBegin(GPUQuery *query, GRAPHICSTHREAD threadID) @@ -289,4 +928,5 @@ namespace wiGraphicsTypes } + #endif // WICKEDENGINE_BUILD_VULKAN diff --git a/WickedEngine/wiGraphicsDevice_Vulkan.h b/WickedEngine/wiGraphicsDevice_Vulkan.h index 7c8ebb700..9c41c8b01 100644 --- a/WickedEngine/wiGraphicsDevice_Vulkan.h +++ b/WickedEngine/wiGraphicsDevice_Vulkan.h @@ -46,6 +46,8 @@ namespace wiGraphicsTypes VkQueueFamilyProperties *queue_props; VkPhysicalDeviceMemoryProperties memory_properties; + VkCommandBuffer commandBuffers[GRAPHICSTHREAD_COUNT]; + uint32_t enabled_extension_count; uint32_t enabled_layer_count; char *extension_names[64]; @@ -84,6 +86,26 @@ namespace wiGraphicsTypes VkFence fences[BACKBUFFER_COUNT]; int frame_index; + + + + VkDescriptorPool desc_pool; + + bool quit; + int32_t curFrame; + int32_t frameCount; + bool validate; + bool validate_checks_disabled; + bool use_break; + bool suppress_popups; + PFN_vkCreateDebugReportCallbackEXT CreateDebugReportCallback; + PFN_vkDestroyDebugReportCallbackEXT DestroyDebugReportCallback; + VkDebugReportCallbackEXT msg_callback; + PFN_vkDebugReportMessageEXT DebugReportMessage; + + uint32_t current_buffer; + uint32_t queue_family_count; + public: GraphicsDevice_Vulkan(wiWindowRegistration::window_type window, bool fullscreen = false); diff --git a/WickedEngine/wiRenderer.cpp b/WickedEngine/wiRenderer.cpp index cc6f29ec6..fe6ff5162 100644 --- a/WickedEngine/wiRenderer.cpp +++ b/WickedEngine/wiRenderer.cpp @@ -21,6 +21,7 @@ #include "wiFont.h" #include "wiGraphicsDevice_DX11.h" #include "wiGraphicsDevice_DX12.h" +#include "wiGraphicsDevice_Vulkan.h" #include "wiTranslator.h" #include "wiRectPacker.h" #include "wiBackLog.h" @@ -124,8 +125,12 @@ wiRenderer::wiRenderer() void wiRenderer::InitDevice(wiWindowRegistration::window_type window, bool fullscreen) { SAFE_DELETE(graphicsDevice); +#ifdef WICKEDENGINE_BUILD_VULKAN + graphicsDevice = new GraphicsDevice_Vulkan(window, fullscreen); +#else graphicsDevice = new GraphicsDevice_DX11(window, fullscreen); //graphicsDevice = new GraphicsDevice_DX12(window, fullscreen); +#endif } void wiRenderer::Present(function drawToScreen1,function drawToScreen2,function drawToScreen3)