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

Work on light rejection. Everything compiles but the algorithm is wrong

Panagiotis Christopoulos Charitos 12 роки тому
батько
коміт
921962c888
5 змінених файлів з 135 додано та 75 видалено
  1. 2 8
      include/anki/renderer/Is.h
  2. 3 3
      shaders/IsLp.glsl
  3. 19 13
      shaders/IsRejectLights.glsl
  4. 110 50
      src/renderer/Is.cpp
  5. 1 1
      testapp/Main.cpp

+ 2 - 8
include/anki/renderer/Is.h

@@ -68,13 +68,11 @@ private:
 
 	/// Contains the indices of lights per tile
 	BufferObject tilesBuffer;
-
-	/// XXX
-	BufferObject tilegridBuffer;
 	/// @}
 
-	/// Light shaders
+	// Light shaders
 	ShaderProgramResourcePointer lightPassProg;
+	ShaderProgramResourcePointer rejectProg;
 
 	/// Shadow mapping
 	Sm sm;
@@ -100,10 +98,6 @@ private:
 	/// Do the actual pass
 	void lightPass();
 
-	/// Reject occluded lights. This pass issues a compute job to reject lights
-	/// from the tiles
-	void rejectLights();
-
 	/// Prepare GL for rendering
 	void setState();
 };

+ 3 - 3
shaders/IsLp.glsl

@@ -326,7 +326,7 @@ void main()
 #endif
 
 #if 0
-	if(tiles[vInstanceId].lightsCount[2] > 0)
+	if(tiles[vInstanceId].lightsCount[0] > 0)
 	{
 		uint lightId = 0;
 
@@ -344,14 +344,14 @@ void main()
 		slights[1].light.diffuseColorShadowmapId.w, 0.0);
 #endif
 
-#if 0
+#if 1
 	if(tiles[vInstanceId].lightsCount[0] > 0)
 	{
 		fColor += vec3(0.0, 0.1, 0.0);
 	}
 #endif
 
-#if 0
+#if 1
 	vec3 tmpc = vec3((vInstanceId % 4) / 3.0, (vInstanceId % 3) / 2.0, 
 		(vInstanceId % 2));
 	fColor += tmpc / 40.0;

+ 19 - 13
shaders/IsRejectLights.glsl

@@ -4,6 +4,8 @@
 
 layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 
+#pragma anki include "shaders/IsCommon.glsl"
+
 #define TILE_W (DEPTHMAP_WIDTH / TILES_X_COUNT)
 #define TILE_H (DEPTHMAP_HEIGHT / TILES_Y_COUNT)
 
@@ -12,22 +14,25 @@ layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;
 
 uniform highp sampler2D depthMap;
 
-layout(std430) buffer tilesBlock
+layout(std140, binding = TILES_BLOCK_BINDING) buffer tilesBlock
 {
 	Tile tiles[TILES_Y_COUNT][TILES_X_COUNT];
 };
 
-layout(std140) buffer pointLightsBlock
+layout(std140) uniform pointLightsBlock
 {
 	PointLight pointLights[MAX_POINT_LIGHTS];
 };
 
-// Common uniforms 
-layout(std430) uniform commonBlock
+// Common uniforms. Make it match the commonBlock in IsLp.glsl
+layout(std140) uniform commonBlock
 {
 	/// Packs:
 	/// - xy: Planes. For the calculation of frag pos in view space
 	uniform vec2 planes;
+
+	uniform vec4 padding1;
+	uniform vec4 padding2;
 };
 
 void main()
@@ -37,13 +42,13 @@ void main()
 	//
 	float minDepth = 10000.0; // min depth of tile
 
-	uvec2 coord = uvec2(uvec2(tileX, tileY) * uvec2(TILE_W, TILE_H));
+	const ivec2 COORD = ivec2(ivec2(tileX, tileY) * ivec2(TILE_W, TILE_H));
 
-	for(uint x = 0; x < TILE_W; x++)
+	for(int x = 0; x < TILE_W; x++)
 	{
-		for(uint y = 0; y < TILE_H; i++)
+		for(int y = 0; y < TILE_H; y++)
 		{
-			float depth = texelFetch(depthMap, coord + uvec2(x, y)).r;
+			float depth = texelFetch(depthMap, COORD + ivec2(x, y), 0).r;
 
 			minDepth = min(depth, minDepth);
 		}
@@ -53,15 +58,15 @@ void main()
 	float nearZ = -planes.y / (planes.x + minDepth);
 
 	//
-	//
+	// Reject point lights
 	//
 	uint newPointLightIndices[MAX_POINT_LIGHTS_PER_TILE];
 	uint newPointLightsCount = 0;
 
-	uint pointLightsCount = tiles[vInstanceId].lightsCount[0];
+	uint pointLightsCount = tiles[tileY][tileX].lightsCount[0];
 	for(uint i = 0U; i < pointLightsCount; ++i)
 	{
-		uint lightId = tiles[tileY][tileX].pointLightIndices[i];
+		uint lightId = tiles[tileY][tileX].pointLightIndices[i / 4U][i % 4U];
 
 		vec4 posRadius = pointLights[lightId].posRadius;
 		vec3 pos = posRadius.xyz;
@@ -79,7 +84,8 @@ void main()
 	// Copy back
 	for(uint i = 0U; i < newPointLightsCount; i++)
 	{
-		tiles[tileY][tileX].pointLightIndices[i] = newPointLightIndices[i];
+		tiles[tileY][tileX].pointLightIndices[i / 4U][i % 4U] = 
+			newPointLightIndices[i];
 	}
-	tiles[vInstanceId].lightsCount[0] = newPointLightsCount;
+	tiles[tileY][tileX].lightsCount[0] = newPointLightsCount;
 }

+ 110 - 50
src/renderer/Is.cpp

@@ -132,7 +132,7 @@ static PtrSize calcLigthsUboSize()
 static Bool useCompute()
 {
 	return GlStateCommonSingleton::get().getMajorVersion() >= 4
-		&& GlStateCommonSingleton::get().getMinorVersion() >= 10; // XXX
+		&& GlStateCommonSingleton::get().getMinorVersion() >= 3;
 }
 
 //==============================================================================
@@ -423,8 +423,6 @@ void Is::initInternal(const RendererInitializer& initializer)
 {
 	groundLightEnabled = initializer.is.groundLightEnabled;
 
-	Bool gpuPath = useCompute();
-
 	//
 	// Init the passes
 	//
@@ -433,36 +431,51 @@ void Is::initInternal(const RendererInitializer& initializer)
 	//
 	// Load the programs
 	//
-	std::string pps =
-		"#define TILES_X_COUNT " + std::to_string(TILES_X_COUNT) + "\n"
-		"#define TILES_Y_COUNT " + std::to_string(TILES_Y_COUNT) + "\n"
-		"#define TILES_COUNT " + std::to_string(TILES_COUNT) + "\n"
-		"#define RENDERER_WIDTH " + std::to_string(r->getWidth()) + "\n"
-		"#define RENDERER_HEIGHT " + std::to_string(r->getHeight()) + "\n"
-		"#define MAX_POINT_LIGHTS_PER_TILE " 
-		+ std::to_string(MAX_POINT_LIGHTS_PER_TILE) + "\n"
-		"#define MAX_SPOT_LIGHTS_PER_TILE " 
-		+ std::to_string(MAX_SPOT_LIGHTS_PER_TILE) + "\n"
-		"#define MAX_SPOT_TEX_LIGHTS_PER_TILE " 
-		+ std::to_string(MAX_SPOT_TEX_LIGHTS_PER_TILE) + "\n"
-		"#define MAX_POINT_LIGHTS " + std::to_string(MAX_POINT_LIGHTS) + "\n"
-		"#define MAX_SPOT_LIGHTS " + std::to_string(MAX_SPOT_LIGHTS) + "\n"
-		"#define MAX_SPOT_TEX_LIGHTS " 
-		+ std::to_string(MAX_SPOT_TEX_LIGHTS) + "\n"
-		"#define GROUND_LIGHT " + std::to_string(groundLightEnabled) + "\n";
+	std::stringstream pps;
+
+	pps << "#define TILES_X_COUNT " << TILES_X_COUNT << "\n"
+		<< "#define TILES_Y_COUNT " << TILES_Y_COUNT << "\n"
+		<< "#define TILES_COUNT " << TILES_COUNT << "\n"
+		<< "#define RENDERER_WIDTH " << r->getWidth() << "\n"
+		<< "#define RENDERER_HEIGHT " << r->getHeight() << "\n"
+		<< "#define MAX_POINT_LIGHTS_PER_TILE " << MAX_POINT_LIGHTS_PER_TILE
+		<< "\n"
+		<< "#define MAX_SPOT_LIGHTS_PER_TILE " << MAX_SPOT_LIGHTS_PER_TILE
+		<< "\n"
+		<< "#define MAX_SPOT_TEX_LIGHTS_PER_TILE " 
+		<< MAX_SPOT_TEX_LIGHTS_PER_TILE << "\n"
+		<< "#define MAX_POINT_LIGHTS " << MAX_POINT_LIGHTS << "\n"
+		<< "#define MAX_SPOT_LIGHTS " << MAX_SPOT_LIGHTS << "\n"
+		<< "#define MAX_SPOT_TEX_LIGHTS " << MAX_SPOT_TEX_LIGHTS << "\n"
+		<< "#define GROUND_LIGHT " << groundLightEnabled << "\n";
 
 	if(sm.getPcfEnabled())
 	{
-		pps += "#define PCF 1\n";
+		pps << "#define PCF 1\n";
 	}
 	else
 	{
-		pps += "#define PCF 0\n";
+		pps << "#define PCF 0\n";
 	}
 
 	// point light
 	lightPassProg.load(ShaderProgramResource::createSrcCodeToCache(
-		"shaders/IsLp.glsl", pps.c_str()).c_str());
+		"shaders/IsLp.glsl", pps.str().c_str()).c_str());
+
+#if ANKI_GL == ANKI_GL_DESKTOP
+	if(useCompute())
+	{
+		pps << "#define DEPTHMAP_WIDTH " 
+			<< r->getMs().getDepthFai().getWidth() << "\n"
+			<< "#define DEPTHMAP_HEIGHT " 
+			<< r->getMs().getDepthFai().getHeight() << "\n"
+			<< "#define TILES_BLOCK_BINDING " 
+			<< TILES_BLOCK_BINDING << "\n";
+
+		rejectProg.load(ShaderProgramResource::createSrcCodeToCache(
+			"shaders/IsRejectLights.glsl", pps.str().c_str()).c_str());
+	}
+#endif
 
 	//
 	// Create FBOs
@@ -510,24 +523,11 @@ void Is::initInternal(const RendererInitializer& initializer)
 	uboAlignment = BufferObject::getUniformBufferOffsetAlignment();
 
 	// tiles BO
-	if(gpuPath)
-	{
-		// as SSBO
-		tilesBuffer.create(
-			GL_SHADER_STORAGE_BUFFER, 
-			sizeof(shader::Tiles), 
-			nullptr, 
-			GL_STATIC_DRAW);
-	}
-	else
-	{
-		// as UBO
-		tilesBuffer.create(
-			GL_UNIFORM_BUFFER, 
-			sizeof(shader::Tiles), 
-			nullptr, 
-			GL_DYNAMIC_DRAW);
-	}
+	tilesBuffer.create(
+		GL_UNIFORM_BUFFER, 
+		sizeof(shader::Tiles), 
+		nullptr, 
+		GL_DYNAMIC_DRAW);
 
 	ANKI_LOGI("Creating BOs: lights: " << calcLigthsUboSize() << "B tiles: "
 		<< sizeof(shader::Tiles) << "B");
@@ -543,6 +543,19 @@ void Is::initInternal(const RendererInitializer& initializer)
 		throw ANKI_EXCEPTION("Problem with the commonBlock");
 	}
 
+#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
+
 	ublock = &lightPassProg->findUniformBlock("pointLightsBlock");
 	ublock->setBinding(POINT_LIGHTS_BLOCK_BINDING);
 	if(ublock->getSize() != sizeof(shader::PointLight) * MAX_POINT_LIGHTS
@@ -551,6 +564,19 @@ void Is::initInternal(const RendererInitializer& initializer)
 		throw ANKI_EXCEPTION("Problem with the pointLightsBlock");
 	}
 
+#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) * MAX_POINT_LIGHTS
+			|| ublock->getBinding() != POINT_LIGHTS_BLOCK_BINDING)
+		{
+			throw ANKI_EXCEPTION("Problem with the pointLightsBlock");
+		}
+	}
+#endif
+
 	ublock = &lightPassProg->findUniformBlock("spotLightsBlock");
 	ublock->setBinding(SPOT_LIGHTS_BLOCK_BINDING);
 	if(ublock->getSize() != sizeof(shader::SpotLight) * MAX_SPOT_LIGHTS
@@ -574,18 +600,18 @@ void Is::initInternal(const RendererInitializer& initializer)
 	{
 		throw ANKI_EXCEPTION("Problem with the tilesBlock");
 	}
-}
 
-//==============================================================================
-void Is::rejectLights()
-{
-#if ANKI_GL == ANKI_GL_DESKTOP
-	if(ANKI_UNLIKELY(!useCompute()))
+#if ANKI_GL == ANKI_GL_DESKTOP && 0
+	if(rejectProg.isLoaded())
 	{
-		return;
+		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
 }
 
@@ -757,6 +783,40 @@ void Is::lightPass()
 		&clientBuffer[0], 0, spotTexLightsOffset + spotTexLightsSize);
 	tilesBuffer.write(&clientTiles);
 
+	//
+	// Reject occluded lights. This operation issues a compute job to reject 
+	// lights from the tiles
+	//
+#if ANKI_GL == ANKI_GL_DESKTOP
+	if(ANKI_UNLIKELY(rejectProg.isLoaded()))
+	{
+		rejectProg->bind();
+
+		if(pointLightsSize > 0)
+		{
+			lightsUbo.setBindingRange(
+				POINT_LIGHTS_BLOCK_BINDING, pointLightsOffset, pointLightsSize);
+		}
+		/*if(spotLightsSize > 0)
+		{
+			lightsUbo.setBindingRange(SPOT_LIGHTS_BLOCK_BINDING, spotLightsOffset,
+				spotLightsSize);
+		}
+		if(spotTexLightsSize > 0)
+		{
+			lightsUbo.setBindingRange(SPOT_TEX_LIGHTS_BLOCK_BINDING, 
+				spotTexLightsOffset, spotTexLightsSize);
+		}*/
+		tilesBuffer.setTarget(GL_SHADER_STORAGE_BUFFER);
+		tilesBuffer.setBinding(TILES_BLOCK_BINDING);
+		tilesBuffer.setTarget(GL_UNIFORM_BUFFER);
+
+		commonUbo.setBinding(COMMON_UNIFORMS_BLOCK_BINDING);
+
+		glDispatchCompute(TILES_X_COUNT, TILES_Y_COUNT, 1);
+	}
+#endif	
+
 	//
 	// Setup shader and draw
 	//

+ 1 - 1
testapp/Main.cpp

@@ -474,7 +474,7 @@ void mainLoop()
 
 		// Sleep
 		//
-#if 0
+#if 1
 		timer.stop();
 		if(timer.getElapsedTime() < AppSingleton::get().getTimerTick())
 		{