Переглянути джерело

Added VulkanImage resource for managing and tracking Vulkan images

BearishSun 9 роки тому
батько
коміт
6455c6237d

+ 21 - 1
Source/BansheeVulkanRenderAPI/Include/BsVulkanResource.h

@@ -24,6 +24,14 @@ namespace BansheeEngine
 	typedef Flags<VulkanUseFlag> VulkanUseFlags;
 	BS_FLAGS_OPERATORS(VulkanUseFlag);
 
+	/** Types of VulkanResource. */
+	enum class VulkanResourceType
+	{
+		Generic,
+		Image,
+		Buffer
+	};
+
 	/** 
 	 * Wraps one or multiple native Vulkan objects. Allows the object usage to be tracked in command buffers, handles
 	 * ownership transitions between different queues, and handles delayed object destruction.
@@ -31,7 +39,7 @@ namespace BansheeEngine
 	class VulkanResource
 	{
 	public:
-		VulkanResource(VulkanResourceManager* owner, bool concurrency);
+		VulkanResource(VulkanResourceManager* owner, bool concurrency, VulkanResourceType type = VulkanResourceType::Generic);
 		virtual ~VulkanResource();
 
 		/** 
@@ -57,6 +65,17 @@ namespace BansheeEngine
 		 */
 		bool isUsed() const { return mNumHandles > 0; }
 
+		/** Returns the type of the object wrapped by the resource. */
+		VulkanResourceType getType() const { return mType; }
+
+		/** 
+		 * Returns the queue family the resource is currently owned by. Returns -1 if owned by no queue.
+		 * 
+		 * @note	If resource concurrency is enabled, then this value has no meaning as the resource can be used on
+		 *			multiple queue families at once.
+		 */
+		UINT32 getQueueFamily() const { return mQueueFamily; }
+
 		/** 
 		 * Destroys the resource and frees its memory. If the resource is currently being used on a device, the
 		 * destruction is delayed until the device is done with it.
@@ -82,6 +101,7 @@ namespace BansheeEngine
 		VulkanResourceManager* mOwner;
 		UINT32 mQueueFamily;
 		State mState;
+		VulkanResourceType mType;
 		
 		UseHandle* mHandles;
 		UINT32 mNumHandles;

+ 42 - 1
Source/BansheeVulkanRenderAPI/Include/BsVulkanTexture.h

@@ -3,6 +3,7 @@
 #pragma once
 
 #include "BsVulkanPrerequisites.h"
+#include "BsVulkanResource.h"
 #include "BsTexture.h"
 
 namespace BansheeEngine
@@ -11,12 +12,51 @@ namespace BansheeEngine
 	 *  @{
 	 */
 
+	/** Wrapper around a Vulkan image object that manages its usage and lifetime. */
+	class VulkanImage : public VulkanResource
+	{
+	public:
+		VulkanImage(VulkanResourceManager* owner, VkImage image, VkImageLayout layout);
+		~VulkanImage();
+
+		/** Returns the internal handle to the Vulkan object. */
+		VkImage getHandle() const { return mImage; }
+
+		/** Returns the layout the image is currently in. */
+		VkImageLayout getLayout() const { return mLayout; }
+
+		/** Notifies the resource that the current image layout has changed. */
+		void setLayout(VkImageLayout layout) { mLayout = layout; }
+
+	private:
+		VkImage mImage;
+		VkImageLayout mLayout;
+	};
+
 	/**	Vulkan implementation of a texture. */
 	class VulkanTextureCore : public TextureCore
 	{
 	public:
 		~VulkanTextureCore();
 
+		/** 
+		 * Gets the resource wrapping the Vulkan image object, on the specified device. If texture device mask doesn't 
+		 * include the provided device, null is returned. 
+		 */
+		VulkanImage* getResource(UINT32 deviceIdx) const { return mImages[deviceIdx]; }
+
+		/** 
+		 * Returns an image view that covers all faces and mip maps of the texture. Usable only on the specified device. 
+		 * If texture device mask doesn't include the provided device, null is returned. 
+		 */
+		VkImageView getView(UINT32 deviceIdx);
+
+		/** 
+		 * Returns an image view that covers the specified faces and mip maps of the texture. Usable only on the specified 
+		 * device. If texture device mask doesn't include the provided device, null is returned. 
+		 */
+		VkImageView getView(UINT32 deviceIdx, const TextureSurface& surface);
+
 	protected:
 		friend class VulkanTextureCoreManager;
 
@@ -40,7 +80,8 @@ namespace BansheeEngine
 		/** @copydoc TextureCore::writeData */
 		void writeData(const PixelData& src, UINT32 mipLevel = 0, UINT32 face = 0, bool discardWholeBuffer = false) override;
 
-	protected:
+	private:
+		VulkanImage* mImages[BS_MAX_DEVICES];
 	};
 
 	/** @} */

+ 1 - 1
Source/BansheeVulkanRenderAPI/Source/BsVulkanCommandBuffer.cpp

@@ -9,7 +9,7 @@
 namespace BansheeEngine
 {
 	VulkanCmdBufferPool::VulkanCmdBufferPool(VulkanDevice& device)
-		:mDevice(device), mPools{}, mBuffers {}, mNextId(1)
+		:mDevice(device), mPools{}, mBuffers{}, mNextId(1)
 	{
 		for (UINT32 i = 0; i < GQT_COUNT; i++)
 		{

+ 3 - 15
Source/BansheeVulkanRenderAPI/Source/BsVulkanGpuParams.cpp

@@ -263,11 +263,7 @@ namespace BansheeEngine
 			if (mPerDeviceData[i].perSetData == nullptr)
 				continue;
 
-			VulkanImage* imageRes = vulkanTexture->getResource(i);
-			if (imageRes != nullptr)
-				mPerDeviceData[i].perSetData[set].writeInfos[slot].image.imageView = imageRes->getView();
-			else
-				mPerDeviceData[i].perSetData[set].writeInfos[slot].image.imageView = VK_NULL_HANDLE;
+			mPerDeviceData[i].perSetData[set].writeInfos[slot].image.imageView = vulkanTexture->getView(i);
 		}
 
 		mSetsDirty[set] = true;
@@ -284,11 +280,7 @@ namespace BansheeEngine
 			if (mPerDeviceData[i].perSetData == nullptr)
 				continue;
 
-			VulkanImage* imageRes = vulkanTexture->getResource(i);
-			if (imageRes != nullptr)
-				mPerDeviceData[i].perSetData[set].writeInfos[slot].image.imageView = imageRes->getView(surface);
-			else
-				mPerDeviceData[i].perSetData[set].writeInfos[slot].image.imageView = VK_NULL_HANDLE;
+			mPerDeviceData[i].perSetData[set].writeInfos[slot].image.imageView = vulkanTexture->getView(i, surface);
 		}
 
 		mSetsDirty[set] = true;
@@ -348,11 +340,7 @@ namespace BansheeEngine
 			if (mPerDeviceData[i].perSetData == nullptr)
 				continue;
 
-			VulkanImage* imageRes = vulkanTexture->getResource(i);
-			if (imageRes != nullptr)
-				mPerDeviceData[i].perSetData[set].writeInfos[slot].image.imageView = imageRes->getView(surface);
-			else
-				mPerDeviceData[i].perSetData[set].writeInfos[slot].image.imageView = VK_NULL_HANDLE;
+			mPerDeviceData[i].perSetData[set].writeInfos[slot].image.imageView = vulkanTexture->getView(i, surface);
 		}
 
 		mSetsDirty[set] = true;

+ 2 - 2
Source/BansheeVulkanRenderAPI/Source/BsVulkanResource.cpp

@@ -5,8 +5,8 @@
 
 namespace BansheeEngine
 {
-	VulkanResource::VulkanResource(VulkanResourceManager* owner, bool concurrency)
-		: mOwner(owner), mState(concurrency ? State::Shared : State::Normal), mNumHandles(0)
+	VulkanResource::VulkanResource(VulkanResourceManager* owner, bool concurrency, VulkanResourceType type)
+		: mOwner(owner), mQueueFamily(-1), mState(concurrency ? State::Shared : State::Normal), mType(type), mNumHandles(0)
 		, mHandleCapacity(INITIAL_HANDLE_CAPACITY)
 	{
 		UINT32 bytesCapacity = sizeof(UseHandle) * mHandleCapacity;

+ 33 - 2
Source/BansheeVulkanRenderAPI/Source/BsVulkanTexture.cpp

@@ -1,16 +1,27 @@
 //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
 //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
 #include "BsVulkanTexture.h"
+#include "BsVulkanDevice.h"
 #include "BsCoreThread.h"
 #include "BsException.h"
-#include "BsAsyncOp.h"
 #include "BsRenderStats.h"
 
 namespace BansheeEngine
 {
+	VulkanImage::VulkanImage(VulkanResourceManager* owner, VkImage image, VkImageLayout layout)
+		:VulkanResource(owner, false, VulkanResourceType::Image), mImage(image), mLayout(layout)
+	{
+		
+	}
+
+	VulkanImage::~VulkanImage()
+	{
+		vkDestroyImage(mOwner->getDevice().getLogical(), mImage, gVulkanAllocator);
+	}
+
 	VulkanTextureCore::VulkanTextureCore(const TEXTURE_DESC& desc, const SPtr<PixelData>& initialData,
 		GpuDeviceFlags deviceMask)
-		: TextureCore(desc, initialData, deviceMask)
+		: TextureCore(desc, initialData, deviceMask), mImages()
 	{
 		
 	}
@@ -28,6 +39,26 @@ namespace BansheeEngine
 		TextureCore::initialize();
 	}
 
+	VkImageView VulkanTextureCore::getView(UINT32 deviceIdx)
+	{
+		// TODO
+		// - If device idx doesn't match the mask, return VK_NULL_HANDLE
+		// - Otherwise return the default image view (created by default in initialize())
+		// - Free the view in destructor
+	}
+
+	VkImageView VulkanTextureCore::getView(UINT32 deviceIdx, const TextureSurface& surface)
+	{
+		// TODO
+		// - If device idx doesn't match the mask, return VK_NULL_HANDLE
+		// - Otherwise
+		//  - Scan the mTextureViews array for an existing view matching the surface
+		//  - If view isn't found create a new one and add it to mTextureViews array
+		//   - Resize the mTextureViews array as needed
+		//   - By default mTextureViews is nullptr, so allocate it during first call
+		// - Free the views in destructor (if any were allocated)
+	}
+
 	void VulkanTextureCore::copyImpl(UINT32 srcFace, UINT32 srcMipLevel, UINT32 destFace, UINT32 destMipLevel, const SPtr<TextureCore>& target)
 	{