This commit is contained in:
		
							parent
							
								
									a9e27d6935
								
							
						
					
					
						commit
						e71aeddbcf
					
				
					 17 changed files with 493 additions and 31 deletions
				
			
		|  | @ -8,15 +8,17 @@ add_library_module( | ||||||
|     backend/vk/context/instance.cpp |     backend/vk/context/instance.cpp | ||||||
|     backend/vk/context/surface.cpp |     backend/vk/context/surface.cpp | ||||||
|     backend/vk/context/swapchain.cpp |     backend/vk/context/swapchain.cpp | ||||||
|  |     backend/vk/data/buffer.cpp | ||||||
|     backend/vk/renderer/pass.cpp |     backend/vk/renderer/pass.cpp | ||||||
|     backend/vk/renderer/renderer.cpp |     backend/vk/renderer/renderer.cpp | ||||||
|     # Vulkan - frontend |     # frontend | ||||||
|     frontend/messenger.cpp |     frontend/messenger.cpp | ||||||
|     frontend/context/device.cpp |     frontend/context/device.cpp | ||||||
|     frontend/context/gpu.cpp |     frontend/context/gpu.cpp | ||||||
|     frontend/context/instance.cpp |     frontend/context/instance.cpp | ||||||
|     frontend/context/surface.cpp |     frontend/context/surface.cpp | ||||||
|     frontend/context/swapchain.cpp |     frontend/context/swapchain.cpp | ||||||
|  |     frontend/data/buffer.cpp | ||||||
|     frontend/renderer/renderer.cpp |     frontend/renderer/renderer.cpp | ||||||
|     frontend/renderer/pass.cpp) |     frontend/renderer/pass.cpp) | ||||||
| 
 | 
 | ||||||
|  | @ -34,11 +36,10 @@ add_test_module( | ||||||
|     frontend/context/surface.test.cpp |     frontend/context/surface.test.cpp | ||||||
|     frontend/context/device.test.cpp |     frontend/context/device.test.cpp | ||||||
|     frontend/context/swapchain.test.cpp |     frontend/context/swapchain.test.cpp | ||||||
|  |     frontend/data/buffer.test.cpp | ||||||
|     frontend/renderer/pass.test.cpp |     frontend/renderer/pass.test.cpp | ||||||
|     frontend/renderer/renderer.test.cpp |     frontend/renderer/renderer.test.cpp | ||||||
|     # backend specific tests -- vk |     # backend specific tests -- vk | ||||||
|     backend/vk/context/instance.test.cpp |     backend/vk/context/instance.test.cpp) | ||||||
|     # backend specific tests -- dx backend specific tests -- mt |  | ||||||
| ) |  | ||||||
| 
 | 
 | ||||||
| target_link_libraries(renderer_tests PRIVATE surface pthread) | target_link_libraries(renderer_tests PRIVATE surface pthread) | ||||||
|  |  | ||||||
|  | @ -207,6 +207,31 @@ void Device::wait_for_fences(std::span<VkFence> fences) const | ||||||
| 	return images; | 	return images; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | [[nodiscard]] auto Device::get_memory_requirements(VkBuffer buffer) const -> VkMemoryRequirements | ||||||
|  | { | ||||||
|  | 	auto requirements = VkMemoryRequirements {}; | ||||||
|  | 	vk_get_buffer_memory_requirements(m_device, buffer, &requirements); | ||||||
|  | 	return requirements; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Device::bind_memory(VkBuffer buffer, VkDeviceMemory memory, size_t offset /* = 0u */) const | ||||||
|  | { | ||||||
|  | 	vkc(vk_bind_buffer_memory(m_device, buffer, memory, offset)); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | [[nodiscard]] auto Device::map_memory(VkDeviceMemory memory, size_t size, size_t offset) const | ||||||
|  |     -> std::span<std::byte> | ||||||
|  | { | ||||||
|  | 	void *data = {}; | ||||||
|  | 	vkc(vk_map_memory(m_device, memory, offset, size, {}, &data)); | ||||||
|  | 	return { std::bit_cast<std::byte *>(data), size }; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Device::unmap_memory(VkDeviceMemory memory) | ||||||
|  | { | ||||||
|  | 	vk_unmap_memory(m_device, memory); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| [[nodiscard]] auto Device::create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR | [[nodiscard]] auto Device::create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR | ||||||
| { | { | ||||||
| 	auto *swapchain = VkSwapchainKHR {}; | 	auto *swapchain = VkSwapchainKHR {}; | ||||||
|  | @ -299,6 +324,13 @@ void Device::wait_for_fences(std::span<VkFence> fences) const | ||||||
| 	return fences; | 	return fences; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | [[nodiscard]] auto Device::create_buffer(VkBufferCreateInfo info) const -> VkBuffer | ||||||
|  | { | ||||||
|  | 	auto *buffer = VkBuffer {}; | ||||||
|  | 	vkc(vk_create_buffer(m_device, &info, nullptr, &buffer)); | ||||||
|  | 	return buffer; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| [[nodiscard]] auto Device::allocate_command_buffers(VkCommandBufferAllocateInfo info) const | [[nodiscard]] auto Device::allocate_command_buffers(VkCommandBufferAllocateInfo info) const | ||||||
|     -> std::vector<VkCommandBuffer> |     -> std::vector<VkCommandBuffer> | ||||||
| { | { | ||||||
|  | @ -307,6 +339,18 @@ void Device::wait_for_fences(std::span<VkFence> fences) const | ||||||
| 	return command_buffers; | 	return command_buffers; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | [[nodiscard]] auto Device::allocate_memory(VkMemoryAllocateInfo info) const -> VkDeviceMemory | ||||||
|  | { | ||||||
|  | 	auto *memory = VkDeviceMemory {}; | ||||||
|  | 	vkc(vk_allocate_memory(m_device, &info, nullptr, &memory)); | ||||||
|  | 	return memory; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Device::free_memory(VkDeviceMemory memory) const | ||||||
|  | { | ||||||
|  | 	vk_free_memory(m_device, memory, nullptr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| void Device::destroy_swapchain(VkSwapchainKHR swapchain) const | void Device::destroy_swapchain(VkSwapchainKHR swapchain) const | ||||||
| { | { | ||||||
| 	vk_destroy_swapchain_khr(m_device, swapchain, m_allocator); | 	vk_destroy_swapchain_khr(m_device, swapchain, m_allocator); | ||||||
|  | @ -389,4 +433,9 @@ void Device::destroy_fences(std::span<VkFence> fences) const | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | void Device::destroy_buffer(VkBuffer buffer) const | ||||||
|  | { | ||||||
|  | 	vk_destroy_buffer(m_device, buffer, nullptr); | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace lt::renderer::vk
 | } // namespace lt::renderer::vk
 | ||||||
|  |  | ||||||
|  | @ -96,6 +96,16 @@ public: | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] auto get_swapchain_images(VkSwapchainKHR swapchain) const -> std::vector<VkImage>; | 	[[nodiscard]] auto get_swapchain_images(VkSwapchainKHR swapchain) const -> std::vector<VkImage>; | ||||||
| 
 | 
 | ||||||
|  | 	[[nodiscard]] auto get_memory_requirements(VkBuffer buffer) const -> VkMemoryRequirements; | ||||||
|  | 
 | ||||||
|  | 	/** binders / mappers  */ | ||||||
|  | 	void bind_memory(VkBuffer buffer, VkDeviceMemory memory, size_t offset = 0u) const; | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto map_memory(VkDeviceMemory memory, size_t size, size_t offset) const | ||||||
|  | 	    -> std::span<std::byte>; | ||||||
|  | 
 | ||||||
|  | 	void unmap_memory(VkDeviceMemory memory); | ||||||
|  | 
 | ||||||
| 	/** create functions */ | 	/** create functions */ | ||||||
| 	[[nodiscard]] auto create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR; | 	[[nodiscard]] auto create_swapchain(VkSwapchainCreateInfoKHR info) const -> VkSwapchainKHR; | ||||||
| 
 | 
 | ||||||
|  | @ -120,10 +130,17 @@ public: | ||||||
| 	[[nodiscard]] auto create_fences(VkFenceCreateInfo info, uint32_t count) const | 	[[nodiscard]] auto create_fences(VkFenceCreateInfo info, uint32_t count) const | ||||||
| 	    -> std::vector<VkFence>; | 	    -> std::vector<VkFence>; | ||||||
| 
 | 
 | ||||||
|  | 	[[nodiscard]] auto create_buffer(VkBufferCreateInfo info) const -> VkBuffer; | ||||||
|  | 
 | ||||||
| 	/** allocation functions */ | 	/** allocation functions */ | ||||||
|  | 	[[nodiscard]] auto allocate_memory(VkMemoryAllocateInfo info) const -> VkDeviceMemory; | ||||||
|  | 
 | ||||||
| 	[[nodiscard]] auto allocate_command_buffers(VkCommandBufferAllocateInfo info) const | 	[[nodiscard]] auto allocate_command_buffers(VkCommandBufferAllocateInfo info) const | ||||||
| 	    -> std::vector<VkCommandBuffer>; | 	    -> std::vector<VkCommandBuffer>; | ||||||
| 
 | 
 | ||||||
|  | 	/** de-allocation functions */ | ||||||
|  | 	void free_memory(VkDeviceMemory memory) const; | ||||||
|  | 
 | ||||||
| 	/** destroy functions */ | 	/** destroy functions */ | ||||||
| 	void destroy_swapchain(VkSwapchainKHR swapchain) const; | 	void destroy_swapchain(VkSwapchainKHR swapchain) const; | ||||||
| 
 | 
 | ||||||
|  | @ -153,6 +170,8 @@ public: | ||||||
| 
 | 
 | ||||||
| 	void destroy_fences(std::span<VkFence> fences) const; | 	void destroy_fences(std::span<VkFence> fences) const; | ||||||
| 
 | 
 | ||||||
|  | 	void destroy_buffer(VkBuffer buffer) const; | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
| 	template<typename T> | 	template<typename T> | ||||||
| 	static auto get_object_type(const T &object) -> VkObjectType | 	static auto get_object_type(const T &object) -> VkObjectType | ||||||
|  |  | ||||||
|  | @ -67,5 +67,11 @@ Gpu::Gpu(IInstance *instance) | ||||||
| 	return formats; | 	return formats; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | [[nodiscard]] auto Gpu::get_memory_properties() const -> VkPhysicalDeviceMemoryProperties | ||||||
|  | { | ||||||
|  | 	auto memory_properties = VkPhysicalDeviceMemoryProperties {}; | ||||||
|  | 	vk_get_physical_device_memory_properties(m_gpu, &memory_properties); | ||||||
|  | 	return memory_properties; | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| } // namespace lt::renderer::vk
 | } // namespace lt::renderer::vk
 | ||||||
|  |  | ||||||
|  | @ -30,6 +30,8 @@ public: | ||||||
| 	[[nodiscard]] auto get_surface_formats(VkSurfaceKHR surface) const | 	[[nodiscard]] auto get_surface_formats(VkSurfaceKHR surface) const | ||||||
| 	    -> std::vector<VkSurfaceFormatKHR>; | 	    -> std::vector<VkSurfaceFormatKHR>; | ||||||
| 
 | 
 | ||||||
|  | 	[[nodiscard]] auto get_memory_properties() const -> VkPhysicalDeviceMemoryProperties; | ||||||
|  | 
 | ||||||
| private: | private: | ||||||
| 	memory::NullOnMove<VkPhysicalDevice> m_gpu = VK_NULL_HANDLE; | 	memory::NullOnMove<VkPhysicalDevice> m_gpu = VK_NULL_HANDLE; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -31,6 +31,7 @@ PFN_vkGetDeviceProcAddr vk_get_device_proc_address {}; | ||||||
| PFN_vkDestroyDevice vk_destroy_device {}; | PFN_vkDestroyDevice vk_destroy_device {}; | ||||||
| PFN_vkGetPhysicalDeviceFeatures vk_get_physical_device_features {}; | PFN_vkGetPhysicalDeviceFeatures vk_get_physical_device_features {}; | ||||||
| PFN_vkEnumerateDeviceExtensionProperties vk_enumerate_device_extension_properties {}; | PFN_vkEnumerateDeviceExtensionProperties vk_enumerate_device_extension_properties {}; | ||||||
|  | PFN_vkGetPhysicalDeviceMemoryProperties vk_get_physical_device_memory_properties {}; | ||||||
| 
 | 
 | ||||||
| // extension instance functions
 | // extension instance functions
 | ||||||
| PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label {}; | PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label {}; | ||||||
|  | @ -87,6 +88,16 @@ PFN_vkCmdDraw vk_cmd_draw {}; | ||||||
| PFN_vkCmdSetViewport vk_cmd_set_viewport {}; | PFN_vkCmdSetViewport vk_cmd_set_viewport {}; | ||||||
| PFN_vkCmdSetScissor vk_cmd_set_scissors {}; | PFN_vkCmdSetScissor vk_cmd_set_scissors {}; | ||||||
| 
 | 
 | ||||||
|  | PFN_vkCreateBuffer vk_create_buffer {}; | ||||||
|  | PFN_vkDestroyBuffer vk_destroy_buffer {}; | ||||||
|  | PFN_vkGetBufferMemoryRequirements vk_get_buffer_memory_requirements {}; | ||||||
|  | PFN_vkAllocateMemory vk_allocate_memory {}; | ||||||
|  | PFN_vkBindBufferMemory vk_bind_buffer_memory {}; | ||||||
|  | PFN_vkMapMemory vk_map_memory {}; | ||||||
|  | PFN_vkUnmapMemory vk_unmap_memory {}; | ||||||
|  | PFN_vkFreeMemory vk_free_memory {}; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| PFN_vkResetCommandBuffer vk_reset_command_buffer {}; | PFN_vkResetCommandBuffer vk_reset_command_buffer {}; | ||||||
| 
 | 
 | ||||||
| PFN_vkGetPhysicalDeviceSurfaceSupportKHR vk_get_physical_device_surface_support {}; | PFN_vkGetPhysicalDeviceSurfaceSupportKHR vk_get_physical_device_surface_support {}; | ||||||
|  | @ -298,6 +309,7 @@ void Instance::load_instance_functions() | ||||||
| 	load_fn(vk_destroy_device, "vkDestroyDevice"); | 	load_fn(vk_destroy_device, "vkDestroyDevice"); | ||||||
| 	load_fn(vk_get_physical_device_features, "vkGetPhysicalDeviceFeatures"); | 	load_fn(vk_get_physical_device_features, "vkGetPhysicalDeviceFeatures"); | ||||||
| 	load_fn(vk_enumerate_device_extension_properties, "vkEnumerateDeviceExtensionProperties"); | 	load_fn(vk_enumerate_device_extension_properties, "vkEnumerateDeviceExtensionProperties"); | ||||||
|  | 	load_fn(vk_get_physical_device_memory_properties, "vkGetPhysicalDeviceMemoryProperties"); | ||||||
| 
 | 
 | ||||||
| 	load_fn(vk_cmd_begin_debug_label, "vkCmdBeginDebugUtilsLabelEXT"); | 	load_fn(vk_cmd_begin_debug_label, "vkCmdBeginDebugUtilsLabelEXT"); | ||||||
| 	load_fn(vk_cmd_end_debug_label, "vkCmdEndDebugUtilsLabelEXT"); | 	load_fn(vk_cmd_end_debug_label, "vkCmdEndDebugUtilsLabelEXT"); | ||||||
|  | @ -370,6 +382,14 @@ void Instance::load_device_functions_impl(VkDevice device) | ||||||
| 	load_fn(vk_cmd_draw, "vkCmdDraw"); | 	load_fn(vk_cmd_draw, "vkCmdDraw"); | ||||||
| 	load_fn(vk_cmd_set_viewport, "vkCmdSetViewport"); | 	load_fn(vk_cmd_set_viewport, "vkCmdSetViewport"); | ||||||
| 	load_fn(vk_cmd_set_scissors, "vkCmdSetScissor"); | 	load_fn(vk_cmd_set_scissors, "vkCmdSetScissor"); | ||||||
|  | 	load_fn(vk_create_buffer, "vkCreateBuffer"); | ||||||
|  | 	load_fn(vk_destroy_buffer, "vkDestroyBuffer"); | ||||||
|  | 	load_fn(vk_allocate_memory, "vkAllocateMemory"); | ||||||
|  | 	load_fn(vk_bind_buffer_memory, "vkBindBufferMemory"); | ||||||
|  | 	load_fn(vk_map_memory, "vkMapMemory"); | ||||||
|  | 	load_fn(vk_unmap_memory, "vkUnmapMemory"); | ||||||
|  | 	load_fn(vk_free_memory, "vkFreeMemory"); | ||||||
|  | 	load_fn(vk_get_buffer_memory_requirements, "vkGetBufferMemoryRequirements"); | ||||||
| 	load_fn(vk_reset_command_buffer, "vkResetCommandBuffer"); | 	load_fn(vk_reset_command_buffer, "vkResetCommandBuffer"); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										72
									
								
								modules/renderer/private/backend/vk/data/buffer.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								modules/renderer/private/backend/vk/data/buffer.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,72 @@ | ||||||
|  | #include <renderer/backend/vk/context/device.hpp> | ||||||
|  | #include <renderer/backend/vk/context/gpu.hpp> | ||||||
|  | #include <renderer/backend/vk/data/buffer.hpp> | ||||||
|  | 
 | ||||||
|  | namespace lt::renderer::vk { | ||||||
|  | 
 | ||||||
|  | Buffer::Buffer(IDevice *device, IGpu *gpu, const CreateInfo &info) | ||||||
|  |     : m_device(static_cast<Device *>(device)) | ||||||
|  |     , m_gpu(static_cast<Gpu *>(gpu)) | ||||||
|  |     , m_buffer( | ||||||
|  |           m_device, | ||||||
|  |           VkBufferCreateInfo { | ||||||
|  |               .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | ||||||
|  |               .size = info.size, | ||||||
|  |               .usage = to_native_usage_flags(info.usage), | ||||||
|  |               .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | ||||||
|  |           } | ||||||
|  |       ) | ||||||
|  |     , m_memory(m_device, m_buffer, allocation_info_from_memory_requirements()) | ||||||
|  |     , m_size(info.size) | ||||||
|  | { | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | [[nodiscard]] auto Buffer::map() -> std::span<std::byte> /* override */ | ||||||
|  | { | ||||||
|  | 	return m_device->map_memory(m_memory, m_size, 0ul); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | void Buffer::unmap() /* override */ | ||||||
|  | { | ||||||
|  | 	m_device->unmap_memory(m_memory); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | [[nodiscard]] auto Buffer::to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags | ||||||
|  | { | ||||||
|  | 	switch (usage) | ||||||
|  | 	{ | ||||||
|  | 	case Usage::vertex: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT; | ||||||
|  | 	case Usage::index: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	std::unreachable(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | [[nodiscard]] auto Buffer::allocation_info_from_memory_requirements() const -> VkMemoryAllocateInfo | ||||||
|  | { | ||||||
|  | 	const auto requirements = m_device->get_memory_requirements(m_buffer); | ||||||
|  | 	auto memory_properties = m_gpu->get_memory_properties(); | ||||||
|  | 
 | ||||||
|  | 	const auto required_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | ||||||
|  | 	                                 | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; | ||||||
|  | 	auto type = 0u; | ||||||
|  | 	for (auto idx = 0; idx < memory_properties.memoryTypeCount; ++idx) | ||||||
|  | 	{ | ||||||
|  | 		if ((requirements.memoryTypeBits & (1 << idx)) | ||||||
|  | 		    && ((memory_properties.memoryTypes[idx].propertyFlags & required_properties) | ||||||
|  | 		        == required_properties)) | ||||||
|  | 
 | ||||||
|  | 		{ | ||||||
|  | 			type = idx; | ||||||
|  | 			break; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return VkMemoryAllocateInfo { | ||||||
|  | 		.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, | ||||||
|  | 		.allocationSize = requirements.size, | ||||||
|  | 		.memoryTypeIndex = type, | ||||||
|  | 	}; | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace lt::renderer::vk
 | ||||||
							
								
								
									
										39
									
								
								modules/renderer/private/backend/vk/data/buffer.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								modules/renderer/private/backend/vk/data/buffer.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,39 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <renderer/backend/vk/raii/raii.hpp> | ||||||
|  | #include <renderer/frontend/data/buffer.hpp> | ||||||
|  | 
 | ||||||
|  | namespace lt::renderer::vk { | ||||||
|  | 
 | ||||||
|  | class Buffer: public IBuffer | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	Buffer(class IDevice *device, class IGpu *gpu, const CreateInfo &info); | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto map() -> std::span<std::byte> override; | ||||||
|  | 
 | ||||||
|  | 	void unmap() override; | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto get_size() const -> size_t override | ||||||
|  | 	{ | ||||||
|  | 		return m_size; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	[[nodiscard]] auto to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags; | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto allocation_info_from_memory_requirements() const -> VkMemoryAllocateInfo; | ||||||
|  | 
 | ||||||
|  | 	Device *m_device {}; | ||||||
|  | 
 | ||||||
|  | 	Gpu *m_gpu {}; | ||||||
|  | 
 | ||||||
|  | 	raii::Buffer m_buffer; | ||||||
|  | 
 | ||||||
|  | 	raii::Memory m_memory; | ||||||
|  | 
 | ||||||
|  | 	// TODO(Light): should this reflect the allocation size instead?
 | ||||||
|  | 	size_t m_size {}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace lt::renderer::vk
 | ||||||
|  | @ -1,10 +1,11 @@ | ||||||
| #include <memory/pointer_types/null_on_move.hpp> | #include <memory/pointer_types/null_on_move.hpp> | ||||||
|  | #include <renderer/backend/vk/context/device.hpp> | ||||||
| #include <renderer/backend/vk/context/instance.hpp> | #include <renderer/backend/vk/context/instance.hpp> | ||||||
| #include <renderer/backend/vk/vulkan.hpp> | #include <renderer/backend/vk/vulkan.hpp> | ||||||
| 
 | 
 | ||||||
| namespace lt::renderer::vk::raii { |  | ||||||
| 
 | 
 | ||||||
| // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
 | namespace lt::renderer::vk::raii { // NOLINTBEGIN(cppcoreguidelines-special-member-functions)
 | ||||||
|  | 
 | ||||||
| class DebugMessenger | class DebugMessenger | ||||||
| { | { | ||||||
| public: | public: | ||||||
|  | @ -16,13 +17,11 @@ public: | ||||||
| 
 | 
 | ||||||
| 	~DebugMessenger() | 	~DebugMessenger() | ||||||
| 	{ | 	{ | ||||||
| 		if (!m_instance) | 		if (m_instance) | ||||||
| 		{ | 		{ | ||||||
| 			return; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 			m_instance->destroy_messenger(m_object); | 			m_instance->destroy_messenger(m_object); | ||||||
| 		} | 		} | ||||||
|  | 	} | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
| 	memory::NullOnMove<Instance *> m_instance {}; | 	memory::NullOnMove<Instance *> m_instance {}; | ||||||
|  | @ -30,4 +29,74 @@ private: | ||||||
| 	VkDebugUtilsMessengerEXT m_object; | 	VkDebugUtilsMessengerEXT m_object; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | // NOLINTNEXTLINE(cppcoreguidelines-special-member-functions)
 | ||||||
|  | class Buffer | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	Buffer(Device *device, VkBufferCreateInfo info) | ||||||
|  | 	    : m_device(device) | ||||||
|  | 	    , m_object(m_device->create_buffer(info)) | ||||||
|  | 	{ | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	~Buffer() | ||||||
|  | 	{ | ||||||
|  | 		if (m_device) | ||||||
|  | 		{ | ||||||
|  | 			m_device->destroy_buffer(m_object); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto operator*() const -> VkBuffer | ||||||
|  | 	{ | ||||||
|  | 		return m_object; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] operator VkBuffer() const | ||||||
|  | 	{ | ||||||
|  | 		return m_object; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	memory::NullOnMove<Device *> m_device {}; | ||||||
|  | 
 | ||||||
|  | 	VkBuffer m_object; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | class Memory | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	Memory(Device *device, VkBuffer buffer, VkMemoryAllocateInfo info) | ||||||
|  | 	    : m_device(device) | ||||||
|  | 	    , m_object(m_device->allocate_memory(info)) | ||||||
|  | 	{ | ||||||
|  | 		m_device->bind_memory(buffer, m_object); | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	~Memory() | ||||||
|  | 	{ | ||||||
|  | 		if (m_device) | ||||||
|  | 		{ | ||||||
|  | 			m_device->free_memory(m_object); | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto operator*() const -> VkDeviceMemory | ||||||
|  | 	{ | ||||||
|  | 		return m_object; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] operator VkDeviceMemory() const | ||||||
|  | 	{ | ||||||
|  | 		return m_object; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | 	memory::NullOnMove<Device *> m_device {}; | ||||||
|  | 
 | ||||||
|  | 	VkDeviceMemory m_object = VK_NULL_HANDLE; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | // NOLINTEND(cppcoreguidelines-special-member-functions)
 | ||||||
| } // namespace lt::renderer::vk::raii
 | } // namespace lt::renderer::vk::raii
 | ||||||
|  |  | ||||||
|  | @ -1,18 +0,0 @@ | ||||||
| // template<>
 |  | ||||||
| // struct std::formatter<VkExtent2D>
 |  | ||||||
| // {
 |  | ||||||
| // 	constexpr auto parse(std::format_parse_context &context)
 |  | ||||||
| // 	{
 |  | ||||||
| // 		return context.begin();
 |  | ||||||
| // 	}
 |  | ||||||
| //
 |  | ||||||
| // 	auto format(const VkExtent2D &val, std::format_context &context) const
 |  | ||||||
| // 	{
 |  | ||||||
| // 		return std::format_to(context.out(), "{}, {}", val.width, val.height);
 |  | ||||||
| // 	}
 |  | ||||||
| // };
 |  | ||||||
| //
 |  | ||||||
| // inline auto operator==(VkExtent2D lhs, VkExtent2D rhs) -> bool
 |  | ||||||
| // {
 |  | ||||||
| // 	return lhs.width == rhs.width && lhs.height == rhs.height;
 |  | ||||||
| // }
 |  | ||||||
|  | @ -15,6 +15,7 @@ extern PFN_vkGetDeviceProcAddr vk_get_device_proc_address; | ||||||
| extern PFN_vkDestroyDevice vk_destroy_device; | extern PFN_vkDestroyDevice vk_destroy_device; | ||||||
| extern PFN_vkGetPhysicalDeviceFeatures vk_get_physical_device_features; | extern PFN_vkGetPhysicalDeviceFeatures vk_get_physical_device_features; | ||||||
| extern PFN_vkEnumerateDeviceExtensionProperties vk_enumerate_device_extension_properties; | extern PFN_vkEnumerateDeviceExtensionProperties vk_enumerate_device_extension_properties; | ||||||
|  | extern PFN_vkGetPhysicalDeviceMemoryProperties vk_get_physical_device_memory_properties; | ||||||
| 
 | 
 | ||||||
| // extension instance functions
 | // extension instance functions
 | ||||||
| extern PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label; | extern PFN_vkCmdBeginDebugUtilsLabelEXT vk_cmd_begin_debug_label; | ||||||
|  | @ -76,6 +77,15 @@ extern PFN_vkCmdDraw vk_cmd_draw; | ||||||
| extern PFN_vkCmdSetViewport vk_cmd_set_viewport; | extern PFN_vkCmdSetViewport vk_cmd_set_viewport; | ||||||
| extern PFN_vkCmdSetScissor vk_cmd_set_scissors; | extern PFN_vkCmdSetScissor vk_cmd_set_scissors; | ||||||
| 
 | 
 | ||||||
|  | extern PFN_vkCreateBuffer vk_create_buffer; | ||||||
|  | extern PFN_vkDestroyBuffer vk_destroy_buffer; | ||||||
|  | extern PFN_vkGetBufferMemoryRequirements vk_get_buffer_memory_requirements; | ||||||
|  | extern PFN_vkAllocateMemory vk_allocate_memory; | ||||||
|  | extern PFN_vkBindBufferMemory vk_bind_buffer_memory; | ||||||
|  | extern PFN_vkMapMemory vk_map_memory; | ||||||
|  | extern PFN_vkUnmapMemory vk_unmap_memory; | ||||||
|  | extern PFN_vkFreeMemory vk_free_memory; | ||||||
|  | 
 | ||||||
| extern PFN_vkResetCommandBuffer vk_reset_command_buffer; | extern PFN_vkResetCommandBuffer vk_reset_command_buffer; | ||||||
| // NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
 | // NOLINTEND(cppcoreguidelines-avoid-non-const-global-variables)
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										29
									
								
								modules/renderer/private/frontend/data/buffer.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								modules/renderer/private/frontend/data/buffer.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,29 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <renderer/backend/vk/data/buffer.hpp> | ||||||
|  | #include <renderer/frontend/data/buffer.hpp> | ||||||
|  | 
 | ||||||
|  | namespace lt::renderer { | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | [[nodiscard]] /* static */ auto IBuffer::create( | ||||||
|  |     Api target_api, | ||||||
|  |     class IDevice *device, | ||||||
|  |     class IGpu *gpu, | ||||||
|  |     const CreateInfo &info | ||||||
|  | ) -> memory::Scope<IBuffer> | ||||||
|  | { | ||||||
|  | 	ensure(device, "Failed to create renderer::IBuffer: null device"); | ||||||
|  | 	ensure(gpu, "Failed to create renderer::IBuffer: null gpu"); | ||||||
|  | 	ensure(info.size > 0, "Failed to create renderer::IBuffer: null size"); | ||||||
|  | 
 | ||||||
|  | 	switch (target_api) | ||||||
|  | 	{ | ||||||
|  | 	case Api::vulkan: return memory::create_scope<vk::Buffer>(device, gpu, info); | ||||||
|  | 	case Api::none: | ||||||
|  | 	case Api::metal: | ||||||
|  | 	case Api::direct_x: throw std::runtime_error { "Invalid API" }; | ||||||
|  | 	} | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | } // namespace lt::renderer
 | ||||||
							
								
								
									
										55
									
								
								modules/renderer/private/frontend/data/buffer.hpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								modules/renderer/private/frontend/data/buffer.hpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,55 @@ | ||||||
|  | #pragma once | ||||||
|  | 
 | ||||||
|  | #include <memory/scope.hpp> | ||||||
|  | #include <renderer/api.hpp> | ||||||
|  | 
 | ||||||
|  | namespace lt::renderer { | ||||||
|  | 
 | ||||||
|  | class IBuffer | ||||||
|  | { | ||||||
|  | public: | ||||||
|  | 	enum Usage : uint8_t | ||||||
|  | 	{ | ||||||
|  | 		vertex, | ||||||
|  | 
 | ||||||
|  | 		index, | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	struct CreateInfo | ||||||
|  | 	{ | ||||||
|  | 		Usage usage; | ||||||
|  | 
 | ||||||
|  | 		size_t size; | ||||||
|  | 
 | ||||||
|  | 		std::string debug_name; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] static auto create( | ||||||
|  | 	    Api target_api, | ||||||
|  | 	    class IDevice *device, | ||||||
|  | 	    class IGpu *gpu, | ||||||
|  | 	    const CreateInfo &info | ||||||
|  | 	) -> memory::Scope<IBuffer>; | ||||||
|  | 
 | ||||||
|  | 	IBuffer() = default; | ||||||
|  | 
 | ||||||
|  | 	virtual ~IBuffer() = default; | ||||||
|  | 
 | ||||||
|  | 	IBuffer(IBuffer &&) = default; | ||||||
|  | 
 | ||||||
|  | 	IBuffer(const IBuffer &) = delete; | ||||||
|  | 
 | ||||||
|  | 	auto operator=(IBuffer &&) -> IBuffer & = default; | ||||||
|  | 
 | ||||||
|  | 	auto operator=(const IBuffer &) -> IBuffer & = delete; | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] virtual auto map() -> std::span<std::byte> = 0; | ||||||
|  | 
 | ||||||
|  | 	virtual void unmap() = 0; | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] virtual auto get_size() const -> size_t = 0; | ||||||
|  | 
 | ||||||
|  | private: | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | } // namespace lt::renderer
 | ||||||
							
								
								
									
										112
									
								
								modules/renderer/private/frontend/data/buffer.test.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								modules/renderer/private/frontend/data/buffer.test.cpp
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,112 @@ | ||||||
|  | #include <renderer/frontend/data/buffer.hpp> | ||||||
|  | #include <renderer/test/utils.hpp> | ||||||
|  | 
 | ||||||
|  | using ::lt::renderer::IBuffer; | ||||||
|  | using enum ::lt::renderer::IMessenger::MessageSeverity; | ||||||
|  | 
 | ||||||
|  | Suite raii = "buffer_raii"_suite = [] { | ||||||
|  | 	Case { "happy path won't throw" } = [] { | ||||||
|  | 		auto fixture = FixtureDeviceSwapchain {}; | ||||||
|  | 
 | ||||||
|  | 		ignore = IBuffer::create( | ||||||
|  | 		    lt::renderer::Api::vulkan, | ||||||
|  | 		    fixture.device(), | ||||||
|  | 		    fixture.gpu(), | ||||||
|  | 		    IBuffer::CreateInfo { | ||||||
|  | 		        .usage = IBuffer::Usage::vertex, | ||||||
|  | 		        .size = 1000u, | ||||||
|  | 		        .debug_name = "", | ||||||
|  | 		    } | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		expect_false(fixture.has_any_messages_of(error)); | ||||||
|  | 		expect_false(fixture.has_any_messages_of(warning)); | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	Case { "unhappy path throws" } = [] { | ||||||
|  | 		auto fixture = FixtureDeviceSwapchain {}; | ||||||
|  | 
 | ||||||
|  | 		auto info = IBuffer::CreateInfo { | ||||||
|  | 			.usage = IBuffer::Usage::vertex, | ||||||
|  | 			.size = 10000u, | ||||||
|  | 			.debug_name = "", | ||||||
|  | 		}; | ||||||
|  | 
 | ||||||
|  | 		expect_throw([&] { | ||||||
|  | 			ignore = IBuffer::create(lt::renderer::Api::vulkan, nullptr, fixture.gpu(), info); | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		expect_throw([&] { | ||||||
|  | 			ignore = IBuffer::create(lt::renderer::Api::vulkan, fixture.device(), nullptr, info); | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		expect_throw([&, info] mutable { | ||||||
|  | 			info.size = 0; | ||||||
|  | 			ignore = IBuffer::create( | ||||||
|  | 			    lt::renderer::Api::vulkan, | ||||||
|  | 			    fixture.device(), | ||||||
|  | 			    fixture.gpu(), | ||||||
|  | 			    info | ||||||
|  | 			); | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		expect_throw([&] { | ||||||
|  | 			ignore = IBuffer::create( | ||||||
|  | 			    lt::renderer::Api::direct_x, | ||||||
|  | 			    fixture.device(), | ||||||
|  | 			    fixture.gpu(), | ||||||
|  | 			    info | ||||||
|  | 			); | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		expect_throw([&] { | ||||||
|  | 			ignore = IBuffer::create( | ||||||
|  | 			    lt::renderer::Api::metal, | ||||||
|  | 			    fixture.device(), | ||||||
|  | 			    fixture.gpu(), | ||||||
|  | 			    info | ||||||
|  | 			); | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		expect_throw([&] { | ||||||
|  | 			ignore = IBuffer::create( | ||||||
|  | 			    lt::renderer::Api::none, | ||||||
|  | 			    fixture.device(), | ||||||
|  | 			    fixture.gpu(), | ||||||
|  | 			    info | ||||||
|  | 			); | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		/** Make sure the default-case was good */ | ||||||
|  | 		ignore = IBuffer::create(lt::renderer::Api::vulkan, fixture.device(), fixture.gpu(), info); | ||||||
|  | 
 | ||||||
|  | 		expect_false(fixture.has_any_messages_of(error)); | ||||||
|  | 		expect_false(fixture.has_any_messages_of(warning)); | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
|  | Suite mapping = "buffer_mapping"_suite = [] { | ||||||
|  | 	Case { "mapping" } = [] { | ||||||
|  | 		auto fixture = FixtureDeviceSwapchain {}; | ||||||
|  | 
 | ||||||
|  | 		constexpr auto size = 1000u; | ||||||
|  | 
 | ||||||
|  | 		auto buffer = IBuffer::create( | ||||||
|  | 		    lt::renderer::Api::vulkan, | ||||||
|  | 		    fixture.device(), | ||||||
|  | 		    fixture.gpu(), | ||||||
|  | 		    IBuffer::CreateInfo { | ||||||
|  | 		        .usage = IBuffer::Usage::vertex, | ||||||
|  | 		        .size = size, | ||||||
|  | 		        .debug_name = "", | ||||||
|  | 		    } | ||||||
|  | 		); | ||||||
|  | 
 | ||||||
|  | 		auto map = buffer->map(); | ||||||
|  | 		expect_eq(map.size(), size); | ||||||
|  | 		expect_not_nullptr(map.data()); | ||||||
|  | 
 | ||||||
|  | 		expect_false(fixture.has_any_messages_of(error)); | ||||||
|  | 		expect_false(fixture.has_any_messages_of(warning)); | ||||||
|  | 	}; | ||||||
|  | }; | ||||||
|  | @ -1 +0,0 @@ | ||||||
| 
 |  | ||||||
|  | @ -148,7 +148,6 @@ public: | ||||||
| 		); | 		); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| 	[[nodiscard]] auto has_any_messages() const -> bool | 	[[nodiscard]] auto has_any_messages() const -> bool | ||||||
| 	{ | 	{ | ||||||
| 		return m_user_data->m_has_any_messages; | 		return m_user_data->m_has_any_messages; | ||||||
|  |  | ||||||
|  | @ -7,7 +7,6 @@ | ||||||
| 
 | 
 | ||||||
| namespace lt::renderer { | namespace lt::renderer { | ||||||
| 
 | 
 | ||||||
| 
 |  | ||||||
| class IMessenger | class IMessenger | ||||||
| { | { | ||||||
| public: | public: | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue