working on adding VK_KHR_surface support; breaks using with vulkaninfo
authorJacob Lifshay <programmerjake@gmail.com>
Sun, 10 Sep 2017 11:23:29 +0000 (04:23 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Sun, 10 Sep 2017 11:23:29 +0000 (04:23 -0700)
src/vulkan/CMakeLists.txt
src/vulkan/api_objects.cpp
src/vulkan/api_objects.h
src/vulkan_icd/vulkan_icd.cpp
src/vulkan_icd/vulkan_icd.h

index 3ef1a808f8688a34b167f0b81b2a3ad73c48ca42..0a259c335f0ee9ff88c6bcc0e9887b5be6ec5d9d 100644 (file)
@@ -23,3 +23,9 @@ set(sources vulkan.cpp
             api_objects.cpp)
 add_library(kazan_vulkan STATIC ${sources})
 target_compile_definitions(kazan_vulkan PUBLIC VK_NO_PROTOTYPES)
+if(UNIX AND NOT CYGWIN AND NOT CMAKE_SYSTEM_NAME STREQUAL "Android")
+    target_compile_definitions(kazan_vulkan PUBLIC VK_USE_PLATFORM_XCB_KHR)
+    target_compile_definitions(kazan_vulkan PUBLIC VK_USE_PLATFORM_WAYLAND_KHR)
+elseif(WIN32)
+    target_compile_definitions(kazan_vulkan PUBLIC VK_USE_PLATFORM_WIN32_KHR)
+endif()
index d57e6458102c6b0f8bc02cc467f62e708439a194..55e7d12ee16e67f3df19df58b3b35f36e2ff1e2f 100644 (file)
@@ -38,7 +38,11 @@ util::variant<std::unique_ptr<Vulkan_instance>, VkResult> Vulkan_instance::creat
     {
         auto extension = parse_extension_name(create_info.ppEnabledExtensionNames[i]);
         if(extension == Supported_extension::Not_supported)
+        {
+            std::cerr << "Error: unsupported extension passed to vkCreateInstance: "
+                      << create_info.ppEnabledExtensionNames[i] << std::endl;
             return VK_ERROR_EXTENSION_NOT_PRESENT;
+        }
         if(get_extension_scope(extension) != Extension_scope::Instance)
         {
             std::cerr << "Error: device extension passed to vkCreateInstance: "
@@ -96,7 +100,11 @@ util::variant<std::unique_ptr<Vulkan_device>, VkResult> Vulkan_device::create(
     {
         auto extension = parse_extension_name(create_info.ppEnabledExtensionNames[i]);
         if(extension == Supported_extension::Not_supported)
+        {
+            std::cerr << "Error: unsupported extension passed to vkCreateDevice: "
+                      << create_info.ppEnabledExtensionNames[i] << std::endl;
             return VK_ERROR_EXTENSION_NOT_PRESENT;
+        }
         if(get_extension_scope(extension) != Extension_scope::Device)
         {
             std::cerr << "Error: instance extension passed to vkCreateDevice: "
@@ -126,6 +134,9 @@ util::variant<std::unique_ptr<Vulkan_device>, VkResult> Vulkan_device::create(
             }
         }
     }
+    // add enabled instance extensions
+    for(auto extension : physical_device.instance.extensions)
+        extensions.insert(extension);
     VkPhysicalDeviceFeatures enabled_features = {};
     if(create_info.pEnabledFeatures)
         enabled_features = *create_info.pEnabledFeatures;
@@ -344,7 +355,7 @@ util::variant<std::unique_ptr<Vulkan_device>, VkResult> Vulkan_device::create(
     assert(create_info.pQueueCreateInfos[0].sType == VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO);
     assert(create_info.pQueueCreateInfos[0].queueFamilyIndex == 0);
     assert(create_info.pQueueCreateInfos[0].queueCount == 1);
-    return std::make_unique<Vulkan_device>(physical_device, enabled_features);
+    return std::make_unique<Vulkan_device>(physical_device, enabled_features, extensions);
 }
 }
 }
index ee05913c4c6502b4bcaf067798d50cff082ab84b..8cb1bcce8da762cbdebd56c9de4c12363d022a64 100644 (file)
@@ -42,9 +42,14 @@ namespace vulkan
 enum class Supported_extension
 {
     Not_supported,
+    KHR_surface,
+    KHR_xcb_surface,
 };
 
-kazan_util_generate_enum_traits(Supported_extension, Supported_extension::Not_supported);
+kazan_util_generate_enum_traits(Supported_extension,
+                                Supported_extension::Not_supported,
+                                Supported_extension::KHR_surface,
+                                Supported_extension::KHR_xcb_surface);
 
 typedef util::Enum_set<Supported_extension> Supported_extensions;
 
@@ -61,6 +66,14 @@ constexpr Extension_scope get_extension_scope(Supported_extension extension) noe
     {
     case Supported_extension::Not_supported:
         return Extension_scope::Not_supported;
+    case Supported_extension::KHR_surface:
+        return Extension_scope::Instance;
+    case Supported_extension::KHR_xcb_surface:
+#ifdef VK_USE_PLATFORM_XCB_KHR
+        return Extension_scope::Instance;
+#else
+        return Extension_scope::Not_supported;
+#endif
     }
     assert(!"unknown extension");
     return Extension_scope::Not_supported;
@@ -72,6 +85,20 @@ constexpr VkExtensionProperties get_extension_properties(Supported_extension ext
     {
     case Supported_extension::Not_supported:
         return {};
+    case Supported_extension::KHR_surface:
+        return {
+            .extensionName = VK_KHR_SURFACE_EXTENSION_NAME,
+            .specVersion = VK_KHR_SURFACE_SPEC_VERSION,
+        };
+    case Supported_extension::KHR_xcb_surface:
+#ifdef VK_USE_PLATFORM_XCB_KHR
+        return {
+            .extensionName = VK_KHR_XCB_SURFACE_EXTENSION_NAME,
+            .specVersion = VK_KHR_XCB_SURFACE_SPEC_VERSION,
+        };
+#else
+        return {};
+#endif
     }
     assert(!"unknown extension");
     return {};
@@ -105,6 +132,10 @@ constexpr Supported_extensions get_extension_dependencies(Supported_extension ex
     {
     case Supported_extension::Not_supported:
         return {};
+    case Supported_extension::KHR_surface:
+        return {};
+    case Supported_extension::KHR_xcb_surface:
+        return {Supported_extension::KHR_surface};
     }
     assert(!"unknown extension");
     return {};
@@ -1446,11 +1477,14 @@ struct Vulkan_device : public Vulkan_dispatchable_object<Vulkan_device, VkDevice
     VkPhysicalDeviceFeatures enabled_features;
     static constexpr std::size_t queue_count = 1;
     Queue queues[queue_count];
+    Supported_extensions extensions; // includes both device and instance extensions
     explicit Vulkan_device(Vulkan_physical_device &physical_device,
-                           const VkPhysicalDeviceFeatures &enabled_features) noexcept
+                           const VkPhysicalDeviceFeatures &enabled_features,
+                           const Supported_extensions &extensions) noexcept
         : instance(physical_device.instance),
           physical_device(physical_device),
-          enabled_features(enabled_features)
+          enabled_features(enabled_features),
+          extensions(extensions)
     {
     }
     void wait_idle()
index d0cebcfb1effdf271309fda6f5a76d6d92c28542..ec2af35a2c8ffce4e56c39eaa3f5bef93b7cb77c 100644 (file)
@@ -170,8 +170,13 @@ extern "C" VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties(
 extern "C" VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device,
                                                                         const char *name)
 {
+    assert(device);
+    auto *device_pointer = vulkan::Vulkan_device::from_handle(device);
     return vulkan_icd::Vulkan_loader_interface::get()->get_procedure_address(
-        name, vulkan_icd::Vulkan_loader_interface::Procedure_address_scope::Device);
+        name,
+        vulkan_icd::Vulkan_loader_interface::Procedure_address_scope::Device,
+        &device_pointer->instance,
+        device_pointer);
 }
 
 extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physical_device,
@@ -212,6 +217,20 @@ extern "C" VKAPI_ATTR VkResult VKAPI_CALL
         physical_device, layer_name, property_count, properties);
 }
 
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkEnumerateInstanceLayerProperties(uint32_t *pPropertyCount, VkLayerProperties *pProperties)
+{
+#warning finish implementing vkEnumerateInstanceLayerProperties
+    assert(!"vkEnumerateInstanceLayerProperties is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateDeviceLayerProperties(
+    VkPhysicalDevice physicalDevice, uint32_t *pPropertyCount, VkLayerProperties *pProperties)
+{
+#warning finish implementing vkEnumerateDeviceLayerProperties
+    assert(!"vkEnumerateDeviceLayerProperties is not implemented");
+}
+
 extern "C" VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(VkDevice device,
                                                        uint32_t queueFamilyIndex,
                                                        uint32_t queueIndex,
@@ -1344,6 +1363,77 @@ extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands(VkCommandBuffer comma
 #warning finish implementing vkCmdExecuteCommands
     assert(!"vkCmdExecuteCommands is not implemented");
 }
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroySurfaceKHR(VkInstance instance,
+                                                          VkSurfaceKHR surface,
+                                                          const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroySurfaceKHR
+    assert(!"vkDestroySurfaceKHR is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkGetPhysicalDeviceSurfaceSupportKHR(VkPhysicalDevice physicalDevice,
+                                         uint32_t queueFamilyIndex,
+                                         VkSurfaceKHR surface,
+                                         VkBool32 *pSupported)
+{
+#warning finish implementing vkGetPhysicalDeviceSurfaceSupportKHR
+    assert(!"vkGetPhysicalDeviceSurfaceSupportKHR is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkGetPhysicalDeviceSurfaceCapabilitiesKHR(VkPhysicalDevice physicalDevice,
+                                              VkSurfaceKHR surface,
+                                              VkSurfaceCapabilitiesKHR *pSurfaceCapabilities)
+{
+#warning finish implementing vkGetPhysicalDeviceSurfaceCapabilitiesKHR
+    assert(!"vkGetPhysicalDeviceSurfaceCapabilitiesKHR is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkGetPhysicalDeviceSurfaceFormatsKHR(VkPhysicalDevice physicalDevice,
+                                         VkSurfaceKHR surface,
+                                         uint32_t *pSurfaceFormatCount,
+                                         VkSurfaceFormatKHR *pSurfaceFormats)
+{
+#warning finish implementing vkGetPhysicalDeviceSurfaceFormatsKHR
+    assert(!"vkGetPhysicalDeviceSurfaceFormatsKHR is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkGetPhysicalDeviceSurfacePresentModesKHR(VkPhysicalDevice physicalDevice,
+                                              VkSurfaceKHR surface,
+                                              uint32_t *pPresentModeCount,
+                                              VkPresentModeKHR *pPresentModes)
+{
+#warning finish implementing vkGetPhysicalDeviceSurfacePresentModesKHR
+    assert(!"vkGetPhysicalDeviceSurfacePresentModesKHR is not implemented");
+}
+
+#ifdef VK_USE_PLATFORM_XCB_KHR
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreateXcbSurfaceKHR(VkInstance instance,
+                          const VkXcbSurfaceCreateInfoKHR *pCreateInfo,
+                          const VkAllocationCallbacks *pAllocator,
+                          VkSurfaceKHR *pSurface)
+{
+#warning finish implementing vkCreateXcbSurfaceKHR
+    assert(!"vkCreateXcbSurfaceKHR is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkBool32 VKAPI_CALL
+    vkGetPhysicalDeviceXcbPresentationSupportKHR(VkPhysicalDevice physicalDevice,
+                                                 uint32_t queueFamilyIndex,
+                                                 xcb_connection_t *connection,
+                                                 xcb_visualid_t visual_id)
+{
+#warning finish implementing vkGetPhysicalDeviceXcbPresentationSupportKHR
+    assert(!"vkGetPhysicalDeviceXcbPresentationSupportKHR is not implemented");
+}
+#endif
+
 namespace kazan
 {
 namespace vulkan_icd
@@ -1355,13 +1445,40 @@ Vulkan_loader_interface *Vulkan_loader_interface::get() noexcept
 }
 
 PFN_vkVoidFunction Vulkan_loader_interface::get_procedure_address(
-    const char *name, Procedure_address_scope scope) noexcept
+    const char *name,
+    Procedure_address_scope scope,
+    vulkan::Vulkan_instance *instance,
+    vulkan::Vulkan_device *device) noexcept
 {
     using namespace util::string_view_literals;
     assert(name != "vkEnumerateInstanceLayerProperties"_sv
            && "shouldn't be called, implemented by the vulkan loader");
     assert(name != "vkEnumerateDeviceLayerProperties"_sv
            && "shouldn't be called, implemented by the vulkan loader");
+    vulkan::Supported_extensions enabled_or_available_extensions{};
+    switch(scope)
+    {
+    case Procedure_address_scope::Library:
+        assert(!instance);
+        assert(!device);
+        // can't use any extension functions at library scope
+        break;
+    case Procedure_address_scope::Instance:
+        assert(instance);
+        assert(!device);
+        enabled_or_available_extensions = instance->extensions;
+        for(auto extension : util::Enum_traits<vulkan::Supported_extension>::values)
+            if(vulkan::get_extension_scope(extension) == vulkan::Extension_scope::Device)
+                enabled_or_available_extensions.insert(extension);
+        break;
+    case Procedure_address_scope::Device:
+        assert(instance);
+        assert(device);
+        enabled_or_available_extensions = device->extensions;
+        break;
+    }
+
+// INSTANCE_SCOPE_* is used for device scope functions as well
 
 #define LIBRARY_SCOPE_FUNCTION(function_name)                     \
     do                                                            \
@@ -1377,9 +1494,41 @@ PFN_vkVoidFunction Vulkan_loader_interface::get_procedure_address(
             return reinterpret_cast<PFN_vkVoidFunction>(                             \
                 static_cast<PFN_##function_name>(function_name));                    \
     } while(0)
+#define INSTANCE_SCOPE_EXTENSION_FUNCTION(function_name, extension)                              \
+    do                                                                                           \
+    {                                                                                            \
+        if(scope != Procedure_address_scope::Library                                             \
+           && enabled_or_available_extensions.count(vulkan::Supported_extension::extension) != 0 \
+           && name == #function_name##_sv)                                                       \
+            return reinterpret_cast<PFN_vkVoidFunction>(                                         \
+                static_cast<PFN_##function_name>(function_name));                                \
+    } while(0)
+// for functions implemented by the vulkan loader that shouldn't reach the ICD
+#define LIBRARY_SCOPE_FUNCTION_IN_LOADER(function_name)                     \
+    do                                                                      \
+    {                                                                       \
+        assert(name != #function_name##_sv                                  \
+               && "shouldn't be called, implemented by the vulkan loader"); \
+    } while(0)
+#define INSTANCE_SCOPE_FUNCTION_IN_LOADER(function_name)                                  \
+    do                                                                                    \
+    {                                                                                     \
+        assert((scope == Procedure_address_scope::Library || name != #function_name##_sv) \
+               && "shouldn't be called, implemented by the vulkan loader");               \
+    } while(0)
+#define INSTANCE_SCOPE_EXTENSION_FUNCTION_IN_LOADER(function_name, extension)                      \
+    do                                                                                             \
+    {                                                                                              \
+        assert(                                                                                    \
+            (scope == Procedure_address_scope::Library                                             \
+             || enabled_or_available_extensions.count(vulkan::Supported_extension::extension) == 0 \
+             || name != #function_name##_sv)                                                       \
+            && "shouldn't be called, implemented by the vulkan loader");                           \
+    } while(0)
 
     LIBRARY_SCOPE_FUNCTION(vkEnumerateInstanceExtensionProperties);
     LIBRARY_SCOPE_FUNCTION(vkCreateInstance);
+    LIBRARY_SCOPE_FUNCTION(vkEnumerateInstanceLayerProperties);
     INSTANCE_SCOPE_FUNCTION(vkDestroyInstance);
     INSTANCE_SCOPE_FUNCTION(vkEnumeratePhysicalDevices);
     INSTANCE_SCOPE_FUNCTION(vkGetPhysicalDeviceFeatures);
@@ -1393,6 +1542,7 @@ PFN_vkVoidFunction Vulkan_loader_interface::get_procedure_address(
     INSTANCE_SCOPE_FUNCTION(vkCreateDevice);
     INSTANCE_SCOPE_FUNCTION(vkDestroyDevice);
     INSTANCE_SCOPE_FUNCTION(vkEnumerateDeviceExtensionProperties);
+    INSTANCE_SCOPE_FUNCTION(vkEnumerateDeviceLayerProperties);
     INSTANCE_SCOPE_FUNCTION(vkGetDeviceQueue);
     INSTANCE_SCOPE_FUNCTION(vkQueueSubmit);
     INSTANCE_SCOPE_FUNCTION(vkQueueWaitIdle);
@@ -1513,9 +1663,20 @@ PFN_vkVoidFunction Vulkan_loader_interface::get_procedure_address(
     INSTANCE_SCOPE_FUNCTION(vkCmdNextSubpass);
     INSTANCE_SCOPE_FUNCTION(vkCmdEndRenderPass);
     INSTANCE_SCOPE_FUNCTION(vkCmdExecuteCommands);
+    INSTANCE_SCOPE_EXTENSION_FUNCTION(vkDestroySurfaceKHR, KHR_surface);
+    INSTANCE_SCOPE_EXTENSION_FUNCTION(vkGetPhysicalDeviceSurfaceSupportKHR, KHR_surface);
+    INSTANCE_SCOPE_EXTENSION_FUNCTION(vkGetPhysicalDeviceSurfaceCapabilitiesKHR, KHR_surface);
+    INSTANCE_SCOPE_EXTENSION_FUNCTION(vkGetPhysicalDeviceSurfaceFormatsKHR, KHR_surface);
+    INSTANCE_SCOPE_EXTENSION_FUNCTION(vkGetPhysicalDeviceSurfacePresentModesKHR, KHR_surface);
+#ifdef VK_USE_PLATFORM_XCB_KHR
+    INSTANCE_SCOPE_EXTENSION_FUNCTION(vkCreateXcbSurfaceKHR, KHR_xcb_surface);
+    INSTANCE_SCOPE_EXTENSION_FUNCTION(vkGetPhysicalDeviceXcbPresentationSupportKHR,
+                                      KHR_xcb_surface);
+#endif
 
 #undef LIBRARY_SCOPE_FUNCTION
 #undef INSTANCE_SCOPE_FUNCTION
+#undef INSTANCE_SCOPE_EXTENSION_FUNCTION
     return nullptr;
 }
 
@@ -1523,8 +1684,11 @@ PFN_vkVoidFunction Vulkan_loader_interface::get_instance_proc_addr(VkInstance in
                                                                    const char *name) noexcept
 {
     if(!instance)
-        return get_procedure_address(name, Procedure_address_scope::Library);
-    return get_procedure_address(name, Procedure_address_scope::Instance);
+        return get_procedure_address(name, Procedure_address_scope::Library, nullptr, nullptr);
+    return get_procedure_address(name,
+                                 Procedure_address_scope::Instance,
+                                 vulkan::Vulkan_instance::from_handle(instance),
+                                 nullptr);
 }
 
 VkResult Vulkan_loader_interface::create_instance(const VkInstanceCreateInfo *create_info,
index df28c8e919b52ab10f8acb622474e0803227f596..d3ebc13bbb6b3bb601fedf1faeef94e3f8a30508 100644 (file)
@@ -79,7 +79,9 @@ public:
         Device
     };
     PFN_vkVoidFunction get_procedure_address(const char *name,
-                                             Procedure_address_scope scope) noexcept;
+                                             Procedure_address_scope scope,
+                                             vulkan::Vulkan_instance *instance,
+                                             vulkan::Vulkan_device *device) noexcept;
     PFN_vkVoidFunction get_instance_proc_addr(VkInstance instance, const char *name) noexcept;
     VkResult create_instance(const VkInstanceCreateInfo *create_info,
                              const VkAllocationCallbacks *allocator,