started adding vulkan icd
authorJacob Lifshay <programmerjake@gmail.com>
Mon, 4 Sep 2017 06:34:51 +0000 (23:34 -0700)
committerJacob Lifshay <programmerjake@gmail.com>
Mon, 4 Sep 2017 06:34:51 +0000 (23:34 -0700)
12 files changed:
CMakeLists.txt
src/CMakeLists.txt
src/util/CMakeLists.txt
src/util/system_memory_info.cpp [new file with mode: 0644]
src/util/system_memory_info.h [new file with mode: 0644]
src/vulkan/CMakeLists.txt
src/vulkan/api_objects.cpp [new file with mode: 0644]
src/vulkan/api_objects.h [new file with mode: 0644]
src/vulkan_icd/CMakeLists.txt [new file with mode: 0644]
src/vulkan_icd/vulkan_cpu_vulkan_icd.json.in [new file with mode: 0644]
src/vulkan_icd/vulkan_icd.cpp [new file with mode: 0644]
src/vulkan_icd/vulkan_icd.h [new file with mode: 0644]

index da0f0e1fe4bd37a9829ab91096927e44adcdbc3c..f809bf7ae3770510414a9b24da238ca046a429e8 100644 (file)
@@ -24,6 +24,7 @@ set(CMAKE_CXX_STANDARD 14)
 set(CMAKE_CXX_STANDARD_REQUIRED ON)
 set(CMAKE_C_VISIBILITY_PRESET hidden)
 set(CMAKE_CXX_VISIBILITY_PRESET hidden)
+set(CMAKE_POSITION_INDEPENDENT_CODE ON)
 
 project(vulkan-cpu CXX C)
 if(NOT ${CMAKE_CXX_COMPILER_ID} MATCHES "Clang")
index 9f4d130f5d02c6dd4ca0dd42575133ea43acce17..20d202e0ffc70002fb052534ffc172bf17e8582d 100644 (file)
@@ -30,3 +30,4 @@ add_subdirectory(spirv)
 add_subdirectory(spirv_to_llvm)
 add_subdirectory(util)
 add_subdirectory(vulkan)
+add_subdirectory(vulkan_icd)
index df1546370920c0d56a5a166fcdaa76c1e81defad..649e2d37c55771bd08e0c3fc6a9a359771f8b390 100644 (file)
@@ -38,6 +38,7 @@ set(sources bit_intrinsics.cpp
             optional.cpp
             soft_float.cpp
             string_view.cpp
+            system_memory_info.cpp
             variant.cpp
             void_t.cpp)
 add_library(vulkan_cpu_util STATIC ${sources})
diff --git a/src/util/system_memory_info.cpp b/src/util/system_memory_info.cpp
new file mode 100644 (file)
index 0000000..0c68572
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * Copyright 2017 Jacob Lifshay
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+#include "system_memory_info.h"
+
+#ifdef __linux__
+#include <sys/sysinfo.h>
+namespace vulkan_cpu
+{
+namespace util
+{
+System_memory_info System_memory_info::get()
+{
+    struct ::sysinfo info
+    {
+    };
+    ::sysinfo(&info);
+    return System_memory_info{
+        .total_usable_ram = static_cast<std::uintmax_t>(info.totalram) * info.mem_unit,
+    };
+}
+}
+}
+#elif defined(_WIN32)
+#include <windows.h>
+
+namespace vulkan_cpu
+{
+namespace util
+{
+System_memory_info System_memory_info::get()
+{
+    ::MEMORYSTATUSEX memory_status;
+    ::GlobalMemoryStatusEx(&memory_status);
+    std::uintmax_t retval = memory_status.ullTotalPageFile;
+    if(retval > memory_status.ullTotalPhys)
+        retval = ullTotalPhys;
+    return System_memory_info{
+        .total_usable_ram = retval,
+    };
+}
+}
+}
+#else
+#error System_memory_info::get() is not implemented for platform
+#endif
diff --git a/src/util/system_memory_info.h b/src/util/system_memory_info.h
new file mode 100644 (file)
index 0000000..051a70c
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2017 Jacob Lifshay
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+#ifndef UTIL_SYSTEM_MEMORY_INFO_H_
+#define UTIL_SYSTEM_MEMORY_INFO_H_
+
+#include <cstdint>
+
+namespace vulkan_cpu
+{
+namespace util
+{
+struct System_memory_info
+{
+    std::uintmax_t total_usable_ram;
+    static System_memory_info get();
+};
+}
+}
+
+#endif // UTIL_SYSTEM_MEMORY_INFO_H_
index e1a1ff28575efc2dad05fb9631fb4aedf81ad8d5..1d232c117cbd6caa238b39f66f3e04c866627b5d 100644 (file)
@@ -19,6 +19,7 @@
 # SOFTWARE.
 #
 cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
-set(sources vulkan.cpp)
+set(sources vulkan.cpp
+            api_objects.cpp)
 add_library(vulkan_cpu_vulkan STATIC ${sources})
 target_compile_definitions(vulkan_cpu_vulkan PUBLIC VK_NO_PROTOTYPES)
diff --git a/src/vulkan/api_objects.cpp b/src/vulkan/api_objects.cpp
new file mode 100644 (file)
index 0000000..557bd64
--- /dev/null
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2017 Jacob Lifshay
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+#include "api_objects.h"
+#include "util/optional.h"
+#include <iostream>
+
+namespace vulkan_cpu
+{
+namespace vulkan
+{
+util::variant<std::unique_ptr<Vulkan_instance>, VkResult> Vulkan_instance::create(
+    const VkInstanceCreateInfo &create_info)
+{
+    assert(create_info.sType == VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO);
+    assert(create_info.enabledLayerCount == 0); // we don't support layers here
+    Supported_extensions 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(!std::get<1>(extensions.insert(extension)))
+        {
+            std::cerr << "Warning: duplicate extension passed to vkCreateInstance: "
+                      << create_info.ppEnabledExtensionNames[i] << std::endl;
+        }
+    }
+    for(auto extension : extensions)
+    {
+        for(auto dependency : get_extension_dependencies(extension))
+        {
+            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;
+                return VK_ERROR_INITIALIZATION_FAILED;
+            }
+        }
+    }
+    util::optional<App_info> app_info;
+    if(create_info.pApplicationInfo)
+    {
+        assert(create_info.pApplicationInfo->sType == VK_STRUCTURE_TYPE_APPLICATION_INFO);
+        if(create_info.pApplicationInfo->apiVersion != 0
+           && (VK_VERSION_MAJOR(create_info.pApplicationInfo->apiVersion) != 1
+               || VK_VERSION_MINOR(create_info.pApplicationInfo->apiVersion) != 0))
+        {
+            return VK_ERROR_INCOMPATIBLE_DRIVER;
+        }
+        app_info.emplace(*create_info.pApplicationInfo);
+    }
+    else
+    {
+        app_info.emplace();
+    }
+    return std::make_unique<Vulkan_instance>(std::move(*app_info), std::move(extensions));
+}
+}
+}
diff --git a/src/vulkan/api_objects.h b/src/vulkan/api_objects.h
new file mode 100644 (file)
index 0000000..d3c5e03
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * Copyright 2017 Jacob Lifshay
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+#ifndef VULKAN_API_OBJECTS_H_
+#define VULKAN_API_OBJECTS_H_
+
+#include "vulkan/vulkan.h"
+#include "vulkan/vk_icd.h"
+#include "util/enum.h"
+#include "util/string_view.h"
+#include "util/variant.h"
+#include <memory>
+#include <cassert>
+#include <chrono>
+
+namespace vulkan_cpu
+{
+namespace vulkan
+{
+enum class Supported_extension
+{
+    Not_supported,
+};
+
+vulkan_cpu_util_generate_enum_traits(Supported_extension, Supported_extension::Not_supported);
+
+typedef util::Enum_set<Supported_extension> Supported_extensions;
+
+enum class Extension_scope
+{
+    Not_supported,
+    Instance,
+    Device,
+};
+
+constexpr Extension_scope get_extension_scope(Supported_extension extension) noexcept
+{
+    switch(extension)
+    {
+    case Supported_extension::Not_supported:
+        return Extension_scope::Not_supported;
+    }
+    assert(!"unknown extension");
+    return Extension_scope::Not_supported;
+}
+
+constexpr util::string_view get_extension_name(Supported_extension extension) noexcept
+{
+    using namespace util::string_view_literals;
+    switch(extension)
+    {
+    case Supported_extension::Not_supported:
+        return ""_sv;
+    }
+    assert(!"unknown extension");
+    return ""_sv;
+}
+
+constexpr Supported_extensions get_extension_dependencies(Supported_extension extension) noexcept
+{
+    switch(extension)
+    {
+    case Supported_extension::Not_supported:
+        return {};
+    }
+    assert(!"unknown extension");
+    return {};
+}
+
+inline Supported_extension parse_extension_name(util::string_view name) noexcept
+{
+    if(name.empty())
+        return Supported_extension::Not_supported;
+    for(auto extension : util::Enum_traits<Supported_extension>::values)
+    {
+        if(extension == Supported_extension::Not_supported)
+            continue;
+        if(get_extension_name(extension) == name)
+            return extension;
+    }
+    return Supported_extension::Not_supported;
+}
+
+template <typename Object_type, typename Vulkan_handle_type>
+struct Vulkan_dispatchable_object
+{
+    VK_LOADER_DATA vulkan_loader_data{.loaderMagic = ICD_LOADER_MAGIC};
+    typedef Vulkan_handle_type Vulkan_handle;
+    typedef Object_type Object;
+    static Object_type *from_handle(Vulkan_handle_type v) noexcept
+    {
+        return static_cast<Object_type *>(reinterpret_cast<Vulkan_dispatchable_object *>(v));
+    }
+    static std::unique_ptr<Object_type> move_from_handle(Vulkan_handle_type v) noexcept
+    {
+        return std::unique_ptr<Object_type>(from_handle(v));
+    }
+};
+
+template <typename Object_type>
+typename std::
+    enable_if<std::is_base_of<Vulkan_dispatchable_object<Object_type,
+                                                         typename Object_type::Vulkan_handle>,
+                              Object_type>::value,
+              typename Object_type::Vulkan_handle>::type
+    to_handle(Object_type *object) noexcept
+{
+    return reinterpret_cast<typename Object_type::Vulkan_handle>(
+        static_cast<Vulkan_dispatchable_object<Object_type, typename Object_type::Vulkan_handle> *>(
+            object));
+}
+
+template <typename Object_type>
+decltype(to_handle(static_cast<Object_type *>(nullptr))) move_to_handle(
+    std::unique_ptr<Object_type> v) noexcept
+{
+    return to_handle(v.release());
+}
+
+struct Vulkan_instance;
+
+struct Vulkan_physical_device
+    : public Vulkan_dispatchable_object<Vulkan_physical_device, VkPhysicalDevice>
+{
+    Vulkan_instance &instance;
+    VkPhysicalDeviceProperties properties;
+    Vulkan_physical_device(Vulkan_instance &instance) noexcept
+        : instance(instance),
+          properties{
+              .apiVersion = VK_MAKE_VERSION(1, 0, VK_HEADER_VERSION),
+              .driverVersion = 0,
+#warning change vendorID to the correct value
+              .vendorID = 0x12345678UL,
+              .deviceID = 0,
+              .deviceType = VK_PHYSICAL_DEVICE_TYPE_CPU,
+              .deviceName = "Vulkan-CPU Device",
+#warning calculate the correct value of pipelineCacheUUID as the hash of the target cpu info and the hashed source code
+              .pipelineCacheUUID = {},
+              .limits =
+                  {
+                      .maxImageDimension1D = 1UL << 23,
+                      .maxImageDimension2D = 1UL << 23,
+                      .maxImageDimension3D = 1UL << 23,
+                      .maxImageDimensionCube = 1UL << 23,
+                      .maxImageArrayLayers = static_cast<std::uint32_t>(-1),
+                      .maxTexelBufferElements = static_cast<std::uint32_t>(-1),
+                      .maxUniformBufferRange = static_cast<std::uint32_t>(-1),
+                      .maxStorageBufferRange = static_cast<std::uint32_t>(-1),
+                      .maxPushConstantsSize = static_cast<std::uint32_t>(-1),
+                      .maxMemoryAllocationCount = static_cast<std::uint32_t>(-1),
+                      .maxSamplerAllocationCount = static_cast<std::uint32_t>(-1),
+                      .bufferImageGranularity = 1,
+                      .sparseAddressSpaceSize = 0,
+                      .maxBoundDescriptorSets = static_cast<std::uint32_t>(-1),
+                      .maxPerStageDescriptorSamplers = static_cast<std::uint32_t>(-1),
+                      .maxPerStageDescriptorUniformBuffers = static_cast<std::uint32_t>(-1),
+                      .maxPerStageDescriptorStorageBuffers = static_cast<std::uint32_t>(-1),
+                      .maxPerStageDescriptorSampledImages = static_cast<std::uint32_t>(-1),
+                      .maxPerStageDescriptorStorageImages = static_cast<std::uint32_t>(-1),
+                      .maxPerStageDescriptorInputAttachments = static_cast<std::uint32_t>(-1),
+                      .maxPerStageResources = static_cast<std::uint32_t>(-1),
+                      .maxDescriptorSetSamplers = static_cast<std::uint32_t>(-1),
+                      .maxDescriptorSetUniformBuffers = static_cast<std::uint32_t>(-1),
+                      .maxDescriptorSetUniformBuffersDynamic = static_cast<std::uint32_t>(-1),
+                      .maxDescriptorSetStorageBuffers = static_cast<std::uint32_t>(-1),
+                      .maxDescriptorSetStorageBuffersDynamic = static_cast<std::uint32_t>(-1),
+                      .maxDescriptorSetSampledImages = static_cast<std::uint32_t>(-1),
+                      .maxDescriptorSetStorageImages = static_cast<std::uint32_t>(-1),
+                      .maxDescriptorSetInputAttachments = static_cast<std::uint32_t>(-1),
+                      .maxVertexInputAttributes = static_cast<std::uint32_t>(-1),
+                      .maxVertexInputBindings = static_cast<std::uint32_t>(-1),
+                      .maxVertexInputAttributeOffset = static_cast<std::uint32_t>(-1),
+                      .maxVertexInputBindingStride = static_cast<std::uint32_t>(-1),
+                      .maxVertexOutputComponents = static_cast<std::uint32_t>(-1),
+                      .maxTessellationGenerationLevel = 0,
+                      .maxTessellationPatchSize = 0,
+                      .maxTessellationControlPerVertexInputComponents = 0,
+                      .maxTessellationControlPerVertexOutputComponents = 0,
+                      .maxTessellationControlPerPatchOutputComponents = 0,
+                      .maxTessellationControlTotalOutputComponents = 0,
+                      .maxTessellationEvaluationInputComponents = 0,
+                      .maxTessellationEvaluationOutputComponents = 0,
+                      .maxGeometryShaderInvocations = 0,
+                      .maxGeometryInputComponents = 0,
+                      .maxGeometryOutputComponents = 0,
+                      .maxGeometryOutputVertices = 0,
+                      .maxGeometryTotalOutputComponents = 0,
+                      .maxFragmentInputComponents = static_cast<std::uint32_t>(-1),
+                      .maxFragmentOutputAttachments = static_cast<std::uint32_t>(-1),
+                      .maxFragmentDualSrcAttachments = 0,
+                      .maxFragmentCombinedOutputResources = static_cast<std::uint32_t>(-1),
+                      .maxComputeSharedMemorySize = static_cast<std::uint32_t>(-1),
+                      .maxComputeWorkGroupCount =
+                          {
+                              static_cast<std::uint32_t>(-1),
+                              static_cast<std::uint32_t>(-1),
+                              static_cast<std::uint32_t>(-1),
+                          },
+                      .maxComputeWorkGroupInvocations = static_cast<std::uint32_t>(-1),
+                      .maxComputeWorkGroupSize =
+                          {
+                              static_cast<std::uint32_t>(-1),
+                              static_cast<std::uint32_t>(-1),
+                              static_cast<std::uint32_t>(-1),
+                          },
+                      .subPixelPrecisionBits = 16,
+                      .subTexelPrecisionBits = 8,
+                      .mipmapPrecisionBits = 8,
+                      .maxDrawIndexedIndexValue = static_cast<std::uint32_t>(-1),
+                      .maxDrawIndirectCount = static_cast<std::uint32_t>(-1),
+                      .maxSamplerLodBias = 65536.0f,
+                      .maxSamplerAnisotropy = 1,
+                      .maxViewports = 1,
+                      .maxViewportDimensions =
+                          {
+                              1UL << 23, 1UL << 23,
+                          },
+                      .viewportBoundsRange = {-1.0f * (1UL << 23), 1UL << 23},
+                      .viewportSubPixelBits = 16,
+                      .minMemoryMapAlignment = 64,
+                      .minTexelBufferOffsetAlignment = alignof(std::max_align_t),
+                      .minUniformBufferOffsetAlignment = alignof(std::max_align_t),
+                      .minStorageBufferOffsetAlignment = alignof(std::max_align_t),
+                      .minTexelOffset = std::numeric_limits<std::int32_t>::min(),
+                      .maxTexelOffset = std::numeric_limits<std::int32_t>::max(),
+                      .minTexelGatherOffset = 0,
+                      .maxTexelGatherOffset = 0,
+                      .minInterpolationOffset = 0,
+                      .maxInterpolationOffset = 0,
+                      .subPixelInterpolationOffsetBits = 0,
+                      .maxFramebufferWidth = 1UL << 23,
+                      .maxFramebufferHeight = 1UL << 23,
+                      .maxFramebufferLayers = static_cast<std::uint32_t>(-1),
+#warning fix up sample counts after adding multisampling
+                      .framebufferColorSampleCounts = VK_SAMPLE_COUNT_1_BIT,
+                      .framebufferDepthSampleCounts = VK_SAMPLE_COUNT_1_BIT,
+                      .framebufferStencilSampleCounts = VK_SAMPLE_COUNT_1_BIT,
+                      .framebufferNoAttachmentsSampleCounts = VK_SAMPLE_COUNT_1_BIT,
+                      .maxColorAttachments = static_cast<std::uint32_t>(-1),
+                      .sampledImageColorSampleCounts = VK_SAMPLE_COUNT_1_BIT,
+                      .sampledImageIntegerSampleCounts = VK_SAMPLE_COUNT_1_BIT,
+                      .sampledImageDepthSampleCounts = VK_SAMPLE_COUNT_1_BIT,
+                      .sampledImageStencilSampleCounts = VK_SAMPLE_COUNT_1_BIT,
+                      .storageImageSampleCounts = VK_SAMPLE_COUNT_1_BIT,
+                      .maxSampleMaskWords = 1,
+                      .timestampComputeAndGraphics = true,
+                      .timestampPeriod =
+                          std::chrono::duration_cast<std::chrono::duration<double, std::nano>>(
+                              std::chrono::steady_clock::duration(1))
+                              .count(),
+                      .maxClipDistances = 0,
+                      .maxCullDistances = 0,
+                      .maxCombinedClipAndCullDistances = 0,
+                      .discreteQueuePriorities = 2,
+                      .pointSizeRange =
+                          {
+                              1, 1,
+                          },
+                      .lineWidthRange =
+                          {
+                              1, 1,
+                          },
+                      .pointSizeGranularity = 0,
+                      .lineWidthGranularity = 0,
+#warning update strictLines when the line rasterizer is implemented
+                      .strictLines = true,
+                      .standardSampleLocations = true,
+                      .optimalBufferCopyOffsetAlignment = 16,
+                      .optimalBufferCopyRowPitchAlignment = 16,
+                      .nonCoherentAtomSize = 1,
+                  },
+              .sparseProperties =
+                  {
+#warning update upon implementation of sparse memory
+                      .residencyStandard2DBlockShape = false,
+                      .residencyStandard2DMultisampleBlockShape = false,
+                      .residencyStandard3DBlockShape = false,
+                      .residencyAlignedMipSize = false,
+                      .residencyNonResidentStrict = false,
+                  },
+          }
+    {
+    }
+};
+
+struct Vulkan_instance : public Vulkan_dispatchable_object<Vulkan_instance, VkInstance>
+{
+    Vulkan_instance(const Vulkan_instance &) = delete;
+    Vulkan_instance &operator=(const Vulkan_instance &) = delete;
+
+    struct App_info
+    {
+        std::string application_name;
+        std::uint32_t application_version;
+        std::string engine_name;
+        std::uint32_t engine_version;
+        std::uint32_t api_version;
+        App_info(std::string application_name,
+                 std::uint32_t application_version,
+                 std::string engine_name,
+                 std::uint32_t engine_version,
+                 std::uint32_t api_version) noexcept
+            : application_name(std::move(application_name)),
+              application_version(application_version),
+              engine_name(std::move(engine_name)),
+              engine_version(engine_version),
+              api_version(api_version)
+        {
+        }
+        explicit App_info(const VkApplicationInfo &application_info)
+            : application_name(
+                  application_info.pApplicationName ? application_info.pApplicationName : ""),
+              application_version(application_info.applicationVersion),
+              engine_name(application_info.pEngineName ? application_info.pEngineName : ""),
+              engine_version(application_info.engineVersion),
+              api_version(application_info.apiVersion)
+        {
+            assert(application_info.sType == VK_STRUCTURE_TYPE_APPLICATION_INFO);
+        }
+        App_info() noexcept : application_name(),
+                              application_version(),
+                              engine_name(),
+                              engine_version(),
+                              api_version()
+        {
+        }
+    };
+    App_info app_info;
+    Supported_extensions extensions;
+    Vulkan_physical_device physical_device;
+    Vulkan_instance(App_info app_info, Supported_extensions extensions) noexcept
+        : app_info(std::move(app_info)),
+          extensions(std::move(extensions)),
+          physical_device(*this)
+    {
+    }
+    static util::variant<std::unique_ptr<Vulkan_instance>, VkResult> create(
+        const VkInstanceCreateInfo &create_info);
+#warning finish implementing Vulkan_instance
+};
+}
+}
+
+#endif // VULKAN_API_OBJECTS_H_
diff --git a/src/vulkan_icd/CMakeLists.txt b/src/vulkan_icd/CMakeLists.txt
new file mode 100644 (file)
index 0000000..97d3826
--- /dev/null
@@ -0,0 +1,30 @@
+# Copyright 2017 Jacob Lifshay
+#
+# Permission is hereby granted, free of charge, to any person obtaining a copy
+# of this software and associated documentation files (the "Software"), to deal
+# in the Software without restriction, including without limitation the rights
+# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+# copies of the Software, and to permit persons to whom the Software is
+# furnished to do so, subject to the following conditions:
+#
+# The above copyright notice and this permission notice shall be included in all
+# copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+# SOFTWARE.
+#
+cmake_minimum_required(VERSION 3.3 FATAL_ERROR)
+set(sources vulkan_icd.cpp)
+add_library(vulkan_cpu_vulkan_icd MODULE ${sources})
+target_link_libraries(vulkan_cpu_vulkan_icd
+                      vulkan_cpu_vulkan
+                      vulkan_cpu_util)
+file(GENERATE OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/vulkan_cpu_vulkan_icd.json INPUT ${CMAKE_CURRENT_SOURCE_DIR}/vulkan_cpu_vulkan_icd.json.in)
+if(UNIX AND NOT CYGWIN)
+    target_link_libraries(vulkan_cpu_vulkan_icd -Wl,--no-undefined)
+endif()
diff --git a/src/vulkan_icd/vulkan_cpu_vulkan_icd.json.in b/src/vulkan_icd/vulkan_cpu_vulkan_icd.json.in
new file mode 100644 (file)
index 0000000..3dc5840
--- /dev/null
@@ -0,0 +1,7 @@
+{
+    "file_format_version": "1.0.0",
+    "ICD": {
+        "library_path": "$<TARGET_FILE:vulkan_cpu_vulkan_icd>",
+        "api_version": "1.0.58"
+    }
+}
diff --git a/src/vulkan_icd/vulkan_icd.cpp b/src/vulkan_icd/vulkan_icd.cpp
new file mode 100644 (file)
index 0000000..70ae76f
--- /dev/null
@@ -0,0 +1,1549 @@
+/*
+ * Copyright 2017 Jacob Lifshay
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+#include "vulkan_icd.h"
+#include "util/string_view.h"
+#include <initializer_list>
+#include <iostream>
+
+using namespace vulkan_cpu;
+
+#ifdef __ELF__
+#define DLLEXPORT_ATTR(original_attributes) \
+    __attribute__((visibility("default"))) original_attributes
+#define DLLEXPORT_CALL(original_attributes) original_attributes
+#elif defined(_WIN32)
+#define DLLEXPORT_ATTR(original_attributes) __declspec(dllexport) original_attributes
+#define DLLEXPORT_CALL(original_attributes) original_attributes
+#else
+#error DLLEXPORT_* macros not implemented for platform
+#endif
+
+extern "C" DLLEXPORT_ATTR(VKAPI_ATTR) PFN_vkVoidFunction DLLEXPORT_CALL(VKAPI_CALL)
+    vk_icdGetInstanceProcAddr(VkInstance instance, const char *name)
+{
+    return vulkan_icd::Vulkan_loader_interface::get()->get_instance_proc_addr(instance, name);
+}
+
+static_assert(static_cast<PFN_vk_icdGetInstanceProcAddr>(&vk_icdGetInstanceProcAddr), "");
+
+static constexpr void validate_allocator(const VkAllocationCallbacks *allocator) noexcept
+{
+    assert(allocator == nullptr && "Vulkan allocation callbacks are not implemented");
+}
+
+extern "C" VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetInstanceProcAddr(VkInstance instance,
+                                                                          const char *name)
+{
+    return vk_icdGetInstanceProcAddr(instance, name);
+}
+
+static_assert(static_cast<PFN_vkGetInstanceProcAddr>(&vkGetInstanceProcAddr), "");
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkCreateInstance(const VkInstanceCreateInfo *create_info,
+                                                           const VkAllocationCallbacks *allocator,
+                                                           VkInstance *instance)
+{
+    return vulkan_icd::Vulkan_loader_interface::get()->create_instance(
+        create_info, allocator, instance);
+}
+
+static_assert(static_cast<PFN_vkCreateInstance>(&vkCreateInstance), "");
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkEnumerateInstanceExtensionProperties(
+    const char *layer_name, uint32_t *property_count, VkExtensionProperties *properties)
+
+{
+    return vulkan_icd::Vulkan_loader_interface::get()->enumerate_instance_extension_properties(
+        layer_name, property_count, properties);
+}
+
+static_assert(static_cast<PFN_vkEnumerateInstanceExtensionProperties>(
+                  &vkEnumerateInstanceExtensionProperties),
+              "");
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyInstance(VkInstance instance,
+                                                        const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+    vulkan::Vulkan_instance::move_from_handle(instance).reset();
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkEnumeratePhysicalDevices(
+    VkInstance instance, uint32_t *physical_device_count, VkPhysicalDevice *physical_devices)
+{
+    assert(instance);
+    return vulkan_icd::catch_exceptions_and_return_result(
+        [&]()
+        {
+            auto *instance_pointer = vulkan::Vulkan_instance::from_handle(instance);
+            return vulkan_icd::vulkan_enumerate_list_helper(
+                physical_device_count,
+                physical_devices,
+                {
+                    to_handle(&instance_pointer->physical_device),
+                });
+        });
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFeatures(
+    VkPhysicalDevice physicalDevice, VkPhysicalDeviceFeatures *pFeatures)
+{
+#warning finish implementing vkGetPhysicalDeviceFeatures
+    assert(!"vkGetPhysicalDeviceFeatures is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceFormatProperties(
+    VkPhysicalDevice physicalDevice, VkFormat format, VkFormatProperties *pFormatProperties)
+{
+#warning finish implementing vkGetPhysicalDeviceFormatProperties
+    assert(!"vkGetPhysicalDeviceFormatProperties is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkGetPhysicalDeviceImageFormatProperties(VkPhysicalDevice physicalDevice,
+                                             VkFormat format,
+                                             VkImageType type,
+                                             VkImageTiling tiling,
+                                             VkImageUsageFlags usage,
+                                             VkImageCreateFlags flags,
+                                             VkImageFormatProperties *pImageFormatProperties)
+{
+#warning finish implementing vkGetPhysicalDeviceImageFormatProperties
+    assert(!"vkGetPhysicalDeviceImageFormatProperties is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceProperties(
+    VkPhysicalDevice physical_device, VkPhysicalDeviceProperties *properties)
+{
+    assert(physical_device);
+    assert(properties);
+    auto *physical_device_pointer = vulkan::Vulkan_physical_device::from_handle(physical_device);
+    *properties = physical_device_pointer->properties;
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL
+    vkGetPhysicalDeviceQueueFamilyProperties(VkPhysicalDevice physicalDevice,
+                                             uint32_t *pQueueFamilyPropertyCount,
+                                             VkQueueFamilyProperties *pQueueFamilyProperties)
+{
+#warning finish implementing vkGetPhysicalDeviceQueueFamilyProperties
+    assert(!"vkGetPhysicalDeviceQueueFamilyProperties is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkGetPhysicalDeviceMemoryProperties(
+    VkPhysicalDevice physicalDevice, VkPhysicalDeviceMemoryProperties *pMemoryProperties)
+{
+#warning finish implementing vkGetPhysicalDeviceMemoryProperties
+    assert(!"vkGetPhysicalDeviceMemoryProperties is not implemented");
+}
+
+extern "C" VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vkGetDeviceProcAddr(VkDevice device,
+                                                                        const char *name)
+{
+    return vulkan_icd::Vulkan_loader_interface::get()->get_procedure_address(
+        name, vulkan_icd::Vulkan_loader_interface::Procedure_address_scope::Device);
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkCreateDevice(VkPhysicalDevice physicalDevice,
+                                                         const VkDeviceCreateInfo *pCreateInfo,
+                                                         const VkAllocationCallbacks *allocator,
+                                                         VkDevice *pDevice)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateDevice
+    assert(!"vkCreateDevice is not implemented");
+}
+
+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");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkEnumerateDeviceExtensionProperties(VkPhysicalDevice physical_device,
+                                         const char *layer_name,
+                                         uint32_t *property_count,
+                                         VkExtensionProperties *properties)
+{
+    return vulkan_icd::Vulkan_loader_interface::get()->enumerate_device_extension_properties(
+        physical_device, layer_name, property_count, properties);
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkGetDeviceQueue(VkDevice device,
+                                                       uint32_t queueFamilyIndex,
+                                                       uint32_t queueIndex,
+                                                       VkQueue *pQueue)
+{
+#warning finish implementing vkGetDeviceQueue
+    assert(!"vkGetDeviceQueue is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkQueueSubmit(VkQueue queue,
+                                                        uint32_t submitCount,
+                                                        const VkSubmitInfo *pSubmits,
+                                                        VkFence fence)
+{
+#warning finish implementing vkQueueSubmit
+    assert(!"vkQueueSubmit is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkQueueWaitIdle(VkQueue queue)
+{
+#warning finish implementing vkQueueWaitIdle
+    assert(!"vkQueueWaitIdle is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkDeviceWaitIdle(VkDevice device)
+{
+#warning finish implementing vkDeviceWaitIdle
+    assert(!"vkDeviceWaitIdle is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkAllocateMemory(VkDevice device,
+                     const VkMemoryAllocateInfo *pAllocateInfo,
+                     const VkAllocationCallbacks *allocator,
+                     VkDeviceMemory *pMemory)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkAllocateMemory
+    assert(!"vkAllocateMemory is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkFreeMemory(VkDevice device,
+                                                   VkDeviceMemory memory,
+                                                   const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkFreeMemory
+    assert(!"vkFreeMemory is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkMapMemory(VkDevice device,
+                                                      VkDeviceMemory memory,
+                                                      VkDeviceSize offset,
+                                                      VkDeviceSize size,
+                                                      VkMemoryMapFlags flags,
+                                                      void **ppData)
+{
+#warning finish implementing vkMapMemory
+    assert(!"vkMapMemory is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkUnmapMemory(VkDevice device, VkDeviceMemory memory)
+{
+#warning finish implementing vkUnmapMemory
+    assert(!"vkUnmapMemory is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkFlushMappedMemoryRanges(
+    VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange *pMemoryRanges)
+{
+#warning finish implementing vkFlushMappedMemoryRanges
+    assert(!"vkFlushMappedMemoryRanges is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkInvalidateMappedMemoryRanges(
+    VkDevice device, uint32_t memoryRangeCount, const VkMappedMemoryRange *pMemoryRanges)
+{
+#warning finish implementing vkInvalidateMappedMemoryRanges
+    assert(!"vkInvalidateMappedMemoryRanges is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkGetDeviceMemoryCommitment(
+    VkDevice device, VkDeviceMemory memory, VkDeviceSize *pCommittedMemoryInBytes)
+{
+#warning finish implementing vkGetDeviceMemoryCommitment
+    assert(!"vkGetDeviceMemoryCommitment is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkBindBufferMemory(VkDevice device,
+                                                             VkBuffer buffer,
+                                                             VkDeviceMemory memory,
+                                                             VkDeviceSize memoryOffset)
+{
+#warning finish implementing vkBindBufferMemory
+    assert(!"vkBindBufferMemory is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkBindImageMemory(VkDevice device,
+                                                            VkImage image,
+                                                            VkDeviceMemory memory,
+                                                            VkDeviceSize memoryOffset)
+{
+#warning finish implementing vkBindImageMemory
+    assert(!"vkBindImageMemory is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkGetBufferMemoryRequirements(
+    VkDevice device, VkBuffer buffer, VkMemoryRequirements *pMemoryRequirements)
+{
+#warning finish implementing vkGetBufferMemoryRequirements
+    assert(!"vkGetBufferMemoryRequirements is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkGetImageMemoryRequirements(
+    VkDevice device, VkImage image, VkMemoryRequirements *pMemoryRequirements)
+{
+#warning finish implementing vkGetImageMemoryRequirements
+    assert(!"vkGetImageMemoryRequirements is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL
+    vkGetImageSparseMemoryRequirements(VkDevice device,
+                                       VkImage image,
+                                       uint32_t *pSparseMemoryRequirementCount,
+                                       VkSparseImageMemoryRequirements *pSparseMemoryRequirements)
+{
+#warning finish implementing vkGetImageSparseMemoryRequirements
+    assert(!"vkGetImageSparseMemoryRequirements is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL
+    vkGetPhysicalDeviceSparseImageFormatProperties(VkPhysicalDevice physicalDevice,
+                                                   VkFormat format,
+                                                   VkImageType type,
+                                                   VkSampleCountFlagBits samples,
+                                                   VkImageUsageFlags usage,
+                                                   VkImageTiling tiling,
+                                                   uint32_t *pPropertyCount,
+                                                   VkSparseImageFormatProperties *pProperties)
+{
+#warning finish implementing vkGetPhysicalDeviceSparseImageFormatProperties
+    assert(!"vkGetPhysicalDeviceSparseImageFormatProperties is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkQueueBindSparse(VkQueue queue,
+                                                            uint32_t bindInfoCount,
+                                                            const VkBindSparseInfo *pBindInfo,
+                                                            VkFence fence)
+{
+#warning finish implementing vkQueueBindSparse
+    assert(!"vkQueueBindSparse is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkCreateFence(VkDevice device,
+                                                        const VkFenceCreateInfo *pCreateInfo,
+                                                        const VkAllocationCallbacks *allocator,
+                                                        VkFence *pFence)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateFence
+    assert(!"vkCreateFence is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyFence(VkDevice device,
+                                                     VkFence fence,
+                                                     const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyFence
+    assert(!"vkDestroyFence is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkResetFences(VkDevice device,
+                                                        uint32_t fenceCount,
+                                                        const VkFence *pFences)
+{
+#warning finish implementing vkResetFences
+    assert(!"vkResetFences is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkGetFenceStatus(VkDevice device, VkFence fence)
+{
+#warning finish implementing vkGetFenceStatus
+    assert(!"vkGetFenceStatus is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkWaitForFences(VkDevice device,
+                                                          uint32_t fenceCount,
+                                                          const VkFence *pFences,
+                                                          VkBool32 waitAll,
+                                                          uint64_t timeout)
+{
+#warning finish implementing vkWaitForFences
+    assert(!"vkWaitForFences is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreateSemaphore(VkDevice device,
+                      const VkSemaphoreCreateInfo *pCreateInfo,
+                      const VkAllocationCallbacks *allocator,
+                      VkSemaphore *pSemaphore)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateSemaphore
+    assert(!"vkCreateSemaphore is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroySemaphore(VkDevice device,
+                                                         VkSemaphore semaphore,
+                                                         const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroySemaphore
+    assert(!"vkDestroySemaphore is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkCreateEvent(VkDevice device,
+                                                        const VkEventCreateInfo *pCreateInfo,
+                                                        const VkAllocationCallbacks *allocator,
+                                                        VkEvent *pEvent)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateEvent
+    assert(!"vkCreateEvent is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyEvent(VkDevice device,
+                                                     VkEvent event,
+                                                     const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyEvent
+    assert(!"vkDestroyEvent is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkGetEventStatus(VkDevice device, VkEvent event)
+{
+#warning finish implementing vkGetEventStatus
+    assert(!"vkGetEventStatus is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkSetEvent(VkDevice device, VkEvent event)
+{
+#warning finish implementing vkSetEvent
+    assert(!"vkSetEvent is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkResetEvent(VkDevice device, VkEvent event)
+{
+#warning finish implementing vkResetEvent
+    assert(!"vkResetEvent is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreateQueryPool(VkDevice device,
+                      const VkQueryPoolCreateInfo *pCreateInfo,
+                      const VkAllocationCallbacks *allocator,
+                      VkQueryPool *pQueryPool)
+{
+#warning finish implementing vkCreateQueryPool
+    assert(!"vkCreateQueryPool is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyQueryPool(VkDevice device,
+                                                         VkQueryPool queryPool,
+                                                         const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyQueryPool
+    assert(!"vkDestroyQueryPool is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkGetQueryPoolResults(VkDevice device,
+                                                                VkQueryPool queryPool,
+                                                                uint32_t firstQuery,
+                                                                uint32_t queryCount,
+                                                                size_t dataSize,
+                                                                void *pData,
+                                                                VkDeviceSize stride,
+                                                                VkQueryResultFlags flags)
+{
+#warning finish implementing vkGetQueryPoolResults
+    assert(!"vkGetQueryPoolResults is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkCreateBuffer(VkDevice device,
+                                                         const VkBufferCreateInfo *pCreateInfo,
+                                                         const VkAllocationCallbacks *allocator,
+                                                         VkBuffer *pBuffer)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateBuffer
+    assert(!"vkCreateBuffer is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyBuffer(VkDevice device,
+                                                      VkBuffer buffer,
+                                                      const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyBuffer
+    assert(!"vkDestroyBuffer is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreateBufferView(VkDevice device,
+                       const VkBufferViewCreateInfo *pCreateInfo,
+                       const VkAllocationCallbacks *allocator,
+                       VkBufferView *pView)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateBufferView
+    assert(!"vkCreateBufferView is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyBufferView(VkDevice device,
+                                                          VkBufferView bufferView,
+                                                          const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyBufferView
+    assert(!"vkDestroyBufferView is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkCreateImage(VkDevice device,
+                                                        const VkImageCreateInfo *pCreateInfo,
+                                                        const VkAllocationCallbacks *allocator,
+                                                        VkImage *pImage)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateImage
+    assert(!"vkCreateImage is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyImage(VkDevice device,
+                                                     VkImage image,
+                                                     const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyImage
+    assert(!"vkDestroyImage is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL
+    vkGetImageSubresourceLayout(VkDevice device,
+                                VkImage image,
+                                const VkImageSubresource *pSubresource,
+                                VkSubresourceLayout *pLayout)
+{
+#warning finish implementing vkGetImageSubresourceLayout
+    assert(!"vkGetImageSubresourceLayout is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreateImageView(VkDevice device,
+                      const VkImageViewCreateInfo *pCreateInfo,
+                      const VkAllocationCallbacks *allocator,
+                      VkImageView *pView)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateImageView
+    assert(!"vkCreateImageView is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyImageView(VkDevice device,
+                                                         VkImageView imageView,
+                                                         const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyImageView
+    assert(!"vkDestroyImageView is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreateShaderModule(VkDevice device,
+                         const VkShaderModuleCreateInfo *pCreateInfo,
+                         const VkAllocationCallbacks *allocator,
+                         VkShaderModule *pShaderModule)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateShaderModule
+    assert(!"vkCreateShaderModule is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyShaderModule(VkDevice device,
+                                                            VkShaderModule shaderModule,
+                                                            const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyShaderModule
+    assert(!"vkDestroyShaderModule is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreatePipelineCache(VkDevice device,
+                          const VkPipelineCacheCreateInfo *pCreateInfo,
+                          const VkAllocationCallbacks *allocator,
+                          VkPipelineCache *pPipelineCache)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreatePipelineCache
+    assert(!"vkCreatePipelineCache is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineCache(VkDevice device,
+                                                             VkPipelineCache pipelineCache,
+                                                             const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyPipelineCache
+    assert(!"vkDestroyPipelineCache is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkGetPipelineCacheData(VkDevice device,
+                                                                 VkPipelineCache pipelineCache,
+                                                                 size_t *pDataSize,
+                                                                 void *pData)
+{
+#warning finish implementing vkGetPipelineCacheData
+    assert(!"vkGetPipelineCacheData is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkMergePipelineCaches(VkDevice device,
+                                                                VkPipelineCache dstCache,
+                                                                uint32_t srcCacheCount,
+                                                                const VkPipelineCache *pSrcCaches)
+{
+#warning finish implementing vkMergePipelineCaches
+    assert(!"vkMergePipelineCaches is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreateGraphicsPipelines(VkDevice device,
+                              VkPipelineCache pipelineCache,
+                              uint32_t createInfoCount,
+                              const VkGraphicsPipelineCreateInfo *pCreateInfos,
+                              const VkAllocationCallbacks *allocator,
+                              VkPipeline *pPipelines)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateGraphicsPipelines
+    assert(!"vkCreateGraphicsPipelines is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreateComputePipelines(VkDevice device,
+                             VkPipelineCache pipelineCache,
+                             uint32_t createInfoCount,
+                             const VkComputePipelineCreateInfo *pCreateInfos,
+                             const VkAllocationCallbacks *allocator,
+                             VkPipeline *pPipelines)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateComputePipelines
+    assert(!"vkCreateComputePipelines is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyPipeline(VkDevice device,
+                                                        VkPipeline pipeline,
+                                                        const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyPipeline
+    assert(!"vkDestroyPipeline is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreatePipelineLayout(VkDevice device,
+                           const VkPipelineLayoutCreateInfo *pCreateInfo,
+                           const VkAllocationCallbacks *allocator,
+                           VkPipelineLayout *pPipelineLayout)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreatePipelineLayout
+    assert(!"vkCreatePipelineLayout is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyPipelineLayout(
+    VkDevice device, VkPipelineLayout pipelineLayout, const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyPipelineLayout
+    assert(!"vkDestroyPipelineLayout is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkCreateSampler(VkDevice device,
+                                                          const VkSamplerCreateInfo *pCreateInfo,
+                                                          const VkAllocationCallbacks *allocator,
+                                                          VkSampler *pSampler)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateSampler
+    assert(!"vkCreateSampler is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroySampler(VkDevice device,
+                                                       VkSampler sampler,
+                                                       const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroySampler
+    assert(!"vkDestroySampler is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreateDescriptorSetLayout(VkDevice device,
+                                const VkDescriptorSetLayoutCreateInfo *pCreateInfo,
+                                const VkAllocationCallbacks *allocator,
+                                VkDescriptorSetLayout *pSetLayout)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateDescriptorSetLayout
+    assert(!"vkCreateDescriptorSetLayout is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL
+    vkDestroyDescriptorSetLayout(VkDevice device,
+                                 VkDescriptorSetLayout descriptorSetLayout,
+                                 const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyDescriptorSetLayout
+    assert(!"vkDestroyDescriptorSetLayout is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreateDescriptorPool(VkDevice device,
+                           const VkDescriptorPoolCreateInfo *pCreateInfo,
+                           const VkAllocationCallbacks *allocator,
+                           VkDescriptorPool *pDescriptorPool)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateDescriptorPool
+    assert(!"vkCreateDescriptorPool is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyDescriptorPool(
+    VkDevice device, VkDescriptorPool descriptorPool, const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyDescriptorPool
+    assert(!"vkDestroyDescriptorPool is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkResetDescriptorPool(VkDevice device,
+                                                                VkDescriptorPool descriptorPool,
+                                                                VkDescriptorPoolResetFlags flags)
+{
+#warning finish implementing vkResetDescriptorPool
+    assert(!"vkResetDescriptorPool is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkAllocateDescriptorSets(VkDevice device,
+                             const VkDescriptorSetAllocateInfo *pAllocateInfo,
+                             VkDescriptorSet *pDescriptorSets)
+{
+#warning finish implementing vkAllocateDescriptorSets
+    assert(!"vkAllocateDescriptorSets is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkFreeDescriptorSets(VkDevice device,
+                         VkDescriptorPool descriptorPool,
+                         uint32_t descriptorSetCount,
+                         const VkDescriptorSet *pDescriptorSets)
+{
+#warning finish implementing vkFreeDescriptorSets
+    assert(!"vkFreeDescriptorSets is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL
+    vkUpdateDescriptorSets(VkDevice device,
+                           uint32_t descriptorWriteCount,
+                           const VkWriteDescriptorSet *pDescriptorWrites,
+                           uint32_t descriptorCopyCount,
+                           const VkCopyDescriptorSet *pDescriptorCopies)
+{
+#warning finish implementing vkUpdateDescriptorSets
+    assert(!"vkUpdateDescriptorSets is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreateFramebuffer(VkDevice device,
+                        const VkFramebufferCreateInfo *pCreateInfo,
+                        const VkAllocationCallbacks *allocator,
+                        VkFramebuffer *pFramebuffer)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateFramebuffer
+    assert(!"vkCreateFramebuffer is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyFramebuffer(VkDevice device,
+                                                           VkFramebuffer framebuffer,
+                                                           const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyFramebuffer
+    assert(!"vkDestroyFramebuffer is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreateRenderPass(VkDevice device,
+                       const VkRenderPassCreateInfo *pCreateInfo,
+                       const VkAllocationCallbacks *allocator,
+                       VkRenderPass *pRenderPass)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateRenderPass
+    assert(!"vkCreateRenderPass is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyRenderPass(VkDevice device,
+                                                          VkRenderPass renderPass,
+                                                          const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyRenderPass
+    assert(!"vkDestroyRenderPass is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkGetRenderAreaGranularity(VkDevice device,
+                                                                 VkRenderPass renderPass,
+                                                                 VkExtent2D *pGranularity)
+{
+#warning finish implementing vkGetRenderAreaGranularity
+    assert(!"vkGetRenderAreaGranularity is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkCreateCommandPool(VkDevice device,
+                        const VkCommandPoolCreateInfo *pCreateInfo,
+                        const VkAllocationCallbacks *allocator,
+                        VkCommandPool *pCommandPool)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkCreateCommandPool
+    assert(!"vkCreateCommandPool is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkDestroyCommandPool(VkDevice device,
+                                                           VkCommandPool commandPool,
+                                                           const VkAllocationCallbacks *allocator)
+{
+    validate_allocator(allocator);
+#warning finish implementing vkDestroyCommandPool
+    assert(!"vkDestroyCommandPool is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandPool(VkDevice device,
+                                                             VkCommandPool commandPool,
+                                                             VkCommandPoolResetFlags flags)
+{
+#warning finish implementing vkResetCommandPool
+    assert(!"vkResetCommandPool is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkAllocateCommandBuffers(VkDevice device,
+                             const VkCommandBufferAllocateInfo *pAllocateInfo,
+                             VkCommandBuffer *pCommandBuffers)
+{
+#warning finish implementing vkAllocateCommandBuffers
+    assert(!"vkAllocateCommandBuffers is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkFreeCommandBuffers(VkDevice device,
+                                                           VkCommandPool commandPool,
+                                                           uint32_t commandBufferCount,
+                                                           const VkCommandBuffer *pCommandBuffers)
+{
+#warning finish implementing vkFreeCommandBuffers
+    assert(!"vkFreeCommandBuffers is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL
+    vkBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo)
+{
+#warning finish implementing vkBeginCommandBuffer
+    assert(!"vkBeginCommandBuffer is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkEndCommandBuffer(VkCommandBuffer commandBuffer)
+{
+#warning finish implementing vkEndCommandBuffer
+    assert(!"vkEndCommandBuffer is not implemented");
+}
+
+extern "C" VKAPI_ATTR VkResult VKAPI_CALL vkResetCommandBuffer(VkCommandBuffer commandBuffer,
+                                                               VkCommandBufferResetFlags flags)
+{
+#warning finish implementing vkResetCommandBuffer
+    assert(!"vkResetCommandBuffer is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdBindPipeline(VkCommandBuffer commandBuffer,
+                                                        VkPipelineBindPoint pipelineBindPoint,
+                                                        VkPipeline pipeline)
+{
+#warning finish implementing vkCmdBindPipeline
+    assert(!"vkCmdBindPipeline is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdSetViewport(VkCommandBuffer commandBuffer,
+                                                       uint32_t firstViewport,
+                                                       uint32_t viewportCount,
+                                                       const VkViewport *pViewports)
+{
+#warning finish implementing vkCmdSetViewport
+    assert(!"vkCmdSetViewport is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdSetScissor(VkCommandBuffer commandBuffer,
+                                                      uint32_t firstScissor,
+                                                      uint32_t scissorCount,
+                                                      const VkRect2D *pScissors)
+{
+#warning finish implementing vkCmdSetScissor
+    assert(!"vkCmdSetScissor is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdSetLineWidth(VkCommandBuffer commandBuffer,
+                                                        float lineWidth)
+{
+#warning finish implementing vkCmdSetLineWidth
+    assert(!"vkCmdSetLineWidth is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBias(VkCommandBuffer commandBuffer,
+                                                        float depthBiasConstantFactor,
+                                                        float depthBiasClamp,
+                                                        float depthBiasSlopeFactor)
+{
+#warning finish implementing vkCmdSetDepthBias
+    assert(!"vkCmdSetDepthBias is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdSetBlendConstants(VkCommandBuffer commandBuffer,
+                                                             const float blendConstants[4])
+{
+#warning finish implementing vkCmdSetBlendConstants
+    assert(!"vkCmdSetBlendConstants is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdSetDepthBounds(VkCommandBuffer commandBuffer,
+                                                          float minDepthBounds,
+                                                          float maxDepthBounds)
+{
+#warning finish implementing vkCmdSetDepthBounds
+    assert(!"vkCmdSetDepthBounds is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilCompareMask(VkCommandBuffer commandBuffer,
+                                                                 VkStencilFaceFlags faceMask,
+                                                                 uint32_t compareMask)
+{
+#warning finish implementing vkCmdSetStencilCompareMask
+    assert(!"vkCmdSetStencilCompareMask is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilWriteMask(VkCommandBuffer commandBuffer,
+                                                               VkStencilFaceFlags faceMask,
+                                                               uint32_t writeMask)
+{
+#warning finish implementing vkCmdSetStencilWriteMask
+    assert(!"vkCmdSetStencilWriteMask is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdSetStencilReference(VkCommandBuffer commandBuffer,
+                                                               VkStencilFaceFlags faceMask,
+                                                               uint32_t reference)
+{
+#warning finish implementing vkCmdSetStencilReference
+    assert(!"vkCmdSetStencilReference is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL
+    vkCmdBindDescriptorSets(VkCommandBuffer commandBuffer,
+                            VkPipelineBindPoint pipelineBindPoint,
+                            VkPipelineLayout layout,
+                            uint32_t firstSet,
+                            uint32_t descriptorSetCount,
+                            const VkDescriptorSet *pDescriptorSets,
+                            uint32_t dynamicOffsetCount,
+                            const uint32_t *pDynamicOffsets)
+{
+#warning finish implementing vkCmdBindDescriptorSets
+    assert(!"vkCmdBindDescriptorSets is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdBindIndexBuffer(VkCommandBuffer commandBuffer,
+                                                           VkBuffer buffer,
+                                                           VkDeviceSize offset,
+                                                           VkIndexType indexType)
+{
+#warning finish implementing vkCmdBindIndexBuffer
+    assert(!"vkCmdBindIndexBuffer is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdBindVertexBuffers(VkCommandBuffer commandBuffer,
+                                                             uint32_t firstBinding,
+                                                             uint32_t bindingCount,
+                                                             const VkBuffer *pBuffers,
+                                                             const VkDeviceSize *pOffsets)
+{
+#warning finish implementing vkCmdBindVertexBuffers
+    assert(!"vkCmdBindVertexBuffers is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdDraw(VkCommandBuffer commandBuffer,
+                                                uint32_t vertexCount,
+                                                uint32_t instanceCount,
+                                                uint32_t firstVertex,
+                                                uint32_t firstInstance)
+{
+#warning finish implementing vkCmdDraw
+    assert(!"vkCmdDraw is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexed(VkCommandBuffer commandBuffer,
+                                                       uint32_t indexCount,
+                                                       uint32_t instanceCount,
+                                                       uint32_t firstIndex,
+                                                       int32_t vertexOffset,
+                                                       uint32_t firstInstance)
+{
+#warning finish implementing vkCmdDrawIndexed
+    assert(!"vkCmdDrawIndexed is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndirect(VkCommandBuffer commandBuffer,
+                                                        VkBuffer buffer,
+                                                        VkDeviceSize offset,
+                                                        uint32_t drawCount,
+                                                        uint32_t stride)
+{
+#warning finish implementing vkCmdDrawIndirect
+    assert(!"vkCmdDrawIndirect is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,
+                                                               VkBuffer buffer,
+                                                               VkDeviceSize offset,
+                                                               uint32_t drawCount,
+                                                               uint32_t stride)
+{
+#warning finish implementing vkCmdDrawIndexedIndirect
+    assert(!"vkCmdDrawIndexedIndirect is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdDispatch(VkCommandBuffer commandBuffer,
+                                                    uint32_t groupCountX,
+                                                    uint32_t groupCountY,
+                                                    uint32_t groupCountZ)
+{
+#warning finish implementing vkCmdDispatch
+    assert(!"vkCmdDispatch is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdDispatchIndirect(VkCommandBuffer commandBuffer,
+                                                            VkBuffer buffer,
+                                                            VkDeviceSize offset)
+{
+#warning finish implementing vkCmdDispatchIndirect
+    assert(!"vkCmdDispatchIndirect is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdCopyBuffer(VkCommandBuffer commandBuffer,
+                                                      VkBuffer srcBuffer,
+                                                      VkBuffer dstBuffer,
+                                                      uint32_t regionCount,
+                                                      const VkBufferCopy *pRegions)
+{
+#warning finish implementing vkCmdCopyBuffer
+    assert(!"vkCmdCopyBuffer is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdCopyImage(VkCommandBuffer commandBuffer,
+                                                     VkImage srcImage,
+                                                     VkImageLayout srcImageLayout,
+                                                     VkImage dstImage,
+                                                     VkImageLayout dstImageLayout,
+                                                     uint32_t regionCount,
+                                                     const VkImageCopy *pRegions)
+{
+#warning finish implementing vkCmdCopyImage
+    assert(!"vkCmdCopyImage is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdBlitImage(VkCommandBuffer commandBuffer,
+                                                     VkImage srcImage,
+                                                     VkImageLayout srcImageLayout,
+                                                     VkImage dstImage,
+                                                     VkImageLayout dstImageLayout,
+                                                     uint32_t regionCount,
+                                                     const VkImageBlit *pRegions,
+                                                     VkFilter filter)
+{
+#warning finish implementing vkCmdBlitImage
+    assert(!"vkCmdBlitImage is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdCopyBufferToImage(VkCommandBuffer commandBuffer,
+                                                             VkBuffer srcBuffer,
+                                                             VkImage dstImage,
+                                                             VkImageLayout dstImageLayout,
+                                                             uint32_t regionCount,
+                                                             const VkBufferImageCopy *pRegions)
+{
+#warning finish implementing vkCmdCopyBufferToImage
+    assert(!"vkCmdCopyBufferToImage is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdCopyImageToBuffer(VkCommandBuffer commandBuffer,
+                                                             VkImage srcImage,
+                                                             VkImageLayout srcImageLayout,
+                                                             VkBuffer dstBuffer,
+                                                             uint32_t regionCount,
+                                                             const VkBufferImageCopy *pRegions)
+{
+#warning finish implementing vkCmdCopyImageToBuffer
+    assert(!"vkCmdCopyImageToBuffer is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdUpdateBuffer(VkCommandBuffer commandBuffer,
+                                                        VkBuffer dstBuffer,
+                                                        VkDeviceSize dstOffset,
+                                                        VkDeviceSize dataSize,
+                                                        const void *pData)
+{
+#warning finish implementing vkCmdUpdateBuffer
+    assert(!"vkCmdUpdateBuffer is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdFillBuffer(VkCommandBuffer commandBuffer,
+                                                      VkBuffer dstBuffer,
+                                                      VkDeviceSize dstOffset,
+                                                      VkDeviceSize size,
+                                                      uint32_t data)
+{
+#warning finish implementing vkCmdFillBuffer
+    assert(!"vkCmdFillBuffer is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdClearColorImage(VkCommandBuffer commandBuffer,
+                                                           VkImage image,
+                                                           VkImageLayout imageLayout,
+                                                           const VkClearColorValue *pColor,
+                                                           uint32_t rangeCount,
+                                                           const VkImageSubresourceRange *pRanges)
+{
+#warning finish implementing vkCmdClearColorImage
+    assert(!"vkCmdClearColorImage is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL
+    vkCmdClearDepthStencilImage(VkCommandBuffer commandBuffer,
+                                VkImage image,
+                                VkImageLayout imageLayout,
+                                const VkClearDepthStencilValue *pDepthStencil,
+                                uint32_t rangeCount,
+                                const VkImageSubresourceRange *pRanges)
+{
+#warning finish implementing vkCmdClearDepthStencilImage
+    assert(!"vkCmdClearDepthStencilImage is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdClearAttachments(VkCommandBuffer commandBuffer,
+                                                            uint32_t attachmentCount,
+                                                            const VkClearAttachment *pAttachments,
+                                                            uint32_t rectCount,
+                                                            const VkClearRect *pRects)
+{
+#warning finish implementing vkCmdClearAttachments
+    assert(!"vkCmdClearAttachments is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdResolveImage(VkCommandBuffer commandBuffer,
+                                                        VkImage srcImage,
+                                                        VkImageLayout srcImageLayout,
+                                                        VkImage dstImage,
+                                                        VkImageLayout dstImageLayout,
+                                                        uint32_t regionCount,
+                                                        const VkImageResolve *pRegions)
+{
+#warning finish implementing vkCmdResolveImage
+    assert(!"vkCmdResolveImage is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdSetEvent(VkCommandBuffer commandBuffer,
+                                                    VkEvent event,
+                                                    VkPipelineStageFlags stageMask)
+{
+#warning finish implementing vkCmdSetEvent
+    assert(!"vkCmdSetEvent is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdResetEvent(VkCommandBuffer commandBuffer,
+                                                      VkEvent event,
+                                                      VkPipelineStageFlags stageMask)
+{
+#warning finish implementing vkCmdResetEvent
+    assert(!"vkCmdResetEvent is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL
+    vkCmdWaitEvents(VkCommandBuffer commandBuffer,
+                    uint32_t eventCount,
+                    const VkEvent *pEvents,
+                    VkPipelineStageFlags srcStageMask,
+                    VkPipelineStageFlags dstStageMask,
+                    uint32_t memoryBarrierCount,
+                    const VkMemoryBarrier *pMemoryBarriers,
+                    uint32_t bufferMemoryBarrierCount,
+                    const VkBufferMemoryBarrier *pBufferMemoryBarriers,
+                    uint32_t imageMemoryBarrierCount,
+                    const VkImageMemoryBarrier *pImageMemoryBarriers)
+{
+#warning finish implementing vkCmdWaitEvents
+    assert(!"vkCmdWaitEvents is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL
+    vkCmdPipelineBarrier(VkCommandBuffer commandBuffer,
+                         VkPipelineStageFlags srcStageMask,
+                         VkPipelineStageFlags dstStageMask,
+                         VkDependencyFlags dependencyFlags,
+                         uint32_t memoryBarrierCount,
+                         const VkMemoryBarrier *pMemoryBarriers,
+                         uint32_t bufferMemoryBarrierCount,
+                         const VkBufferMemoryBarrier *pBufferMemoryBarriers,
+                         uint32_t imageMemoryBarrierCount,
+                         const VkImageMemoryBarrier *pImageMemoryBarriers)
+{
+#warning finish implementing vkCmdPipelineBarrier
+    assert(!"vkCmdPipelineBarrier is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdBeginQuery(VkCommandBuffer commandBuffer,
+                                                      VkQueryPool queryPool,
+                                                      uint32_t query,
+                                                      VkQueryControlFlags flags)
+{
+#warning finish implementing vkCmdBeginQuery
+    assert(!"vkCmdBeginQuery is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdEndQuery(VkCommandBuffer commandBuffer,
+                                                    VkQueryPool queryPool,
+                                                    uint32_t query)
+{
+#warning finish implementing vkCmdEndQuery
+    assert(!"vkCmdEndQuery is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdResetQueryPool(VkCommandBuffer commandBuffer,
+                                                          VkQueryPool queryPool,
+                                                          uint32_t firstQuery,
+                                                          uint32_t queryCount)
+{
+#warning finish implementing vkCmdResetQueryPool
+    assert(!"vkCmdResetQueryPool is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdWriteTimestamp(VkCommandBuffer commandBuffer,
+                                                          VkPipelineStageFlagBits pipelineStage,
+                                                          VkQueryPool queryPool,
+                                                          uint32_t query)
+{
+#warning finish implementing vkCmdWriteTimestamp
+    assert(!"vkCmdWriteTimestamp is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdCopyQueryPoolResults(VkCommandBuffer commandBuffer,
+                                                                VkQueryPool queryPool,
+                                                                uint32_t firstQuery,
+                                                                uint32_t queryCount,
+                                                                VkBuffer dstBuffer,
+                                                                VkDeviceSize dstOffset,
+                                                                VkDeviceSize stride,
+                                                                VkQueryResultFlags flags)
+{
+#warning finish implementing vkCmdCopyQueryPoolResults
+    assert(!"vkCmdCopyQueryPoolResults is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdPushConstants(VkCommandBuffer commandBuffer,
+                                                         VkPipelineLayout layout,
+                                                         VkShaderStageFlags stageFlags,
+                                                         uint32_t offset,
+                                                         uint32_t size,
+                                                         const void *pValues)
+{
+#warning finish implementing vkCmdPushConstants
+    assert(!"vkCmdPushConstants is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL
+    vkCmdBeginRenderPass(VkCommandBuffer commandBuffer,
+                         const VkRenderPassBeginInfo *pRenderPassBegin,
+                         VkSubpassContents contents)
+{
+#warning finish implementing vkCmdBeginRenderPass
+    assert(!"vkCmdBeginRenderPass is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdNextSubpass(VkCommandBuffer commandBuffer,
+                                                       VkSubpassContents contents)
+{
+#warning finish implementing vkCmdNextSubpass
+    assert(!"vkCmdNextSubpass is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdEndRenderPass(VkCommandBuffer commandBuffer)
+{
+#warning finish implementing vkCmdEndRenderPass
+    assert(!"vkCmdEndRenderPass is not implemented");
+}
+
+extern "C" VKAPI_ATTR void VKAPI_CALL vkCmdExecuteCommands(VkCommandBuffer commandBuffer,
+                                                           uint32_t commandBufferCount,
+                                                           const VkCommandBuffer *pCommandBuffers)
+{
+#warning finish implementing vkCmdExecuteCommands
+    assert(!"vkCmdExecuteCommands is not implemented");
+}
+namespace vulkan_cpu
+{
+namespace vulkan_icd
+{
+Vulkan_loader_interface *Vulkan_loader_interface::get() noexcept
+{
+    static Vulkan_loader_interface vulkan_loader_interface{};
+    return &vulkan_loader_interface;
+}
+
+PFN_vkVoidFunction Vulkan_loader_interface::get_procedure_address(
+    const char *name, Procedure_address_scope scope) 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");
+
+#define LIBRARY_SCOPE_FUNCTION(function_name)                     \
+    do                                                            \
+    {                                                             \
+        if(name == #function_name##_sv)                           \
+            return reinterpret_cast<PFN_vkVoidFunction>(          \
+                static_cast<PFN_##function_name>(function_name)); \
+    } while(0)
+#define INSTANCE_SCOPE_FUNCTION(function_name)                                       \
+    do                                                                               \
+    {                                                                                \
+        if(scope != Procedure_address_scope::Library && name == #function_name##_sv) \
+            return reinterpret_cast<PFN_vkVoidFunction>(                             \
+                static_cast<PFN_##function_name>(function_name));                    \
+    } while(0)
+
+    LIBRARY_SCOPE_FUNCTION(vkEnumerateInstanceExtensionProperties);
+    LIBRARY_SCOPE_FUNCTION(vkCreateInstance);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyInstance);
+    INSTANCE_SCOPE_FUNCTION(vkEnumeratePhysicalDevices);
+    INSTANCE_SCOPE_FUNCTION(vkGetPhysicalDeviceFeatures);
+    INSTANCE_SCOPE_FUNCTION(vkGetPhysicalDeviceFormatProperties);
+    INSTANCE_SCOPE_FUNCTION(vkGetPhysicalDeviceImageFormatProperties);
+    INSTANCE_SCOPE_FUNCTION(vkGetPhysicalDeviceProperties);
+    INSTANCE_SCOPE_FUNCTION(vkGetPhysicalDeviceQueueFamilyProperties);
+    INSTANCE_SCOPE_FUNCTION(vkGetPhysicalDeviceMemoryProperties);
+    INSTANCE_SCOPE_FUNCTION(vkGetInstanceProcAddr);
+    INSTANCE_SCOPE_FUNCTION(vkGetDeviceProcAddr);
+    INSTANCE_SCOPE_FUNCTION(vkCreateDevice);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyDevice);
+    INSTANCE_SCOPE_FUNCTION(vkEnumerateDeviceExtensionProperties);
+    INSTANCE_SCOPE_FUNCTION(vkGetDeviceQueue);
+    INSTANCE_SCOPE_FUNCTION(vkQueueSubmit);
+    INSTANCE_SCOPE_FUNCTION(vkQueueWaitIdle);
+    INSTANCE_SCOPE_FUNCTION(vkDeviceWaitIdle);
+    INSTANCE_SCOPE_FUNCTION(vkAllocateMemory);
+    INSTANCE_SCOPE_FUNCTION(vkFreeMemory);
+    INSTANCE_SCOPE_FUNCTION(vkMapMemory);
+    INSTANCE_SCOPE_FUNCTION(vkUnmapMemory);
+    INSTANCE_SCOPE_FUNCTION(vkFlushMappedMemoryRanges);
+    INSTANCE_SCOPE_FUNCTION(vkInvalidateMappedMemoryRanges);
+    INSTANCE_SCOPE_FUNCTION(vkGetDeviceMemoryCommitment);
+    INSTANCE_SCOPE_FUNCTION(vkBindBufferMemory);
+    INSTANCE_SCOPE_FUNCTION(vkBindImageMemory);
+    INSTANCE_SCOPE_FUNCTION(vkGetBufferMemoryRequirements);
+    INSTANCE_SCOPE_FUNCTION(vkGetImageMemoryRequirements);
+    INSTANCE_SCOPE_FUNCTION(vkGetImageSparseMemoryRequirements);
+    INSTANCE_SCOPE_FUNCTION(vkGetPhysicalDeviceSparseImageFormatProperties);
+    INSTANCE_SCOPE_FUNCTION(vkQueueBindSparse);
+    INSTANCE_SCOPE_FUNCTION(vkCreateFence);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyFence);
+    INSTANCE_SCOPE_FUNCTION(vkResetFences);
+    INSTANCE_SCOPE_FUNCTION(vkGetFenceStatus);
+    INSTANCE_SCOPE_FUNCTION(vkWaitForFences);
+    INSTANCE_SCOPE_FUNCTION(vkCreateSemaphore);
+    INSTANCE_SCOPE_FUNCTION(vkDestroySemaphore);
+    INSTANCE_SCOPE_FUNCTION(vkCreateEvent);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyEvent);
+    INSTANCE_SCOPE_FUNCTION(vkGetEventStatus);
+    INSTANCE_SCOPE_FUNCTION(vkSetEvent);
+    INSTANCE_SCOPE_FUNCTION(vkResetEvent);
+    INSTANCE_SCOPE_FUNCTION(vkCreateQueryPool);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyQueryPool);
+    INSTANCE_SCOPE_FUNCTION(vkGetQueryPoolResults);
+    INSTANCE_SCOPE_FUNCTION(vkCreateBuffer);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyBuffer);
+    INSTANCE_SCOPE_FUNCTION(vkCreateBufferView);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyBufferView);
+    INSTANCE_SCOPE_FUNCTION(vkCreateImage);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyImage);
+    INSTANCE_SCOPE_FUNCTION(vkGetImageSubresourceLayout);
+    INSTANCE_SCOPE_FUNCTION(vkCreateImageView);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyImageView);
+    INSTANCE_SCOPE_FUNCTION(vkCreateShaderModule);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyShaderModule);
+    INSTANCE_SCOPE_FUNCTION(vkCreatePipelineCache);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyPipelineCache);
+    INSTANCE_SCOPE_FUNCTION(vkGetPipelineCacheData);
+    INSTANCE_SCOPE_FUNCTION(vkMergePipelineCaches);
+    INSTANCE_SCOPE_FUNCTION(vkCreateGraphicsPipelines);
+    INSTANCE_SCOPE_FUNCTION(vkCreateComputePipelines);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyPipeline);
+    INSTANCE_SCOPE_FUNCTION(vkCreatePipelineLayout);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyPipelineLayout);
+    INSTANCE_SCOPE_FUNCTION(vkCreateSampler);
+    INSTANCE_SCOPE_FUNCTION(vkDestroySampler);
+    INSTANCE_SCOPE_FUNCTION(vkCreateDescriptorSetLayout);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyDescriptorSetLayout);
+    INSTANCE_SCOPE_FUNCTION(vkCreateDescriptorPool);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyDescriptorPool);
+    INSTANCE_SCOPE_FUNCTION(vkResetDescriptorPool);
+    INSTANCE_SCOPE_FUNCTION(vkAllocateDescriptorSets);
+    INSTANCE_SCOPE_FUNCTION(vkFreeDescriptorSets);
+    INSTANCE_SCOPE_FUNCTION(vkUpdateDescriptorSets);
+    INSTANCE_SCOPE_FUNCTION(vkCreateFramebuffer);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyFramebuffer);
+    INSTANCE_SCOPE_FUNCTION(vkCreateRenderPass);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyRenderPass);
+    INSTANCE_SCOPE_FUNCTION(vkGetRenderAreaGranularity);
+    INSTANCE_SCOPE_FUNCTION(vkCreateCommandPool);
+    INSTANCE_SCOPE_FUNCTION(vkDestroyCommandPool);
+    INSTANCE_SCOPE_FUNCTION(vkResetCommandPool);
+    INSTANCE_SCOPE_FUNCTION(vkAllocateCommandBuffers);
+    INSTANCE_SCOPE_FUNCTION(vkFreeCommandBuffers);
+    INSTANCE_SCOPE_FUNCTION(vkBeginCommandBuffer);
+    INSTANCE_SCOPE_FUNCTION(vkEndCommandBuffer);
+    INSTANCE_SCOPE_FUNCTION(vkResetCommandBuffer);
+    INSTANCE_SCOPE_FUNCTION(vkCmdBindPipeline);
+    INSTANCE_SCOPE_FUNCTION(vkCmdSetViewport);
+    INSTANCE_SCOPE_FUNCTION(vkCmdSetScissor);
+    INSTANCE_SCOPE_FUNCTION(vkCmdSetLineWidth);
+    INSTANCE_SCOPE_FUNCTION(vkCmdSetDepthBias);
+    INSTANCE_SCOPE_FUNCTION(vkCmdSetBlendConstants);
+    INSTANCE_SCOPE_FUNCTION(vkCmdSetDepthBounds);
+    INSTANCE_SCOPE_FUNCTION(vkCmdSetStencilCompareMask);
+    INSTANCE_SCOPE_FUNCTION(vkCmdSetStencilWriteMask);
+    INSTANCE_SCOPE_FUNCTION(vkCmdSetStencilReference);
+    INSTANCE_SCOPE_FUNCTION(vkCmdBindDescriptorSets);
+    INSTANCE_SCOPE_FUNCTION(vkCmdBindIndexBuffer);
+    INSTANCE_SCOPE_FUNCTION(vkCmdBindVertexBuffers);
+    INSTANCE_SCOPE_FUNCTION(vkCmdDraw);
+    INSTANCE_SCOPE_FUNCTION(vkCmdDrawIndexed);
+    INSTANCE_SCOPE_FUNCTION(vkCmdDrawIndirect);
+    INSTANCE_SCOPE_FUNCTION(vkCmdDrawIndexedIndirect);
+    INSTANCE_SCOPE_FUNCTION(vkCmdDispatch);
+    INSTANCE_SCOPE_FUNCTION(vkCmdDispatchIndirect);
+    INSTANCE_SCOPE_FUNCTION(vkCmdCopyBuffer);
+    INSTANCE_SCOPE_FUNCTION(vkCmdCopyImage);
+    INSTANCE_SCOPE_FUNCTION(vkCmdBlitImage);
+    INSTANCE_SCOPE_FUNCTION(vkCmdCopyBufferToImage);
+    INSTANCE_SCOPE_FUNCTION(vkCmdCopyImageToBuffer);
+    INSTANCE_SCOPE_FUNCTION(vkCmdUpdateBuffer);
+    INSTANCE_SCOPE_FUNCTION(vkCmdFillBuffer);
+    INSTANCE_SCOPE_FUNCTION(vkCmdClearColorImage);
+    INSTANCE_SCOPE_FUNCTION(vkCmdClearDepthStencilImage);
+    INSTANCE_SCOPE_FUNCTION(vkCmdClearAttachments);
+    INSTANCE_SCOPE_FUNCTION(vkCmdResolveImage);
+    INSTANCE_SCOPE_FUNCTION(vkCmdSetEvent);
+    INSTANCE_SCOPE_FUNCTION(vkCmdResetEvent);
+    INSTANCE_SCOPE_FUNCTION(vkCmdWaitEvents);
+    INSTANCE_SCOPE_FUNCTION(vkCmdPipelineBarrier);
+    INSTANCE_SCOPE_FUNCTION(vkCmdBeginQuery);
+    INSTANCE_SCOPE_FUNCTION(vkCmdEndQuery);
+    INSTANCE_SCOPE_FUNCTION(vkCmdResetQueryPool);
+    INSTANCE_SCOPE_FUNCTION(vkCmdWriteTimestamp);
+    INSTANCE_SCOPE_FUNCTION(vkCmdCopyQueryPoolResults);
+    INSTANCE_SCOPE_FUNCTION(vkCmdPushConstants);
+    INSTANCE_SCOPE_FUNCTION(vkCmdBeginRenderPass);
+    INSTANCE_SCOPE_FUNCTION(vkCmdNextSubpass);
+    INSTANCE_SCOPE_FUNCTION(vkCmdEndRenderPass);
+    INSTANCE_SCOPE_FUNCTION(vkCmdExecuteCommands);
+
+#undef LIBRARY_SCOPE_FUNCTION
+#undef INSTANCE_SCOPE_FUNCTION
+    return nullptr;
+}
+
+PFN_vkVoidFunction Vulkan_loader_interface::get_instance_proc_addr(VkInstance instance,
+                                                                   const char *name) noexcept
+{
+    if(!instance)
+        return get_procedure_address(name, Procedure_address_scope::Library);
+    return get_procedure_address(name, Procedure_address_scope::Instance);
+}
+
+VkResult Vulkan_loader_interface::create_instance(const VkInstanceCreateInfo *create_info,
+                                                  const VkAllocationCallbacks *allocator,
+                                                  VkInstance *instance) noexcept
+{
+    validate_allocator(allocator);
+    assert(create_info);
+    assert(instance);
+    return catch_exceptions_and_return_result(
+        [&]()
+        {
+            auto create_result = vulkan::Vulkan_instance::create(*create_info);
+            if(util::holds_alternative<VkResult>(create_result))
+                return util::get<VkResult>(create_result);
+            *instance = move_to_handle(
+                util::get<std::unique_ptr<vulkan::Vulkan_instance>>(std::move(create_result)));
+            return VK_SUCCESS;
+        });
+}
+
+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);
+}
+
+VkResult Vulkan_loader_interface::enumerate_device_extension_properties(
+    VkPhysicalDevice physical_device,
+    const char *layer_name,
+    uint32_t *property_count,
+    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);
+}
+}
+
+void vulkan_icd::print_exception(std::exception &e) noexcept
+{
+    std::cerr << "error: " << e.what() << std::endl;
+}
+}
diff --git a/src/vulkan_icd/vulkan_icd.h b/src/vulkan_icd/vulkan_icd.h
new file mode 100644 (file)
index 0000000..8f63728
--- /dev/null
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2017 Jacob Lifshay
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ *
+ */
+#ifndef VULKAN_ICD_VULKAN_ICD_H_
+#define VULKAN_ICD_VULKAN_ICD_H_
+
+#include "vulkan/vulkan.h"
+#include "vulkan/vk_icd.h"
+#include "vulkan/api_objects.h"
+#include <type_traits>
+#include <cstdint>
+#include <cassert>
+#include <initializer_list>
+#include <memory>
+#include <stdexcept>
+#include <new>
+
+extern "C" VKAPI_ATTR PFN_vkVoidFunction VKAPI_CALL vk_icdGetInstanceProcAddr(VkInstance instance,
+                                                                              const char *pName);
+
+typedef PFN_vkVoidFunction (*VKAPI_PTR PFN_vk_icdGetInstanceProcAddr)(VkInstance instance,
+                                                                      const char *pName);
+
+namespace vulkan_cpu
+{
+namespace vulkan_icd
+{
+class Vulkan_loader_interface
+{
+public:
+    enum class Version : std::uint32_t
+    {
+        Version_0 = 0,
+        Version_1 = 1,
+        Version_2 = 2,
+        Version_3 = 3,
+        Version_4 = 4,
+        Version_5 = 5,
+    };
+
+public:
+    static Vulkan_loader_interface *get() noexcept;
+
+private:
+    constexpr Vulkan_loader_interface() noexcept
+    {
+    }
+
+public:
+    constexpr Version get_negotiated_version() const noexcept
+    {
+        return negotiated_version;
+    }
+
+public:
+    enum class Procedure_address_scope
+    {
+        Library,
+        Instance,
+        Device
+    };
+    PFN_vkVoidFunction get_procedure_address(const char *name,
+                                             Procedure_address_scope scope) noexcept;
+    PFN_vkVoidFunction get_instance_proc_addr(VkInstance instance, const char *name) noexcept;
+    VkResult create_instance(const VkInstanceCreateInfo *create_info,
+                             const VkAllocationCallbacks *allocator,
+                             VkInstance *instance) noexcept;
+    VkResult enumerate_instance_extension_properties(const char *layer_name,
+                                                     uint32_t *property_count,
+                                                     VkExtensionProperties *properties) noexcept;
+    VkResult enumerate_device_extension_properties(VkPhysicalDevice physical_device,
+                                                   const char *layer_name,
+                                                   uint32_t *property_count,
+                                                   VkExtensionProperties *properties) noexcept;
+
+private:
+    Version negotiated_version = Version::Version_0;
+};
+
+static_assert(std::is_trivially_destructible<Vulkan_loader_interface>::value, "");
+static_assert(std::is_literal_type<Vulkan_loader_interface>::value, "");
+
+template <typename T>
+VkResult vulkan_enumerate_list_helper(std::uint32_t *api_value_count,
+                                      T *api_values,
+                                      const T *generated_values,
+                                      std::size_t generated_value_count) noexcept
+{
+    static_assert(std::is_trivially_copyable<T>::value, "");
+    assert(api_value_count);
+    assert(static_cast<std::uint32_t>(generated_value_count) == generated_value_count);
+    if(!api_values)
+    {
+        *api_value_count = generated_value_count;
+        return VK_SUCCESS;
+    }
+    auto api_values_length = *api_value_count;
+    auto copy_length = api_values_length;
+    if(copy_length > generated_value_count)
+        copy_length = generated_value_count;
+    for(std::size_t i = 0; i < copy_length; i++)
+        api_values[i] = generated_values[i];
+    *api_value_count = copy_length;
+    if(copy_length < generated_value_count)
+        return VK_INCOMPLETE;
+    return VK_SUCCESS;
+}
+
+template <typename T>
+VkResult vulkan_enumerate_list_helper(std::uint32_t *api_value_count,
+                                      T *api_values,
+                                      std::initializer_list<T> generated_values) noexcept
+{
+    return vulkan_enumerate_list_helper(
+        api_value_count, api_values, generated_values.begin(), generated_values.size());
+}
+
+void print_exception(std::exception &e) noexcept;
+
+template <typename Fn>
+VkResult catch_exceptions_and_return_result(Fn &&fn) noexcept
+{
+    try
+    {
+        return std::forward<Fn>(fn)();
+    }
+    catch(std::bad_alloc &)
+    {
+        return VK_ERROR_OUT_OF_HOST_MEMORY;
+    }
+    catch(std::exception &e)
+    {
+        print_exception(e);
+        throw; // send to std::terminate
+    }
+    // explicitly don't catch other exceptions and let std::terminate handle them
+}
+}
+}
+
+#endif // VULKAN_ICD_VULKAN_ICD_H_