Browse Source

Fixing tessellation bugs

Panagiotis Christopoulos Charitos 11 years ago
parent
commit
ca4cd48cf7

+ 1 - 1
include/anki/renderer/Renderer.h

@@ -162,7 +162,7 @@ public:
 		return m_isOffscreen;
 	}
 
-	Bool usesTessellation() const
+	Bool getTessellationEnabled() const
 	{
 		return m_tessellation;
 	}

+ 3 - 0
include/anki/resource/Material.h

@@ -377,6 +377,9 @@ private:
 	/// Read all shader programs and pupulate the @a vars and @a nameToVar
 	/// containers
 	void populateVariables(const MaterialProgramCreator& mspc);
+
+	U countShaders(ShaderType type) const;
+	U getShaderIndex(const RenderingKey key, ShaderType type) const;
 };
 
 } // end namespace anki

+ 23 - 6
shaders/MsCommonTesse.glsl

@@ -8,6 +8,10 @@ layout(triangles, equal_spacing, ccw) in;
 #define IN_POS4(i_) gl_in[i_].gl_Position
 #define IN_POS3(i_) gl_in[i_].gl_Position.xyz
 
+//
+// Input
+//
+
 struct PNPatch
 {
 	vec3 pos021;
@@ -31,6 +35,11 @@ struct CommonPatch
 };
 #endif
 
+in gl_PerVertex
+{
+	vec4 gl_Position;
+} gl_in[];
+
 in patch PNPatch pnPatch;
 in patch PhongPatch phongPatch;
 #if INSTANCE_ID_FRAGMENT_SHADER
@@ -39,13 +48,21 @@ in patch CommonPatch commonPatch;
 
 layout(location = 0) in vec2 inTexCoord[];
 layout(location = 1) in vec3 inNormal[];
-#if PASS_COLOR
+#if PASS == COLOR
 layout(location = 2) in vec4 inTangent[];
 #endif
 
-// Varyings out
+//
+// Output
+//
+
+out gl_PerVertex
+{
+	vec4 gl_Position;
+};
+
 layout(location = 0) out highp vec2 outTexCoord;
-#if PASS_COLOR
+#if PASS == COLOR
 layout(location = 1) out mediump vec3 outNormal;
 layout(location = 2) out mediump vec4 outTangent;
 #endif
@@ -56,7 +73,7 @@ layout(location = 2) out mediump vec4 outTangent;
 #define tessellatePNPositionNormalTangentTexCoord_DEFINED
 void tessellatePNPositionNormalTangentTexCoord(in mat4 mvp, in mat3 normalMat)
 {
-#if PASS_COLOR
+#if PASS == COLOR
 	outNormal = normalize(normalMat * INTERPOLATE(inNormal));
 	outTangent = INTERPOLATE(inTangent);
 	outTangent.xyz = normalize(normalMat * outTangent.xyz);
@@ -98,7 +115,7 @@ void tessellatePNPositionNormalTangentTexCoord(in mat4 mvp, in mat3 normalMat)
 void tessellatePhongPositionNormalTangentTexCoord(
 	in mat4 mvp, in mat3 normalMat)
 {
-#if PASS_COLOR
+#if PASS == COLOR
 	outNormal = normalize(normalMat * INTERPOLATE(inNormal));
 	outTangent = INTERPOLATE(inTangent);
 	outTangent.xyz = normalize(normalMat * outTangent.xyz);
@@ -145,7 +162,7 @@ void tessellateDispMapPositionNormalTangentTexCoord(
 	in mat4 mvp, in mat3 normalMat, in sampler2D dispMap)
 {
 	vec3 norm = INTERPOLATE(inNormal);
-#if PASS_COLOR
+#if PASS == COLOR
 	outNormal = normalize(normalMat * norm);
 	outTangent = INTERPOLATE(inTangent);
 	outTangent.xyz = normalize(normalMat * outTangent.xyz);

+ 3 - 0
src/gl/GlCommandBufferHandle.cpp

@@ -505,6 +505,9 @@ void GlCommandBufferHandle::drawElements(
 		case GL_LINES:
 			_pushBackNewCommand<DrawElementsCommand<GL_LINES, 2>>(info);
 			break;
+		case GL_PATCHES:
+			_pushBackNewCommand<DrawElementsCommand<GL_PATCHES, 2>>(info);
+			break;
 		default:
 			ANKI_ASSERT(0 && "Not implemented");
 		}

+ 1 - 1
src/gl/GlSync.cpp

@@ -11,7 +11,7 @@ namespace anki {
 //==============================================================================
 void GlClientSync::wait()
 {
-	Bool timeout = m_barrier.wait(2.0);
+	Bool timeout = m_barrier.wait();
 	if(timeout)
 	{
 		ANKI_LOGW("Sync timed out. Probably because of exception");

+ 11 - 1
src/renderer/Drawer.cpp

@@ -326,10 +326,15 @@ void RenderableDrawer::render(SceneNode& frsn, VisibleNode& visibleNode)
 	build.m_key.m_lod = flod;
 	build.m_key.m_pass = m_pass;
 	build.m_key.m_tessellation = 
-		m_r->usesTessellation() 
+		m_r->getTessellationEnabled() 
 		&& mtl.getTessellation()
 		&& build.m_key.m_lod == 0;
 
+	if(m_pass == Pass::DEPTH)
+	{
+		build.m_key.m_tessellation = false;
+	}
+
 	// Blending
 	Bool blending = mtl.isBlendingEnabled();
 	if(!blending)
@@ -374,6 +379,11 @@ void RenderableDrawer::prepareDraw(RenderingStage stage, Pass pass,
 	m_pass = pass;
 	m_cmdBuff = cmdBuff;
 
+	if(m_r->getTessellationEnabled())
+	{
+		m_cmdBuff.setPatchVertexCount(3);
+	}
+
 	if(m_r->getFramesCount() > m_uniformsUsedSizeFrame)
 	{
 		// New frame, reset used size

+ 1 - 1
src/renderer/MainRenderer.cpp

@@ -91,7 +91,7 @@ void MainRenderer::render(SceneGraph& scene)
 			rt = &getIs()._getRt();
 		}
 
-		//rt = &getIs()._getRt();
+		//rt = &getMs()._getRt1();
 		//rt = &getPps().getSsao().getRt();
 
 		rt->setFilter(lastJobs, GlTextureHandle::Filter::LINEAR);

+ 107 - 45
src/resource/Material.cpp

@@ -146,8 +146,43 @@ Material::~Material()
 }
 
 //==============================================================================
-ProgramResourcePointer& Material::getProgram(
-	const RenderingKey key, ShaderType shaderId)
+U Material::countShaders(ShaderType type) const
+{
+	U count = 0;
+	U tessCount = m_tessellation ? 2 : 1;
+
+	switch(type)
+	{
+	case ShaderType::VERTEX:
+		count = m_passesCount * m_lodsCount * tessCount;
+		break;
+	case ShaderType::TESSELLATION_CONTROL:
+		if(m_tessellation)
+		{
+			count = m_passesCount;
+		}
+		break;
+	case ShaderType::TESSELLATION_EVALUATION:
+		if(m_tessellation)
+		{
+			count = m_passesCount;
+		}
+		break;
+	case ShaderType::GEOMETRY:
+		count = 0;
+		break;
+	case ShaderType::FRAGMENT:
+		count = m_passesCount * m_lodsCount;
+		break;
+	default:
+		ANKI_ASSERT(0);
+	}
+
+	return count;
+}
+
+//==============================================================================
+U Material::getShaderIndex(const RenderingKey key, ShaderType type) const
 {
 	ANKI_ASSERT((U)key.m_pass < m_passesCount);
 	ANKI_ASSERT(key.m_lod < m_lodsCount);
@@ -157,60 +192,69 @@ ProgramResourcePointer& Material::getProgram(
 		ANKI_ASSERT(m_tessellation);
 	}
 
-	// Calc the count that are before this shader
 	U tessCount = m_tessellation ? 2 : 1;
-	U count = 0;
-	switch(shaderId)
+
+	U pass = enumToType(key.m_pass);
+	U lod = key.m_lod;
+	U tess = key.m_tessellation;
+
+	U offset = 0;
+	switch(type)
 	{
 	case ShaderType::FRAGMENT:
-		// Count of geom
-		count += 0;
+		offset += countShaders(ShaderType::GEOMETRY);
 	case ShaderType::GEOMETRY:
-		// Count of tess
-		if(m_tessellation)
-		{
-			count += m_passesCount * m_lodsCount;
-		}
+		offset += countShaders(ShaderType::TESSELLATION_EVALUATION);
 	case ShaderType::TESSELLATION_EVALUATION:
-		// Count of tess
-		if(m_tessellation)
-		{
-			count += m_passesCount * m_lodsCount;
-		}
+		offset += countShaders(ShaderType::TESSELLATION_CONTROL);
 	case ShaderType::TESSELLATION_CONTROL:
-		// Count of vert
-		count += m_passesCount * m_lodsCount * tessCount;
+		offset += countShaders(ShaderType::VERTEX);
 	case ShaderType::VERTEX:
+		offset += 0;
 		break;
 	default:
 		ANKI_ASSERT(0);
 	}
 
-	// Calc the idx
-	U idx = 0;
-	switch(shaderId)
+	U idx = MAX_U32;
+	switch(type)
 	{
 	case ShaderType::VERTEX:
-		idx = (U)key.m_pass * m_lodsCount * tessCount + key.m_lod * tessCount 
-			+ (key.m_tessellation ? 1 : 0);
+		// Like referencing an array of [pass][lod][tess]
+		idx = pass * m_lodsCount * tessCount + lod * tessCount + tess;
 		break;
 	case ShaderType::TESSELLATION_CONTROL:
+		// Like an array [pass]
+		idx = pass;
+		break;
 	case ShaderType::TESSELLATION_EVALUATION:
+		// Like an array [pass]
+		idx = pass;
+		break;
+	case ShaderType::GEOMETRY:
+		idx = 0;
+		break;
 	case ShaderType::FRAGMENT:
-		idx = (U)key.m_pass * m_lodsCount + key.m_lod;
+		// Like an array [pass][lod]
+		idx = pass * m_lodsCount + lod;
 		break;
 	default:
 		ANKI_ASSERT(0);
 	}
 
-	idx += count;
-	ANKI_ASSERT(idx < m_progs.size());
-	ProgramResourcePointer& out = m_progs[idx];
+	return offset + idx;
+}
+
+//==============================================================================
+ProgramResourcePointer& Material::getProgram(
+	const RenderingKey key, ShaderType type)
+{
+	ProgramResourcePointer& out = m_progs[getShaderIndex(key, type)];
 
 	if(out.isLoaded())
 	{
 		ANKI_ASSERT(
-			computeShaderTypeIndex(out->getGlProgram().getType()) == shaderId);
+			computeShaderTypeIndex(out->getGlProgram().getType()) == type);
 	}
 
 	return out;
@@ -220,20 +264,22 @@ ProgramResourcePointer& Material::getProgram(
 GlProgramPipelineHandle Material::getProgramPipeline(
 	const RenderingKey& key)
 {
-	ANKI_ASSERT((U)key.m_pass < m_passesCount);
+	ANKI_ASSERT(enumToType(key.m_pass) < m_passesCount);
 	ANKI_ASSERT(key.m_lod < m_lodsCount);
 
 	U tessCount = 1;
-	if(key.m_tessellation)
+	if(m_tessellation)
 	{
-		ANKI_ASSERT(m_tessellation);
 		tessCount = 2;
 	}
+	else
+	{
+		ANKI_ASSERT(!key.m_tessellation);
+	}
 
-	U idx = (U)key.m_pass * m_lodsCount * tessCount
+	U idx = enumToType(key.m_pass) * m_lodsCount * tessCount
 		+ key.m_lod * tessCount + key.m_tessellation;
 
-	ANKI_ASSERT(idx < m_pplines.size());
 	GlProgramPipelineHandle& ppline = m_pplines[idx];
 
 	// Lazily create it
@@ -361,14 +407,12 @@ void Material::parseMaterialTag(const XmlElement& materialEl,
 	U tessCount = m_tessellation ? 2 : 1;
 
 	// Alloc program vector
-	U progCount = 0;
-	progCount += m_passesCount * m_lodsCount * tessCount;
-	if(m_tessellation)
-	{
-		progCount += m_passesCount * m_lodsCount * 2;
-	}
-	progCount += m_passesCount * m_lodsCount;
-	m_progs.resize(progCount);
+	m_progs.resize(
+		countShaders(ShaderType::VERTEX) 
+		+ countShaders(ShaderType::TESSELLATION_CONTROL)
+		+ countShaders(ShaderType::TESSELLATION_EVALUATION)
+		+ countShaders(ShaderType::GEOMETRY)
+		+ countShaders(ShaderType::FRAGMENT));
 
 	// Aloc progam descriptors
 	m_pplines.resize(m_passesCount * m_lodsCount * tessCount);
@@ -378,24 +422,42 @@ void Material::parseMaterialTag(const XmlElement& materialEl,
 		shader <= ShaderType::FRAGMENT; 
 		++shader)
 	{
-		if(!m_tessellation 
-			&& (shader == ShaderType::TESSELLATION_CONTROL 
-				|| shader == ShaderType::TESSELLATION_EVALUATION))
+		Bool isTessellationShader = shader == ShaderType::TESSELLATION_CONTROL 
+			|| shader == ShaderType::TESSELLATION_EVALUATION;
+
+		if(!m_tessellation && isTessellationShader)
 		{
+			// Skip tessellation if not enabled
 			continue;
 		}
 
 		if(shader == ShaderType::GEOMETRY)
 		{
+			// Skip geometry for now
 			continue;
 		}
 
 		for(U level = 0; level < m_lodsCount; ++level)
 		{
+			if(level > 0 && isTessellationShader)
+			{
+				continue;
+			}
+
 			for(U pid = 0; pid < m_passesCount; ++pid)
 			{
 				for(U tess = 0; tess < tessCount; ++tess)
 				{
+					if(tess == 0 && isTessellationShader)
+					{
+						continue;
+					}
+
+					if(tess > 0 && shader == ShaderType::FRAGMENT)
+					{
+						continue;
+					}
+
 					TempResourceString src(rinit.m_tempAlloc);
 
 					src.sprintf(

+ 5 - 0
src/resource/MaterialProgramCreator.cpp

@@ -303,6 +303,11 @@ void MaterialProgramCreator::parseInputsTag(const XmlElement& programEl)
 
 			duplicateInp->m_shaderDefinedMask |= glshaderbit;
 
+			if(duplicateInp->m_inBlock)
+			{
+				m_uniformBlockReferencedMask |= glshaderbit;
+			}
+
 			goto advance;
 		}
 

+ 14 - 11
src/util/HighRezTimerPosix.cpp

@@ -15,31 +15,33 @@ namespace anki {
 //==============================================================================
 namespace {
 
-// The first ticks value of the application
-struct timespec gstart;
-
 /// A dummy struct that inits the timer
-struct DummyInitTimer
+class StartTime
 {
-	DummyInitTimer()
+public:
+	/// The first ticks value of the application
+	timespec m_time;
+
+	StartTime()
 	{
-		clock_gettime(CLOCK_MONOTONIC, &gstart);
+		clock_gettime(CLOCK_MONOTONIC, &m_time);
 	}
 };
 
-DummyInitTimer dummy;
+StartTime startTime;
 
 } // end namespace anonymous 
 
 //==============================================================================
 static U64 getNs()
 {
-	U32 ticks;
+	U64 ticks;
 
-	struct timespec now;
+	timespec now;
 	clock_gettime(CLOCK_MONOTONIC, &now);
-	ticks = (now.tv_sec - gstart.tv_sec) * 1000000000 
-		+ (now.tv_nsec - gstart.tv_nsec);
+	ticks = 
+		static_cast<U64>(now.tv_sec - startTime.m_time.tv_sec) * 1000000000 
+		+ (now.tv_nsec - startTime.m_time.tv_nsec);
 
 	return ticks;
 }
@@ -47,6 +49,7 @@ static U64 getNs()
 //==============================================================================
 void HighRezTimer::sleep(Scalar sec)
 {
+	ANKI_ASSERT(sec >= 0.0);
 	int wasError;
 	U64 ns = static_cast<U64>(sec * 1e+9);
 

+ 11 - 2
src/util/ThreadPosix.cpp

@@ -257,9 +257,18 @@ Bool ConditionVariable::wait(Mutex& amtx, F64 timeoutSeconds)
 	else
 	{
 		U64 ns = static_cast<U64>(timeoutSeconds * 1e+9);
+		struct timespec reltime;
+		reltime.tv_sec = ns / 1000000000;
+		reltime.tv_nsec = (ns % 1000000000);
+
+		struct timespec now;
+		clock_gettime(CLOCK_REALTIME, &now);
+
 		struct timespec abstime;
-		abstime.tv_sec = ns / 1000000000;
-		abstime.tv_nsec = (ns % 1000000000);
+		memset(&abstime, 0, sizeof(abstime));
+		abstime.tv_sec = now.tv_sec + reltime.tv_sec;
+		abstime.tv_nsec = now.tv_nsec + reltime.tv_nsec;
+		
 		err = pthread_cond_timedwait(cond, mtx, &abstime);
 	}
 

+ 2 - 2
testapp/Main.cpp

@@ -120,7 +120,7 @@ void init()
 	spot->setShadowEnabled(true);
 #endif
 
-#if 1
+#if 0
 	// Vase point lights
 	F32 x = 8.5; 
 	F32 y = 2.25;
@@ -506,7 +506,7 @@ void initSubsystems(int argc, char* argv[])
 	config.set("height", 720);
 	config.set("lodDistance", 20.0);
 	config.set("samples", 1);
-	config.set("tessellation", false);
+	config.set("tessellation", true);
 	config.set("tilesXCount", 16);
 	config.set("tilesYCount", 16);
 

+ 20 - 0
tests/util/Thread.cpp

@@ -152,3 +152,23 @@ ANKI_TEST(Util, Threadpool)
 	delete tp;
 }
 
+//==============================================================================
+ANKI_TEST(Util, Barrier)
+{
+	// Simple test
+	{
+		Barrier b(2);
+		Thread t(nullptr);
+
+		t.start(&b, [](Thread::Info& info) -> I
+		{
+			Barrier& b = *reinterpret_cast<Barrier*>(info.m_userData);
+			b.wait();
+			return 0;
+		});
+
+		b.wait();
+		t.join();
+	}
+}
+