Browse Source

Fixing and refactoring GpuParams

BearishSun 9 years ago
parent
commit
efd471af58

+ 3 - 0
Source/BansheeCore/Include/BsGpuParams.h

@@ -52,6 +52,9 @@ namespace bs
 		/** Returns a description of all stored parameters. */
 		SPtr<GpuParamDesc> getParamDesc(GpuProgramType type) const;
 
+		/** Gets the object that contains the processed information about all parameters. */
+		SPtr<GpuPipelineParamInfoBase> getParamInfo() const { return mParamInfo; }
+
 		/**
 		 * Returns the size of a data parameter with the specified name, in bytes. Returns 0 if such parameter doesn't exist.
 		 */

+ 22 - 24
Source/BansheeCore/Include/BsGpuPipelineParamInfo.h

@@ -36,44 +36,42 @@ namespace bs
 		GpuPipelineParamInfoBase(const GPU_PIPELINE_PARAMS_DESC& desc);
 		virtual ~GpuPipelineParamInfoBase();
 
-		/** Gets the total number of sets, across all parameter types. */
-		UINT32 getNumSets() const { return mTotalNumSets; }
-
-		/** Returns the number of sets for the specified parameter type. */
-		UINT32 getNumSets(ParamType type) { return mNumSets[(int)type]; }
+		/** Gets the total number of sets. */
+		UINT32 getNumSets() const { return mNumSets; }
 
 		/** Returns the total number of elements across all sets. */
-		UINT32 getNumElements() const { return mTotalNumElements; }
+		UINT32 getNumElements() const { return mNumElements; }
 
 		/** Returns the number of elements in all sets for the specified parameter type. */
-		UINT32 getNumElements(ParamType type) { return mNumElements[(int)type]; }
-
-		/**
-		* Assuming all elements for a specific parameter type are laid out sequentially and grouped by their sets,
-		* returns the sequential index to the first parameter of the provided set.
-		*/
-		UINT32 getSetOffset(ParamType type, UINT32 set) { return mOffsets[(int)type][set]; }
+		UINT32 getNumElements(ParamType type) { return mNumElementsPerType[(int)type]; }
 
 		/**
-		* Converts a set/slot combination into a sequential index that maps to the parameter in that parameter type's
-		* array.
-		*
-		* If the set or slot is out of valid range, the method logs an error and returns -1. Only performs range checking
-		* in debug mode.
-		*/
+		 * Converts a set/slot combination into a sequential index that maps to the parameter in that parameter type's
+		 * array.
+		 *
+		 * If the set or slot is out of valid range, the method logs an error and returns -1. Only performs range checking
+		 * in debug mode.
+		 */
 		UINT32 getSequentialSlot(ParamType type, UINT32 set, UINT32 slot) const;
 
 		/** Returns descriptions of individual parameters for the specified GPU program type. */
 		const SPtr<GpuParamDesc>& getParamDesc(GpuProgramType type) const { return mParamDescs[(int)type]; }
 
 	protected:
+		/** Information about a single set in the param info object. */
+		struct SetInfo
+		{
+			UINT32* slotIndices;
+			ParamType* slotTypes;
+			UINT32 numSlots;
+		};
+		
 		std::array<SPtr<GpuParamDesc>, 6> mParamDescs;
 
-		UINT32 mTotalNumSets;
-		UINT32 mTotalNumElements;
-		UINT32 mNumSets[(int)ParamType::Count];
-		UINT32 mNumElements[(int)ParamType::Count];
-		UINT32* mOffsets[(int)ParamType::Count];
+		UINT32 mNumSets;
+		UINT32 mNumElements;
+		SetInfo* mSetInfos;
+		UINT32 mNumElementsPerType[(int)ParamType::Count];
 
 		UINT8* mData;
 	};

+ 113 - 87
Source/BansheeCore/Source/BsGpuPipelineParamInfo.cpp

@@ -7,8 +7,10 @@
 namespace bs
 {
 	GpuPipelineParamInfoBase::GpuPipelineParamInfoBase(const GPU_PIPELINE_PARAMS_DESC& desc)
-		:mTotalNumSets(0), mTotalNumElements(0)
+		:mNumSets(0), mNumElements(0), mSetInfos(nullptr)
 	{
+		bs_zero_out(mNumElementsPerType);
+
 		mParamDescs[GPT_FRAGMENT_PROGRAM] = desc.fragmentParams;
 		mParamDescs[GPT_VERTEX_PROGRAM] = desc.vertexParams;
 		mParamDescs[GPT_GEOMETRY_PROGRAM] = desc.geometryParams;
@@ -16,13 +18,6 @@ namespace bs
 		mParamDescs[GPT_DOMAIN_PROGRAM] = desc.domainParams;
 		mParamDescs[GPT_COMPUTE_PROGRAM] = desc.computeParams;
 
-		for (UINT32 i = 0; i < (UINT32)ParamType::Count; i++)
-		{
-			mNumSets[i] = 0;
-			mNumElements[i] = 0;
-			mOffsets[i] = nullptr;
-		}
-
 		UINT32 numParamDescs = sizeof(mParamDescs) / sizeof(mParamDescs[0]);
 		for (UINT32 i = 0; i < numParamDescs; i++)
 		{
@@ -32,52 +27,100 @@ namespace bs
 
 			for (auto& paramBlock : paramDesc->paramBlocks)
 			{
-				if ((paramBlock.second.set + 1) > mNumSets[(int)ParamType::ParamBlock])
-					mNumSets[(int)ParamType::ParamBlock] = paramBlock.second.set + 1;
+				if ((paramBlock.second.set + 1) > mNumSets)
+					mNumSets = paramBlock.second.set + 1;
+
+				mNumElements++;
 			}
 
 			for (auto& texture : paramDesc->textures)
 			{
-				if ((texture.second.set + 1) > mNumSets[(int)ParamType::Texture])
-					mNumSets[(int)ParamType::Texture] = texture.second.set + 1;
+				if ((texture.second.set + 1) > mNumSets)
+					mNumSets = texture.second.set + 1;
+
+				mNumElements++;
 			}
 
 			for (auto& texture : paramDesc->loadStoreTextures)
 			{
-				if ((texture.second.set + 1) > mNumSets[(int)ParamType::LoadStoreTexture])
-					mNumSets[(int)ParamType::LoadStoreTexture] = texture.second.set + 1;
+				if ((texture.second.set + 1) > mNumSets)
+					mNumSets = texture.second.set + 1;
+
+				mNumElements++;
 			}
 
 			for (auto& buffer : paramDesc->buffers)
 			{
-				if ((buffer.second.set + 1) > mNumSets[(int)ParamType::Buffer])
-					mNumSets[(int)ParamType::Buffer] = buffer.second.set + 1;
+				if ((buffer.second.set + 1) > mNumSets)
+					mNumSets = buffer.second.set + 1;
+
+				mNumElements++;
 			}
 
 			for (auto& sampler : paramDesc->samplers)
 			{
-				if ((sampler.second.set + 1) > mNumSets[(int)ParamType::SamplerState])
-					mNumSets[(int)ParamType::SamplerState] = sampler.second.set + 1;
+				if ((sampler.second.set + 1) > mNumSets)
+					mNumSets = sampler.second.set + 1;
+
+				mNumElements++;
 			}
 		}
 
-		UINT32 totalNumSets = 0;
-		for (UINT32 i = 0; i < (UINT32)ParamType::Count; i++)
+		UINT32* numSlotsPerSet = (UINT32*)bs_stack_alloc(mNumSets * sizeof(UINT32));
+		bs_zero_out(numSlotsPerSet, mNumSets);
+
+		for (UINT32 i = 0; i < numParamDescs; i++)
 		{
-			totalNumSets += mNumSets[i];
-			mTotalNumSets = std::max(mTotalNumSets, mNumSets[i]);
+			const SPtr<GpuParamDesc>& paramDesc = mParamDescs[i];
+			if (paramDesc == nullptr)
+				continue;
+
+			for (auto& paramBlock : paramDesc->paramBlocks)
+				numSlotsPerSet[paramBlock.second.set] = 
+					std::max(numSlotsPerSet[paramBlock.second.set], paramBlock.second.slot + 1);
+
+			for (auto& texture : paramDesc->textures)
+				numSlotsPerSet[texture.second.set] =
+					std::max(numSlotsPerSet[texture.second.set], texture.second.slot + 1);
+
+			for (auto& texture : paramDesc->loadStoreTextures)
+				numSlotsPerSet[texture.second.set] =
+					std::max(numSlotsPerSet[texture.second.set], texture.second.slot + 1);
+
+			for (auto& buffer : paramDesc->buffers)
+				numSlotsPerSet[buffer.second.set] =
+					std::max(numSlotsPerSet[buffer.second.set], buffer.second.slot + 1);
+
+			for (auto& sampler : paramDesc->samplers)
+				numSlotsPerSet[sampler.second.set] =
+					std::max(numSlotsPerSet[sampler.second.set], sampler.second.slot + 1);
 		}
 
-		UINT32* slotsPerSetData = bs_stack_alloc<UINT32>(totalNumSets);
-		memset(slotsPerSetData, 0, sizeof(UINT32) * totalNumSets);
+		UINT32 totalNumSlots = 0;
+		for (UINT32 i = 0; i < mNumSets; i++)
+			totalNumSlots += numSlotsPerSet[i];
+
+		UINT32 allocSize = mNumSets * sizeof(SetInfo) + totalNumSlots * (sizeof(UINT32) * sizeof(ParamType));
+		mData = (UINT8*)bs_alloc(allocSize);
+		UINT8* dataPtr = mData;
+
+		mSetInfos = (SetInfo*)dataPtr;
+		bs_zero_out(mSetInfos, mNumSets);
+
+		dataPtr += mNumSets * sizeof(SetInfo);
+
+		for (UINT32 i = 0; i < mNumSets; i++)
+			mSetInfos[i].numSlots = numSlotsPerSet[i];
+
+		bs_stack_free(numSlotsPerSet);
 
-		UINT32* slotsPerSet[(UINT32)ParamType::Count];
-		for (UINT32 i = 0; i < (UINT32)ParamType::Count; i++)
+		for(UINT32 i = 0; i < mNumSets; i++)
 		{
-			if (i == 0)
-				slotsPerSet[i] = slotsPerSetData;
-			else
-				slotsPerSet[i] = slotsPerSet[i - 1] + mNumSets[i - 1];
+			mSetInfos[i].slotIndices = (UINT32*)dataPtr;
+			dataPtr += sizeof(UINT32) * mSetInfos[i].numSlots;
+
+			mSetInfos[i].slotTypes = (ParamType*)dataPtr;
+			dataPtr += sizeof(ParamType) * mSetInfos[i].numSlots;
 		}
 
 		for (UINT32 i = 0; i < numParamDescs; i++)
@@ -88,62 +131,49 @@ namespace bs
 
 			for (auto& paramBlock : paramDesc->paramBlocks)
 			{
-				UINT32* slots = slotsPerSet[(int)ParamType::ParamBlock];
-				slots[paramBlock.second.set] = std::max(slots[paramBlock.second.set], paramBlock.second.slot + 1);
+				SetInfo& setInfo = mSetInfos[paramBlock.second.set];
+				setInfo.slotIndices[paramBlock.second.slot] = mNumElementsPerType[(int)ParamType::ParamBlock];
+				setInfo.slotTypes[paramBlock.second.slot] = ParamType::ParamBlock;
+
+				mNumElementsPerType[(int)ParamType::ParamBlock]++;
 			}
 
 			for (auto& texture : paramDesc->textures)
 			{
-				UINT32* slots = slotsPerSet[(int)ParamType::Texture];
-				slots[texture.second.set] = std::max(slots[texture.second.set], texture.second.slot + 1);
+				SetInfo& setInfo = mSetInfos[texture.second.set];
+				setInfo.slotIndices[texture.second.slot] = mNumElementsPerType[(int)ParamType::Texture];
+				setInfo.slotTypes[texture.second.slot] = ParamType::Texture;
+
+				mNumElementsPerType[(int)ParamType::Texture]++;
 			}
 
 			for (auto& texture : paramDesc->loadStoreTextures)
 			{
-				UINT32* slots = slotsPerSet[(int)ParamType::LoadStoreTexture];
-				slots[texture.second.set] = std::max(slots[texture.second.set], texture.second.slot + 1);
+				SetInfo& setInfo = mSetInfos[texture.second.set];
+				setInfo.slotIndices[texture.second.slot] = mNumElementsPerType[(int)ParamType::LoadStoreTexture];
+				setInfo.slotTypes[texture.second.slot] = ParamType::LoadStoreTexture;
+
+				mNumElementsPerType[(int)ParamType::LoadStoreTexture]++;
 			}
 
 			for (auto& buffer : paramDesc->buffers)
 			{
-				UINT32* slots = slotsPerSet[(int)ParamType::Buffer];
-				slots[buffer.second.set] = std::max(slots[buffer.second.set], buffer.second.slot + 1);
+				SetInfo& setInfo = mSetInfos[buffer.second.set];
+				setInfo.slotIndices[buffer.second.slot] = mNumElementsPerType[(int)ParamType::Buffer];
+				setInfo.slotTypes[buffer.second.slot] = ParamType::Buffer;
+
+				mNumElementsPerType[(int)ParamType::Buffer]++;
 			}
 
 			for (auto& sampler : paramDesc->samplers)
 			{
-				UINT32* slots = slotsPerSet[(int)ParamType::SamplerState];
-				slots[sampler.second.set] = std::max(slots[sampler.second.set], sampler.second.slot + 1);
-			}
-		}
-
-		for (UINT32 i = 0; i < (UINT32)ParamType::Count; i++)
-		{
-			for (UINT32 j = 0; j < mNumSets[i]; j++)
-				mNumElements[i] += slotsPerSet[i][j];
-
-			mTotalNumElements += mNumElements[i];
-		}
-
-		UINT32 setOffsetsSize = sizeof(UINT32) * totalNumSets;
-		mData = (UINT8*)bs_alloc(setOffsetsSize);
-
-		UINT8* dataPtr = mData;
-		for (UINT32 i = 0; i < (UINT32)ParamType::Count; i++)
-		{
-			mOffsets[i] = (UINT32*)dataPtr;
-			dataPtr += sizeof(UINT32) * mNumSets[i];
+				SetInfo& setInfo = mSetInfos[sampler.second.set];
+				setInfo.slotIndices[sampler.second.slot] = mNumElementsPerType[(int)ParamType::SamplerState];
+				setInfo.slotTypes[sampler.second.slot] = ParamType::SamplerState;
 
-			if (mNumSets[i] == 0)
-				continue;
-
-			mOffsets[i][0] = 0;
-
-			for (UINT32 j = 0; j < mNumSets[i] - 1; j++)
-				mOffsets[i][j + 1] = mOffsets[i][j] + slotsPerSet[i][j];
+				mNumElementsPerType[(int)ParamType::SamplerState]++;
+			}
 		}
-
-		bs_stack_free(slotsPerSetData);
 	}
 
 	GpuPipelineParamInfoBase::~GpuPipelineParamInfoBase()
@@ -154,34 +184,30 @@ namespace bs
 	UINT32 GpuPipelineParamInfoBase::getSequentialSlot(ParamType type, UINT32 set, UINT32 slot) const
 	{
 #if BS_DEBUG_MODE
-		if (set >= mNumSets[(int)type])
+		if (set >= mNumSets)
 		{
 			LOGERR("Set index out of range: Valid range: 0 .. " +
-				   toString(mNumSets[(int)type] - 1) + ". Requested: " + toString(set));
-			return (UINT32)-1;
+				   toString(mNumSets - 1) + ". Requested: " + toString(set));
+			return -1;
 		}
-#endif
-
-		UINT32 globalSlot = mOffsets[(int)type][set] + slot;
 
-#if BS_DEBUG_MODE
-		if (globalSlot >= mNumElements[(int)type])
+		if (slot >= mSetInfos[set].numSlots)
 		{
-			UINT32 maxSlot;
-			if (set < (mNumSets[(int)type] - 1))
-				maxSlot = mOffsets[(int)type][set + 1];
-			else
-				maxSlot = mNumElements[(int)type];
-
-			maxSlot -= mOffsets[(int)type][set];
-
 			LOGERR("Slot index out of range: Valid range: 0 .. " +
-				   toString(maxSlot - 1) + ". Requested: " + toString(slot));
-			return (UINT32)-1;
+				   toString(mSetInfos[set].numSlots - 1) + ". Requested: " + toString(slot));
+			return -1;
 		}
+
+		if(mSetInfos[set].slotTypes[slot] != type)
+		{
+			LOGERR("Requested parameter is not of the valid type. Requested: " + toString((UINT32)type) + ". Actual: " + 
+				toString((UINT32)mSetInfos[set].slotTypes[slot]) + ".");
+			return -1;
+		}
+
 #endif
 
-		return globalSlot;
+		return mSetInfos[set].slotIndices[slot];
 	}
 
 	GpuPipelineParamInfoCore::GpuPipelineParamInfoCore(const GPU_PIPELINE_PARAMS_DESC& desc, GpuDeviceFlags deviceMask)

+ 13 - 0
Source/BansheeD3D11RenderAPI/Include/BsD3D11HLSLParamParser.h

@@ -28,6 +28,16 @@ namespace bs
 		void parse(ID3DBlob* microcode, GpuProgramType type, GpuParamDesc& desc, List<VertexElement>* inputParams);
 
 	private:
+		/** Types of HLSL parameters. */
+		enum class ParamType
+		{
+			ConstantBuffer,
+			Texture,
+			Sampler,
+			UAV,
+			Count // Keep at end
+		};
+
 		/**
 		 * Parses the provided constant buffer retrieving information about all of its members and storing them in the
 		 * provided GPU params description object.
@@ -43,6 +53,9 @@ namespace bs
 		 */
 		void parseVariable(D3D11_SHADER_TYPE_DESC& varTypeDesc, D3D11_SHADER_VARIABLE_DESC& varDesc, GpuParamDesc& desc,
 			GpuParamBlockDesc& paramBlock);
+
+		/** Maps a parameter in a specific shader stage, of a specific type to a unique set index. */
+		static UINT32 mapParameterToSet(GpuProgramType progType, ParamType paramType);
 	};
 
 	/** @} */

+ 1 - 1
Source/BansheeD3D11RenderAPI/Include/BsD3D11RenderAPI.h

@@ -98,7 +98,7 @@ namespace bs
 		/** @copydoc RenderAPICore::addCommands() */
 		void addCommands(const SPtr<CommandBuffer>& commandBuffer, const SPtr<CommandBuffer>& secondary) override;
 
-		/** @copydoc RenderAPICore::executeCommands() */
+		/** @copydoc RenderAPICore::submitCommandBuffer() */
 		void submitCommandBuffer(const SPtr<CommandBuffer>& commandBuffer, UINT32 syncMask = 0xFFFFFFFF) override;
 
 		/** @copydoc RenderAPICore::convertProjectionMatrix */

+ 34 - 9
Source/BansheeD3D11RenderAPI/Source/BsD3D11HLSLParamParser.cpp

@@ -87,7 +87,7 @@ namespace bs
 				GpuParamBlockDesc blockDesc;
 				blockDesc.name = resourceDesc.Name;
 				blockDesc.slot = resourceDesc.BindPoint + i;
-				blockDesc.set = (UINT32)type;
+				blockDesc.set = mapParameterToSet(type, ParamType::ConstantBuffer);
 				blockDesc.blockSize = 0; // Calculated manually as we add parameters
 
 				if(strcmp(resourceDesc.Name, "$Globals") == 0 || strcmp(resourceDesc.Name, "$Param") == 0) // Special buffers, as defined by DX11 docs
@@ -102,13 +102,14 @@ namespace bs
 				GpuParamObjectDesc memberDesc;
 				memberDesc.name = resourceDesc.Name;
 				memberDesc.slot = resourceDesc.BindPoint + i;
-				memberDesc.set = (UINT32)type;
 				memberDesc.type = GPOT_UNKNOWN;
 
 				switch(resourceDesc.Type)
 				{
 				case D3D_SIT_SAMPLER:
 					memberDesc.type = GPOT_SAMPLER2D; // Actual dimension of the sampler doesn't matter
+					memberDesc.set = mapParameterToSet(type, ParamType::Sampler);
+
 					desc.samplers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D_SIT_TEXTURE:
@@ -133,20 +134,28 @@ namespace bs
 						LOGWRN("Skipping texture because it has unsupported dimension: " + toString(resourceDesc.Dimension));
 					}
 
-					if(memberDesc.type != GPOT_UNKNOWN)
+					if (memberDesc.type != GPOT_UNKNOWN)
+					{
+						memberDesc.set = mapParameterToSet(type, ParamType::Texture);
 						desc.textures.insert(std::make_pair(memberDesc.name, memberDesc));
-
+					}
 					break;
 				case D3D_SIT_STRUCTURED:
 					memberDesc.type = GPOT_STRUCTURED_BUFFER;
+					memberDesc.set = mapParameterToSet(type, ParamType::Texture);
+
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D_SIT_BYTEADDRESS:
 					memberDesc.type = GPOT_BYTE_BUFFER;
+					memberDesc.set = mapParameterToSet(type, ParamType::Texture);
+
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D11_SIT_UAV_RWTYPED:
 				{
+					memberDesc.set = mapParameterToSet(type, ParamType::UAV);
+
 					switch (resourceDesc.Dimension)
 					{
 					case D3D_SRV_DIMENSION_TEXTURE1D:
@@ -177,22 +186,32 @@ namespace bs
 				}
 				case D3D11_SIT_UAV_RWSTRUCTURED:
 					memberDesc.type = GPOT_RWSTRUCTURED_BUFFER;
+					memberDesc.set = mapParameterToSet(type, ParamType::UAV);
+
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D11_SIT_UAV_RWBYTEADDRESS:
 					memberDesc.type = GPOT_RWBYTE_BUFFER;
+					memberDesc.set = mapParameterToSet(type, ParamType::UAV);
+
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D_SIT_UAV_APPEND_STRUCTURED:
 					memberDesc.type = GPOT_RWAPPEND_BUFFER;
+					memberDesc.set = mapParameterToSet(type, ParamType::UAV);
+
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D_SIT_UAV_CONSUME_STRUCTURED:
 					memberDesc.type = GPOT_RWCONSUME_BUFFER;
+					memberDesc.set = mapParameterToSet(type, ParamType::UAV);
+
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				case D3D_SIT_UAV_RWSTRUCTURED_WITH_COUNTER:
 					memberDesc.type = GPOT_RWSTRUCTURED_BUFFER_WITH_COUNTER;
+					memberDesc.set = mapParameterToSet(type, ParamType::UAV);
+
 					desc.buffers.insert(std::make_pair(memberDesc.name, memberDesc));
 					break;
 				default:
@@ -220,16 +239,14 @@ namespace bs
 
 		for(UINT32 j = 0; j < constantBufferDesc.Variables; j++)
 		{
-			ID3D11ShaderReflectionVariable* varRef;
-			varRef = bufferReflection->GetVariableByIndex(j);
+			ID3D11ShaderReflectionVariable* varRef = bufferReflection->GetVariableByIndex(j);
 			D3D11_SHADER_VARIABLE_DESC varDesc;
-			HRESULT hr = varRef->GetDesc(&varDesc);
+			hr = varRef->GetDesc(&varDesc);
 
 			if (FAILED(hr))
 				BS_EXCEPT(RenderingAPIException, "Failed to retrieve HLSL constant buffer variable description.");
 
-			ID3D11ShaderReflectionType* varRefType;
-			varRefType = varRef->GetType();
+			ID3D11ShaderReflectionType* varRefType = varRef->GetType();
 			D3D11_SHADER_TYPE_DESC varTypeDesc;
 			varRefType->GetDesc(&varTypeDesc);
 
@@ -393,4 +410,12 @@ namespace bs
 
 		desc.params.insert(std::make_pair(memberDesc.name, memberDesc));
 	}
+
+	UINT32 D3D11HLSLParamParser::mapParameterToSet(GpuProgramType progType, ParamType paramType)
+	{
+		UINT32 progTypeIdx = (UINT32)progType;
+		UINT32 paramTypeIdx = (UINT32)paramType;
+		
+		return progTypeIdx * (UINT32)ParamType::Count + paramTypeIdx;
+	}
 }

+ 2 - 1
Source/BansheeD3D11RenderAPI/Source/BsD3D11RenderAPI.cpp

@@ -461,13 +461,14 @@ namespace bs
 					{
 						UINT32 slot = iter->second.slot;
 						SPtr<GpuParamBlockBufferCore> buffer = gpuParams->getParamBlockBuffer(iter->second.set, slot);
-						buffer->flushToGPU();
 
 						while (slot >= (UINT32)constBuffers.size())
 							constBuffers.push_back(nullptr);
 
 						if (buffer != nullptr)
 						{
+							buffer->flushToGPU();
+
 							const D3D11GpuParamBlockBufferCore* d3d11paramBlockBuffer =
 								static_cast<const D3D11GpuParamBlockBufferCore*>(buffer.get());
 							constBuffers[slot] = d3d11paramBlockBuffer->getD3D11Buffer();

+ 1 - 1
Source/BansheeGLRenderAPI/Include/BsGLRenderAPI.h

@@ -100,7 +100,7 @@ namespace bs
 		/** @copydoc RenderAPICore::addCommands() */
 		void addCommands(const SPtr<CommandBuffer>& commandBuffer, const SPtr<CommandBuffer>& secondary) override;
 
-		/** @copydoc RenderAPICore::executeCommands() */
+		/** @copydoc RenderAPICore::submitCommandBuffer() */
 		void submitCommandBuffer(const SPtr<CommandBuffer>& commandBuffer, UINT32 syncMask = 0xFFFFFFFF) override;
 
 		/** @copydoc RenderAPICore::convertProjectionMatrix() */

+ 21 - 8
Source/BansheeGLRenderAPI/Source/BsGLSLParamParser.cpp

@@ -138,7 +138,7 @@ namespace bs
 
 		GpuParamBlockDesc newGlobalBlockDesc;
 		newGlobalBlockDesc.slot = 0;
-		newGlobalBlockDesc.set = (UINT32)type;
+		newGlobalBlockDesc.set = mapParameterToSet(type, ParamType::UniformBlock);
 		newGlobalBlockDesc.name = "BS_INTERNAL_Globals";
 		newGlobalBlockDesc.blockSize = 0;
 		newGlobalBlockDesc.isShareable = false;
@@ -158,7 +158,7 @@ namespace bs
 
 			GpuParamBlockDesc newBlockDesc;
 			newBlockDesc.slot = index + 1;
-			newBlockDesc.set = (UINT32)type;
+			newBlockDesc.set = mapParameterToSet(type, ParamType::UniformBlock);
 			newBlockDesc.name = uniformName;
 			newBlockDesc.blockSize = 0;
 			newBlockDesc.isShareable = true;
@@ -313,12 +313,12 @@ namespace bs
 				GpuParamObjectDesc samplerParam;
 				samplerParam.name = paramName;
 				samplerParam.slot = glGetUniformLocation(glProgram, uniformName);
-				samplerParam.set = (UINT32)type;
+				samplerParam.set = mapParameterToSet(type, ParamType::Sampler);
 
 				GpuParamObjectDesc textureParam;
 				textureParam.name = paramName;
 				textureParam.slot = samplerParam.slot;
-				textureParam.set = (UINT32)type;
+				textureParam.set = mapParameterToSet(type, ParamType::Texture);
 
 				switch (uniformType)
 				{
@@ -352,7 +352,7 @@ namespace bs
 				GpuParamObjectDesc textureParam;
 				textureParam.name = paramName;
 				textureParam.slot = glGetUniformLocation(glProgram, uniformName);
-				textureParam.set = (UINT32)type;
+				textureParam.set = mapParameterToSet(type, ParamType::Image);
 
 				switch (uniformType)
 				{
@@ -377,12 +377,17 @@ namespace bs
 				GpuParamObjectDesc bufferParam;
 				bufferParam.name = paramName;
 				bufferParam.slot = glGetUniformLocation(glProgram, uniformName);
-				bufferParam.set = (UINT32)type;
 
 				if (uniformType == GL_IMAGE_BUFFER)
+				{
 					bufferParam.type = GPOT_RWSTRUCTURED_BUFFER;
+					bufferParam.set = mapParameterToSet(type, ParamType::Image);
+				}
 				else // Sampler buffer
+				{
 					bufferParam.type = GPOT_STRUCTURED_BUFFER;
+					bufferParam.set = mapParameterToSet(type, ParamType::Texture);
+				}
 
 				returnParamDesc.buffers.insert(std::make_pair(paramName, bufferParam));
 			}
@@ -413,7 +418,7 @@ namespace bs
 
 					gpuParam.gpuMemOffset = blockOffset;
 					gpuParam.paramBlockSlot = blockIndex + 1; // 0 is reserved for globals
-					gpuParam.paramBlockSet = (UINT32)type;
+					gpuParam.paramBlockSet = mapParameterToSet(type, ParamType::UniformBlock);
 
 					String& blockName = blockSlotToName[gpuParam.paramBlockSlot];
 					GpuParamBlockDesc& curBlockDesc = returnParamDesc.paramBlocks[blockName];
@@ -425,7 +430,7 @@ namespace bs
 				{
 					gpuParam.gpuMemOffset = glGetUniformLocation(glProgram, uniformName);
 					gpuParam.paramBlockSlot = 0;
-					gpuParam.paramBlockSet = (UINT32)type;
+					gpuParam.paramBlockSet = mapParameterToSet(type, ParamType::UniformBlock);
 					gpuParam.cpuMemOffset = globalBlockDesc.blockSize;
 
 					globalBlockDesc.blockSize = std::max(globalBlockDesc.blockSize, gpuParam.cpuMemOffset + gpuParam.arrayElementStride * gpuParam.arraySize);
@@ -619,4 +624,12 @@ namespace bs
 		else
 			desc.arrayElementStride = desc.elementSize;
 	}
+
+	UINT32 GLSLParamParser::mapParameterToSet(GpuProgramType progType, ParamType paramType)
+	{
+		UINT32 progTypeIdx = (UINT32)progType;
+		UINT32 paramTypeIdx = (UINT32)paramType;
+
+		return progTypeIdx * (UINT32)ParamType::Count + paramTypeIdx;
+	}
 }

+ 13 - 0
Source/BansheeGLRenderAPI/Source/GLSL/include/BsGLSLParamParser.h

@@ -60,6 +60,16 @@ namespace bs
 		List<VertexElement> buildVertexDeclaration(GLuint glProgram);
 
 	private:
+		/** Types of HLSL parameters. */
+		enum class ParamType
+		{
+			UniformBlock,
+			Texture,
+			Sampler,
+			Image,
+			Count // Keep at end
+		};
+
 		/**
 		 * Populates information for uniform with the specified index into the provided structure.
 		 *
@@ -92,6 +102,9 @@ namespace bs
 
 		/**	Converts an OpenGL type to vertex element type. */
 		VertexElementType glTypeToAttributeType(GLenum glType);
+
+		/** Maps a parameter in a specific shader stage, of a specific type to a unique set index. */
+		static UINT32 mapParameterToSet(GpuProgramType progType, ParamType paramType);
 	};
 
 	/** @} */

+ 0 - 1
Source/BansheeUtility/Include/BsUtil.h

@@ -45,7 +45,6 @@ namespace bs
 	void bs_zero_out(T * arr, size_t count)
 	{
 		assert(arr != nullptr);
-		assert(count != 0);
 		std::memset(arr, 0, sizeof(T) * count);
 	}
 

+ 12 - 29
Source/BansheeVulkanRenderAPI/Source/BsVulkanGpuPipelineParamInfo.cpp

@@ -31,10 +31,9 @@ namespace bs
 				numDevices++;
 		}
 
-		UINT32 numElementTypes = (UINT32)ParamType::Count;
-		UINT32 bindingsSize = sizeof(VkDescriptorSetLayoutBinding) * mTotalNumElements;
-		UINT32 layoutInfoSize = sizeof(LayoutInfo) * mTotalNumSets;
-		UINT32 layoutsSize = sizeof(VulkanDescriptorLayout*) * mTotalNumSets;
+		UINT32 bindingsSize = sizeof(VkDescriptorSetLayoutBinding) * mNumElements;
+		UINT32 layoutInfoSize = sizeof(LayoutInfo) * mNumSets;
+		UINT32 layoutsSize = sizeof(VulkanDescriptorLayout*) * mNumSets;
 
 		mData = (UINT8*)bs_alloc(bindingsSize + layoutInfoSize + layoutsSize * numDevices);
 		UINT8* dataPtr = mData;
@@ -60,39 +59,23 @@ namespace bs
 		memset(bindings, 0, bindingsSize);
 
 		UINT32 globalBindingIdx = 0;
-		for (UINT32 i = 0; i < mTotalNumSets; i++)
+		for (UINT32 i = 0; i < mNumSets; i++)
 		{
 			mLayoutInfos[i].numBindings = 0;
 			mLayoutInfos[i].bindings = nullptr;
 
-			for (UINT32 j = 0; j < numElementTypes; j++)
+			for (UINT32 j = 0; j < mSetInfos[i].numSlots; j++)
 			{
-				if (i >= mNumSets[j])
-					continue;
-				
-				UINT32 start = mOffsets[j][i];
-
-				UINT32 end;
-				if (i < (mNumSets[j] - 1))
-					end = mOffsets[j][i + 1];
-				else
-					end = mNumElements[j];
-
-				UINT32 elementsInSet = end - start;
-				for (UINT32 k = 0; k < elementsInSet; k++)
-				{
-					VkDescriptorSetLayoutBinding& binding = bindings[globalBindingIdx + k];
-					binding.binding = mLayoutInfos[i].numBindings + k;
-				}
-
-				globalBindingIdx += elementsInSet;
-
-				mLayoutInfos[i].numBindings += elementsInSet;
+				VkDescriptorSetLayoutBinding& binding = bindings[globalBindingIdx + j];
+				binding.binding = mLayoutInfos[i].numBindings + j;
 			}
+
+			globalBindingIdx += mSetInfos[i].numSlots;
+			mLayoutInfos[i].numBindings += mSetInfos[i].numSlots;
 		}
 
 		UINT32 offset = 0;
-		for (UINT32 i = 0; i < mTotalNumSets; i++)
+		for (UINT32 i = 0; i < mNumSets; i++)
 		{
 			mLayoutInfos[i].bindings = &bindings[offset];
 			offset += mLayoutInfos[i].numBindings;
@@ -150,7 +133,7 @@ namespace bs
 				continue;
 
 			VulkanDescriptorManager& descManager = devices[i]->getDescriptorManager();
-			for (UINT32 j = 0; j < mTotalNumSets; j++)
+			for (UINT32 j = 0; j < mNumSets; j++)
 				mLayouts[i][j] = descManager.getLayout(mLayoutInfos[j].bindings, mLayoutInfos[j].numBindings);
 		}
 	}

+ 2 - 0
Source/RenderBeast/Include/BsSamplerOverrides.h

@@ -23,6 +23,8 @@ namespace bs
 		UINT32 paramIdx;
 		UINT64 originalStateHash;
 		SPtr<SamplerStateCore> state;
+		UINT32 set;
+		UINT32 slot;
 	};
 
 	/**	Contains data about an overridden sampler states in the entire material. */

+ 10 - 7
Source/RenderBeast/Source/BsSamplerOverrides.cpp

@@ -146,21 +146,26 @@ namespace bs
 				outputData += sizeof(UINT32*) * passOverrides.numSets;
 
 				for (UINT32 j = 0; j < passOverrides.numSets; j++)
+				{
+					passOverrides.stateOverrides[j] = (UINT32*)outputData;
+					outputData += sizeof(UINT32) * slotsPerSetIter[j];
+				}
+
+				for (UINT32 j = 0; j < GpuParamsSetCore::NUM_STAGES; j++)
 				{
 					GpuProgramType progType = (GpuProgramType)j;
 					SPtr<GpuParamDesc> paramDesc = paramsPtr->getParamDesc(progType);
 					if (paramDesc == nullptr)
 						continue;
 
-					passOverrides.stateOverrides[j] = (UINT32*)outputData;
-
 					UINT32 numStates = 0;
 					for (auto iter = paramDesc->samplers.begin(); iter != paramDesc->samplers.end(); ++iter)
 					{
+						UINT32 set = iter->second.set;
 						UINT32 slot = iter->second.slot;
 						while (slot > numStates)
 						{
-							passOverrides.stateOverrides[j][numStates] = (UINT32)-1;
+							passOverrides.stateOverrides[set][numStates] = (UINT32)-1;
 							numStates++;
 						}
 
@@ -168,12 +173,10 @@ namespace bs
 
 						auto iterFind = overrideLookup.find(iter->first);
 						if (iterFind != overrideLookup.end())
-							passOverrides.stateOverrides[j][slot] = iterFind->second;
+							passOverrides.stateOverrides[set][slot] = iterFind->second;
 						else
-							passOverrides.stateOverrides[j][slot] = (UINT32)-1;
+							passOverrides.stateOverrides[set][slot] = (UINT32)-1;
 					}
-
-					outputData += sizeof(UINT32) * slotsPerSetIter[j];
 				}
 
 				slotsPerSetIter += passOverrides.numSets;