Jelajahi Sumber

Vulkan: More fixes, all crashes so far resolved, moving toward fixing non-catastrophic issues

BearishSun 9 tahun lalu
induk
melakukan
3f6cdb3db7

+ 0 - 1
Source/BansheeVulkanRenderAPI/Include/BsVulkanGpuParams.h

@@ -60,7 +60,6 @@ namespace bs
 		{
 			VkDescriptorImageInfo image;
 			VkDescriptorBufferInfo buffer;
-			VkBufferView bufferView;
 		};
 
 		/** All GPU param data related to a single descriptor set. */

+ 14 - 0
Source/BansheeVulkanRenderAPI/Include/BsVulkanHardwareBufferManager.h

@@ -16,6 +16,16 @@ namespace bs
 	{
 	public:
 		VulkanHardwareBufferCoreManager();
+		~VulkanHardwareBufferCoreManager();
+
+		/** Returns a buffer view that can be used for buffer read operations when no other buffer is bound. */
+		VkBufferView getDummyReadBufferView(UINT32 deviceIdx) const;
+
+		/** Returns a buffer view that can be used for buffer storage operations when no other buffer is bound. */
+		VkBufferView getDummyStorageBufferView(UINT32 deviceIdx) const;
+
+		/** Returns a buffer that can be used for uniform storage when no other buffer is bound. */
+		VkBuffer getDummyUniformBuffer(UINT32 deviceIdx) const;
 
 	protected:     
 		/** @copydoc HardwareBufferCoreManager::createVertexBufferInternal */
@@ -37,6 +47,10 @@ namespace bs
 		/** @copydoc HardwareBufferCoreManager::createGpuParamsInternal */
 		SPtr<GpuParamsCore> createGpuParamsInternal(const SPtr<GpuPipelineParamInfoCore>& paramInfo,
 													GpuDeviceFlags deviceMask = GDF_DEFAULT) override;
+
+		VulkanHardwareBuffer* mDummyReadBuffer;
+		VulkanHardwareBuffer* mDummyStorageBuffer;
+		VulkanHardwareBuffer* mDummyUniformBuffer;
 	};
 
 	/** @} */

+ 3 - 3
Source/BansheeVulkanRenderAPI/Include/BsVulkanQueue.h

@@ -63,13 +63,12 @@ namespace bs
 		/** Information about a single submitted command buffer. */
 		struct SubmitInfo
 		{
-			SubmitInfo(VulkanCmdBuffer* cmdBuffer, UINT32 submitIdx, VulkanSemaphore** semaphores, UINT32 numSemaphores)
-				:cmdBuffer(cmdBuffer), submitIdx(submitIdx), semaphores(semaphores), numSemaphores(numSemaphores)
+			SubmitInfo(VulkanCmdBuffer* cmdBuffer, UINT32 submitIdx, UINT32 numSemaphores)
+				:cmdBuffer(cmdBuffer), submitIdx(submitIdx), numSemaphores(numSemaphores)
 			{ }
 
 			VulkanCmdBuffer* cmdBuffer;
 			UINT32 submitIdx;
-			VulkanSemaphore** semaphores;
 			UINT32 numSemaphores;
 		};
 
@@ -80,6 +79,7 @@ namespace bs
 		VkPipelineStageFlags mSubmitDstWaitMask[BS_MAX_UNIQUE_QUEUES];
 
 		List<SubmitInfo> mActiveBuffers;
+		Queue<VulkanSemaphore*> mActiveSemaphores;
 		VulkanCmdBuffer* mLastCommandBuffer;
 		UINT32 mNextSubmitIdx;
 

+ 0 - 11
Source/BansheeVulkanRenderAPI/Include/BsVulkanSamplerState.h

@@ -38,17 +38,6 @@ namespace bs
 		 */
 		VulkanSampler* getResource(UINT32 deviceIdx) const { return mSamplers[deviceIdx]; }
 
-		/* 
-		 * Returns a set sampler handles for the devices matching the provided mask. 
-		 * 
-		 * @param[in]	mask		Mask which determines for which devices we want the handles for. The device must exist 
-		 *							in both the provided mask and the mask of the sampler state was created with.
-		 * @param[out]	handles		Output array holding up to BS_MAX_LINKED_DEVICES handles. Only the first @p numHandles
-		 *							entries of the array are defined.
-		 * @param[out]	numHandles	Number of entries in the @p handles array. 
-		 */
-		void getHandles(GpuDeviceFlags mask, VkSampler(&handles)[BS_MAX_LINKED_DEVICES], UINT32& numHandles);
-
 	protected:
 		friend class VulkanRenderStateCoreManager;
 

+ 13 - 0
Source/BansheeVulkanRenderAPI/Include/BsVulkanTextureManager.h

@@ -26,6 +26,16 @@ namespace bs
 	/**	Handles creation of Vulkan textures. */
 	class VulkanTextureCoreManager : public TextureCoreManager
 	{
+	public:
+		/** @copydoc TextureCoreManager::onStartUp */
+		void onStartUp() override;
+
+		/** Returns a image view that can be used for shader read operations when no other image is bound. */
+		VkImageView getDummyReadImageView(UINT32 deviceIdx) const;
+
+		/** Returns a image view that can be used for shader storage operations when no other image is bound. */
+		VkImageView getDummyStorageImageView(UINT32 deviceIdx) const;
+
 	protected:
 		/** @copydoc TextureCoreManager::createTextureInternal */
 		SPtr<TextureCore> createTextureInternal(const TEXTURE_DESC& desc, 
@@ -34,6 +44,9 @@ namespace bs
 		/** @copydoc TextureCoreManager::createRenderTextureInternal */
 		SPtr<RenderTextureCore> createRenderTextureInternal(const RENDER_TEXTURE_DESC_CORE& desc, 
 			UINT32 deviceIdx = 0) override;
+
+		SPtr<VulkanTextureCore> mDummyReadTexture;
+		SPtr<VulkanTextureCore> mDummyStorageTexture;
 	};
 
 	/** @} */

+ 86 - 13
Source/BansheeVulkanRenderAPI/Source/BsVulkanGpuParams.cpp

@@ -13,6 +13,8 @@
 #include "BsVulkanSamplerState.h"
 #include "BsVulkanGpuPipelineParamInfo.h"
 #include "BsVulkanCommandBuffer.h"
+#include "BsVulkanTextureManager.h"
+#include "BsVulkanHardwareBufferManager.h"
 #include "BsGpuParamDesc.h"
 
 namespace bs
@@ -79,6 +81,11 @@ namespace bs
 		memset(mSetsDirty, 1, setsDirtyBytes);
 		dataIter += setsDirtyBytes;
 
+		VulkanSamplerStateCore* defaultSampler = static_cast<VulkanSamplerStateCore*>(SamplerStateCore::getDefault().get());
+		VulkanTextureCoreManager& vkTexManager = static_cast<VulkanTextureCoreManager&>(TextureCoreManager::instance());
+		VulkanHardwareBufferCoreManager& vkBufManager = static_cast<VulkanHardwareBufferCoreManager&>(
+			HardwareBufferCoreManager::instance());
+
 		for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
 		{
 			if (devices[i] == nullptr)
@@ -92,6 +99,8 @@ namespace bs
 			dataIter += perSetBytes;
 
 			VulkanDescriptorManager& descManager = devices[i]->getDescriptorManager();
+			VulkanSampler* vkDefaultSampler = defaultSampler->getResource(i);
+
 			for (UINT32 j = 0; j < numSets; j++)
 			{
 				UINT32 numBindingsPerSet = vkParamInfo.getNumBindings(j);
@@ -133,9 +142,18 @@ namespace bs
 						bool isLoadStore = writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
 
 						VkDescriptorImageInfo& imageInfo = perSetData.writeInfos[k].image;
-						imageInfo.sampler = VK_NULL_HANDLE;
-						imageInfo.imageView = VK_NULL_HANDLE;
-						imageInfo.imageLayout = isLoadStore ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+						imageInfo.sampler = vkDefaultSampler->getHandle();
+						
+						if(isLoadStore)
+						{
+							imageInfo.imageView = vkTexManager.getDummyStorageImageView(i);
+							imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
+						}
+						else
+						{
+							imageInfo.imageView = vkTexManager.getDummyReadImageView(i);
+							imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
+						}
 
 						writeSetInfo.pImageInfo = &imageInfo;
 						writeSetInfo.pBufferInfo = nullptr;
@@ -143,21 +161,32 @@ namespace bs
 					}
 					else
 					{
-						bool isLoadStore = writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+						bool isUniform = writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER;
 
-						if (!isLoadStore)
+						if (isUniform)
 						{
 							VkDescriptorBufferInfo& bufferInfo = perSetData.writeInfos[k].buffer;
-							bufferInfo.buffer = VK_NULL_HANDLE;
+							bufferInfo.buffer = vkBufManager.getDummyUniformBuffer(i);
 							bufferInfo.offset = 0;
 							bufferInfo.range = VK_WHOLE_SIZE;
 
 							writeSetInfo.pBufferInfo = &bufferInfo;
+							writeSetInfo.pTexelBufferView = nullptr;
 						}
 						else
+						{
 							writeSetInfo.pBufferInfo = nullptr;
 
-						writeSetInfo.pTexelBufferView = nullptr;
+							bool isLoadStore = writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+							VkBufferView bufferView;
+							if(isLoadStore)
+								bufferView = vkBufManager.getDummyStorageBufferView(i);
+							else
+								bufferView = vkBufManager.getDummyReadBufferView(i);
+
+							writeSetInfo.pTexelBufferView = &bufferView;
+						}
+
 						writeSetInfo.pImageInfo = nullptr;
 					}
 				}
@@ -198,7 +227,13 @@ namespace bs
 			if (bufferRes != nullptr)
 				mPerDeviceData[i].perSetData[set].writeInfos[bindingIdx].buffer.buffer = bufferRes->getHandle();
 			else
-				mPerDeviceData[i].perSetData[set].writeInfos[bindingIdx].buffer.buffer = VK_NULL_HANDLE;
+			{
+				VulkanHardwareBufferCoreManager& vkBufManager = static_cast<VulkanHardwareBufferCoreManager&>(
+					HardwareBufferCoreManager::instance());
+
+				mPerDeviceData[i].perSetData[set].writeInfos[bindingIdx].buffer.buffer = 
+					vkBufManager.getDummyUniformBuffer(i);
+			}
 		}
 
 		mSetsDirty[set] = true;
@@ -225,7 +260,16 @@ namespace bs
 			if (mPerDeviceData[i].perSetData == nullptr)
 				continue;
 
-			mPerDeviceData[i].perSetData[set].writeInfos[bindingIdx].image.imageView = vulkanTexture->getView(i);
+			VkImageView& imageView = mPerDeviceData[i].perSetData[set].writeInfos[bindingIdx].image.imageView;
+			if (vulkanTexture != nullptr)
+				imageView = vulkanTexture->getView(i);
+			else
+			{
+				VulkanTextureCoreManager& vkTexManager = static_cast<VulkanTextureCoreManager&>(
+					TextureCoreManager::instance());
+
+				imageView = vkTexManager.getDummyReadImageView(i);
+			}
 		}
 
 		mSetsDirty[set] = true;
@@ -253,7 +297,16 @@ namespace bs
 			if (mPerDeviceData[i].perSetData == nullptr)
 				continue;
 
-			mPerDeviceData[i].perSetData[set].writeInfos[bindingIdx].image.imageView = vulkanTexture->getView(i, surface);
+			VkImageView& imageView = mPerDeviceData[i].perSetData[set].writeInfos[bindingIdx].image.imageView;
+			if (vulkanTexture != nullptr)
+				imageView = vulkanTexture->getView(i, surface);
+			else
+			{
+				VulkanTextureCoreManager& vkTexManager = static_cast<VulkanTextureCoreManager&>(
+					TextureCoreManager::instance());
+
+				imageView = vkTexManager.getDummyStorageImageView(i);
+			}
 		}
 
 		mSetsDirty[set] = true;
@@ -281,10 +334,24 @@ namespace bs
 				continue;
 
 			VulkanBuffer* bufferRes = vulkanBuffer->getResource(i);
+			VkWriteDescriptorSet& writeSetInfo = mPerDeviceData[i].perSetData[set].writeSetInfos[bindingIdx];
+			VkBufferView bufferView;
+
 			if (bufferRes != nullptr)
-				mPerDeviceData[i].perSetData[set].writeInfos[bindingIdx].bufferView = bufferRes->getView();
+				bufferView = bufferRes->getView();
 			else
-				mPerDeviceData[i].perSetData[set].writeInfos[bindingIdx].bufferView = VK_NULL_HANDLE;
+			{
+				VulkanHardwareBufferCoreManager& vkBufManager = static_cast<VulkanHardwareBufferCoreManager&>(
+					HardwareBufferCoreManager::instance());
+
+				bool isLoadStore = writeSetInfo.descriptorType == VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
+				if(isLoadStore)
+					bufferView = vkBufManager.getDummyStorageBufferView(i);
+				else
+					bufferView = vkBufManager.getDummyReadBufferView(i);
+			}
+
+			writeSetInfo.pTexelBufferView = &bufferView;
 		}
 
 		mSetsDirty[set] = true;
@@ -315,7 +382,13 @@ namespace bs
 			if (samplerRes != nullptr)
 				mPerDeviceData[i].perSetData[set].writeInfos[bindingIdx].image.sampler = samplerRes->getHandle();
 			else
-				mPerDeviceData[i].perSetData[set].writeInfos[bindingIdx].image.sampler = VK_NULL_HANDLE;
+			{
+				VulkanSamplerStateCore* defaultSampler = 
+					static_cast<VulkanSamplerStateCore*>(SamplerStateCore::getDefault().get());
+
+				VkSampler vkSampler = defaultSampler->getResource(i)->getHandle();;
+				mPerDeviceData[i].perSetData[set].writeInfos[bindingIdx].image.sampler = vkSampler;
+			}
 		}
 
 		mSetsDirty[set] = true;

+ 34 - 1
Source/BansheeVulkanRenderAPI/Source/BsVulkanHardwareBufferManager.cpp

@@ -6,12 +6,45 @@
 #include "BsVulkanGpuBuffer.h"
 #include "BsVulkanGpuParamBlockBuffer.h"
 #include "BsVulkanGpuParams.h"
+#include "BsVulkanHardwareBuffer.h"
 #include "BsGpuParamDesc.h"
 
 namespace bs
 {
 	VulkanHardwareBufferCoreManager::VulkanHardwareBufferCoreManager()
-	{ }
+	{
+		// Note: When multi-GPU is properly tested, make sure to create these textures on all GPUs
+		mDummyReadBuffer = bs_new<VulkanHardwareBuffer>(
+			VulkanHardwareBuffer::BT_GENERIC, BF_32X1F, GBU_STATIC, 16, GDF_DEFAULT);
+
+		mDummyStorageBuffer = bs_new<VulkanHardwareBuffer>(
+			VulkanHardwareBuffer::BT_STORAGE, BF_32X1F, GBU_STATIC, 16, GDF_DEFAULT);
+
+		mDummyUniformBuffer = bs_new<VulkanHardwareBuffer>(
+			VulkanHardwareBuffer::BT_UNIFORM, BF_UNKNOWN, GBU_STATIC, 16, GDF_DEFAULT);
+	}
+
+	VulkanHardwareBufferCoreManager::~VulkanHardwareBufferCoreManager()
+	{
+		bs_delete(mDummyReadBuffer);
+		bs_delete(mDummyStorageBuffer);
+		bs_delete(mDummyUniformBuffer);
+	}
+
+	VkBufferView VulkanHardwareBufferCoreManager::getDummyReadBufferView(UINT32 deviceIdx) const
+	{
+		return mDummyReadBuffer->getResource(deviceIdx)->getView();
+	}
+
+	VkBufferView VulkanHardwareBufferCoreManager::getDummyStorageBufferView(UINT32 deviceIdx) const
+	{
+		return mDummyStorageBuffer->getResource(deviceIdx)->getView();
+	}
+
+	VkBuffer VulkanHardwareBufferCoreManager::getDummyUniformBuffer(UINT32 deviceIdx) const
+	{
+		return mDummyUniformBuffer->getResource(deviceIdx)->getHandle();
+	}
 
 	SPtr<VertexBufferCore> VulkanHardwareBufferCoreManager::createVertexBufferInternal(const VERTEX_BUFFER_DESC& desc,
 		GpuDeviceFlags deviceMask)

+ 16 - 4
Source/BansheeVulkanRenderAPI/Source/BsVulkanQueue.cpp

@@ -61,9 +61,11 @@ namespace bs
 		{
 			waitSemaphores[i]->notifyBound();
 			waitSemaphores[i]->notifyUsed(0, 0, VulkanUseFlag::Read | VulkanUseFlag::Write);
+
+			mActiveSemaphores.push(waitSemaphores[i]);
 		}
 
-		mActiveBuffers.push_back(SubmitInfo(cmdBuffer, mNextSubmitIdx++, waitSemaphores, semaphoresCount));
+		mActiveBuffers.push_back(SubmitInfo(cmdBuffer, mNextSubmitIdx++, semaphoresCount));
 	}
 
 	void VulkanQueue::present(VulkanSwapChain* swapChain, VulkanSemaphore** waitSemaphores, UINT32 semaphoresCount)
@@ -101,9 +103,11 @@ namespace bs
 		{
 			waitSemaphores[i]->notifyBound();
 			waitSemaphores[i]->notifyUsed(0, 0, VulkanUseFlag::Read | VulkanUseFlag::Write);
+
+			mActiveSemaphores.push(waitSemaphores[i]);
 		}
 
-		mActiveBuffers.push_back(SubmitInfo(nullptr, mNextSubmitIdx++, waitSemaphores, semaphoresCount));
+		mActiveBuffers.push_back(SubmitInfo(nullptr, mNextSubmitIdx++, semaphoresCount));
 	}
 
 	void VulkanQueue::waitIdle() const
@@ -121,7 +125,10 @@ namespace bs
 		{
 			VulkanCmdBuffer* cmdBuffer = iter->cmdBuffer;
 			if (cmdBuffer == nullptr)
+			{
+				++iter;
 				continue;
+			}
 
 			cmdBuffer->refreshFenceStatus();
 			if (cmdBuffer->isSubmitted())
@@ -137,8 +144,13 @@ namespace bs
 			if (iter->submitIdx > lastFinishedSubmission)
 				break;
 
-			for(UINT32 i = 0; i < iter->numSemaphores; i++)
-				iter->semaphores[i]->notifyDone(0, VulkanUseFlag::Read | VulkanUseFlag::Write);
+			for (UINT32 i = 0; i < iter->numSemaphores; i++)
+			{
+				VulkanSemaphore* semaphore = mActiveSemaphores.front();
+				mActiveSemaphores.pop();
+
+				semaphore->notifyDone(0, VulkanUseFlag::Read | VulkanUseFlag::Write);
+			}
 
 			iter = mActiveBuffers.erase(iter);
 		}

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

@@ -338,7 +338,7 @@ namespace bs
 		{
 			SPtr<GpuParamDesc> paramDesc = gpuParams->getParamDesc((GpuProgramType)i);
 			if (paramDesc == nullptr)
-				return;
+				continue;
 
 			// Flush all param block buffers
 			for (auto iter = paramDesc->paramBlocks.begin(); iter != paramDesc->paramBlocks.end(); ++iter)

+ 0 - 18
Source/BansheeVulkanRenderAPI/Source/BsVulkanSamplerState.cpp

@@ -79,22 +79,4 @@ namespace bs
 			mSamplers[i] = devices[i]->getResourceManager().create<VulkanSampler>(sampler);
 		}
 	}
-
-	void VulkanSamplerStateCore::getHandles(GpuDeviceFlags mask, VkSampler(&handles)[BS_MAX_LINKED_DEVICES], 
-		UINT32& numHandles)
-	{
-		numHandles = 0;
-
-		for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
-		{
-			UINT32 deviceMask = 1 << i;
-			if ((mask & deviceMask) == 0 || mSamplers[i] == nullptr)
-				continue;
-
-			handles[numHandles++] = mSamplers[i]->getHandle();
-
-			if (numHandles >= BS_MAX_LINKED_DEVICES)
-				break;
-		}
-	}
 }

+ 38 - 0
Source/BansheeVulkanRenderAPI/Source/BsVulkanTextureManager.cpp

@@ -3,6 +3,7 @@
 #include "BsVulkanTextureManager.h"
 #include "BsVulkanTexture.h"
 #include "BsVulkanRenderTexture.h"
+#include "BsVulkanResource.h"
 
 namespace bs
 {
@@ -18,6 +19,43 @@ namespace bs
 		return PF_R8G8B8A8;;
 	}
 
+	void VulkanTextureCoreManager::onStartUp()
+	{
+		TextureCoreManager::onStartUp();
+
+		SPtr<PixelData> whitePixelData = PixelData::create(2, 2, 1, PF_R8G8B8A8);
+		whitePixelData->setColorAt(Color::White, 0, 0);
+		whitePixelData->setColorAt(Color::White, 0, 1);
+		whitePixelData->setColorAt(Color::White, 1, 0);
+		whitePixelData->setColorAt(Color::White, 1, 1);
+
+		TEXTURE_DESC desc;
+		desc.type = TEX_TYPE_2D;
+		desc.width = 2;
+		desc.height = 2;
+		desc.format = PF_R8G8B8A8;
+		desc.usage = TU_STATIC;
+
+		// Note: When multi-GPU is properly tested, make sure to create these textures on all GPUs
+		mDummyReadTexture = std::static_pointer_cast<VulkanTextureCore>(createTexture(desc));
+		mDummyReadTexture->writeData(*whitePixelData);
+
+		desc.usage = TU_LOADSTORE;
+
+		mDummyStorageTexture = std::static_pointer_cast<VulkanTextureCore>(createTexture(desc));
+		mDummyStorageTexture->writeData(*whitePixelData);
+	}
+
+	VkImageView VulkanTextureCoreManager::getDummyReadImageView(UINT32 deviceIdx) const
+	{
+		return mDummyReadTexture->getResource(deviceIdx)->getView();
+	}
+
+	VkImageView VulkanTextureCoreManager::getDummyStorageImageView(UINT32 deviceIdx) const
+	{
+		return mDummyStorageTexture->getResource(deviceIdx)->getView();
+	}
+
 	SPtr<TextureCore> VulkanTextureCoreManager::createTextureInternal(const TEXTURE_DESC& desc,
 		const SPtr<PixelData>& initialData, GpuDeviceFlags deviceMask)
 	{