diff --git a/fwd.hpp b/fwd.hpp index 94a5e55..0e37d35 100644 --- a/fwd.hpp +++ b/fwd.hpp @@ -102,7 +102,115 @@ namespace cruft::vk { VK_DESCENDANT_TYPE_MAP(FUNC) \ VK_OWNED_TYPE_MAP(FUNC) - #define VK_NATIVE_TYPE_MAP(FUNC) \ + #define VK_NATIVE_ENUM_MAP(FUNC) \ + MAP0(FUNC, \ + VkImageAspectFlagBits, \ + VkShaderStageFlagBits, \ + VkSystemAllocationScope, \ + VkInternalAllocationType, \ + VkQueueFlagBits, \ + VkStructureType, \ + VkFilter, \ + VkSamplerMipmapMode, \ + VkSamplerAddressMode, \ + VkCompareOp, \ + VkBorderColor, \ + VkIndexType, \ + VkBufferCreateFlagBits, \ + VkBufferUsageFlagBits, \ + VkExternalMemoryHandleTypeFlagBitsKHR, \ + VkPrimitiveTopology, \ + VkIndirectCommandsTokenTypeNVX, \ + VkDisplayPlaneAlphaFlagBitsKHR, \ + VkSurfaceTransformFlagBitsKHR, \ + VkCompositeAlphaFlagBitsKHR, \ + VkImageUsageFlagBits, \ + VkViewportCoordinateSwizzleNV, \ + VkPipelineBindPoint, \ + VkExternalMemoryFeatureFlagBitsNV, \ + VkDebugReportFlagBitsEXT, \ + VkDebugReportObjectTypeEXT, \ + VkCommandBufferResetFlagBits, \ + VkPhysicalDeviceType, \ + VkFenceImportFlagBitsKHR, \ + VkExternalFenceHandleTypeFlagBitsKHR, \ + VkQueryType, \ + VkQueryPipelineStatisticFlagBits, \ + VkExternalSemaphoreHandleTypeFlagBitsKHR, \ + VkImageLayout, \ + VkFormatFeatureFlagBits, \ + VkObjectEntryTypeNVX, \ + VkObjectEntryUsageFlagBitsNVX, \ + VkDescriptorType, \ + VkSparseImageFormatFlagBits, \ + VkComponentSwizzle, \ + VkDescriptorSetLayoutCreateFlagBits, \ + VkIndirectCommandsLayoutUsageFlagBitsNVX, \ + VkAttachmentDescriptionFlagBits, \ + VkSampleCountFlagBits, \ + VkAttachmentLoadOp, \ + VkAttachmentStoreOp, \ + VkImageType, \ + VkImageTiling, \ + VkExternalMemoryFeatureFlagBitsKHR, \ + VkStencilFaceFlagBits, \ + VkStencilOp, \ + VkPolygonMode, \ + VkCullModeFlagBits, \ + VkFrontFace, \ + VkImageCreateFlagBits, \ + VkExternalMemoryHandleTypeFlagBitsNV, \ + VkImageViewType, \ + VkSharingMode, \ + VkDynamicState, \ + VkCommandPoolCreateFlagBits, \ + VkSemaphoreImportFlagBitsKHR, \ + VkPipelineStageFlagBits, \ + VkSwapchainCreateFlagBitsKHR, \ + VkMemoryHeapFlagBits, \ + VkPipelineCreateFlagBits, \ + VkBlendOverlapEXT, \ + VkSurfaceCounterFlagBitsEXT, \ + VkDescriptorUpdateTemplateTypeKHR, \ + VkExternalFenceFeatureFlagBitsKHR, \ + VkQueryResultFlagBits, \ + VkSparseMemoryBindFlagBits, \ + VkValidationCacheHeaderVersionEXT, \ + VkDeviceGroupPresentModeFlagBitsKHX, \ + VkColorSpaceKHR, \ + VkPresentModeKHR, \ + VkCommandPoolResetFlagBits, \ + VkVertexInputRate, \ + VkSubpassDescriptionFlagBits, \ + VkAccessFlagBits, \ + VkDependencyFlagBits, \ + VkExternalSemaphoreFeatureFlagBitsKHR, \ + VkBlendFactor, \ + VkBlendOp, \ + VkColorComponentFlagBits, \ + VkMemoryPropertyFlagBits, \ + VkCommandBufferUsageFlagBits, \ + VkQueryControlFlagBits, \ + VkCommandBufferLevel, \ + VkValidationCheckEXT, \ + VkSubpassContents, \ + VkLogicOp, \ + VkDisplayPowerStateEXT, \ + VkFenceCreateFlagBits, \ + VkDisplayEventTypeEXT, \ + VkDescriptorPoolCreateFlagBits, \ + VkPeerMemoryFeatureFlagBitsKHX, \ + VkCoverageModulationModeNV, \ + VkObjectType, \ + VkMemoryAllocateFlagBitsKHX, \ + VkPipelineCacheHeaderVersion, \ + VkDiscardRectangleModeEXT, \ + VkDeviceEventTypeEXT, \ + VkSamplerReductionModeEXT, \ + VkRasterizationOrderAMD \ + ) + + #define VK_NATIVE_STRUCT_MAP(FUNC) \ MAP0(FUNC, \ VkClearColorValue, \ VkClearValue, \ @@ -379,6 +487,10 @@ namespace cruft::vk { VkValidationCacheCreateInfoEXT, \ VkShaderModuleValidationCacheCreateInfoEXT) + #define VK_NATIVE_TYPE_MAP(FUNC) \ + VK_NATIVE_ENUM_MAP(FUNC) \ + VK_NATIVE_STRUCT_MAP(FUNC) + } #endif diff --git a/object.hpp b/object.hpp index 07e948b..6f941ac 100644 --- a/object.hpp +++ b/object.hpp @@ -190,6 +190,10 @@ namespace cruft::vk { SelfT& operator* ()& noexcept { return m_self; } + const SelfT* + operator-> () const& noexcept + { return &m_self; } + SelfT* operator-> ()& noexcept { return &m_self; } @@ -229,6 +233,65 @@ namespace cruft::vk { owner }; }; + + + /////////////////////////////////////////////////////////////////////////// + template + struct function_wrapper { + using value_type = ReturnT(*)(Args...) noexcept; + + constexpr function_wrapper (value_type _value): m_function {_value} { ; } + constexpr function_wrapper (): m_function { nullptr } { ; } + + + value_type + reset (value_type _value) + { + value_type old = std::move (m_function); + m_function = _value; + return old; + } + + + template + auto + operator () (const owned_ptr &owned, Tail &&...tail) const + { + return dispatch (owned.owner (), owned.get (), std::forward (tail)...); + } + + + template + auto operator () (Tail &&...tail) const + { + return dispatch (std::forward (tail)...); + } + + + private: + template + auto dispatch (Tail &&...tail) const + { + if constexpr (is_values_function_v) + return error::try_values (m_function, std::forward (tail)...); + else if constexpr (is_query_function_v) + return error::try_query (m_function, std::forward (tail)...); + else + return error::try_func (m_function, std::forward (tail)...); + } + + + value_type m_function; + }; + + + #define WRAP_FUNCTION(NAME,FUNC) \ + namespace detail { const function_wrapper __##NAME {FUNC}; } \ + template \ + auto NAME (Args &&...args) \ + { \ + return detail::__##NAME (std::forward (args)... ); \ + }; }; #endif diff --git a/physical_device.cpp b/physical_device.cpp index 9513928..eb951f4 100644 --- a/physical_device.cpp +++ b/physical_device.cpp @@ -58,16 +58,6 @@ physical_device::features (void) const } -//----------------------------------------------------------------------------- -VkSurfaceCapabilitiesKHR -physical_device::surface_capabilities (surface &_surface) const -{ - return error::try_query ( - vkGetPhysicalDeviceSurfaceCapabilitiesKHR, native (), _surface - ); -} - - //----------------------------------------------------------------------------- VkPhysicalDeviceMemoryProperties physical_device::memory_properties (void) const @@ -88,28 +78,6 @@ physical_device::queue_families (void) const } -/////////////////////////////////////////////////////////////////////////////// -std::vector -physical_device::surface_formats (surface &_surface) -{ - return error::try_values ( - vkGetPhysicalDeviceSurfaceFormatsKHR, - native (), _surface - ); -} - - -//----------------------------------------------------------------------------- -std::vector -physical_device::present_modes (surface &_surface) -{ - return error::try_values ( - vkGetPhysicalDeviceSurfacePresentModesKHR, - native (), _surface - ); -} - - /////////////////////////////////////////////////////////////////////////////// std::string physical_device::name (void) const diff --git a/physical_device.hpp b/physical_device.hpp index b9b90ce..8855f77 100644 --- a/physical_device.hpp +++ b/physical_device.hpp @@ -33,14 +33,10 @@ namespace cruft::vk { VkPhysicalDeviceProperties properties (void) const; VkPhysicalDeviceFeatures features (void) const; - VkSurfaceCapabilitiesKHR surface_capabilities (surface&) const; VkPhysicalDeviceMemoryProperties memory_properties (void) const; std::vector queue_families (void) const; - std::vector surface_formats (surface&); - std::vector present_modes (surface&); - std::string name (void) const; }; } diff --git a/surface.cpp b/surface.cpp index 4851431..030ac53 100644 --- a/surface.cpp +++ b/surface.cpp @@ -18,6 +18,6 @@ #include "./surface.hpp" #include "./instance.hpp" +#include "./physical_device.hpp" using cruft::vk::surface; - diff --git a/surface.hpp b/surface.hpp index 6419ae0..d5b7d7e 100644 --- a/surface.hpp +++ b/surface.hpp @@ -24,9 +24,16 @@ namespace cruft::vk { + /////////////////////////////////////////////////////////////////////////// struct surface : public owned { using owned::owned; }; + + + /////////////////////////////////////////////////////////////////////////// + WRAP_FUNCTION (capabilities, vkGetPhysicalDeviceSurfaceCapabilitiesKHR); + WRAP_FUNCTION (formats, vkGetPhysicalDeviceSurfaceFormatsKHR); + WRAP_FUNCTION (present_modes, vkGetPhysicalDeviceSurfacePresentModesKHR); }; #endif diff --git a/swapchain.hpp b/swapchain.hpp index 8d78611..f679171 100644 --- a/swapchain.hpp +++ b/swapchain.hpp @@ -24,6 +24,9 @@ namespace cruft::vk { struct swapchain : public owned { using owned::owned; }; + + + function_wrapper images; }; #endif diff --git a/tools/hello.cpp b/tools/hello.cpp index 7b0eec8..d52f550 100644 --- a/tools/hello.cpp +++ b/tools/hello.cpp @@ -19,11 +19,14 @@ #include #include +#include #include #include #include #include +#include +#include #include #include @@ -69,27 +72,237 @@ static constexpr vertex_t VERTICES[] = { }; +namespace glfw { + namespace detail { + constexpr const char* error_string (int code) noexcept; + } + + + struct error : public std::exception { + public: + static void try_code (int code); + static void throw_code [[noreturn]] (int code); + static void throw_code [[noreturn]] (void); + + static void push (int code) + { + s_current = code; + } + + private: + static std::atomic s_current; + }; + + + template + struct error_code : public error { + virtual ~error_code () = default; + static constexpr const char *message = detail::error_string (CodeV); + }; +} + + +std::atomic glfw::error::s_current; + + +void +glfw_error_callback (int code ,const char *description) +{ + LOG_WARN ("glfw: %s", description); + glfw::error::push (code); +} + + +namespace glfw { + class instance { + public: + instance () + { + if (std::lock_guard l {s_count.guard}; !s_count.value++) + glfwInit (); + + glfwSetErrorCallback (glfw_error_callback); + + static constexpr struct { + int tag; + int val; + } HINTS[] { + { GLFW_CLIENT_API, GLFW_NO_API }, + { GLFW_RESIZABLE, GLFW_FALSE }, + }; + + for (const auto [tag,val]: HINTS) + glfwWindowHint (tag, val); + } + + + std::vector + required_extensions (void) const + { + unsigned count; + auto values = glfwGetRequiredInstanceExtensions (&count); + + return { + values + 0, + values + count + }; + } + + + void poll_events (void) + { + glfwPollEvents (); + } + + ~instance () + { + if (std::lock_guard l {s_count.guard}; !--s_count.value) + glfwTerminate (); + } + + + private: + // TODO: value doesnt' need to be atomic, but it's not performance + // critical, and I'm not particularly familiar with c++ memory + // ordering primitives. so it's probably safer this way for now. + static struct count_t { + std::mutex guard; + std::atomic value; + } s_count; + }; + + + class window { + public: + using native_t = GLFWwindow*; + + window (util::extent2i resolution, const char *name): + m_native (glfwCreateWindow (resolution.w, resolution.h, name, nullptr, nullptr)) + { + if (!m_native) + error::throw_code (); + } + + native_t native (void) const { return m_native; } + + bool + should_close (void) const + { + return glfwWindowShouldClose (native ()); + } + + + private: + native_t m_native; + }; +}; + + + +/////////////////////////////////////////////////////////////////////////////// +template +struct to_format; + + +#define TO_FORMAT(S,T,VALUE) \ +template