diff --git a/CMakeLists.txt b/CMakeLists.txt index f16a772..89c73f0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,14 +7,9 @@ include (nc) ############################################################################### -include (FindVulkan) -if (NOT Vulkan_FOUND) - message (FATAL_ERROR "Vulkan client library not found") -endif () - - -##----------------------------------------------------------------------------- -find_package(PythonInterp 3 REQUIRED) +find_package (Vulkan REQUIRED) +find_package (PythonInterp 3 REQUIRED) +find_package (glfw3 REQUIRED) ############################################################################### @@ -99,7 +94,7 @@ endif () ############################################################################### -foreach (t info) +foreach (t info hello) add_executable (vk_${t} "tools/${t}.cpp") set_target_properties(vk_${t} PROPERTIES OUTPUT_NAME @@ -107,7 +102,7 @@ foreach (t info) set_target_properties(vk_${t} PROPERTIES RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/tools") - target_link_libraries (vk_${t} cruft-vk) + target_link_libraries (vk_${t} cruft-vk glfw) endforeach () ############################################################################### diff --git a/device.cpp b/device.cpp index 158de23..26c0eef 100644 --- a/device.cpp +++ b/device.cpp @@ -18,6 +18,7 @@ #include "./device.hpp" #include "./physical_device.hpp" +#include "./queue.hpp" #include #include @@ -28,7 +29,7 @@ using cruft::vk::device; /////////////////////////////////////////////////////////////////////////////// device::device (const physical_device &phys, const VkDeviceCreateInfo &info): - instantiated (phys.id (), &info, nullptr) + descendant (phys, &info, nullptr) { ; } @@ -42,6 +43,14 @@ device::physical_properties (void) const } +/////////////////////////////////////////////////////////////////////////////// +cruft::vk::queue +device::queue (uint32_t id) +{ + return ::cruft::vk::queue (*this, id, 0); +} + + /////////////////////////////////////////////////////////////////////////////// void device::flush (const VkMappedMemoryRange *first, diff --git a/device.hpp b/device.hpp index 8e394fe..4aeb96b 100644 --- a/device.hpp +++ b/device.hpp @@ -23,13 +23,15 @@ #include "./fwd.hpp" namespace cruft::vk { - struct device : public instantiated { + struct device : public descendant { device (const physical_device&, const VkDeviceCreateInfo&); VkPhysicalDeviceMemoryProperties physical_properties (void) const; + struct queue queue (uint32_t id); + void flush (const VkMappedMemoryRange *first, const VkMappedMemoryRange *last); diff --git a/except.cpp b/except.cpp index 3adeeb6..5e0da57 100644 --- a/except.cpp +++ b/except.cpp @@ -43,8 +43,7 @@ using cruft::vk::error_code; VK_ERROR_FEATURE_NOT_PRESENT, \ VK_ERROR_INCOMPATIBLE_DRIVER, \ VK_ERROR_TOO_MANY_OBJECTS, \ - VK_ERROR_FORMAT_NOT_SUPPORTED, \ - VK_ERROR_FRAGMENTED_POOL) + VK_ERROR_FORMAT_NOT_SUPPORTED) /////////////////////////////////////////////////////////////////////////////// @@ -74,7 +73,6 @@ to_string (VkResult res) case VK_ERROR_INCOMPATIBLE_DRIVER: return "incompatible driver"; case VK_ERROR_TOO_MANY_OBJECTS: return "too many objects"; case VK_ERROR_FORMAT_NOT_SUPPORTED: return "format not supported"; - case VK_ERROR_FRAGMENTED_POOL: return "fragmented pool"; } unreachable (); diff --git a/except.hpp b/except.hpp index 319f0d4..ccff147 100644 --- a/except.hpp +++ b/except.hpp @@ -30,6 +30,23 @@ namespace cruft::vk { }; + class invalid_argument : public error { + public: + invalid_argument (const char *_what) noexcept: + m_what (_what) + { ; } + + const char* + what (void) const noexcept override + { + return m_what; + } + + private: + const char *m_what; + }; + + template class error_code : public error { public: diff --git a/fwd.hpp b/fwd.hpp index d717492..71d464c 100644 --- a/fwd.hpp +++ b/fwd.hpp @@ -24,7 +24,7 @@ namespace cruft::vk { - template struct instantiated; + template struct descendant; template struct enumerated; template struct owned; @@ -53,14 +53,19 @@ namespace cruft::vk { MAP(FUNC, \ physical_device) - #define VK_INSTANTIATED_TYPE_MAP(FUNC) \ + #define VK_DESCENDANT_TYPE_MAP(FUNC) \ MAP(FUNC, \ - device, \ - instance) + device) + + #define VK_OWNED_TYPE_MAP(FUNC) \ + MAP(FUNC, \ + queue) #define VK_TYPE_MAP(FUNC) \ + MAP(FUNC,instance) \ VK_ENUMERATED_TYPE_MAP(FUNC) \ - VK_INSTANTIATED_TYPE_MAP(FUNC) + VK_DESCENDANT_TYPE_MAP(FUNC) \ + VK_OWNED_TYPE_MAP(FUNC) } #endif diff --git a/instance.cpp b/instance.cpp index 8416aab..5013bf1 100644 --- a/instance.cpp +++ b/instance.cpp @@ -57,11 +57,28 @@ instance::instance (): //----------------------------------------------------------------------------- -instance::instance (const create_info_t &info): - instantiated (&info, nullptr) +instance::instance (const util::view layers, + const util::view extensions): + instance (VkInstanceCreateInfo { + .sType = cruft::vk::structure_type_v, + .pNext = nullptr, + .flags = {}, + .pApplicationInfo = nullptr, + .enabledLayerCount = static_cast (layers.size ()), + .ppEnabledLayerNames = layers.data (), + .enabledExtensionCount = static_cast (extensions.size ()), + .ppEnabledExtensionNames = extensions.data () + }) { ; } +//----------------------------------------------------------------------------- +instance::instance (const create_info_t &info): + root (&info, nullptr) +{ ; } + + + /////////////////////////////////////////////////////////////////////////////// std::set instance::extensions (void) const @@ -78,3 +95,17 @@ instance::extensions (void) const ext.insert (i.extensionName); return ext; } + + +/////////////////////////////////////////////////////////////////////////////// +std::vector +instance::available_layers (void) +{ + + uint32_t count; + vk::error::try_code (vkEnumerateInstanceLayerProperties (&count, nullptr)); + + std::vector layers (count); + vk::error::try_code (vkEnumerateInstanceLayerProperties (&count, layers.data ())); + return layers; +} diff --git a/instance.hpp b/instance.hpp index 040d0d3..46a2c7a 100644 --- a/instance.hpp +++ b/instance.hpp @@ -22,12 +22,15 @@ #include "./vk.hpp" #include "./traits.hpp" +#include "./except.hpp" + +#include #include #include namespace cruft::vk { - struct instance : public instantiated { + struct instance : public root { struct create_info_t : public VkInstanceCreateInfo { create_info_t (); create_info_t (const VkInstanceCreateInfo&); @@ -39,9 +42,24 @@ namespace cruft::vk { }; instance (); + instance (util::view layers, + util::view extensions); instance (const create_info_t &info); + template + T + proc (const char *name) + { + auto ret = vkGetInstanceProcAddr (id (), name); + if (!ret) + throw vk::invalid_argument ("invalid procedure name"); + + return reinterpret_cast (ret); + } + std::set extensions (void) const; + + static std::vector available_layers (void); }; } diff --git a/object.cpp b/object.cpp index abc015a..36a9520 100644 --- a/object.cpp +++ b/object.cpp @@ -69,8 +69,8 @@ VK_TYPE_MAP (OBJECT) /////////////////////////////////////////////////////////////////////////////// -#define INSTANTIATED(T) template struct cruft::vk::instantiated; -VK_INSTANTIATED_TYPE_MAP (INSTANTIATED) +#define DESCENDANT(T) template struct cruft::vk::descendant; +VK_DESCENDANT_TYPE_MAP (DESCENDANT) /////////////////////////////////////////////////////////////////////////////// diff --git a/object.hpp b/object.hpp index 0320cc2..0fc65c7 100644 --- a/object.hpp +++ b/object.hpp @@ -43,30 +43,57 @@ namespace cruft::vk { }; + template + struct root : public object { + using id_t = typename object::id_t; + + template + root (Args &&...args): + object (make (std::forward (args)...)) + { ; } + + ~root () + { + life_traits::destroy (this->id (), nullptr); + } + + private: + template + static id_t + make (Args &&...args) + { + id_t id; + auto res = life_traits::create (std::forward (args)..., &id); + error::try_code (res); + return id; + } + }; + + /// a vulkan object that must be directly instantiated through /// constructor arguments, rather than being enumerated and owned by /// another object. template - struct instantiated : public object { + struct descendant : public object { using id_t = typename object::id_t; template - instantiated (Args &&...args): + descendant (Args &&...args): object (make (std::forward (args)...)) { ; } - ~instantiated () + ~descendant () { life_traits::destroy (this->id (), nullptr); } private: - template + template static - id_t make (Args &&...args) + id_t make (Base &&base, Args &&...args) { id_t id; - auto res = life_traits::create (std::forward (args)..., &id); + auto res = life_traits::create (base.id (), std::forward (args)..., &id); error::try_code (res); return id; } @@ -86,8 +113,26 @@ namespace cruft::vk { /// /// typically implies that this object must be freed using a reference to /// the parent object. - template - struct owned : public object { }; + template + struct owned : public object { + using id_t = typename object::id_t; + using object::object; + + template + owned (Args &&...args): + object (make (std::forward (args)...)) + { ; } + + private: + template + static + id_t make (OwnerT &owner, Args &&...args) + { + id_t id; + life_traits::get (owner.id (), std::forward (args)..., &id); + return id; + } + }; } #endif diff --git a/ostream.cpp b/ostream.cpp index 118509f..66c12b2 100644 --- a/ostream.cpp +++ b/ostream.cpp @@ -93,6 +93,18 @@ cruft::vk::operator<< (std::ostream &os, const instance &i) } +/////////////////////////////////////////////////////////////////////////////// +std::ostream& +operator<< (std::ostream &os, const VkLayerProperties &val) +{ + return os << "{ name: '" << val.layerName << "'" + << ", specVersion: " << val.specVersion + << ", implementationVersion: " << val.implementationVersion + << ", description: '" << val.description << "'" + << " }"; +}; + + /////////////////////////////////////////////////////////////////////////////// std::ostream& operator<< (std::ostream &os, VkPhysicalDeviceType t) diff --git a/ostream.hpp b/ostream.hpp index f86b568..0dc5e1b 100644 --- a/ostream.hpp +++ b/ostream.hpp @@ -33,10 +33,13 @@ std::ostream& operator<< (std::ostream&, VkPhysicalDeviceType); /////////////////////////////////////////////////////////////////////////////// -std::ostream& operator<< (std::ostream&, const VkQueueFamilyProperties&); +std::ostream& operator<< (std::ostream&, const VkLayerProperties&); + std::ostream& operator<< (std::ostream&, const VkPhysicalDeviceLimits&); std::ostream& operator<< (std::ostream&, const VkPhysicalDeviceProperties&); +std::ostream& operator<< (std::ostream&, const VkQueueFamilyProperties&); + /////////////////////////////////////////////////////////////////////////////// namespace cruft::vk { diff --git a/queue.hpp b/queue.hpp index 74b02a7..6fdda1b 100644 --- a/queue.hpp +++ b/queue.hpp @@ -23,6 +23,8 @@ namespace cruft::vk { struct queue : public owned { + using owned::owned; + void wait_idle (void); template diff --git a/tools/info.cpp b/tools/info.cpp index 10e0f9f..fbef787 100644 --- a/tools/info.cpp +++ b/tools/info.cpp @@ -15,16 +15,23 @@ * 2017, Danny Robson */ +#include + #include #include #include #include + /////////////////////////////////////////////////////////////////////////////// int main (int, char**) { + std::cout << "available_layers: [ " + << util::make_infix (cruft::vk::instance::available_layers ()) + << " ]\n"; + cruft::vk::instance instance; std::cout << "instance: " << instance << '\n'; diff --git a/traits.hpp b/traits.hpp index 4caf953..670f4ee 100644 --- a/traits.hpp +++ b/traits.hpp @@ -31,13 +31,23 @@ namespace cruft::vk { //------------------------------------------------------------------------- - #define DEFINE_STRUCTURE_TYPE(KLASS,VALUE) \ - template <> \ - struct structure_type : \ - public std::integral_constant \ + #define DEFINE_STRUCTURE_TYPE(KLASS,VALUE) \ + template <> \ + struct structure_type : \ + public std::integral_constant< \ + VkStructureType, \ + PASTE(VK_STRUCTURE_TYPE_,VALUE) \ + > \ { } - DEFINE_STRUCTURE_TYPE (VkInstanceCreateInfo, VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO); + 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); #undef DEFINE_STRUCTURE_TYPE @@ -47,6 +57,28 @@ namespace cruft::vk { constexpr auto structure_type_v = structure_type::value; + /////////////////////////////////////////////////////////////////////////// + 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); + + #undef DEFINE_CREATE_INFO + + + //------------------------------------------------------------------------- + template + using create_info_t = typename create_info::type; + + /////////////////////////////////////////////////////////////////////////// template struct id_traits { }; @@ -117,6 +149,11 @@ namespace cruft::vk { static constexpr auto destroy = vkDestroyShaderModule; }; + template <> + struct life_traits { + static constexpr auto get = vkGetDeviceQueue; + }; + template struct create_traits { }; template <> struct create_traits { static constexpr auto func = vkCreateComputePipelines; @@ -160,6 +197,10 @@ namespace cruft::vk { template <> struct enum_traits { static constexpr auto enumerate = vkEnumeratePhysicalDevices; }; + + + /////////////////////////////////////////////////////////////////////////// + template struct format_traits {}; } #endif