Ver Fonte

Vulkan: Properly handle unbound textures

BearishSun há 8 anos atrás
pai
commit
6edba43c31

+ 4 - 1
Data/Raw/Editor/Includes/SelectionBase.bslinc

@@ -20,7 +20,10 @@ Technique : base("SelectionBase") =
 
 		Fragment =
 		{
-			float4 selColor;
+			cbuffer FragParams
+			{	
+				float4 selColor;
+			};
 
 			float4 main(in float4 inPos : SV_Position) : SV_Target
 			{

+ 7 - 0
Source/BansheeCore/Include/BsCommonTypes.h

@@ -410,6 +410,13 @@ namespace bs
 		GPOT_RWTEXTURE2D = 51, /**< 2D texture with unordered read/writes. */
 		GPOT_RWTEXTURE3D = 52, /**< 3D texture with unordered read/writes. */
 		GPOT_RWTEXTURE2DMS = 53, /**< 2D texture with multiple samples and unordered read/writes. */
+		GPOT_TEXTURE1DARRAY = 54, /**< 1D texture with multiple array entries. */
+		GPOT_TEXTURE2DARRAY = 55, /**< 2D texture with multiple array entries. */
+		GPOT_TEXTURECUBEARRAY = 56, /**< Cubemap texture with multiple array entries. */
+		GPOT_TEXTURE2DMSARRAY = 57, /**< 2D texture with multiple samples and array entries. */
+		GPOT_RWTEXTURE1DARRAY = 58, /**< 1D texture with multiple array entries and unordered read/writes. */
+		GPOT_RWTEXTURE2DARRAY = 59, /**< 2D texture with multiple array entries and unordered read/writes. */
+		GPOT_RWTEXTURE2DMSARRAY = 60, /**< 2D texture with multiple array entries, samples and unordered read/writes. */
 		GPOT_UNKNOWN = 0xffff
 	};
 

+ 7 - 0
Source/BansheeCore/Source/BsShader.cpp

@@ -419,6 +419,10 @@ namespace bs
 		case GPOT_TEXTURE3D:
 		case GPOT_TEXTURECUBE:
 		case GPOT_TEXTURE2DMS:
+		case GPOT_TEXTURE1DARRAY:
+		case GPOT_TEXTURE2DARRAY:
+		case GPOT_TEXTURE2DMSARRAY:
+		case GPOT_TEXTURECUBEARRAY:
 			return true;
 		default:
 			return false;
@@ -433,6 +437,9 @@ namespace bs
 		case GPOT_RWTEXTURE2D:
 		case GPOT_RWTEXTURE3D:
 		case GPOT_RWTEXTURE2DMS:
+		case GPOT_RWTEXTURE1DARRAY:
+		case GPOT_RWTEXTURE2DARRAY:
+		case GPOT_RWTEXTURE2DMSARRAY:
 			return true;
 		default:
 			return false;

+ 24 - 7
Source/BansheeD3D11RenderAPI/Source/BsD3D11HLSLParamParser.cpp

@@ -118,24 +118,32 @@ namespace bs { namespace ct
 					switch (resourceDesc.Dimension)
 					{
 					case D3D_SRV_DIMENSION_TEXTURE1D:
-					case D3D_SRV_DIMENSION_TEXTURE1DARRAY:
 						memberDesc.type = GPOT_TEXTURE1D;
 						break;
+					case D3D_SRV_DIMENSION_TEXTURE1DARRAY:
+						memberDesc.type = GPOT_TEXTURE1DARRAY;
+						break;
 					case D3D_SRV_DIMENSION_TEXTURE2D:
-					case D3D_SRV_DIMENSION_TEXTURE2DARRAY:
 						memberDesc.type = GPOT_TEXTURE2D;
 						break;
+					case D3D_SRV_DIMENSION_TEXTURE2DARRAY:
+						memberDesc.type = GPOT_TEXTURE2DARRAY;
+						break;
 					case D3D_SRV_DIMENSION_TEXTURE3D:
 						memberDesc.type = GPOT_TEXTURE3D;
 						break;
 					case D3D_SRV_DIMENSION_TEXTURECUBE:
-					case D3D_SRV_DIMENSION_TEXTURECUBEARRAY:
 						memberDesc.type = GPOT_TEXTURECUBE;
 						break;
+					case D3D_SRV_DIMENSION_TEXTURECUBEARRAY:
+						memberDesc.type = GPOT_TEXTURECUBEARRAY;
+						break;
 					case D3D_SRV_DIMENSION_TEXTURE2DMS:
-					case D3D_SRV_DIMENSION_TEXTURE2DMSARRAY:
 						memberDesc.type = GPOT_TEXTURE2DMS;
 						break;
+					case D3D_SRV_DIMENSION_TEXTURE2DMSARRAY:
+						memberDesc.type = GPOT_TEXTURE2DMSARRAY;
+						break;
 					case D3D_SRV_DIMENSION_BUFFER:
 						memberDesc.type = GPOT_BYTE_BUFFER;
 						isTexture = false;
@@ -174,24 +182,33 @@ namespace bs { namespace ct
 					switch (resourceDesc.Dimension)
 					{
 					case D3D_SRV_DIMENSION_TEXTURE1D:
-					case D3D_SRV_DIMENSION_TEXTURE1DARRAY:
 						memberDesc.type = GPOT_RWTEXTURE1D;
 						desc.loadStoreTextures.insert(std::make_pair(memberDesc.name, memberDesc));
 						break;
+					case D3D_SRV_DIMENSION_TEXTURE1DARRAY:
+						memberDesc.type = GPOT_RWTEXTURE1DARRAY;
+						desc.loadStoreTextures.insert(std::make_pair(memberDesc.name, memberDesc));
+						break;
 					case D3D_SRV_DIMENSION_TEXTURE2D:
-					case D3D_SRV_DIMENSION_TEXTURE2DARRAY:
 						memberDesc.type = GPOT_RWTEXTURE2D;
 						desc.loadStoreTextures.insert(std::make_pair(memberDesc.name, memberDesc));
 						break;
+					case D3D_SRV_DIMENSION_TEXTURE2DARRAY:
+						memberDesc.type = GPOT_RWTEXTURE2DARRAY;
+						desc.loadStoreTextures.insert(std::make_pair(memberDesc.name, memberDesc));
+						break;
 					case D3D_SRV_DIMENSION_TEXTURE3D:
 						memberDesc.type = GPOT_RWTEXTURE3D;
 						desc.loadStoreTextures.insert(std::make_pair(memberDesc.name, memberDesc));
 						break;
 					case D3D_SRV_DIMENSION_TEXTURE2DMS:
-					case D3D_SRV_DIMENSION_TEXTURE2DMSARRAY:
 						memberDesc.type = GPOT_RWTEXTURE2DMS;
 						desc.loadStoreTextures.insert(std::make_pair(memberDesc.name, memberDesc));
 						break;
+					case D3D_SRV_DIMENSION_TEXTURE2DMSARRAY:
+						memberDesc.type = GPOT_RWTEXTURE2DMSARRAY;
+						desc.loadStoreTextures.insert(std::make_pair(memberDesc.name, memberDesc));
+						break;
 					case D3D_SRV_DIMENSION_BUFFER:
 						memberDesc.type = GPOT_RWTYPED_BUFFER;
 						desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));

+ 42 - 15
Source/BansheeGLRenderAPI/Source/BsGLSLParamParser.cpp

@@ -323,38 +323,50 @@ namespace bs { namespace ct
 			{
 			case GL_SAMPLER_1D:
 			case GL_SAMPLER_1D_SHADOW:
-			case GL_SAMPLER_1D_ARRAY:
-			case GL_SAMPLER_1D_ARRAY_SHADOW:
 			case GL_UNSIGNED_INT_SAMPLER_1D:
 			case GL_INT_SAMPLER_1D:
+				samplerType = GPOT_SAMPLER1D;
+				textureType = GPOT_TEXTURE1D;
+				isSampler = true;
+				break;
+			case GL_SAMPLER_1D_ARRAY:
+			case GL_SAMPLER_1D_ARRAY_SHADOW:
 			case GL_UNSIGNED_INT_SAMPLER_1D_ARRAY:
 			case GL_INT_SAMPLER_1D_ARRAY:
 				samplerType = GPOT_SAMPLER1D;
-				textureType = GPOT_TEXTURE1D;
+				textureType = GPOT_TEXTURE1DARRAY;
 				isSampler = true;
 				break;
 			case GL_SAMPLER_2D:
 			case GL_SAMPLER_2D_SHADOW:
-			case GL_SAMPLER_2D_ARRAY:
-			case GL_SAMPLER_2D_ARRAY_SHADOW:
 			case GL_UNSIGNED_INT_SAMPLER_2D:
 			case GL_INT_SAMPLER_2D:
+				samplerType = GPOT_SAMPLER2D;
+				textureType = GPOT_TEXTURE2D;
+				isSampler = true;
+				break;
+			case GL_SAMPLER_2D_ARRAY:
+			case GL_SAMPLER_2D_ARRAY_SHADOW:
 			case GL_UNSIGNED_INT_SAMPLER_2D_ARRAY:
 			case GL_INT_SAMPLER_2D_ARRAY:
 				samplerType = GPOT_SAMPLER2D;
-				textureType = GPOT_TEXTURE2D;
+				textureType = GPOT_TEXTURE2DARRAY;
 				isSampler = true;
 				break;
 			case GL_SAMPLER_2D_MULTISAMPLE:
-			case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
 			case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE:
-			case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
 			case GL_INT_SAMPLER_2D_MULTISAMPLE:
-			case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
 				samplerType = GPOT_SAMPLER2DMS;
 				textureType = GPOT_TEXTURE2DMS;
 				isSampler = true;
 				break;
+			case GL_SAMPLER_2D_MULTISAMPLE_ARRAY:
+			case GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+			case GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY:
+				samplerType = GPOT_SAMPLER2DMS;
+				textureType = GPOT_TEXTURE2DMSARRAY;
+				isSampler = true;
+				break;
 			case GL_SAMPLER_3D:
 			case GL_UNSIGNED_INT_SAMPLER_3D:
 			case GL_INT_SAMPLER_3D:
@@ -363,42 +375,57 @@ namespace bs { namespace ct
 				isSampler = true;
 				break;
 			case GL_SAMPLER_CUBE:
-			case GL_SAMPLER_CUBE_MAP_ARRAY:
 			case GL_SAMPLER_CUBE_SHADOW:
-			case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
 			case GL_UNSIGNED_INT_SAMPLER_CUBE:
 			case GL_INT_SAMPLER_CUBE:
+				samplerType = GPOT_SAMPLERCUBE;
+				textureType = GPOT_TEXTURECUBE;
+				isSampler = true;
+				break;
+			case GL_SAMPLER_CUBE_MAP_ARRAY:
+			case GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW:
 			case GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY:
 			case GL_INT_SAMPLER_CUBE_MAP_ARRAY:
 				samplerType = GPOT_SAMPLERCUBE;
-				textureType = GPOT_TEXTURECUBE;
+				textureType = GPOT_TEXTURECUBEARRAY;
 				isSampler = true;
 				break;
 			case GL_IMAGE_1D:
 			case GL_UNSIGNED_INT_IMAGE_1D:
 			case GL_INT_IMAGE_1D:
+				textureType = GPOT_RWTEXTURE1D;
+				isImage = true;
+				break;
 			case GL_IMAGE_1D_ARRAY:
 			case GL_UNSIGNED_INT_IMAGE_1D_ARRAY:
 			case GL_INT_IMAGE_1D_ARRAY:
-				textureType = GPOT_RWTEXTURE1D;
+				textureType = GPOT_RWTEXTURE1DARRAY;
 				isImage = true;
 				break;
 			case GL_IMAGE_2D:
 			case GL_UNSIGNED_INT_IMAGE_2D:
 			case GL_INT_IMAGE_2D:
+				textureType = GPOT_RWTEXTURE2D;
+				isImage = true;
+				break;
 			case GL_IMAGE_2D_ARRAY:
 			case GL_UNSIGNED_INT_IMAGE_2D_ARRAY:
 			case GL_INT_IMAGE_2D_ARRAY:
-				textureType = GPOT_RWTEXTURE2D;
+				textureType = GPOT_RWTEXTURE2DARRAY;
 				isImage = true;
 				break;
 			case GL_IMAGE_2D_MULTISAMPLE:
-			case GL_IMAGE_2D_MULTISAMPLE_ARRAY:
 			case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE:
 			case GL_INT_IMAGE_2D_MULTISAMPLE:
 				textureType = GPOT_RWTEXTURE2DMS;
 				isImage = true;
 				break;
+			case GL_IMAGE_2D_MULTISAMPLE_ARRAY:
+			case GL_UNSIGNED_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
+			case GL_INT_IMAGE_2D_MULTISAMPLE_ARRAY:
+				textureType = GPOT_RWTEXTURE2DMSARRAY;
+				isImage = true;
+				break;
 			case GL_IMAGE_3D:
 			case GL_UNSIGNED_INT_IMAGE_3D:
 			case GL_INT_IMAGE_3D:

+ 4 - 0
Source/BansheeVulkanRenderAPI/Include/BsVulkanGpuPipelineParamInfo.h

@@ -25,6 +25,9 @@ namespace bs { namespace ct
 		/** Returns a pointer to an array of bindings for the layout at the specified index. */
 		VkDescriptorSetLayoutBinding* getBindings(UINT32 layoutIdx) const { return mLayoutInfos[layoutIdx].bindings; }
 
+		/** Returns a pointer to any array of types expected by layout bindings. */
+		GpuParamObjectType* getLayoutTypes(UINT32 layoutIdx) const { return mLayoutInfos[layoutIdx].types; }
+
 		/** Returns the sequential index of the binding at the specificn set/slot. Returns -1 if slot is not used. */
 		UINT32 getBindingIdx(UINT32 set, UINT32 slot) const { return mSetExtraInfos[set].slotIndices[slot]; }
 
@@ -42,6 +45,7 @@ namespace bs { namespace ct
 		struct LayoutInfo
 		{
 			VkDescriptorSetLayoutBinding* bindings;
+			GpuParamObjectType* types;
 			UINT32 numBindings;
 		};
 

+ 4 - 7
Source/BansheeVulkanRenderAPI/Include/BsVulkanTextureManager.h

@@ -32,11 +32,8 @@ namespace bs
 		/** @copydoc TextureManager::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;
+		/** Returns a image view that can be used for shader operations when no other image is bound. */
+		VkImageView getDummyImageView(GpuParamObjectType type, UINT32 deviceIdx) const;
 
 	protected:
 		/** @copydoc TextureManager::createTextureInternal */
@@ -47,8 +44,8 @@ namespace bs
 		SPtr<RenderTexture> createRenderTextureInternal(const RENDER_TEXTURE_DESC& desc, 
 			UINT32 deviceIdx = 0) override;
 
-		SPtr<VulkanTexture> mDummyReadTexture;
-		SPtr<VulkanTexture> mDummyStorageTexture;
+		SPtr<VulkanTexture> mDummyReadTextures[7];
+		SPtr<VulkanTexture> mDummyStorageTextures[7];
 	};
 	}
 	/** @} */

+ 11 - 4
Source/BansheeVulkanRenderAPI/Source/BsVulkanGpuParams.cpp

@@ -136,6 +136,7 @@ namespace bs { namespace ct
 				perSetData.sets.push_back(perSetData.latestSet);
 
 				VkDescriptorSetLayoutBinding* perSetBindings = vkParamInfo.getBindings(j);
+				GpuParamObjectType* types = vkParamInfo.getLayoutTypes(j);
 				for (UINT32 k = 0; k < numBindingsPerSet; k++)
 				{
 					// Note: Instead of using one structure per binding, it's possible to update multiple at once
@@ -162,12 +163,12 @@ namespace bs { namespace ct
 						
 						if(isLoadStore)
 						{
-							imageInfo.imageView = vkTexManager.getDummyStorageImageView(i);
+							imageInfo.imageView = vkTexManager.getDummyImageView(types[k], i);
 							imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
 						}
 						else
 						{
-							imageInfo.imageView = vkTexManager.getDummyReadImageView(i);
+							imageInfo.imageView = vkTexManager.getDummyImageView(types[k], i);
 							imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
 						}
 
@@ -319,7 +320,10 @@ namespace bs { namespace ct
 				VulkanTextureManager& vkTexManager = static_cast<VulkanTextureManager&>(
 					TextureManager::instance());
 
-				perSetData.writeInfos[bindingIdx].image.imageView = vkTexManager.getDummyReadImageView(i);
+				GpuParamObjectType* types = vkParamInfo.getLayoutTypes(set);
+				GpuParamObjectType type = types[bindingIdx];
+
+				perSetData.writeInfos[bindingIdx].image.imageView = vkTexManager.getDummyImageView(type, i);
 				mPerDeviceData[i].sampledImages[sequentialIdx] = VK_NULL_HANDLE;
 			}
 		}
@@ -368,7 +372,10 @@ namespace bs { namespace ct
 				VulkanTextureManager& vkTexManager = static_cast<VulkanTextureManager&>(
 					TextureManager::instance());
 
-				perSetData.writeInfos[bindingIdx].image.imageView = vkTexManager.getDummyStorageImageView(i);
+				GpuParamObjectType* types = vkParamInfo.getLayoutTypes(set);
+				GpuParamObjectType type = types[bindingIdx];
+
+				perSetData.writeInfos[bindingIdx].image.imageView = vkTexManager.getDummyImageView(type, i);
 				mPerDeviceData[i].storageImages[sequentialIdx] = VK_NULL_HANDLE;
 			}
 		}

+ 28 - 2
Source/BansheeVulkanRenderAPI/Source/BsVulkanGpuPipelineParamInfo.cpp

@@ -37,6 +37,7 @@ namespace bs { namespace ct
 			totalNumSlots += mSetInfos[i].numSlots;
 
 		mAlloc.reserve<VkDescriptorSetLayoutBinding>(mNumElements)
+			.reserve<GpuParamObjectType>(mNumElements)
 			.reserve<LayoutInfo>(mNumSets)
 			.reserve<VulkanDescriptorLayout*>(mNumSets * numDevices)
 			.reserve<SetExtraInfo>(mNumSets)
@@ -45,6 +46,7 @@ namespace bs { namespace ct
 
 		mLayoutInfos = mAlloc.alloc<LayoutInfo>(mNumSets);
 		VkDescriptorSetLayoutBinding* bindings = mAlloc.alloc<VkDescriptorSetLayoutBinding>(mNumElements);
+		GpuParamObjectType* types = mAlloc.alloc<GpuParamObjectType>(mNumElements);
 
 		for (UINT32 i = 0; i < BS_MAX_DEVICES; i++)
 		{
@@ -62,6 +64,9 @@ namespace bs { namespace ct
 		if(bindings != nullptr)
 			bs_zero_out(bindings, mNumElements);
 
+		if (types != nullptr)
+			bs_zero_out(types, mNumElements);
+
 		UINT32 globalBindingIdx = 0;
 		for (UINT32 i = 0; i < mNumSets; i++)
 		{
@@ -69,6 +74,7 @@ namespace bs { namespace ct
 
 			mLayoutInfos[i].numBindings = 0;
 			mLayoutInfos[i].bindings = nullptr;
+			mLayoutInfos[i].types = nullptr;
 
 			for (UINT32 j = 0; j < mSetInfos[i].numSlots; j++)
 			{
@@ -91,6 +97,7 @@ namespace bs { namespace ct
 		for (UINT32 i = 0; i < mNumSets; i++)
 		{
 			mLayoutInfos[i].bindings = &bindings[offset];
+			mLayoutInfos[i].types = &types[offset];
 			offset += mLayoutInfos[i].numBindings;
 		}
 
@@ -109,6 +116,21 @@ namespace bs { namespace ct
 			if (paramDesc == nullptr)
 				continue;
 
+			auto setUpBlockBindings = [&](auto& params, VkDescriptorType descType)
+			{
+				for (auto& entry : params)
+				{
+					UINT32 bindingIdx = getBindingIdx(entry.second.set, entry.second.slot);
+					assert(bindingIdx != -1);
+
+					LayoutInfo& layoutInfo = mLayoutInfos[entry.second.set];
+					VkDescriptorSetLayoutBinding& binding = layoutInfo.bindings[bindingIdx];
+					binding.descriptorCount = 1;
+					binding.stageFlags |= stageFlagsLookup[i];
+					binding.descriptorType = descType;
+				}
+			};
+
 			auto setUpBindings = [&](auto& params, VkDescriptorType descType)
 			{
 				for (auto& entry : params)
@@ -121,14 +143,16 @@ namespace bs { namespace ct
 					binding.descriptorCount = 1;
 					binding.stageFlags |= stageFlagsLookup[i];
 					binding.descriptorType = descType;
+
+					layoutInfo.types[bindingIdx] = entry.second.type;
 				}
 			};
 
 			// Note: Assuming all textures and samplers use the same set/slot combination, and that they're combined
-			setUpBindings(paramDesc->paramBlocks, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
+			setUpBlockBindings(paramDesc->paramBlocks, VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER);
 			setUpBindings(paramDesc->textures, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
 			setUpBindings(paramDesc->loadStoreTextures, VK_DESCRIPTOR_TYPE_STORAGE_IMAGE);
-			setUpBindings(paramDesc->samplers, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
+			//setUpBindings(paramDesc->samplers, VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER);
 
 			// Set up buffer bindings
 			for (auto& entry : paramDesc->buffers)
@@ -155,6 +179,8 @@ namespace bs { namespace ct
 					binding.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_BUFFER;
 					break;
 				}
+
+				layoutInfo.types[bindingIdx] = entry.second.type;
 			}
 		}
 

+ 15 - 5
Source/BansheeVulkanRenderAPI/Source/BsVulkanGpuProgram.cpp

@@ -453,8 +453,13 @@ namespace bs { namespace ct
 				{
 					switch (sampler.dim)
 					{
-					case glslang::Esd1D:		param.type = GPOT_RWTEXTURE1D; break;
-					case glslang::Esd2D:		param.type = sampler.isMultiSample() ? GPOT_RWTEXTURE2DMS : GPOT_RWTEXTURE2D; break;
+					case glslang::Esd1D:		param.type = sampler.isArrayed() ? GPOT_RWTEXTURE1DARRAY : GPOT_RWTEXTURE1D; break;
+					case glslang::Esd2D:
+						if(sampler.isArrayed())
+							param.type = sampler.isMultiSample() ? GPOT_RWTEXTURE2DMSARRAY : GPOT_RWTEXTURE2DARRAY; 
+						else
+							param.type = sampler.isMultiSample() ? GPOT_RWTEXTURE2DMS : GPOT_RWTEXTURE2D;
+						break;
 					case glslang::Esd3D:		param.type = GPOT_RWTEXTURE3D; break;
 					case glslang::EsdBuffer:	param.type = GPOT_RWBYTE_BUFFER; break;
 					}
@@ -480,10 +485,15 @@ namespace bs { namespace ct
 					{
 						switch (sampler.dim)
 						{
-						case glslang::Esd1D:		param.type = GPOT_TEXTURE1D; break;
-						case glslang::Esd2D:		param.type = sampler.isMultiSample() ? GPOT_TEXTURE2DMS : GPOT_TEXTURE2D; break;
+						case glslang::Esd1D:		param.type = sampler.isArrayed() ? GPOT_TEXTURE1DARRAY : GPOT_TEXTURE1D; break;
+						case glslang::Esd2D:
+							if(sampler.isArrayed())
+								param.type = sampler.isMultiSample() ? GPOT_TEXTURE2DMSARRAY : GPOT_TEXTURE2DARRAY; 
+							else
+								param.type = sampler.isMultiSample() ? GPOT_TEXTURE2DMS : GPOT_TEXTURE2D;
+							break;
 						case glslang::Esd3D:		param.type = GPOT_TEXTURE3D; break;
-						case glslang::EsdCube:		param.type = GPOT_TEXTURECUBE; break;
+						case glslang::EsdCube:		param.type = sampler.isArrayed() ? GPOT_TEXTURECUBEARRAY : GPOT_TEXTURECUBE; break;
 						case glslang::EsdBuffer:	param.type = GPOT_BYTE_BUFFER; break;
 						}
 

+ 88 - 22
Source/BansheeVulkanRenderAPI/Source/BsVulkanTextureManager.cpp

@@ -8,6 +8,26 @@
 
 namespace bs
 {
+	struct DummyTexFormat
+	{
+		TextureType type;
+		int arraySize;
+		int width;
+		int height;
+		int depth;
+	};
+
+	const static DummyTexFormat DummyTexTypes[] =
+	{
+		{ TEX_TYPE_1D,			1, 2, 1, 1 },
+		{ TEX_TYPE_1D,			2, 2, 1, 1 },
+		{ TEX_TYPE_2D,			1, 2, 2, 1 },
+		{ TEX_TYPE_2D,			2, 2, 2, 1 },
+		{ TEX_TYPE_3D,			1, 2, 2, 2 },
+		{ TEX_TYPE_CUBE_MAP,	1, 2, 2, 1 },
+		{ TEX_TYPE_CUBE_MAP,	2, 2, 2, 1 }
+	};
+
 	SPtr<RenderTexture> VulkanTextureManager::createRenderTextureImpl(const RENDER_TEXTURE_DESC& desc)
 	{
 		VulkanRenderTexture* tex = new (bs_alloc<VulkanRenderTexture>()) VulkanRenderTexture(desc);
@@ -31,36 +51,82 @@ namespace bs
 	{
 		TextureManager::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);
+		int idx = 0;
+		for(auto& entry : DummyTexTypes)
+		{
+			SPtr<PixelData> pixelData = PixelData::create(entry.width, entry.height, entry.depth, PF_R8G8B8A8);
 
-		TEXTURE_DESC desc;
-		desc.type = TEX_TYPE_2D;
-		desc.width = 2;
-		desc.height = 2;
-		desc.format = PF_R8G8B8A8;
-		desc.usage = TU_STATIC;
+			for(int depth = 0; depth < entry.depth; depth++)
+				for(int height = 0; height < entry.height; height++)
+					for(int width = 0; width < entry.width; width++)
+						pixelData->setColorAt(Color::White, width, height, depth);
 
-		// Note: When multi-GPU is properly tested, make sure to create these textures on all GPUs
-		mDummyReadTexture = std::static_pointer_cast<VulkanTexture>(createTexture(desc));
-		mDummyReadTexture->writeData(*whitePixelData);
+			TEXTURE_DESC desc;
+			desc.type = entry.type;
+			desc.width = entry.width;
+			desc.height = entry.height;
+			desc.depth = entry.depth;
+			desc.format = PF_R8G8B8A8;
+			desc.usage = TU_STATIC;
 
-		desc.usage = TU_LOADSTORE;
+			mDummyReadTextures[idx] = std::static_pointer_cast<VulkanTexture>(createTexture(desc));
+			mDummyReadTextures[idx]->writeData(*pixelData);
 
-		mDummyStorageTexture = std::static_pointer_cast<VulkanTexture>(createTexture(desc));
-	}
+			desc.usage = TU_LOADSTORE;
+			mDummyStorageTextures[idx] = std::static_pointer_cast<VulkanTexture>(createTexture(desc));
 
-	VkImageView VulkanTextureManager::getDummyReadImageView(UINT32 deviceIdx) const
-	{
-		return mDummyReadTexture->getResource(deviceIdx)->getView(false);
+			idx++;
+		}
 	}
 
-	VkImageView VulkanTextureManager::getDummyStorageImageView(UINT32 deviceIdx) const
+	VkImageView VulkanTextureManager::getDummyImageView(GpuParamObjectType type, UINT32 deviceIdx) const
 	{
-		return mDummyStorageTexture->getResource(deviceIdx)->getView(false);
+		SPtr<VulkanTexture> texture;
+		switch(type)
+		{
+		case GPOT_TEXTURE2DMS:
+		case GPOT_TEXTURE2D:
+			texture = mDummyReadTextures[2];
+			break;
+		case GPOT_RWTEXTURE2D:
+		case GPOT_RWTEXTURE2DMS:
+			texture = mDummyStorageTextures[2];
+			break;
+		case GPOT_TEXTURECUBE:
+			texture = mDummyReadTextures[5];
+			break;
+		case GPOT_TEXTURECUBEARRAY:
+			texture = mDummyReadTextures[6];
+			break;
+		case GPOT_TEXTURE2DARRAY:
+		case GPOT_TEXTURE2DMSARRAY:
+			texture = mDummyReadTextures[3];
+			break;
+		case GPOT_RWTEXTURE2DARRAY:
+		case GPOT_RWTEXTURE2DMSARRAY:
+			texture = mDummyStorageTextures[3];
+			break;
+		case GPOT_TEXTURE3D:
+			texture = mDummyReadTextures[4];
+			break;
+		case GPOT_RWTEXTURE3D:
+			texture = mDummyStorageTextures[4];
+			break;
+		case GPOT_TEXTURE1D:
+			texture = mDummyReadTextures[0];
+			break;
+		case GPOT_TEXTURE1DARRAY:
+			texture = mDummyReadTextures[1];
+			break;
+		case GPOT_RWTEXTURE1D:
+			texture = mDummyStorageTextures[0];
+			break;
+		case GPOT_RWTEXTURE1DARRAY:
+			texture = mDummyStorageTextures[1];
+			break;
+		}
+
+		return texture->getResource(deviceIdx)->getView(false);
 	}
 
 	SPtr<Texture> VulkanTextureManager::createTextureInternal(const TEXTURE_DESC& desc,