From e167746b04bc60d533779944b5c29e654d24a7b1 Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Sun, 30 May 2021 02:07:26 +0200
Subject: [PATCH] [#31] Texture loads into image, format should be supported,
 fingers crossed

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 include/vkcv/Core.hpp            | 12 +++++++
 include/vkcv/Image.hpp           |  6 ++--
 projects/first_mesh/src/main.cpp |  5 +++
 src/vkcv/BufferManager.cpp       |  2 ++
 src/vkcv/Core.cpp                |  5 +++
 src/vkcv/ImageManager.cpp        | 54 +++++++++++++++++++++++---------
 6 files changed, 68 insertions(+), 16 deletions(-)

diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index d139649b..388bc0ea 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -173,6 +173,18 @@ namespace vkcv
         Buffer<T> createBuffer(vkcv::BufferType type, size_t count, BufferMemoryType memoryType = BufferMemoryType::DEVICE_LOCAL) {
         	return Buffer<T>::create(m_BufferManager.get(), type, count, memoryType);
         }
+        
+        /**
+         * Creates an #Image with a given format, width, height and depth.
+         *
+         * @param format Image format
+         * @param width Image width
+         * @param height Image height
+         * @param depth Image depth
+         * @return Image-Object
+         */
+        [[nodiscard]]
+        Image createImage(vk::Format format, uint32_t width, uint32_t height, uint32_t depth = 1);
 
         /** TODO:
          *   @param setDescriptions
diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp
index 1c162cdc..5050513b 100644
--- a/include/vkcv/Image.hpp
+++ b/include/vkcv/Image.hpp
@@ -12,9 +12,8 @@ namespace vkcv {
 	
 	class ImageManager;
 	class Image {
+		friend class Core;
 	public:
-		static Image create(ImageManager* manager, vk::Format format, uint32_t width, uint32_t height, uint32_t depth);
-		
 		[[nodiscard]]
 		vk::Format getFormat() const;
 		
@@ -43,6 +42,9 @@ namespace vkcv {
 		vk::ImageLayout m_layout;
 
 		Image(ImageManager* manager, const ImageHandle& handle, vk::Format format, uint32_t width, uint32_t height, uint32_t depth);
+		
+		static Image create(ImageManager* manager, vk::Format format, uint32_t width, uint32_t height, uint32_t depth);
+		
 	};
 	
 }
diff --git a/projects/first_mesh/src/main.cpp b/projects/first_mesh/src/main.cpp
index e1cbc40e..ced7867e 100644
--- a/projects/first_mesh/src/main.cpp
+++ b/projects/first_mesh/src/main.cpp
@@ -83,6 +83,10 @@ int main(int argc, const char** argv) {
 		std::cout << "Error. Could not create graphics pipeline. Exiting." << std::endl;
 		return EXIT_FAILURE;
 	}
+	
+	vkcv::Image texture = core.createImage(vk::Format::eR8G8B8A8Srgb, mesh.texture_hack.w, mesh.texture_hack.h);
+	
+	texture.fill(mesh.texture_hack.img);
 
 	auto start = std::chrono::system_clock::now();
 	while (window.isWindowOpen()) {
@@ -97,5 +101,6 @@ int main(int argc, const char** argv) {
 		core.renderMesh(trianglePass, trianglePipeline, windowWidth, windowHeight, sizeof(mvp), &mvp, vertexBuffer.getHandle(), indexBuffer.getHandle(), mesh.vertexGroups[0].numIndices);
 		core.endFrame();
 	}
+	
 	return 0;
 }
diff --git a/src/vkcv/BufferManager.cpp b/src/vkcv/BufferManager.cpp
index a6ec8008..740e8999 100644
--- a/src/vkcv/BufferManager.cpp
+++ b/src/vkcv/BufferManager.cpp
@@ -328,10 +328,12 @@ namespace vkcv {
 		
 		if (buffer.m_memory) {
 			device.freeMemory(buffer.m_memory);
+			buffer.m_memory = nullptr;
 		}
 		
 		if (buffer.m_handle) {
 			device.destroyBuffer(buffer.m_handle);
+			buffer.m_handle = nullptr;
 		}
 	}
 
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index ecadba04..5c924743 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -266,6 +266,11 @@ namespace vkcv
 			finish();
 		}
 	}
+	
+	Image Core::createImage(vk::Format format, uint32_t width, uint32_t height, uint32_t depth)
+	{
+    	return Image::create(m_ImageManager.get(), format, width, height, depth);
+	}
 
     ResourcesHandle Core::createResourceDescription(const std::vector<DescriptorSet> &descriptorSets)
     {
diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp
index 188bbebd..39cca04b 100644
--- a/src/vkcv/ImageManager.cpp
+++ b/src/vkcv/ImageManager.cpp
@@ -47,22 +47,49 @@ namespace vkcv {
 
 	ImageHandle ImageManager::createImage(uint32_t width, uint32_t height, uint32_t depth, vk::Format format)
 	{
-		vk::ImageCreateFlags createFlags;
-		vk::ImageUsageFlags imageUsageFlags = (vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst);
+		const vk::PhysicalDevice& physicalDevice = m_core->getContext().getPhysicalDevice();
+		
+		const vk::FormatProperties formatProperties = physicalDevice.getFormatProperties(format);
 		
-		format = vk::Format::eR8G8B8A8Unorm; // TODO
+		vk::ImageCreateFlags createFlags;
+		vk::ImageUsageFlags imageUsageFlags = (
+				vk::ImageUsageFlagBits::eSampled | vk::ImageUsageFlagBits::eTransferDst
+		);
 
 		const vk::Device& device = m_core->getContext().getDevice();
 
+		vk::ImageType imageType = vk::ImageType::e3D;
+		
+		if (depth <= 1) {
+			if (height <= 1) {
+				imageType = vk::ImageType::e1D;
+			} else {
+				imageType = vk::ImageType::e2D;
+			}
+		}
+		
+		vk::ImageTiling imageTiling = vk::ImageTiling::eOptimal;
+		
+		if (!formatProperties.optimalTilingFeatures) {
+			if (!formatProperties.linearTilingFeatures)
+				return ImageHandle();
+			
+			imageTiling = vk::ImageTiling::eLinear;
+		}
+		
+		const vk::ImageFormatProperties imageFormatProperties = physicalDevice.getImageFormatProperties(
+				format, imageType, imageTiling, imageUsageFlags
+		);
+		
 		vk::ImageCreateInfo imageCreateInfo(
 			createFlags,
-			vk::ImageType::e2D,
+			imageType,
 			format,
-			vk::Extent3D(width, height, 1),
+			vk::Extent3D(width, height, depth),
 			1,
 			1,
 			vk::SampleCountFlagBits::e1,
-			vk::ImageTiling::eOptimal,
+			imageTiling,
 			imageUsageFlags,
 			vk::SharingMode::eExclusive,
 			{},
@@ -72,7 +99,6 @@ namespace vkcv {
 		vk::Image image = device.createImage(imageCreateInfo);
 		
 		const vk::MemoryRequirements requirements = device.getImageMemoryRequirements(image);
-		const vk::PhysicalDevice& physicalDevice = m_core->getContext().getPhysicalDevice();
 
 		vk::MemoryPropertyFlags memoryTypeFlags = vk::MemoryPropertyFlagBits::eDeviceLocal;
 
@@ -102,6 +128,7 @@ namespace vkcv {
 			(newLayout == vk::ImageLayout::eTransferDstOptimal))
 		{
 			destinationAccessMask = vk::AccessFlagBits::eTransferWrite;
+			
 			sourceStage = vk::PipelineStageFlagBits::eTopOfPipe;
 			destinationStage = vk::PipelineStageFlagBits::eTransfer;
 		}
@@ -110,6 +137,7 @@ namespace vkcv {
 		{
 			sourceAccessMask = vk::AccessFlagBits::eTransferWrite;
 			destinationAccessMask = vk::AccessFlagBits::eShaderRead;
+			
 			sourceStage = vk::PipelineStageFlagBits::eTransfer;
 			destinationStage = vk::PipelineStageFlagBits::eFragmentShader;
 		}
@@ -142,7 +170,7 @@ namespace vkcv {
 		);
 		
 		SubmitInfo submitInfo;
-		submitInfo.queueType = QueueType::Transfer;
+		submitInfo.queueType = QueueType::Graphics;
 		
 		m_core->submitCommands(
 			submitInfo,
@@ -162,10 +190,6 @@ namespace vkcv {
 	
 	void ImageManager::fillImage(const ImageHandle& handle, void* data, size_t size)
 	{
-		if (size == 0) {
-			size = SIZE_MAX;
-		}
-		
 		const uint64_t id = handle.getId();
 		
 		if (id >= m_images.size()) {
@@ -180,9 +204,9 @@ namespace vkcv {
 				vk::ImageLayout::eTransferDstOptimal
 		);
 		
-		uint32_t channels = 3; // TODO
+		uint32_t channels = 4; // TODO: check image.m_format
 		const size_t image_size = (
-				image.m_width * image.m_height * image.m_depth * channels * sizeof(char)
+				image.m_width * image.m_height * image.m_depth * channels
 		);
 		
 		const size_t max_size = std::min(size, image_size);
@@ -249,10 +273,12 @@ namespace vkcv {
 
 		if (image.m_memory) {
 			device.freeMemory(image.m_memory);
+			image.m_memory = nullptr;
 		}
 
 		if (image.m_handle) {
 			device.destroyImage(image.m_handle);
+			image.m_handle = nullptr;
 		}
 	}
 
-- 
GitLab