summaryrefslogtreecommitdiffstats
path: root/src/libixion/vulkan_obj.hpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libixion/vulkan_obj.hpp')
-rw-r--r--src/libixion/vulkan_obj.hpp319
1 files changed, 319 insertions, 0 deletions
diff --git a/src/libixion/vulkan_obj.hpp b/src/libixion/vulkan_obj.hpp
new file mode 100644
index 0000000..498efa8
--- /dev/null
+++ b/src/libixion/vulkan_obj.hpp
@@ -0,0 +1,319 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ */
+
+#ifndef INCLUDED_IXION_VULKAN_OBJ_HPP
+#define INCLUDED_IXION_VULKAN_OBJ_HPP
+
+#include <vulkan/vulkan.h>
+#include <memory>
+#include <limits>
+
+namespace ixion { namespace draft {
+
+template<typename T, typename U = void>
+struct null_value;
+
+template<typename T>
+struct null_value<T, typename std::enable_if<std::is_pointer<T>::value>::type>
+{
+ static constexpr std::nullptr_t value = nullptr;
+};
+
+template<typename T>
+struct null_value<T, typename std::enable_if<std::is_integral<T>::value>::type>
+{
+ static constexpr T value = 0;
+};
+
+struct runtime_context
+{
+ uint32_t input_buffer_size = 0;
+};
+
+class vk_buffer;
+class vk_command_buffer;
+class vk_command_pool;
+class vk_descriptor_set;
+class vk_descriptor_set_layout;
+class vk_fence;
+class vk_pipeline;
+class vk_pipeline_layout;
+
+class vk_instance
+{
+ VkInstance m_instance = null_value<VkInstance>::value;
+ VkDebugUtilsMessengerEXT m_debug_messenger = null_value<VkDebugUtilsMessengerEXT>::value;
+
+public:
+ vk_instance();
+ ~vk_instance();
+
+ VkInstance& get();
+};
+
+class vk_queue
+{
+ VkQueue m_queue;
+
+public:
+ vk_queue(VkQueue queue);
+ ~vk_queue();
+
+ void submit(vk_command_buffer& cmd, vk_fence& fence, VkPipelineStageFlags dst_stages = 0);
+
+ void wait_idle();
+};
+
+class vk_device
+{
+ friend class vk_command_pool;
+ friend class vk_buffer;
+
+ static constexpr uint32_t QUEUE_FAMILY_NOT_SET = std::numeric_limits<uint32_t>::max();
+
+ VkPhysicalDevice m_physical_device = null_value<VkPhysicalDevice>::value;
+ VkPhysicalDeviceProperties m_physical_device_props;
+ VkDevice m_device = null_value<VkDevice>::value;
+ uint32_t m_queue_family_index = QUEUE_FAMILY_NOT_SET;
+ VkQueue m_queue = null_value<VkQueue>::value;
+
+ uint32_t get_queue_family_index() const
+ {
+ return m_queue_family_index;
+ }
+
+public:
+ vk_device(vk_instance& instance);
+ ~vk_device();
+
+ VkDevice& get();
+ const VkDevice& get() const;
+
+ VkPhysicalDevice get_physical_device();
+
+ const VkPhysicalDeviceLimits& get_physical_device_limits() const;
+
+ vk_queue get_queue();
+};
+
+class vk_command_pool
+{
+ friend class vk_command_buffer;
+
+ VkDevice m_device = null_value<VkDevice>::value;
+ VkCommandPool m_cmd_pool = null_value<VkCommandPool>::value;
+
+ VkDevice& get_device();
+ VkCommandPool& get();
+
+public:
+ vk_command_pool(vk_device& device);
+ ~vk_command_pool();
+
+ vk_command_buffer create_command_buffer();
+};
+
+class vk_command_buffer
+{
+ friend class vk_command_pool;
+
+ vk_command_pool& m_cmd_pool;
+ VkCommandBuffer m_cmd_buffer = null_value<VkCommandBuffer>::value;
+
+ vk_command_buffer(vk_command_pool& cmd_pool);
+
+public:
+ ~vk_command_buffer();
+
+ VkCommandBuffer& get();
+
+ void begin();
+ void end();
+
+ void copy_buffer(vk_buffer& src, vk_buffer& dst, VkDeviceSize size);
+
+ void buffer_memory_barrier(
+ const vk_buffer& buffer, VkAccessFlags src_access, VkAccessFlags dst_access,
+ VkPipelineStageFlagBits src_stage, VkPipelineStageFlagBits dst_stage);
+
+ void bind_pipeline(const vk_pipeline& pipeline, VkPipelineBindPoint bind_point);
+
+ void bind_descriptor_set(
+ VkPipelineBindPoint bind_point, const vk_pipeline_layout& pl_layout,
+ const vk_descriptor_set& desc_set);
+
+ void dispatch(uint32_t gc_x, uint32_t gc_y, uint32_t gc_z);
+};
+
+class vk_buffer
+{
+ vk_device& m_device;
+ VkBuffer m_buffer = null_value<VkBuffer>::value;
+ VkDeviceMemory m_memory = null_value<VkDeviceMemory>::value;
+
+ struct mem_type
+ {
+ uint32_t index;
+ VkDeviceSize size;
+ };
+
+ /**
+ * Find a suitable device memory type that can be used to store data for
+ * the buffer.
+ *
+ * @param mem_props desired memory properties.
+ *
+ * @return mem_type memory type as an index into the list of device memory
+ * types, and the memory size as required by the buffer.
+ */
+ mem_type find_memory_type(VkMemoryPropertyFlags mem_props) const;
+
+public:
+ vk_buffer(vk_device& device, VkDeviceSize size, VkBufferUsageFlags usage, VkMemoryPropertyFlags mem_props);
+ ~vk_buffer();
+
+ VkBuffer& get();
+ const VkBuffer& get() const;
+
+ void write_to_memory(void* data, VkDeviceSize size);
+
+ void read_from_memory(void* data, VkDeviceSize size);
+};
+
+class vk_fence
+{
+ vk_device& m_device;
+ VkFence m_fence = null_value<VkFence>::value;
+
+public:
+ vk_fence(vk_device& device, VkFenceCreateFlags flags);
+ ~vk_fence();
+
+ VkFence& get();
+
+ void wait();
+ void reset();
+};
+
+class vk_descriptor_pool
+{
+ vk_device& m_device;
+ VkDescriptorPool m_pool = null_value<VkDescriptorPool>::value;
+
+public:
+ vk_descriptor_pool(vk_device& device, uint32_t max_sets, std::initializer_list<VkDescriptorPoolSize> sizes);
+ ~vk_descriptor_pool();
+
+ vk_descriptor_set allocate(const vk_descriptor_set_layout& ds_layout);
+};
+
+class vk_descriptor_set_layout
+{
+ vk_device& m_device;
+ VkDescriptorSetLayout m_ds_layout = null_value<VkDescriptorSetLayout>::value;
+
+public:
+ vk_descriptor_set_layout(vk_device& device, std::initializer_list<VkDescriptorSetLayoutBinding> bindings);
+ ~vk_descriptor_set_layout();
+
+ VkDescriptorSetLayout& get();
+ const VkDescriptorSetLayout& get() const;
+};
+
+/**
+ * Descriptor set contains a collection of descriptors. Think of a
+ * descriptor as a handle into a resource, which can be a buffer or an
+ * image.
+ *
+ * @see https://vkguide.dev/docs/chapter-4/descriptors/
+ *
+ */
+class vk_descriptor_set
+{
+ friend class vk_descriptor_pool;
+ VkDescriptorSet m_set = null_value<VkDescriptorSet>::value;
+
+ vk_descriptor_set(VkDescriptorSet ds);
+public:
+ ~vk_descriptor_set();
+
+ VkDescriptorSet& get();
+ const VkDescriptorSet& get() const;
+
+ /**
+ * Update the descriptor set with the content of the device local buffer.
+ *
+ * @param device logical device
+ * @param binding binding position
+ * @param type descriptor type.
+ * @param buffer device local buffer to get the content from.
+ */
+ void update(const vk_device& device, uint32_t binding, VkDescriptorType type, const vk_buffer& buffer);
+};
+
+class vk_pipeline_layout
+{
+ vk_device& m_device;
+ VkPipelineLayout m_layout = null_value<VkPipelineLayout>::value;
+
+public:
+ vk_pipeline_layout(vk_device& device, vk_descriptor_set_layout& ds_layout);
+ ~vk_pipeline_layout();
+
+ VkPipelineLayout& get();
+ const VkPipelineLayout& get() const;
+};
+
+class vk_pipeline_cache
+{
+ vk_device& m_device;
+ VkPipelineCache m_cache = null_value<VkPipelineCache>::value;
+
+public:
+ vk_pipeline_cache(vk_device& device);
+ ~vk_pipeline_cache();
+
+ VkPipelineCache& get();
+ const VkPipelineCache& get() const;
+};
+
+class vk_shader_module
+{
+ vk_device& m_device;
+ VkShaderModule m_module = null_value<VkShaderModule>::value;
+
+public:
+ enum class module_type { fibonacci };
+
+ vk_shader_module(vk_device& device, module_type mt);
+ ~vk_shader_module();
+
+ VkShaderModule& get();
+ const VkShaderModule& get() const;
+};
+
+class vk_pipeline
+{
+ vk_device& m_device;
+ VkPipeline m_pipeline = null_value<VkPipeline>::value;
+
+public:
+ vk_pipeline(
+ const runtime_context& cxt, vk_device& device, vk_pipeline_layout& pl_layout,
+ vk_pipeline_cache& pl_cache, vk_shader_module& shader);
+
+ ~vk_pipeline();
+
+ VkPipeline& get();
+ const VkPipeline& get() const;
+};
+
+}}
+
+#endif
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */