feat(renderer): storage & staging buffer types
	
		
			
	
		
	
	
		
	
		
			Some checks reported errors
		
		
	
	
		
			
				
	
				continuous-integration/drone/push Build was killed
				
			
		
		
	
	
				
					
				
			
		
			Some checks reported errors
		
		
	
	continuous-integration/drone/push Build was killed
				
			This commit is contained in:
		
							parent
							
								
									2ddb90faff
								
							
						
					
					
						commit
						5422792705
					
				
					 5 changed files with 101 additions and 34 deletions
				
			
		|  | @ -16,7 +16,7 @@ Buffer::Buffer(IDevice *device, IGpu *gpu, const CreateInfo &info) | ||||||
|               .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |               .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | ||||||
|           } |           } | ||||||
|       ) |       ) | ||||||
|     , m_memory(m_device, m_buffer, allocation_info_from_memory_requirements()) |     , m_memory(m_device, m_buffer, determine_allocation_info(info.usage)) | ||||||
|     , m_size(info.size) |     , m_size(info.size) | ||||||
| { | { | ||||||
| } | } | ||||||
|  | @ -31,30 +31,18 @@ void Buffer::unmap() /* override */ | ||||||
| 	m_device->unmap_memory(m_memory); | 	m_device->unmap_memory(m_memory); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| [[nodiscard]] auto Buffer::to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags | [[nodiscard]] auto Buffer::determine_allocation_info(Usage usage) const -> VkMemoryAllocateInfo | ||||||
| { |  | ||||||
| 	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); | 	const auto requirements = m_device->get_memory_requirements(m_buffer); | ||||||
| 	auto memory_properties = m_gpu->get_memory_properties(); | 	auto memory_properties = m_gpu->get_memory_properties(); | ||||||
| 
 | 
 | ||||||
| 	const auto required_properties = VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | 	const auto required_properties = to_native_memory_properties(usage); | ||||||
| 	                                 | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; |  | ||||||
| 	auto type = 0u; | 	auto type = 0u; | ||||||
| 	for (auto idx = 0; idx < memory_properties.memoryTypeCount; ++idx) | 	for (auto idx = 0; idx < memory_properties.memoryTypeCount; ++idx) | ||||||
| 	{ | 	{ | ||||||
| 		if ((requirements.memoryTypeBits & (1 << idx)) | 		const auto property_flags = memory_properties.memoryTypes[idx].propertyFlags; | ||||||
| 		    && ((memory_properties.memoryTypes[idx].propertyFlags & required_properties) | 		if (has_correct_memory_type_bit(requirements.memoryTypeBits, idx) | ||||||
| 		        == required_properties)) | 		    && has_required_memory_properties(required_properties, property_flags)) | ||||||
| 
 | 
 | ||||||
| 		{ | 		{ | ||||||
| 			type = idx; | 			type = idx; | ||||||
|  | @ -69,4 +57,50 @@ void Buffer::unmap() /* override */ | ||||||
| 	}; | 	}; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | [[nodiscard]] auto Buffer::to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags | ||||||
|  | { | ||||||
|  | 	switch (usage) | ||||||
|  | 	{ | ||||||
|  | 	case Usage::vertex: return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; | ||||||
|  | 
 | ||||||
|  | 	case Usage::index: return VK_BUFFER_USAGE_INDEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT; | ||||||
|  | 
 | ||||||
|  | 	case Usage::storage: | ||||||
|  | 		return VK_BUFFER_USAGE_TRANSFER_DST_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; | ||||||
|  | 
 | ||||||
|  | 	case Usage::staging: return VK_BUFFER_USAGE_TRANSFER_SRC_BIT; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	std::unreachable(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | [[nodiscard]] auto Buffer::to_native_memory_properties(Usage usage) const -> VkMemoryPropertyFlags | ||||||
|  | { | ||||||
|  | 	switch (usage) | ||||||
|  | 	{ | ||||||
|  | 	case Usage::vertex: | ||||||
|  | 	case Usage::index: | ||||||
|  | 	case Usage::storage: return VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; | ||||||
|  | 
 | ||||||
|  | 	case Usage::staging: | ||||||
|  | 		return VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	std::unreachable(); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | [[nodiscard]] auto Buffer::has_correct_memory_type_bit(uint32_t type_bits, uint32_t type_idx) const | ||||||
|  |     -> bool | ||||||
|  | { | ||||||
|  | 	return type_bits & (1 << type_idx); | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | [[nodiscard]] auto Buffer::has_required_memory_properties( | ||||||
|  |     uint32_t required_properties, | ||||||
|  |     uint32_t property_flags | ||||||
|  | ) const -> bool | ||||||
|  | { | ||||||
|  | 	return (property_flags & required_properties) == required_properties; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| } // namespace lt::renderer::vk
 | } // namespace lt::renderer::vk
 | ||||||
|  |  | ||||||
|  | @ -14,15 +14,36 @@ public: | ||||||
| 
 | 
 | ||||||
| 	void unmap() override; | 	void unmap() override; | ||||||
| 
 | 
 | ||||||
|  | 	// TODO(Light): this is to make copying possible.
 | ||||||
|  | 	// But it should be removed in the future,
 | ||||||
|  | 	// Right now it's not possible because: buffers can't understand CommandBuffers.
 | ||||||
|  | 	// And I'm not sure how to properly abstract over command buffers,
 | ||||||
|  | 	// before using other APIs...
 | ||||||
|  | 	[[nodiscard]] auto vk() | ||||||
|  | 	{ | ||||||
|  | 		return *m_buffer; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	[[nodiscard]] auto get_size() const -> size_t override | 	[[nodiscard]] auto get_size() const -> size_t override | ||||||
| 	{ | 	{ | ||||||
| 		return m_size; | 		return m_size; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| private: | private: | ||||||
|  | 	[[nodiscard]] auto determine_allocation_info(Usage usage) const -> VkMemoryAllocateInfo; | ||||||
|  | 
 | ||||||
| 	[[nodiscard]] auto to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags; | 	[[nodiscard]] auto to_native_usage_flags(Usage usage) const -> VkBufferUsageFlags; | ||||||
| 
 | 
 | ||||||
| 	[[nodiscard]] auto allocation_info_from_memory_requirements() const -> VkMemoryAllocateInfo; | 	[[nodiscard]] auto to_native_memory_properties(Usage usage) const -> VkMemoryPropertyFlags; | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto has_correct_memory_type_bit(uint32_t type_bits, uint32_t type_idx) const | ||||||
|  | 	    -> bool; | ||||||
|  | 
 | ||||||
|  | 	[[nodiscard]] auto has_required_memory_properties( | ||||||
|  | 	    uint32_t required_properties, | ||||||
|  | 	    uint32_t property_flags | ||||||
|  | 	) const -> bool; | ||||||
| 
 | 
 | ||||||
| 	Device *m_device {}; | 	Device *m_device {}; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,5 +1,3 @@ | ||||||
| #pragma once |  | ||||||
| 
 |  | ||||||
| #include <renderer/backend/vk/data/buffer.hpp> | #include <renderer/backend/vk/data/buffer.hpp> | ||||||
| #include <renderer/frontend/data/buffer.hpp> | #include <renderer/frontend/data/buffer.hpp> | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -8,11 +8,15 @@ namespace lt::renderer { | ||||||
| class IBuffer | class IBuffer | ||||||
| { | { | ||||||
| public: | public: | ||||||
| 	enum Usage : uint8_t | 	enum class Usage : uint8_t | ||||||
| 	{ | 	{ | ||||||
| 		vertex, | 		vertex, | ||||||
| 
 | 
 | ||||||
| 		index, | 		index, | ||||||
|  | 
 | ||||||
|  | 		storage, | ||||||
|  | 
 | ||||||
|  | 		staging, | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
| 	struct CreateInfo | 	struct CreateInfo | ||||||
|  | @ -24,6 +28,13 @@ public: | ||||||
| 		std::string debug_name; | 		std::string debug_name; | ||||||
| 	}; | 	}; | ||||||
| 
 | 
 | ||||||
|  | 	struct CopyInfo | ||||||
|  | 	{ | ||||||
|  | 		size_t offset; | ||||||
|  | 
 | ||||||
|  | 		size_t size; | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
| 	[[nodiscard]] static auto create( | 	[[nodiscard]] static auto create( | ||||||
| 	    Api target_api, | 	    Api target_api, | ||||||
| 	    class IDevice *device, | 	    class IDevice *device, | ||||||
|  |  | ||||||
|  | @ -8,16 +8,19 @@ Suite raii = "buffer_raii"_suite = [] { | ||||||
| 	Case { "happy path won't throw" } = [] { | 	Case { "happy path won't throw" } = [] { | ||||||
| 		auto fixture = FixtureDeviceSwapchain {}; | 		auto fixture = FixtureDeviceSwapchain {}; | ||||||
| 
 | 
 | ||||||
| 		ignore = IBuffer::create( | 		for (auto idx = 0; idx <= std::to_underlying(IBuffer::Usage::staging); ++idx) | ||||||
| 		    lt::renderer::Api::vulkan, | 		{ | ||||||
| 		    fixture.device(), | 			ignore = IBuffer::create( | ||||||
| 		    fixture.gpu(), | 			    lt::renderer::Api::vulkan, | ||||||
| 		    IBuffer::CreateInfo { | 			    fixture.device(), | ||||||
| 		        .usage = IBuffer::Usage::vertex, | 			    fixture.gpu(), | ||||||
| 		        .size = 1000u, | 			    IBuffer::CreateInfo { | ||||||
| 		        .debug_name = "", | 			        .usage = static_cast<IBuffer::Usage>(idx), | ||||||
| 		    } | 			        .size = 1000u, | ||||||
| 		); | 			        .debug_name = "", | ||||||
|  | 			    } | ||||||
|  | 			); | ||||||
|  | 		} | ||||||
| 
 | 
 | ||||||
| 		expect_false(fixture.has_any_messages_of(error)); | 		expect_false(fixture.has_any_messages_of(error)); | ||||||
| 		expect_false(fixture.has_any_messages_of(warning)); | 		expect_false(fixture.has_any_messages_of(warning)); | ||||||
|  | @ -77,7 +80,7 @@ Suite raii = "buffer_raii"_suite = [] { | ||||||
| 			); | 			); | ||||||
| 		}); | 		}); | ||||||
| 
 | 
 | ||||||
| 		/** Make sure the default-case was good */ | 		/** Make sure the default-case was OK */ | ||||||
| 		ignore = IBuffer::create(lt::renderer::Api::vulkan, fixture.device(), fixture.gpu(), info); | 		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(error)); | ||||||
|  | @ -96,7 +99,7 @@ Suite mapping = "buffer_mapping"_suite = [] { | ||||||
| 		    fixture.device(), | 		    fixture.device(), | ||||||
| 		    fixture.gpu(), | 		    fixture.gpu(), | ||||||
| 		    IBuffer::CreateInfo { | 		    IBuffer::CreateInfo { | ||||||
| 		        .usage = IBuffer::Usage::vertex, | 		        .usage = IBuffer::Usage::staging, | ||||||
| 		        .size = size, | 		        .size = size, | ||||||
| 		        .debug_name = "", | 		        .debug_name = "", | ||||||
| 		    } | 		    } | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		
		Reference in a new issue