From 362702b31a502063ac0f5734d36f55cba3c352e0 Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Wed, 19 May 2021 17:26:35 +0200
Subject: [PATCH] Added create()-function for buffer to allow the code to
 handle issues

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 include/vkcv/Buffer.hpp              | 114 +++++++++++++++++----------
 include/vkcv/Core.hpp                |   7 +-
 projects/first_triangle/src/main.cpp |  11 +++
 3 files changed, 88 insertions(+), 44 deletions(-)

diff --git a/include/vkcv/Buffer.hpp b/include/vkcv/Buffer.hpp
index c97417fa..69e59d3b 100644
--- a/include/vkcv/Buffer.hpp
+++ b/include/vkcv/Buffer.hpp
@@ -44,7 +44,6 @@ namespace vkcv {
 		        m_Buffer(other.m_Buffer),
 				m_BufferMemory(other.m_BufferMemory),
 				m_Device(other.m_Device),
-				m_MemoryRequirement(other.m_MemoryRequirement),
 		        m_Type(other.m_Type),
 		        m_Size(other.m_Size),
 		        m_DataP(other.m_DataP)
@@ -52,7 +51,6 @@ namespace vkcv {
 			other.m_Buffer = nullptr;
 			other.m_BufferMemory = nullptr;
 			other.m_Device = nullptr;
-			//other.m_MemoryRequirement = nullptr; // WIP alternative to nullptr has to be found
 			other.m_Type = vkcv::VERTEX; //set to 0
 			other.m_Size = 0;
 			other.m_DataP = nullptr;
@@ -63,7 +61,6 @@ namespace vkcv {
 			m_Buffer = other.m_Buffer;
 			m_BufferMemory = other.m_BufferMemory;
 			m_Device = other.m_Device;
-			m_MemoryRequirement = other.m_MemoryRequirement;
 			m_Type = other.m_Type;
 			m_Size = other.m_Size;
 			m_DataP = other.m_DataP;
@@ -71,7 +68,6 @@ namespace vkcv {
 			other.m_Buffer = nullptr;
 			other.m_BufferMemory = nullptr;
 			other.m_Device = nullptr;
-			//other.m_MemoryRequirement = nullptr; // WIP alternative to nullptr has to be found
 			other.m_Type = vkcv::VERTEX; //set to 0
 			other.m_Size = 0;
 			other.m_DataP = nullptr;
@@ -83,40 +79,106 @@ namespace vkcv {
 		
 		// TODO: we will probably need staging-buffer here later (possible add in BufferManager later?)
 		void fill(T* data, size_t count) {
+			const vk::MemoryRequirements requirements = m_Device.getBufferMemoryRequirements(m_Buffer);
+			
 			// TODO: check if mapped already
-			m_DataP = static_cast<uint8_t*>(m_Device.mapMemory(m_BufferMemory, 0, m_MemoryRequirement.size));
+			m_DataP = static_cast<uint8_t*>(m_Device.mapMemory(m_BufferMemory, 0, requirements.size));
 			memcpy(m_DataP, data, sizeof(T) * count);
 			m_Device.unmapMemory(m_BufferMemory);
 		};
 		
-		void map() {
-			m_DataP = static_cast<uint8_t*>(m_Device.mapMemory(m_BufferMemory, 0, m_MemoryRequirement.size));
+		T* map() {
+			const vk::MemoryRequirements requirements = m_Device.getBufferMemoryRequirements(m_Buffer);
+			
+			m_DataP = static_cast<uint8_t*>(m_Device.mapMemory(m_BufferMemory, 0, requirements.size));
 			// TODO: make sure to unmap before deallocation
+			
+			return reinterpret_cast<T*>(m_DataP);
 		};
 		
 		void unmap() {
 			m_Device.unmapMemory(m_BufferMemory);
 			// TODO: mark m_DataP as invalid?
 		};
+		
+		/**
+		 * * Create function of #Buffer requires a @p device, a @p physicalDevice, a @p buffer type and a @p size.		 *
+		 * @param device Vulkan-Device
+		 * @param physicalDevice Vulkan-PhysicalDevice
+		 * @param type Enum type of possible vkcv::BufferType
+		 * @param Size size of data
+		 */
+		static Buffer<T> create(vk::Device device, vk::PhysicalDevice physicalDevice, BufferType type, size_t size) {
+			vk::Buffer buffer = nullptr;
+			
+			switch (type) {
+				case VERTEX: {
+					//create vertex buffer
+					buffer = device.createBuffer(vk::BufferCreateInfo(vk::BufferCreateFlags(), sizeof(T) * size, vk::BufferUsageFlagBits::eVertexBuffer));
+				}
+				default: {
+					// TODO: maybe an issue
+				}
+			}
+			
+			if (!buffer) {
+				//TODO: potential issue
+			}
+			
+			//get requirements for allocation
+			const vk::MemoryRequirements requirements = device.getBufferMemoryRequirements(buffer);
+			
+			//find Memory Type
+			uint32_t memoryType = searchMemoryType(physicalDevice.getMemoryProperties(), requirements.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
+			
+			//allocate memory for buffer
+			vk::DeviceMemory memory = device.allocateMemory(vk::MemoryAllocateInfo(requirements.size, memoryType));
+			
+			if (!memory) {
+				//TODO: other potential issue
+			}
+			
+			device.bindBufferMemory(buffer, memory, 0);
+			
+			return Buffer<T>(buffer, memory, device, type, size);
+		}
 
 	private:
 		vk::Buffer m_Buffer;
 		vk::DeviceMemory m_BufferMemory;
 		vk::Device m_Device;
-		vk::MemoryRequirements m_MemoryRequirement;
 		BufferType m_Type;
 		size_t m_Size=0;
 		uint8_t* m_DataP;
 
+		/**
+		 * * Constructor of #Buffer requires a @p buffer, a @p memory, @p device, @ requirement, a @p buffer type and a @p size.
+		 * @param buffer Vulkan-Buffer
+		 * @param memory Vulkan-DeviceMemory
+		 * @param device Vulkan-Device
+		 * @param requirement Vulkan-MemoryRequirements
+		 * @param type Enum type of possible vkcv::BufferType
+		 * @param Size size of data
+		 */
+		Buffer<T>(vk::Buffer buffer, vk::DeviceMemory memory, vk::Device device, BufferType type, size_t size) :
+				m_Buffer(buffer),
+				m_BufferMemory(memory),
+				m_Device(device),
+				m_Type(type),
+				m_Size(size),
+				m_DataP(nullptr)
+		{}
+		
 		/**
 		 * @brief searches memory type index for buffer allocation, inspired by vulkan tutorial and "https://github.com/KhronosGroup/Vulkan-Hpp/blob/master/samples/utils/utils.hpp"
-		 * @param physicalMemoryProperties Memory Properties of physical device 
-		 * @param typeBits 
+		 * @param physicalMemoryProperties Memory Properties of physical device
+		 * @param typeBits
 		 * @param requirements Property flags that are required
 		 * @return memory type index for Buffer
 		*/
-		uint32_t searchMemoryType(vk::PhysicalDeviceMemoryProperties const& physicalMemoryProperties, uint32_t typeBits, vk::MemoryPropertyFlags requirements) {
+		static uint32_t searchMemoryType(vk::PhysicalDeviceMemoryProperties const& physicalMemoryProperties, uint32_t typeBits, vk::MemoryPropertyFlags requirements) {
 			uint32_t memoryTypeIndex = uint32_t(0);
+			
 			for (uint32_t i = 0; i < physicalMemoryProperties.memoryTypeCount; i++)
 			{
 				if ((typeBits & 1) &&
@@ -127,36 +189,8 @@ namespace vkcv {
 				}
 				typeBits >>= 1;
 			}
+			
 			return memoryTypeIndex;
-		};
-
-		/**
-		 * * Constructor of #Buffer requires a @p device, a @p physicalDevice, a @p buffer type and a @p size.		 *
-		 * @param device Vulkan-Device
-		 * @param physicalDevice Vulkan-PhysicalDevice
-		 * @param type Enum type of possible vkcv::BufferType
-		 * @param Size size of data
-		 */
-		Buffer<T>(vk::Device device, vk::PhysicalDevice physicalDevice, BufferType type, size_t size) {
-			m_Type = type;
-			m_Size = size;
-			m_Device = device;
-			m_DataP = nullptr;
-
-			switch (m_Type) {
-				case VERTEX: {
-					//create vertex buffer
-					m_Buffer = m_Device.createBuffer(vk::BufferCreateInfo(vk::BufferCreateFlags(), sizeof(T) * m_Size, vk::BufferUsageFlagBits::eVertexBuffer));
-				}
-			}
-			//get requirements for allocation
-			m_MemoryRequirement = m_Device.getBufferMemoryRequirements(m_Buffer);
-			//find Memory Type 
-			uint32_t memoryType = searchMemoryType(physicalDevice.getMemoryProperties(), m_MemoryRequirement.memoryTypeBits, vk::MemoryPropertyFlagBits::eHostVisible | vk::MemoryPropertyFlagBits::eHostCoherent);
-			//allocate memory for buffer
-			m_BufferMemory = m_Device.allocateMemory(vk::MemoryAllocateInfo(m_MemoryRequirement.size, memoryType));
-
-			device.bindBufferMemory(m_Buffer, m_BufferMemory, 0);
 		}
 	
 	};
diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index 93ab5d4c..752dce3b 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -100,10 +100,9 @@ namespace vkcv
             */
         template<typename T>
         Buffer<T> createBuffer(vkcv::BufferType bufferType,size_t size) {
-            Buffer<T> buffer(m_Context.getDevice(), m_Context.getPhysicalDevice(), bufferType, size);
-            return std::move(buffer);
-            //return std::move(Buffer<T>(m_Context.getDevice(),m_Context.getPhysicalDevice, bufferType,size));
-        };
+        	return Buffer<T>::create(m_Context.getDevice(), m_Context.getPhysicalDevice(), bufferType, size);
+        }
+        
         PassHandle createRenderPass(const Renderpass &pass) ;
         PipelineHandle createPipeline(const Pipeline &pipeline);
 
diff --git a/projects/first_triangle/src/main.cpp b/projects/first_triangle/src/main.cpp
index 0c981a25..cd5978fb 100644
--- a/projects/first_triangle/src/main.cpp
+++ b/projects/first_triangle/src/main.cpp
@@ -21,6 +21,17 @@ int main(int argc, const char** argv) {
 	const vk::Instance& instance = context.getInstance();
 	const vk::PhysicalDevice& physicalDevice = context.getPhysicalDevice();
 	const vk::Device& device = context.getDevice();
+	
+	struct vec3 {
+		float x, y, z;
+	};
+	
+	auto buffer = core.createBuffer<vec3>(vkcv::BufferType::VERTEX, 3);
+	
+	vec3* m = buffer.map();
+	m[0] = { 0, 0, 0 };
+	m[0] = { 0, 0, 0 };
+	m[0] = { 0, 0, 0 };
 
 	std::cout << "Physical device: " << physicalDevice.getProperties().deviceName << std::endl;
 
-- 
GitLab