implement more api functions
authorJacob Lifshay <programmerjake@gmail.com>
Thu, 7 Sep 2017 07:53:22 +0000 (00:53 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Thu, 7 Sep 2017 07:53:22 +0000 (00:53 -0700)
src/vulkan/api_objects.cpp
src/vulkan/api_objects.h
src/vulkan_icd/vulkan_icd.cpp

index 1c140d78c50c891b784f8d7ff7576bb19c92f5c5..d57e6458102c6b0f8bc02cc467f62e708439a194 100644 (file)
@@ -39,6 +39,12 @@ 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)
             return VK_ERROR_EXTENSION_NOT_PRESENT;
+        if(get_extension_scope(extension) != Extension_scope::Instance)
+        {
+            std::cerr << "Error: device extension passed to vkCreateInstance: "
+                      << create_info.ppEnabledExtensionNames[i] << std::endl;
+            return VK_ERROR_EXTENSION_NOT_PRESENT;
+        }
         if(!std::get<1>(extensions.insert(extension)))
         {
             std::cerr << "Warning: duplicate extension passed to vkCreateInstance: "
@@ -52,9 +58,11 @@ util::variant<std::unique_ptr<Vulkan_instance>, VkResult> Vulkan_instance::creat
             if(extensions.count(dependency) == 0)
             {
                 std::cerr << "Error: vkCreateInstance: enabled extension "
-                          << get_extension_name(extension) << " depends on extension "
-                          << get_extension_name(dependency) << ", however "
-                          << get_extension_name(dependency) << " is not enabled" << std::endl;
+                          << get_extension_properties(extension).extensionName
+                          << " depends on extension "
+                          << get_extension_properties(dependency).extensionName << ", however "
+                          << get_extension_properties(dependency).extensionName << " is not enabled"
+                          << std::endl;
                 return VK_ERROR_INITIALIZATION_FAILED;
             }
         }
@@ -77,5 +85,266 @@ util::variant<std::unique_ptr<Vulkan_instance>, VkResult> Vulkan_instance::creat
     }
     return std::make_unique<Vulkan_instance>(std::move(*app_info), std::move(extensions));
 }
+
+util::variant<std::unique_ptr<Vulkan_device>, VkResult> Vulkan_device::create(
+    Vulkan_physical_device &physical_device, const VkDeviceCreateInfo &create_info)
+{
+    assert(create_info.sType == VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO);
+    Supported_extensions extensions;
+    Supported_extensions all_extensions = physical_device.instance.extensions;
+    for(std::size_t i = 0; i < create_info.enabledExtensionCount; i++)
+    {
+        auto extension = parse_extension_name(create_info.ppEnabledExtensionNames[i]);
+        if(extension == Supported_extension::Not_supported)
+            return VK_ERROR_EXTENSION_NOT_PRESENT;
+        if(get_extension_scope(extension) != Extension_scope::Device)
+        {
+            std::cerr << "Error: instance extension passed to vkCreateDevice: "
+                      << create_info.ppEnabledExtensionNames[i] << std::endl;
+            return VK_ERROR_EXTENSION_NOT_PRESENT;
+        }
+        if(!std::get<1>(extensions.insert(extension)))
+        {
+            std::cerr << "Warning: duplicate extension passed to vkCreateDevice: "
+                      << create_info.ppEnabledExtensionNames[i] << std::endl;
+        }
+        all_extensions.insert(extension);
+    }
+    for(auto extension : extensions)
+    {
+        for(auto dependency : get_extension_dependencies(extension))
+        {
+            if(all_extensions.count(dependency) == 0)
+            {
+                std::cerr << "Error: vkCreateDevice: enabled extension "
+                          << get_extension_properties(extension).extensionName
+                          << " depends on extension "
+                          << get_extension_properties(dependency).extensionName << ", however "
+                          << get_extension_properties(dependency).extensionName << " is not enabled"
+                          << std::endl;
+                return VK_ERROR_INITIALIZATION_FAILED;
+            }
+        }
+    }
+    VkPhysicalDeviceFeatures enabled_features = {};
+    if(create_info.pEnabledFeatures)
+        enabled_features = *create_info.pEnabledFeatures;
+    struct Feature_descriptor
+    {
+        VkBool32 VkPhysicalDeviceFeatures::*member;
+        const char *name;
+    };
+    static constexpr std::initializer_list<Feature_descriptor> features = {
+        {
+            .member = &VkPhysicalDeviceFeatures::robustBufferAccess, .name = "robustBufferAccess",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::fullDrawIndexUint32, .name = "fullDrawIndexUint32",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::imageCubeArray, .name = "imageCubeArray",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::independentBlend, .name = "independentBlend",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::geometryShader, .name = "geometryShader",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::tessellationShader, .name = "tessellationShader",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::sampleRateShading, .name = "sampleRateShading",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::dualSrcBlend, .name = "dualSrcBlend",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::logicOp, .name = "logicOp",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::multiDrawIndirect, .name = "multiDrawIndirect",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::drawIndirectFirstInstance,
+            .name = "drawIndirectFirstInstance",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::depthClamp, .name = "depthClamp",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::depthBiasClamp, .name = "depthBiasClamp",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::fillModeNonSolid, .name = "fillModeNonSolid",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::depthBounds, .name = "depthBounds",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::wideLines, .name = "wideLines",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::largePoints, .name = "largePoints",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::alphaToOne, .name = "alphaToOne",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::multiViewport, .name = "multiViewport",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::samplerAnisotropy, .name = "samplerAnisotropy",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::textureCompressionETC2,
+            .name = "textureCompressionETC2",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::textureCompressionASTC_LDR,
+            .name = "textureCompressionASTC_LDR",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::textureCompressionBC,
+            .name = "textureCompressionBC",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::occlusionQueryPrecise,
+            .name = "occlusionQueryPrecise",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::pipelineStatisticsQuery,
+            .name = "pipelineStatisticsQuery",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::vertexPipelineStoresAndAtomics,
+            .name = "vertexPipelineStoresAndAtomics",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::fragmentStoresAndAtomics,
+            .name = "fragmentStoresAndAtomics",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderTessellationAndGeometryPointSize,
+            .name = "shaderTessellationAndGeometryPointSize",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderImageGatherExtended,
+            .name = "shaderImageGatherExtended",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderStorageImageExtendedFormats,
+            .name = "shaderStorageImageExtendedFormats",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderStorageImageMultisample,
+            .name = "shaderStorageImageMultisample",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderStorageImageReadWithoutFormat,
+            .name = "shaderStorageImageReadWithoutFormat",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderStorageImageWriteWithoutFormat,
+            .name = "shaderStorageImageWriteWithoutFormat",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderUniformBufferArrayDynamicIndexing,
+            .name = "shaderUniformBufferArrayDynamicIndexing",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderSampledImageArrayDynamicIndexing,
+            .name = "shaderSampledImageArrayDynamicIndexing",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderStorageBufferArrayDynamicIndexing,
+            .name = "shaderStorageBufferArrayDynamicIndexing",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderStorageImageArrayDynamicIndexing,
+            .name = "shaderStorageImageArrayDynamicIndexing",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderClipDistance, .name = "shaderClipDistance",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderCullDistance, .name = "shaderCullDistance",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderFloat64, .name = "shaderFloat64",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderInt64, .name = "shaderInt64",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderInt16, .name = "shaderInt16",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderResourceResidency,
+            .name = "shaderResourceResidency",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::shaderResourceMinLod,
+            .name = "shaderResourceMinLod",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::sparseBinding, .name = "sparseBinding",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::sparseResidencyBuffer,
+            .name = "sparseResidencyBuffer",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::sparseResidencyImage2D,
+            .name = "sparseResidencyImage2D",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::sparseResidencyImage3D,
+            .name = "sparseResidencyImage3D",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::sparseResidency2Samples,
+            .name = "sparseResidency2Samples",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::sparseResidency4Samples,
+            .name = "sparseResidency4Samples",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::sparseResidency8Samples,
+            .name = "sparseResidency8Samples",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::sparseResidency16Samples,
+            .name = "sparseResidency16Samples",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::sparseResidencyAliased,
+            .name = "sparseResidencyAliased",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::variableMultisampleRate,
+            .name = "variableMultisampleRate",
+        },
+        {
+            .member = &VkPhysicalDeviceFeatures::inheritedQueries, .name = "inheritedQueries",
+        },
+    };
+    for(auto &feature : features)
+    {
+        if(enabled_features.*feature.member && !(physical_device.features.*feature.member))
+        {
+            std::cerr << "Error: vkCreateDevice: feature not supported: " << feature.name
+                      << std::endl;
+            return VK_ERROR_FEATURE_NOT_PRESENT;
+        }
+    }
+    assert(create_info.queueCreateInfoCount == 1);
+    assert(create_info.pQueueCreateInfos);
+    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);
+}
 }
 }
index 151307b45a44684cb6ff5e56eade765a8bcd04c4..0c496b921294ae44a6561697118d7caddc94ed44 100644 (file)
 #include "util/enum.h"
 #include "util/string_view.h"
 #include "util/variant.h"
+#include "util/system_memory_info.h"
+#include "util/constexpr_array.h"
 #include <memory>
 #include <cassert>
 #include <chrono>
+#include <limits>
 
 namespace kazan
 {
@@ -63,16 +66,37 @@ constexpr Extension_scope get_extension_scope(Supported_extension extension) noe
     return Extension_scope::Not_supported;
 }
 
-constexpr util::string_view get_extension_name(Supported_extension extension) noexcept
+constexpr VkExtensionProperties get_extension_properties(Supported_extension extension) noexcept
 {
-    using namespace util::string_view_literals;
     switch(extension)
     {
     case Supported_extension::Not_supported:
-        return ""_sv;
+        return {};
     }
     assert(!"unknown extension");
-    return ""_sv;
+    return {};
+}
+
+constexpr std::size_t get_extension_count(Extension_scope scope) noexcept
+{
+    std::size_t retval = 0;
+    for(auto extension : util::Enum_traits<Supported_extension>::values)
+        if(get_extension_scope(extension) == scope)
+            retval++;
+    return retval;
+}
+
+template <Extension_scope Scope>
+constexpr util::Constexpr_array<VkExtensionProperties, get_extension_count(Scope)>
+    get_extensions() noexcept
+{
+    util::Constexpr_array<VkExtensionProperties, get_extension_count(Scope)> retval{};
+    std::size_t index = 0;
+    for(auto extension : util::Enum_traits<Supported_extension>::values)
+        if(get_extension_scope(extension) == Scope)
+            retval[index++] = get_extension_properties(extension);
+    assert(index == retval.size());
+    return retval;
 }
 
 constexpr Supported_extensions get_extension_dependencies(Supported_extension extension) noexcept
@@ -94,7 +118,7 @@ inline Supported_extension parse_extension_name(util::string_view name) noexcept
     {
         if(extension == Supported_extension::Not_supported)
             continue;
-        if(get_extension_name(extension) == name)
+        if(get_extension_properties(extension).extensionName == name)
             return extension;
     }
     return Supported_extension::Not_supported;
@@ -143,6 +167,23 @@ struct Vulkan_physical_device
 {
     Vulkan_instance &instance;
     VkPhysicalDeviceProperties properties;
+    static constexpr std::size_t queue_family_property_count = 1;
+    VkQueueFamilyProperties queue_family_properties[queue_family_property_count];
+    VkPhysicalDeviceMemoryProperties memory_properties;
+    VkPhysicalDeviceFeatures features;
+    static VkDeviceSize calculate_heap_size() noexcept
+    {
+        std::uintmax_t total_usable_ram = util::System_memory_info::get().total_usable_ram;
+        constexpr std::uintmax_t transition_memory_size = 4ULL << 30; // 4 GiB
+        std::uintmax_t heap_size;
+        if(total_usable_ram >= transition_memory_size)
+            heap_size = total_usable_ram * 3 / 4;
+        else
+            heap_size = total_usable_ram / 2;
+        if(heap_size > std::numeric_limits<VkDeviceSize>::max())
+            heap_size = std::numeric_limits<VkDeviceSize>::max();
+        return heap_size;
+    }
     Vulkan_physical_device(Vulkan_instance &instance) noexcept
         : instance(instance),
           properties{
@@ -157,10 +198,10 @@ struct Vulkan_physical_device
               .pipelineCacheUUID = {},
               .limits =
                   {
-                      .maxImageDimension1D = 1UL << 23,
-                      .maxImageDimension2D = 1UL << 23,
-                      .maxImageDimension3D = 1UL << 23,
-                      .maxImageDimensionCube = 1UL << 23,
+                      .maxImageDimension1D = 1UL << 20,
+                      .maxImageDimension2D = 1UL << 20,
+                      .maxImageDimension3D = 1UL << 20,
+                      .maxImageDimensionCube = 1UL << 20,
                       .maxImageArrayLayers = static_cast<std::uint32_t>(-1),
                       .maxTexelBufferElements = static_cast<std::uint32_t>(-1),
                       .maxUniformBufferRange = static_cast<std::uint32_t>(-1),
@@ -232,9 +273,12 @@ struct Vulkan_physical_device
                       .maxViewports = 1,
                       .maxViewportDimensions =
                           {
-                              1UL << 23, 1UL << 23,
+                              1UL << 20, 1UL << 20,
+                          },
+                      .viewportBoundsRange =
+                          {
+                              static_cast<float>(-1) * (1UL << 21), 1UL << 21,
                           },
-                      .viewportBoundsRange = {-1.0f * (1UL << 23), 1UL << 23},
                       .viewportSubPixelBits = 16,
                       .minMemoryMapAlignment = 64,
                       .minTexelBufferOffsetAlignment = alignof(std::max_align_t),
@@ -247,8 +291,8 @@ struct Vulkan_physical_device
                       .minInterpolationOffset = 0,
                       .maxInterpolationOffset = 0,
                       .subPixelInterpolationOffsetBits = 0,
-                      .maxFramebufferWidth = 1UL << 23,
-                      .maxFramebufferHeight = 1UL << 23,
+                      .maxFramebufferWidth = 1UL << 20,
+                      .maxFramebufferHeight = 1UL << 20,
                       .maxFramebufferLayers = static_cast<std::uint32_t>(-1),
 #warning fix up sample counts after adding multisampling
                       .framebufferColorSampleCounts = VK_SAMPLE_COUNT_1_BIT,
@@ -297,6 +341,96 @@ struct Vulkan_physical_device
                       .residencyAlignedMipSize = false,
                       .residencyNonResidentStrict = false,
                   },
+          },
+          queue_family_properties{
+              {
+                  .queueFlags = VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_COMPUTE_BIT,
+                  .queueCount = 1,
+                  .timestampValidBits = std::numeric_limits<std::chrono::steady_clock::rep>::digits
+                                        + 1, // 1 extra for sign bit
+                  .minImageTransferGranularity =
+                      {
+                          1, 1, 1,
+                      },
+              },
+          },
+          memory_properties{
+              .memoryTypeCount = 1,
+              .memoryTypes =
+                  {
+                      {
+                          .propertyFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT
+                                           | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT
+                                           | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT
+                                           | VK_MEMORY_PROPERTY_HOST_CACHED_BIT,
+                          .heapIndex = 0,
+                      },
+                  },
+              .memoryHeapCount = 1,
+              .memoryHeaps =
+                  {
+                      {
+                          .size = calculate_heap_size(), .flags = VK_MEMORY_HEAP_DEVICE_LOCAL_BIT,
+                      },
+                  },
+          },
+          features{
+#warning implement robust buffer access
+              .robustBufferAccess = false,
+              .fullDrawIndexUint32 = true,
+              .imageCubeArray = false,
+              .independentBlend = true,
+              .geometryShader = false,
+              .tessellationShader = false,
+              .sampleRateShading = false,
+              .dualSrcBlend = false,
+              .logicOp = false,
+              .multiDrawIndirect = true,
+              .drawIndirectFirstInstance = true,
+              .depthClamp = false,
+              .depthBiasClamp = false,
+              .fillModeNonSolid = false,
+              .depthBounds = false,
+              .wideLines = false,
+              .largePoints = false,
+              .alphaToOne = false,
+              .multiViewport = false,
+              .samplerAnisotropy = false,
+              .textureCompressionETC2 = false,
+              .textureCompressionASTC_LDR = false,
+              .textureCompressionBC = false,
+              .occlusionQueryPrecise = false,
+              .pipelineStatisticsQuery = false,
+              .vertexPipelineStoresAndAtomics = false,
+              .fragmentStoresAndAtomics = false,
+              .shaderTessellationAndGeometryPointSize = false,
+              .shaderImageGatherExtended = false,
+              .shaderStorageImageExtendedFormats = false,
+              .shaderStorageImageMultisample = false,
+              .shaderStorageImageReadWithoutFormat = false,
+              .shaderStorageImageWriteWithoutFormat = false,
+              .shaderUniformBufferArrayDynamicIndexing = true,
+              .shaderSampledImageArrayDynamicIndexing = true,
+              .shaderStorageBufferArrayDynamicIndexing = true,
+              .shaderStorageImageArrayDynamicIndexing = true,
+              .shaderClipDistance = false,
+              .shaderCullDistance = false,
+              .shaderFloat64 = false,
+              .shaderInt64 = true,
+              .shaderInt16 = false,
+              .shaderResourceResidency = false,
+              .shaderResourceMinLod = false,
+              .sparseBinding = false,
+              .sparseResidencyBuffer = false,
+              .sparseResidencyImage2D = false,
+              .sparseResidencyImage3D = false,
+              .sparseResidency2Samples = false,
+              .sparseResidency4Samples = false,
+              .sparseResidency8Samples = false,
+              .sparseResidency16Samples = false,
+              .sparseResidencyAliased = false,
+              .variableMultisampleRate = false,
+              .inheritedQueries = false,
           }
     {
     }
@@ -357,6 +491,27 @@ struct Vulkan_instance : public Vulkan_dispatchable_object<Vulkan_instance, VkIn
         const VkInstanceCreateInfo &create_info);
 #warning finish implementing Vulkan_instance
 };
+
+struct Vulkan_device : public Vulkan_dispatchable_object<Vulkan_device, VkDevice>
+{
+    struct Queue
+    {
+    };
+    Vulkan_instance &instance;
+    Vulkan_physical_device &physical_device;
+    VkPhysicalDeviceFeatures enabled_features;
+    static constexpr std::size_t queue_count = 1;
+    Queue queues[queue_count];
+    explicit Vulkan_device(Vulkan_physical_device &physical_device,
+                           const VkPhysicalDeviceFeatures &enabled_features) noexcept
+        : instance(physical_device.instance),
+          physical_device(physical_device),
+          enabled_features(enabled_features)
+    {
+    }
+    static util::variant<std::unique_ptr<Vulkan_device>, VkResult> create(
+        Vulkan_physical_device &physical_device, const VkDeviceCreateInfo &create_info);
+};
 }
 }
 
index 3393dfb0b37d837eda148c5a97ace9a4f1281753..b8efedbd3a8e2eb5d823d6e4a634363a4fdd27c8 100644 (file)
@@ -106,10 +106,12 @@ extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(
 }
 
 extern "C" VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures(
-    VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures)
+    VkPhysicalDevice physical_device, VkPhysicalDeviceFeatures *features)
 {
-#warning finish implementing vkGetPhysicalDeviceFeatures
-    assert(!"vkGetPhysicalDeviceFeatures is not implemented");
+    assert(physical_device);
+    assert(features);
+    auto *physical_device_pointer = vulkan::Vulkan_physical_device::from_handle(physical_device);
+    *features = physical_device_pointer->features;
 }
 
 extern "C" VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties(
@@ -142,19 +144,26 @@ extern "C" VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(
 }
 
 extern "C" VKAPI_ATTR void VKAPI_CALL
-    vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
-                                             uint32_t *pQueueFamilyPropertyCount,
-                                             VkQueueFamilyProperties *pQueueFamilyProperties)
+    vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physical_device,
+                                             uint32_t *queue_family_property_count,
+                                             VkQueueFamilyProperties *queue_family_properties)
 {
-#warning finish implementing vkGetPhysicalDeviceQueueFamilyProperties
-    assert(!"vkGetPhysicalDeviceQueueFamilyProperties is not implemented");
+    assert(physical_device);
+    auto *physical_device_pointer = vulkan::Vulkan_physical_device::from_handle(physical_device);
+    vulkan_icd::vulkan_enumerate_list_helper(
+        queue_family_property_count,
+        queue_family_properties,
+        physical_device_pointer->queue_family_properties,
+        vulkan::Vulkan_physical_device::queue_family_property_count);
 }
 
 extern "C" VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties(
-    VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties)
+    VkPhysicalDevice physical_device, VkPhysicalDeviceMemoryProperties *memory_properties)
 {
-#warning finish implementing vkGetPhysicalDeviceMemoryProperties
-    assert(!"vkGetPhysicalDeviceMemoryProperties is not implemented");
+    assert(physical_device);
+    assert(memory_properties);
+    auto *physical_device_pointer = vulkan::Vulkan_physical_device::from_handle(physical_device);
+    *memory_properties = physical_device_pointer->memory_properties;
 }
 
 extern "C" VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device,
@@ -164,22 +173,32 @@ extern "C" VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice
         name, vulkan_icd::Vulkan_loader_interface::Procedure_address_scope::Device);
 }
 
-extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice,
-                                                         const VkDeviceCreateInfo *pCreateInfo,
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physical_device,
+                                                         const VkDeviceCreateInfo *create_info,
                                                          const VkAllocationCallbacks *allocator,
-                                                         VkDevice *pDevice)
+                                                         VkDevice *device)
 {
     validate_allocator(allocator);
-#warning finish implementing vkCreateDevice
-    assert(!"vkCreateDevice is not implemented");
+    assert(create_info);
+    assert(physical_device);
+    return vulkan_icd::catch_exceptions_and_return_result(
+        [&]()
+        {
+            auto create_result = vulkan::Vulkan_device::create(
+                *vulkan::Vulkan_physical_device::from_handle(physical_device), *create_info);
+            if(util::holds_alternative<VkResult>(create_result))
+                return util::get<VkResult>(create_result);
+            *device = move_to_handle(
+                util::get<std::unique_ptr<vulkan::Vulkan_device>>(std::move(create_result)));
+            return VK_SUCCESS;
+        });
 }
 
 extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyDevice(VkDevice device,
                                                       const VkAllocationCallbacks *allocator)
 {
     validate_allocator(allocator);
-#warning finish implementing vkDestroyDevice
-    assert(!"vkDestroyDevice is not implemented");
+    vulkan::Vulkan_device::move_from_handle(device).reset();
 }
 
 extern "C" VKAPI_ATTR VkResult VKAPI_CALL
@@ -1525,8 +1544,9 @@ VkResult Vulkan_loader_interface::enumerate_instance_extension_properties(
     const char *layer_name, uint32_t *property_count, VkExtensionProperties *properties) noexcept
 {
     assert(layer_name == nullptr);
-    static constexpr std::initializer_list<VkExtensionProperties> extensions = {};
-    return vulkan_enumerate_list_helper(property_count, properties, extensions);
+    static constexpr auto extensions = vulkan::get_extensions<vulkan::Extension_scope::Instance>();
+    return vulkan_enumerate_list_helper(
+        property_count, properties, extensions.data(), extensions.size());
 }
 
 VkResult Vulkan_loader_interface::enumerate_device_extension_properties(
@@ -1536,9 +1556,10 @@ VkResult Vulkan_loader_interface::enumerate_device_extension_properties(
     VkExtensionProperties *properties) noexcept
 {
     assert(layer_name == nullptr);
-    assert(physical_device != nullptr);
-    static constexpr std::initializer_list<VkExtensionProperties> extensions = {};
-    return vulkan_enumerate_list_helper(property_count, properties, extensions);
+    assert(physical_device != VK_NULL_HANDLE);
+    static constexpr auto extensions = vulkan::get_extensions<vulkan::Extension_scope::Device>();
+    return vulkan_enumerate_list_helper(
+        property_count, properties, extensions.data(), extensions.size());
 }
 }