diff --git a/except.cpp b/except.cpp index efa5f3d..3adeeb6 100644 --- a/except.cpp +++ b/except.cpp @@ -24,6 +24,63 @@ using cruft::vk::error; using cruft::vk::error_code; +/////////////////////////////////////////////////////////////////////////////// +#define VK_RESULT_MAP(FUNC)\ + MAP(FUNC, \ + VK_SUCCESS, \ + VK_NOT_READY, \ + VK_TIMEOUT, \ + VK_EVENT_SET, \ + VK_EVENT_RESET, \ + VK_INCOMPLETE, \ + VK_ERROR_OUT_OF_HOST_MEMORY, \ + VK_ERROR_OUT_OF_DEVICE_MEMORY, \ + VK_ERROR_INITIALIZATION_FAILED, \ + VK_ERROR_DEVICE_LOST, \ + VK_ERROR_MEMORY_MAP_FAILED, \ + VK_ERROR_LAYER_NOT_PRESENT, \ + VK_ERROR_EXTENSION_NOT_PRESENT, \ + VK_ERROR_FEATURE_NOT_PRESENT, \ + VK_ERROR_INCOMPATIBLE_DRIVER, \ + VK_ERROR_TOO_MANY_OBJECTS, \ + VK_ERROR_FORMAT_NOT_SUPPORTED, \ + VK_ERROR_FRAGMENTED_POOL) + + +/////////////////////////////////////////////////////////////////////////////// +static constexpr +const char* +to_string (VkResult res) +{ + switch (res) { + case VK_SUCCESS: return "success"; + + // partial successes + case VK_NOT_READY: return "not ready"; + case VK_TIMEOUT: return "timeout"; + case VK_EVENT_SET: return "event set"; + case VK_EVENT_RESET: return "event reset"; + case VK_INCOMPLETE: return "incomplete"; + + // errors + case VK_ERROR_OUT_OF_HOST_MEMORY: return "out of host memory"; + case VK_ERROR_OUT_OF_DEVICE_MEMORY: return "out of device memory"; + case VK_ERROR_INITIALIZATION_FAILED: return "initialization failed"; + case VK_ERROR_DEVICE_LOST: return "device lost"; + case VK_ERROR_MEMORY_MAP_FAILED: return "memory map failed"; + case VK_ERROR_LAYER_NOT_PRESENT: return "layer not present"; + case VK_ERROR_EXTENSION_NOT_PRESENT: return "extension not present"; + case VK_ERROR_FEATURE_NOT_PRESENT: return "feature not present"; + 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 (); +} + + /////////////////////////////////////////////////////////////////////////////// void error::try_code (VkResult res) @@ -39,29 +96,25 @@ error::try_code (VkResult res) void error::throw_code (VkResult res) { +#define THROW_CODE(C) case C: throw error_code (); switch (res) { - case VK_SUCCESS: throw error_code (); - - // partial successes - case VK_NOT_READY: throw error_code (); - case VK_TIMEOUT: throw error_code (); - case VK_EVENT_SET: throw error_code (); - case VK_EVENT_RESET: throw error_code (); - case VK_INCOMPLETE: throw error_code (); - - // errors - case VK_ERROR_OUT_OF_HOST_MEMORY: throw error_code (); - case VK_ERROR_OUT_OF_DEVICE_MEMORY: throw error_code (); - case VK_ERROR_INITIALIZATION_FAILED: throw error_code (); - case VK_ERROR_DEVICE_LOST: throw error_code (); - case VK_ERROR_MEMORY_MAP_FAILED: throw error_code (); - case VK_ERROR_LAYER_NOT_PRESENT: throw error_code (); - case VK_ERROR_EXTENSION_NOT_PRESENT: throw error_code (); - case VK_ERROR_FEATURE_NOT_PRESENT: throw error_code (); - case VK_ERROR_INCOMPATIBLE_DRIVER: throw error_code (); - case VK_ERROR_TOO_MANY_OBJECTS: throw error_code (); - case VK_ERROR_FORMAT_NOT_SUPPORTED: throw error_code (); + VK_RESULT_MAP (THROW_CODE) } +#undef THROW_CODE unreachable (); } + + +/////////////////////////////////////////////////////////////////////////////// +template +const char* +error_code::what (void) const noexcept +{ + return to_string (res); +} + + +/////////////////////////////////////////////////////////////////////////////// +#define ERROR_CODE(R) template class cruft::vk::error_code; +VK_RESULT_MAP(ERROR_CODE) diff --git a/fwd.hpp b/fwd.hpp index 1e1ad0d..d717492 100644 --- a/fwd.hpp +++ b/fwd.hpp @@ -20,6 +20,9 @@ #include "./vk.hpp" +#include + + namespace cruft::vk { template struct instantiated; template struct enumerated; @@ -45,6 +48,19 @@ namespace cruft::vk { class error; template class error_code; + + #define VK_ENUMERATED_TYPE_MAP(FUNC) \ + MAP(FUNC, \ + physical_device) + + #define VK_INSTANTIATED_TYPE_MAP(FUNC) \ + MAP(FUNC, \ + device, \ + instance) + + #define VK_TYPE_MAP(FUNC) \ + VK_ENUMERATED_TYPE_MAP(FUNC) \ + VK_INSTANTIATED_TYPE_MAP(FUNC) } #endif diff --git a/instance.cpp b/instance.cpp index c52348f..99f790f 100644 --- a/instance.cpp +++ b/instance.cpp @@ -21,6 +21,41 @@ using cruft::vk::instance; /////////////////////////////////////////////////////////////////////////////// +instance::create_info::create_info () +{ + sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; + pNext = nullptr; + flags = 0; + + pApplicationInfo = nullptr; + + enabledLayerCount = 0; + ppEnabledLayerNames = nullptr; + + enabledExtensionCount = 0; + ppEnabledExtensionNames = nullptr; +} + + +//----------------------------------------------------------------------------- instance::instance (const VkInstanceCreateInfo &info): instantiated (&info, nullptr) { ; } + + +/////////////////////////////////////////////////////////////////////////////// +std::set +instance::extensions (void) const +{ + uint32_t expected = 0; + error::try_code (vkEnumerateInstanceExtensionProperties (nullptr, &expected, nullptr)); + + VkExtensionProperties props[expected]; + uint32_t found = expected; + error::try_code (vkEnumerateInstanceExtensionProperties (nullptr, &found, props)); + + std::set ext; + for (const auto &i: props) + ext.insert (i.extensionName); + return ext; +} diff --git a/instance.hpp b/instance.hpp index 64e0b19..272007f 100644 --- a/instance.hpp +++ b/instance.hpp @@ -23,9 +23,18 @@ #include "./vk.hpp" #include "./traits.hpp" +#include +#include + namespace cruft::vk { struct instance : public instantiated { + struct create_info : public VkInstanceCreateInfo { + create_info (); + }; + instance (const VkInstanceCreateInfo &info); + + std::set extensions (void) const; }; } diff --git a/object.cpp b/object.cpp index 3070ef6..e9b219e 100644 --- a/object.cpp +++ b/object.cpp @@ -17,5 +17,77 @@ #include "./object.hpp" +#include "./instance.hpp" + +#include "./physical_device.hpp" + +#include + using cruft::vk::object; using cruft::vk::enumerated; + + +/////////////////////////////////////////////////////////////////////////////// +template +object::object (id_t _id): + m_id (_id) +{ + CHECK_NEQ (m_id, VK_NULL_HANDLE); +} + + +//----------------------------------------------------------------------------- +template +object::object (object &&rhs): + m_id (VK_NULL_HANDLE) +{ + std::swap (m_id, rhs.m_id); +} + + +//----------------------------------------------------------------------------- +template +const typename object::id_t& +object::id (void) const& +{ + return m_id; +} + + +//----------------------------------------------------------------------------- +template +typename object::id_t& +object::id (void) & +{ + return m_id; +} + + +//----------------------------------------------------------------------------- +#define OBJECT(T) template struct cruft::vk::object; +VK_TYPE_MAP (OBJECT) + + +/////////////////////////////////////////////////////////////////////////////// +#define INSTANTIATED(T) template struct cruft::vk::instantiated; +VK_INSTANTIATED_TYPE_MAP (INSTANTIATED) + + +/////////////////////////////////////////////////////////////////////////////// +template +std::vector +cruft::vk::enumerated::find (const instance &inst) { + uint32_t expected = 0; + error::try_code (enum_traits::enumerate (inst.id (), &expected, nullptr)); + + uint32_t found = expected; + typename T::id_t handles[expected]; + error::try_code (enum_traits::enumerate (inst.id (), &found, handles)); + + return std::vector (handles, handles + found); +} + + +//----------------------------------------------------------------------------- +#define ENUMERATED(T) template struct cruft::vk::enumerated; +VK_ENUMERATED_TYPE_MAP (ENUMERATED) diff --git a/object.hpp b/object.hpp index a17a72b..803922e 100644 --- a/object.hpp +++ b/object.hpp @@ -22,6 +22,7 @@ #include "./except.hpp" #include +#include namespace cruft::vk { template @@ -29,8 +30,11 @@ namespace cruft::vk { using id_t = typename id_traits::id_t; object (id_t); + object (object&&); + object (const object&) = delete; - id_t& id (void) const&; + const id_t& id (void) const&; + id_t& id (void) &; private: id_t m_id; @@ -64,7 +68,11 @@ namespace cruft::vk { }; template - struct enumerated : public object { }; + struct enumerated : public object { + using object::object; + + static std::vector find (const instance&); + }; template struct owned : public object { }; diff --git a/physical_device.cpp b/physical_device.cpp index f2524d6..c69c2cc 100644 --- a/physical_device.cpp +++ b/physical_device.cpp @@ -19,4 +19,49 @@ #include "./except.hpp" +using cruft::vk::physical_device; + + /////////////////////////////////////////////////////////////////////////////// +std::set +physical_device::extensions (void) const +{ + uint32_t expected = 0; + error::try_code (vkEnumerateDeviceExtensionProperties (id (), nullptr, &expected, nullptr)); + + VkExtensionProperties props[expected]; + uint32_t found = expected; + error::try_code (vkEnumerateDeviceExtensionProperties (id (), nullptr, &found, props)); + + std::set ext; + for (const auto &i: props) + ext.insert (i.extensionName); + return ext; +} + +/////////////////////////////////////////////////////////////////////////////// +VkPhysicalDeviceProperties +physical_device::properties (void) const +{ + VkPhysicalDeviceProperties props; + vkGetPhysicalDeviceProperties (id (), &props); + return props; +} + + +//----------------------------------------------------------------------------- +VkPhysicalDeviceFeatures +physical_device::features (void) const +{ + VkPhysicalDeviceFeatures feat; + vkGetPhysicalDeviceFeatures (id (), &feat); + return feat; +} + + +/////////////////////////////////////////////////////////////////////////////// +std::string +physical_device::name (void) const +{ + return properties ().deviceName; +} diff --git a/physical_device.hpp b/physical_device.hpp index 95747bd..1a70b7c 100644 --- a/physical_device.hpp +++ b/physical_device.hpp @@ -22,8 +22,19 @@ #include "./vk.hpp" +#include +#include + namespace cruft::vk { struct physical_device : public enumerated { + using enumerated::enumerated; + + std::set extensions (void) const; + + VkPhysicalDeviceProperties properties (void) const; + VkPhysicalDeviceFeatures features (void) const; + + std::string name (void) const; }; } diff --git a/traits.hpp b/traits.hpp index ac10ac2..67975b8 100644 --- a/traits.hpp +++ b/traits.hpp @@ -126,7 +126,14 @@ namespace cruft::vk { template <> struct life_traits { static constexpr auto create = vkCreateBufferView; + }; + + /////////////////////////////////////////////////////////////////////////// + template struct enum_traits { }; + + template <> struct enum_traits { + static constexpr auto enumerate = vkEnumeratePhysicalDevices; }; }