Browse Source

Splitting some UBOs to make some room for more lights

Panagiotis Christopoulos Charitos 12 years ago
parent
commit
3dbc75489c
5 changed files with 169 additions and 154 deletions
  1. 15 6
      include/anki/renderer/Is.h
  2. 34 0
      include/anki/util/StdTypes.h
  3. 11 9
      shaders/IsCommon.glsl
  4. 14 21
      shaders/IsLp.glsl
  5. 95 118
      src/renderer/Is.cpp

+ 15 - 6
include/anki/renderer/Is.h

@@ -51,6 +51,8 @@ private:
 	static const U SPOT_LIGHTS_BLOCK_BINDING = 2;
 	static const U SPOT_TEX_LIGHTS_BLOCK_BINDING = 3;
 	static const U TILES_BLOCK_BINDING = 4;
+	static const U TILES_POINT_LIGHT_INDICES_BLOCK_BINDING = 5;
+	static const U TILES_SPOT_LIGHT_INDICES_BLOCK_BINDING = 6;
 
 	/// The IS FAI
 	Texture fai;
@@ -61,6 +63,8 @@ private:
 	/// @name GPU buffers
 	/// @{
 
+	PtrSize uboAlignment = MAX_PTR_SIZE; ///< Cache the value here
+
 	/// Contains common data for all shader programs
 	Ubo commonUbo;
 
@@ -69,10 +73,12 @@ private:
 
 	/// Contains all the lights
 	Ubo lightsUbo;
-	PtrSize uboAlignment;
 
-	/// Contains the indices of lights per tile
+	/// Contains the number of lights per tile
 	BufferObject tilesBuffer;
+
+	BufferObject pointLightIndicesBuffer;
+	BufferObject spotLightIndicesBuffer;
 	/// @}
 
 	// Light shaders
@@ -119,11 +125,14 @@ private:
 	/// Calculate the size of the lights UBO
 	PtrSize calcLightsUboSize() const;
 
-	/// Calculate the size of the tiles UBO
-	PtrSize calcTileSize() const;
+	/// Calculate the size of the indices of point lights
+	PtrSize calcPointLightIndicesBufferSize() const;
+
+	/// Calculate the size of the indices of spot lights
+	PtrSize calcSpotLightIndicesBufferSize() const;
 
-	/// Calculate the size of the tiles UBO
-	PtrSize calcTilesUboSize() const;
+	/// Setup the binding of the block and do some sanity checks on the size
+	void blockSetupAndSanityCheck(const char* name, U binding, PtrSize size);
 };
 
 } // end namespace anki

+ 34 - 0
include/anki/util/StdTypes.h

@@ -3,29 +3,63 @@
 
 #include <cstdint>
 #include <cstddef>
+#include <limits>
 
 namespace anki {
 
 /// @addtogroup util
 /// @{
 typedef int8_t I8;
+const I8 MAX_I8 = std::numeric_limits<I8>::max();
+const I8 MIN_I8 = std::numeric_limits<I8>::min();
+
 typedef int16_t I16;
+const I16 MAX_I16 = std::numeric_limits<I16>::max();
+const I16 MIN_I16 = std::numeric_limits<I16>::min();
+
 typedef int32_t I32;
+const I32 MAX_I32 = std::numeric_limits<I32>::max();
+const I32 MIN_I32 = std::numeric_limits<I32>::min();
+
 typedef int64_t I64;
+const I64 MAX_I64 = std::numeric_limits<I64>::max();
+const I64 MIN_I64 = std::numeric_limits<I64>::min();
 
 typedef int_fast32_t I; ///< Fast signed integer at least 32bit
+const I MAX_I = std::numeric_limits<I>::max();
+const I MIN_I = std::numeric_limits<I>::min();
 
 typedef uint8_t U8;
+const U8 MAX_U8 = std::numeric_limits<U8>::max();
+const U8 MIN_U8 = std::numeric_limits<U8>::min();
+
 typedef uint16_t U16;
+const U16 MAX_U16 = std::numeric_limits<U16>::max();
+const U16 MIN_U16 = std::numeric_limits<U16>::min();
+
 typedef uint32_t U32;
+const U32 MAX_U32 = std::numeric_limits<U32>::max();
+const U32 MIN_U32 = std::numeric_limits<U32>::min();
+
 typedef uint64_t U64;
+const U64 MAX_U64 = std::numeric_limits<U64>::max();
+const U64 MIN_U64 = std::numeric_limits<U64>::min();
 
 typedef uint_fast32_t U; ///< fast unsigned integer at least 32bit
+const U MAX_U = std::numeric_limits<U>::max();
+const U MIN_U = std::numeric_limits<U>::min();
 
 typedef size_t PtrSize; ///< Like size_t
+const PtrSize MAX_PTR_SIZE = std::numeric_limits<PtrSize>::max();
+const PtrSize MIN_PTR_SIZE = std::numeric_limits<PtrSize>::min();
 
 typedef float F32;
+const F32 MAX_F32 = std::numeric_limits<F32>::max();
+const F32 MIN_F32 = -std::numeric_limits<F32>::max();
+
 typedef double F64;
+const F64 MAX_F64 = std::numeric_limits<F64>::max();
+const F64 MIN_F64 = -std::numeric_limits<F64>::max();
 
 typedef bool Bool;
 typedef U8 Bool8;

+ 11 - 9
shaders/IsCommon.glsl

@@ -19,15 +19,17 @@ struct Tilegrid
 struct Tile
 {
 	uvec4 lightsCount;
-#if __VERSION__ > 430
-	uint pointLightIndices[MAX_POINT_LIGHTS_PER_TILE];
-	uint spotLightIndices[MAX_SPOT_LIGHTS_PER_TILE];
-	uint spotTexLightndices[MAX_SPOT_TEX_LIGHTS_PER_TILE];
-#else
-	uvec4 pointLightIndices[MAX_POINT_LIGHTS_PER_TILE / 4];
-	uvec4 spotLightIndices[MAX_SPOT_LIGHTS_PER_TILE / 4];
-	uvec4 spotTexLightIndices[MAX_SPOT_TEX_LIGHTS_PER_TILE / 4];
-#endif
+};
+
+struct PointLightIndices
+{
+	uvec4 indices[MAX_POINT_LIGHTS_PER_TILE / 4];
+};
+
+struct SpotLightIndices
+{
+	uvec4 indices[MAX_SPOT_LIGHTS_PER_TILE / 4];
+	uvec4 indicesTex[MAX_SPOT_TEX_LIGHTS_PER_TILE / 4];	
 };
 
 // The base of all lights

+ 14 - 21
shaders/IsLp.glsl

@@ -79,16 +79,21 @@ layout(std140) uniform spotTexLightsBlock
 	SpotTexLight spotTexLights[MAX_SPOT_TEX_LIGHTS];
 };
 
-#if __VERSION__ > 430
-layout(std430) 
-#else
-layout(std140) 
-#endif
-	uniform tilesBlock
+layout(std140) uniform tilesBlock
 {
 	Tile tiles[TILES_COUNT];
 };
 
+layout(std140) uniform pointLightIndicesBlock
+{
+	PointLightIndices pointLightIndices[TILES_COUNT];
+};
+
+layout(std140) uniform spotLightIndicesBlock
+{
+	SpotLightIndices spotLightIndices[TILES_COUNT];
+};
+
 #if USE_MRT
 uniform sampler2D msFai0;
 uniform sampler2D msFai1;
@@ -247,11 +252,7 @@ void main()
 	uint pointLightsCount = tile.lightsCount[0];
 	for(uint i = 0U; i < pointLightsCount; ++i)
 	{
-#if __VERSION__ > 430
-		uint lightId = tile.pointLightIndices[i];
-#else
-		uint lightId = tile.pointLightIndices[i / 4U][i % 4U];
-#endif
+		uint lightId = pointLightIndices[vInstanceId].indices[i / 4U][i % 4U];
 		PointLight light = pointLights[lightId];
 
 		vec3 ray;
@@ -268,11 +269,7 @@ void main()
 
 	for(uint i = 0U; i < spotLightsCount; ++i)
 	{
-#if __VERSION__ > 430
-		uint lightId = tile.spotLightIndices[i];
-#else
-		uint lightId = tile.spotLightIndices[i / 4U][i % 4U];
-#endif
+		uint lightId = spotLightIndices[vInstanceId].indices[i / 4U][i % 4U];
 		SpotLight light = spotLights[lightId];
 
 		vec3 ray;
@@ -294,11 +291,7 @@ void main()
 
 	for(uint i = 0U; i < spotTexLightsCount; ++i)
 	{
-#if __VERSION__ > 430
-		uint lightId = tile.spotTexLightIndices[i];
-#else
-		uint lightId = tile.spotTexLightIndices[i / 4U][i % 4U];
-#endif
+		uint lightId = spotLightIndices[vInstanceId].indicesTex[i / 4U][i % 4U];
 		SpotTexLight light = spotTexLights[lightId];
 
 		vec3 ray;

+ 95 - 118
src/renderer/Is.cpp

@@ -14,6 +14,8 @@ namespace anki {
 // Misc                                                                        =
 //==============================================================================
 
+const PtrSize TILE_SIZE = sizeof(UVec4);
+
 //==============================================================================
 /// Check if the prev ground light vector is almost equal to the current
 static Bool groundVectorsEqual(const Vec3& prev, const Vec3& crnt)
@@ -91,6 +93,8 @@ struct WriteLightsJob: ThreadJob
 	shader::SpotTexLight* spotTexLights = nullptr;
 
 	U8* tileBuffer = nullptr;
+	U8* plightsIdsBuffer = nullptr;
+	U8* slightsIdsBuffer = nullptr;
 
 	VisibilityTestResults::Container::const_iterator lightsBegin;
 	VisibilityTestResults::Container::const_iterator lightsEnd;
@@ -350,36 +354,38 @@ struct WriteLightsJob: ThreadJob
 	void writeIndexToTileBuffer(
 		U lightType, U lightIndex, U indexInTileArray, U tileX, U tileY)
 	{
-		const PtrSize tileSize = is->calcTileSize();
-		PtrSize offset;
-
-		// Calc the start of the tile
-		offset = (tileY * is->r->getTilesCount().x() + tileX) * tileSize;
-
-		// Skip the lightsCount header
-		offset += sizeof(Vec4);
+		U8* storage = nullptr;
+		U tileIndex = tileY * is->r->getTilesCount().x() + tileX;
 
 		// Move to the correct light section
 		switch(lightType)
 		{
 		case 0:
+			storage = plightsIdsBuffer 
+				+ tileIndex * is->maxPointLightsPerTile * sizeof(U32);
 			break;
 		case 1:
-			offset += sizeof(U32) * is->maxPointLightsPerTile;
+			storage = slightsIdsBuffer 
+				+ tileIndex 
+				* (is->maxSpotLightsPerTile + is->maxSpotTexLightsPerTile) 
+				* sizeof(U32);
 			break;
 		case 2:
-			offset += sizeof(U32) * is->maxPointLightsPerTile
-				+ sizeof(U32) * is->maxSpotLightsPerTile;
+			storage = slightsIdsBuffer 
+				+ tileIndex 
+				* (is->maxSpotLightsPerTile + is->maxSpotTexLightsPerTile) 
+				* sizeof(U32)
+				+ is->maxSpotLightsPerTile * sizeof(U32);
 			break;
 		default:
 			ANKI_ASSERT(0);
 		}
 
 		// Move to the array offset
-		offset += sizeof(U32) * indexInTileArray;
+		storage += sizeof(U32) * indexInTileArray;
 
 		// Write the lightIndex
-		*((U32*)(tileBuffer + offset)) = lightIndex;
+		*((U32*)(storage)) = lightIndex;
 	}
 };
 
@@ -517,104 +523,54 @@ void Is::initInternal(const RendererInitializer& initializer)
 	// Create UBOs
 	//
 
-	// Common UBO
+	uboAlignment = BufferObject::getUniformBufferOffsetAlignment();
+
 	commonUbo.create(sizeof(shader::CommonUniforms), nullptr);
 
-	// lights UBO
 	lightsUbo.create(calcLightsUboSize(), nullptr);
-	uboAlignment = BufferObject::getUniformBufferOffsetAlignment();
 
-	// tiles BO
 	tilesBuffer.create(
 		GL_UNIFORM_BUFFER, 
-		calcTilesUboSize(), 
+		r->getTilesCount().x() * r->getTilesCount().y() * sizeof(UVec4),
 		nullptr, 
 		GL_DYNAMIC_DRAW);
 
-	ANKI_LOGI("Creating BOs: lights: %uB, tiles: %uB", calcLightsUboSize(), 
-		calcTilesUboSize());
-
-	// Sanity checks
-	const ShaderProgramUniformBlock* ublock;
+	pointLightIndicesBuffer.create(
+		GL_UNIFORM_BUFFER, 
+		calcPointLightIndicesBufferSize(),
+		nullptr, 
+		GL_DYNAMIC_DRAW);
 
-	ublock = &lightPassProg->findUniformBlock("commonBlock");
-	ublock->setBinding(COMMON_UNIFORMS_BLOCK_BINDING);
-	if(ublock->getSize() != sizeof(shader::CommonUniforms)
-		|| ublock->getBinding() != COMMON_UNIFORMS_BLOCK_BINDING)
-	{
-		throw ANKI_EXCEPTION("Problem with the commonBlock");
-	}
+	spotLightIndicesBuffer.create(
+		GL_UNIFORM_BUFFER, 
+		calcSpotLightIndicesBufferSize(),
+		nullptr, 
+		GL_DYNAMIC_DRAW);
 
-#if ANKI_GL == ANKI_GL_DESKTOP
-	if(rejectProg.isLoaded())
-	{
-		ublock = &rejectProg->findUniformBlock("commonBlock");
-		ublock->setBinding(COMMON_UNIFORMS_BLOCK_BINDING);
-		if(ublock->getSize() != sizeof(shader::CommonUniforms)
-			|| ublock->getBinding() != COMMON_UNIFORMS_BLOCK_BINDING)
-		{
-			throw ANKI_EXCEPTION("Problem with the commonBlock");
-		}
-	}
-#endif
+	// Sanity checks
+	blockSetupAndSanityCheck("commonBlock", COMMON_UNIFORMS_BLOCK_BINDING,
+		commonUbo.getSizeInBytes());
 
-	ublock = &lightPassProg->findUniformBlock("pointLightsBlock");
-	ublock->setBinding(POINT_LIGHTS_BLOCK_BINDING);
-	if(ublock->getSize() != sizeof(shader::PointLight) * maxPointLights
-		|| ublock->getBinding() != POINT_LIGHTS_BLOCK_BINDING)
-	{
-		throw ANKI_EXCEPTION("Problem with the pointLightsBlock");
-	}
+	blockSetupAndSanityCheck("pointLightsBlock", POINT_LIGHTS_BLOCK_BINDING,
+		sizeof(shader::PointLight) * maxPointLights);
 
-#if ANKI_GL == ANKI_GL_DESKTOP
-	if(rejectProg.isLoaded())
-	{
-		ublock = &rejectProg->findUniformBlock("pointLightsBlock");
-		ublock->setBinding(POINT_LIGHTS_BLOCK_BINDING);
-		if(ublock->getSize() != sizeof(shader::PointLight) * maxPointLights
-			|| ublock->getBinding() != POINT_LIGHTS_BLOCK_BINDING)
-		{
-			throw ANKI_EXCEPTION("Problem with the pointLightsBlock");
-		}
-	}
-#endif
+	blockSetupAndSanityCheck("spotLightsBlock", SPOT_LIGHTS_BLOCK_BINDING,
+		sizeof(shader::SpotLight) * maxSpotLights);
 
-	ublock = &lightPassProg->findUniformBlock("spotLightsBlock");
-	ublock->setBinding(SPOT_LIGHTS_BLOCK_BINDING);
-	if(ublock->getSize() != sizeof(shader::SpotLight) * maxSpotLights
-		|| ublock->getBinding() != SPOT_LIGHTS_BLOCK_BINDING)
-	{
-		throw ANKI_EXCEPTION("Problem with the spotLightsBlock");
-	}
+	blockSetupAndSanityCheck("spotTexLightsBlock", 
+		SPOT_TEX_LIGHTS_BLOCK_BINDING,
+		sizeof(shader::SpotTexLight) * maxSpotTexLights);
 
-	ublock = &lightPassProg->findUniformBlock("spotTexLightsBlock");
-	ublock->setBinding(SPOT_TEX_LIGHTS_BLOCK_BINDING);
-	if(ublock->getSize() != sizeof(shader::SpotTexLight) * maxSpotTexLights
-		|| ublock->getBinding() != SPOT_TEX_LIGHTS_BLOCK_BINDING)
-	{
-		throw ANKI_EXCEPTION("Problem with the spotTexLightsBlock");
-	}
+	blockSetupAndSanityCheck("tilesBlock", TILES_BLOCK_BINDING,
+		tilesBuffer.getSizeInBytes());
 
-	ublock = &lightPassProg->findUniformBlock("tilesBlock");
-	ublock->setBinding(TILES_BLOCK_BINDING);
-	if(ublock->getSize() != calcTilesUboSize()
-		|| ublock->getBinding() != TILES_BLOCK_BINDING)
-	{
-		throw ANKI_EXCEPTION("Problem with the tilesBlock");
-	}
+	blockSetupAndSanityCheck("pointLightIndicesBlock", 
+		TILES_POINT_LIGHT_INDICES_BLOCK_BINDING,
+		pointLightIndicesBuffer.getSizeInBytes());
 
-#if ANKI_GL == ANKI_GL_DESKTOP && 0
-	if(rejectProg.isLoaded())
-	{
-		ublock = &rejectProg->findUniformBlock("tilesBlock");
-		ublock->setBinding(TILES_BLOCK_BINDING);
-		if(ublock->getSize() != sizeof(shader::Tiles)
-			|| ublock->getBinding() != TILES_BLOCK_BINDING)
-		{
-			throw ANKI_EXCEPTION("Problem with the tilesBlock");
-		}
-	}
-#endif
+	blockSetupAndSanityCheck("spotLightIndicesBlock", 
+		TILES_SPOT_LIGHT_INDICES_BLOCK_BINDING,
+		spotLightIndicesBuffer.getSizeInBytes());
 }
 
 //==============================================================================
@@ -624,6 +580,8 @@ void Is::lightPass()
 	VisibilityTestResults& vi = 
 		cam->getFrustumComponent()->getVisibilityTestResults();
 
+	SceneFrameAllocator<U8> alloc = r->getSceneGraph().getFrameAllocator();
+
 	//
 	// Quickly get the lights
 	//
@@ -639,7 +597,6 @@ void Is::lightPass()
 		switch(light->getLightType())
 		{
 		case Light::LT_POINT:
-			// Use % to avoid overflows
 			++visiblePointLightsCount;
 			break;
 		case Light::LT_SPOT:
@@ -684,28 +641,32 @@ void Is::lightPass()
 	PtrSize pointLightsOffset = 0;
 	PtrSize pointLightsSize = 
 		sizeof(shader::PointLight) * visiblePointLightsCount;
-	pointLightsSize = getAlignedRoundUp(uboAlignment, pointLightsSize);
+	alignRoundUp(uboAlignment, pointLightsSize);
 
 	PtrSize spotLightsOffset = pointLightsSize;
 	PtrSize spotLightsSize = 
 		sizeof(shader::SpotLight) * visibleSpotLightsCount;
-	spotLightsSize = getAlignedRoundUp(uboAlignment, spotLightsSize);
+	alignRoundUp(uboAlignment, spotLightsSize);
 
 	PtrSize spotTexLightsOffset = spotLightsOffset + spotLightsSize;
 	PtrSize spotTexLightsSize = 
 		sizeof(shader::SpotTexLight) * visibleSpotTexLightsCount;
-	spotTexLightsSize = getAlignedRoundUp(uboAlignment, spotTexLightsSize);
+	alignRoundUp(uboAlignment, spotTexLightsSize);
 
 	ANKI_ASSERT(spotTexLightsOffset + spotTexLightsSize <= calcLightsUboSize());
 
 	// Fire the super jobs
 	Array<WriteLightsJob, ThreadPool::MAX_THREADS> jobs;
 
-	U8 clientBuffer[32 * 1024]; // Aproximate size
-	ANKI_ASSERT(sizeof(clientBuffer) >= calcLightsUboSize());
+	U8* lightsClientBuffer = alloc.allocate(lightsUbo.getSizeInBytes());
+
+	U8* tilesClientBuffer = alloc.allocate(tilesBuffer.getSizeInBytes());
 
-	U8 tilesClientBuffer[64 * 1024]; // Aproximate size
-	ANKI_ASSERT(sizeof(tilesClientBuffer) >= calcTilesUboSize());
+	U8* plightIdsClientBuffer = 
+		alloc.allocate(pointLightIndicesBuffer.getSizeInBytes());
+
+	U8* slightIdsClientBuffer = 
+		alloc.allocate(spotLightIndicesBuffer.getSizeInBytes());
 
 	std::atomic<U32> pointLightsAtomicCount(0);
 	std::atomic<U32> spotLightsAtomicCount(0);
@@ -733,13 +694,16 @@ void Is::lightPass()
 		WriteLightsJob& job = jobs[i];
 
 		job.pointLights = 
-			(shader::PointLight*)(&clientBuffer[0] + pointLightsOffset);
+			(shader::PointLight*)(&lightsClientBuffer[0] + pointLightsOffset);
 		job.spotLights = 
-			(shader::SpotLight*)(&clientBuffer[0] + spotLightsOffset);
+			(shader::SpotLight*)(&lightsClientBuffer[0] + spotLightsOffset);
 		job.spotTexLights = 
-			(shader::SpotTexLight*)(&clientBuffer[0] + spotTexLightsOffset);
+			(shader::SpotTexLight*)(
+			&lightsClientBuffer[0] + spotTexLightsOffset);
 
-		job.tileBuffer = &tilesClientBuffer[0];
+		job.tileBuffer = tilesClientBuffer;
+		job.plightsIdsBuffer = plightIdsClientBuffer;
+		job.slightsIdsBuffer = slightIdsClientBuffer;
 
 		job.lightsBegin = vi.getLightsBegin();
 		job.lightsEnd = vi.getLightsEnd();
@@ -769,7 +733,7 @@ void Is::lightPass()
 	{
 		for(U x = 0; x < r->getTilesCount().x(); x++)
 		{
-			const PtrSize tileSize = calcTileSize();
+			const PtrSize tileSize = TILE_SIZE;
 			UVec4* vec;
 
 			vec = (UVec4*)(
@@ -791,8 +755,10 @@ void Is::lightPass()
 
 	// Write BOs
 	lightsUbo.write(
-		&clientBuffer[0], 0, spotTexLightsOffset + spotTexLightsSize);
+		&lightsClientBuffer[0], 0, spotTexLightsOffset + spotTexLightsSize);
 	tilesBuffer.write(&tilesClientBuffer[0]);
+	pointLightIndicesBuffer.write(plightIdsClientBuffer);
+	spotLightIndicesBuffer.write(slightIdsClientBuffer);
 
 	//
 	// Reject occluded lights. This operation issues a compute job to reject 
@@ -860,6 +826,8 @@ void Is::lightPass()
 			spotTexLightsOffset, spotTexLightsSize);
 	}
 	tilesBuffer.setBinding(TILES_BLOCK_BINDING);
+	pointLightIndicesBuffer.setBinding(TILES_POINT_LIGHT_INDICES_BLOCK_BINDING);
+	spotLightIndicesBuffer.setBinding(TILES_SPOT_LIGHT_INDICES_BLOCK_BINDING);
 
 	lightPassProg->findUniformVariable("msFai0").set(r->getMs().getFai0());
 	if(r->getUseMrt())
@@ -946,8 +914,8 @@ void Is::run()
 //==============================================================================
 PtrSize Is::calcLightsUboSize() const
 {
+	ANKI_ASSERT(uboAlignment != MAX_PTR_SIZE);
 	PtrSize size;
-	PtrSize uboAlignment = BufferObject::getUniformBufferOffsetAlignment();
 
 	size = getAlignedRoundUp(
 		uboAlignment,
@@ -965,21 +933,30 @@ PtrSize Is::calcLightsUboSize() const
 }
 
 //==============================================================================
-PtrSize Is::calcTileSize() const
+PtrSize Is::calcPointLightIndicesBufferSize() const
 {
-	PtrSize size =
-		sizeof(Vec4) // lightsCount
-		+ maxPointLightsPerTile * sizeof(U32) // pointLightIndices
-		+ maxSpotLightsPerTile * sizeof(U32) // spotLightIndices
-		+ maxSpotTexLightsPerTile * sizeof(U32); // spotTexLightIndices
+	return maxPointLightsPerTile * sizeof(U32) 
+		* r->getTilesCount().x() * r->getTilesCount().y();
+}
 
-	return size;
+//==============================================================================
+PtrSize Is::calcSpotLightIndicesBufferSize() const
+{
+	return (maxSpotLightsPerTile + maxSpotTexLightsPerTile) * sizeof(U32) 
+		* r->getTilesCount().x() * r->getTilesCount().y();
 }
 
 //==============================================================================
-PtrSize Is::calcTilesUboSize() const
+void Is::blockSetupAndSanityCheck(const char* name, U binding, PtrSize size)
 {
-	return calcTileSize() * r->getTilesCount().x() * r->getTilesCount().y();
+	const ShaderProgramUniformBlock* ublock;
+
+	ublock = &lightPassProg->findUniformBlock(name);
+	ublock->setBinding(binding);
+	if(ublock->getSize() != size || ublock->getBinding() != binding)
+	{
+		throw ANKI_EXCEPTION("Problem with the block: " + name);
+	}
 }
 
 } // end namespace anki