/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * * Copyright: * 2016-2017, Danny Robson */ #ifndef CRUFT_VK_TRAITS_HPP #define CRUFT_VK_TRAITS_HPP #include "./fwd.hpp" #include "./vk.hpp" #include #include namespace cruft::vk { /////////////////////////////////////////////////////////////////////////// /// describes the native type that corresponds to a given vk-cruft type. template struct native_traits { }; //------------------------------------------------------------------------- template <> struct native_traits { using type = VkBuffer; }; template <> struct native_traits { using type = VkBufferView; }; template <> struct native_traits { using type = VkCommandBuffer; }; template <> struct native_traits { using type = VkCommandPool; }; template <> struct native_traits { using type = VkDeviceMemory; }; template <> struct native_traits { using type = VkDevice; }; template <> struct native_traits { using type = VkEvent; }; template <> struct native_traits { using type = VkFence; }; template <> struct native_traits { using type = VkFramebuffer; }; template <> struct native_traits { using type = VkImageView; }; template <> struct native_traits { using type = VkInstance; }; template <> struct native_traits { using type = VkPhysicalDevice; }; template <> struct native_traits { using type = VkPipelineCache; }; template <> struct native_traits { using type = VkPipelineLayout; }; template <> struct native_traits { using type = VkQueue; }; template <> struct native_traits { using type = VkRenderPass; }; template <> struct native_traits { using type = VkSemaphore; }; template <> struct native_traits { using type = VkShaderModule; }; template <> struct native_traits { using type = VkSurfaceKHR; }; template <> struct native_traits { using type = VkSwapchainKHR; }; //------------------------------------------------------------------------- template <> struct native_traits> { using type = VkPipeline; }; template <> struct native_traits> { using type = VkPipeline; }; //------------------------------------------------------------------------- template using native_t = typename native_traits::type; /////////////////////////////////////////////////////////////////////////// /// defines whether a type is a native vulkan object. /// /// note that this only returns true for handle types, not parameter types. /// eg, VkDevice will return true, but VkDeviceCreateInfo will not. template struct is_native : public std::false_type { }; //------------------------------------------------------------------------- #define DEFINE_IS_HANDLE(KLASS) \ template <> \ struct is_native> : \ public std::true_type \ { }; VK_TYPE_MAP (DEFINE_IS_HANDLE) #undef DEFINE_IS_HANDLE //------------------------------------------------------------------------- template static constexpr auto is_native_v = is_native::value; /////////////////////////////////////////////////////////////////////////// template struct is_wrapper : public std::false_type { }; //------------------------------------------------------------------------- #define IS_WRAPPER(KLASS) \ template <> \ struct is_wrapper : \ public std::true_type \ { }; VK_TYPE_MAP(IS_WRAPPER) #undef IS_WRAPPER //------------------------------------------------------------------------- template static constexpr auto is_wrapper_v = is_wrapper::value; /////////////////////////////////////////////////////////////////////////// /// describes the corresponding value for sType in native structures template struct structure_type {}; //------------------------------------------------------------------------- #define DEFINE_STRUCTURE_TYPE(KLASS,VALUE) \ template <> \ struct structure_type : \ public std::integral_constant< \ VkStructureType, \ PASTE(VK_STRUCTURE_TYPE_,VALUE) \ > \ { } DEFINE_STRUCTURE_TYPE (VkInstanceCreateInfo, INSTANCE_CREATE_INFO); DEFINE_STRUCTURE_TYPE (VkApplicationInfo, APPLICATION_INFO); DEFINE_STRUCTURE_TYPE (VkDeviceQueueCreateInfo, DEVICE_QUEUE_CREATE_INFO); DEFINE_STRUCTURE_TYPE (VkDeviceCreateInfo, DEVICE_CREATE_INFO); DEFINE_STRUCTURE_TYPE (VkSwapchainCreateInfoKHR, SWAPCHAIN_CREATE_INFO_KHR); DEFINE_STRUCTURE_TYPE (VkImageViewCreateInfo, IMAGE_VIEW_CREATE_INFO); DEFINE_STRUCTURE_TYPE (VkShaderModuleCreateInfo, SHADER_MODULE_CREATE_INFO); DEFINE_STRUCTURE_TYPE (VkPipelineShaderStageCreateInfo, PIPELINE_SHADER_STAGE_CREATE_INFO); DEFINE_STRUCTURE_TYPE (VkDebugReportCallbackCreateInfoEXT, DEBUG_REPORT_CALLBACK_CREATE_INFO_EXT); #undef DEFINE_STRUCTURE_TYPE //------------------------------------------------------------------------- template constexpr auto structure_type_v = structure_type::value; /////////////////////////////////////////////////////////////////////////// /// describes the native type that owns a given native type, and hence /// forms part of the create/destroy process. /// /// undefined for types that aren't `owned' types. template struct owner_traits {}; template <> struct owner_traits { using type = device; }; template <> struct owner_traits { using type = device; }; template <> struct owner_traits { using type = device; }; template <> struct owner_traits { using type = device; }; template <> struct owner_traits { using type = device; }; template <> struct owner_traits { using type = device; }; template <> struct owner_traits { using type = device; }; template <> struct owner_traits { using type = device; }; template <> struct owner_traits { using type = device; }; template <> struct owner_traits { using type = device; }; template <> struct owner_traits { using type = instance; }; template <> struct owner_traits { using type = device; }; template using owner_t = typename owner_traits::type; /////////////////////////////////////////////////////////////////////////// /// describes the parameter struct used to create a given vulkan type. /// /// explicitly does not operate on vk-cruft types, only native types. template struct create_info { }; //------------------------------------------------------------------------- #define DEFINE_CREATE_INFO(TARGET,INFO) \ template <> \ struct create_info \ { using type = INFO; } DEFINE_CREATE_INFO (VkImageViewCreateInfo, VkImageViewCreateInfo); DEFINE_CREATE_INFO (VkShaderModule, VkShaderModuleCreateInfo); DEFINE_CREATE_INFO (VkPipelineLayout, VkPipelineLayoutCreateInfo); #undef DEFINE_CREATE_INFO //------------------------------------------------------------------------- template using create_info_t = typename create_info::type; /////////////////////////////////////////////////////////////////////////// /// lists the `create' and `destroy' methods for a given native type. /// /// XXX: if such a function does not exist anywhere then we currently use /// tuple::ignore to simplify implementation elsewhere. we should probably /// investigate std::is_detected for these cases though. /// /// clang#18781: we make use of references types extensively here to /// workaround a potential ODR bug in clang which results in undefined /// references. /// or potentially i'm being too clever for my own good, but it works fine /// in gcc... template struct life_traits { }; //------------------------------------------------------------------------- template <> struct life_traits { static constexpr auto& create = vkCreateInstance; static constexpr auto& destroy = vkDestroyInstance; }; template <> struct life_traits { static constexpr auto& create = vkCreateDevice; static constexpr auto& destroy = vkDestroyDevice; }; template <> struct life_traits { static constexpr auto& create = vkCreateImageView; static constexpr auto& destroy = vkDestroyImageView; }; template <> struct life_traits { static constexpr auto& create = vkCreateCommandPool; static constexpr auto& destroy = vkDestroyCommandPool; }; template <> struct life_traits { static constexpr auto& create = vkCreateFence; static constexpr auto& destroy = vkDestroyFence; }; template <> struct life_traits { static constexpr auto& create = vkCreateSemaphore; static constexpr auto& destroy = vkDestroySemaphore; }; template <> struct life_traits { static constexpr auto& create = vkCreateEvent; static constexpr auto& destroy = vkDestroyEvent; }; template <> struct life_traits { static constexpr auto& create = vkCreateRenderPass; static constexpr auto& destroy = vkDestroyRenderPass; }; template <> struct life_traits { static constexpr auto& create = vkCreateFramebuffer; static constexpr auto& destroy = vkDestroyFramebuffer; }; template <> struct life_traits { static constexpr auto& create = vkCreateShaderModule; static constexpr auto& destroy = vkDestroyShaderModule; }; template <> struct life_traits { static constexpr auto& destroy = vkDestroySurfaceKHR; }; template <> struct life_traits { static constexpr auto& create = vkGetDeviceQueue; static constexpr auto destroy = ::util::tuple::ignore< native_t>, native_t, const VkAllocationCallbacks* >; }; template <> struct life_traits { static constexpr auto& create = vkCreatePipelineLayout; static constexpr auto& destroy = vkDestroyPipelineLayout; }; template <> struct life_traits { static constexpr auto& create = vkCreatePipelineCache; static constexpr auto& destroy = vkDestroyPipelineCache; }; template <> struct life_traits { static constexpr auto& create = vkAllocateMemory; static constexpr auto& destroy = vkFreeMemory; }; template <> struct life_traits { static constexpr auto& create = vkCreateBuffer; static constexpr auto& destroy = vkDestroyBuffer; }; template <> struct life_traits { static constexpr auto& create = vkCreateBufferView; }; template <> struct life_traits { static constexpr auto& create = vkCreateSwapchainKHR; static constexpr auto& destroy = vkDestroySwapchainKHR; }; //------------------------------------------------------------------------- template <> struct life_traits> { static constexpr auto &create = vkCreateGraphicsPipelines; static constexpr auto &destroy = vkDestroyPipeline; }; template <> struct life_traits> { static constexpr auto &create = vkCreateComputePipelines; static constexpr auto &destroy = vkDestroyPipeline; }; /////////////////////////////////////////////////////////////////////////// /// describes the functions required to enumerate native types template struct enum_traits { }; template <> struct enum_traits { static constexpr auto &enumerate = vkEnumeratePhysicalDevices; }; } #endif