Преглед изворни кода

Tried to optimize a bit. AnKi has two different paths (MRT+non-MRT and UBOs+non-UBOs) but none of them are faster.

Panagiotis Christopoulos Charitos пре 12 година
родитељ
комит
19d39b65fb

+ 1 - 1
CMakeLists.txt

@@ -97,7 +97,7 @@ IF(CMAKE_BUILD_TYPE STREQUAL "Debug")
 ELSE()
 	# Release
 
-	SET(COMMON_FLAGS "${COMMON_FLAGS} -ffast-math -O4 ")
+	SET(COMMON_FLAGS "${COMMON_FLAGS} -ffast-math -O4 -flto ")
 
 	SET(CXX_FLAGS "${CXX_FLAGS} -fno-rtti ")
 ENDIF()

+ 7 - 5
include/anki/Config.h.cmake

@@ -95,7 +95,7 @@
 #define ANKI_MAX_MULTIDRAW_PRIMITIVES 64
 #define ANKI_MAX_INSTANCES 64
 
-// Renderer config
+// Renderer and rendering related config options
 #define ANKI_RENDERER_MAX_POINT_LIGHTS (512 - 16)
 #define ANKI_RENDERER_MAX_SPOT_LIGHTS 8
 #define ANKI_RENDERER_MAX_SPOT_TEX_LIGHTS 8
@@ -107,14 +107,16 @@
 #define ANKI_RENDERER_TILES_X_COUNT 16
 #define ANKI_RENDERER_TILES_Y_COUNT 16
 
+#define ANKI_RENDERER_USE_MRT 1
+
+#define ANKI_RENDERER_USE_MATERIAL_UBOS 0
+
 // Scene config
 #define ANKI_SCENE_OPTIMAL_SCENE_NODES_COUNT 1024
 
-/// 1MB
-#define ANKI_SCENE_ALLOCATOR_SIZE 0x100000 
+#define ANKI_SCENE_ALLOCATOR_SIZE (1024 * 1024) 
 
-// 512K
-#define ANKI_SCENE_FRAME_ALLOCATOR_SIZE 0x80000
+#define ANKI_SCENE_FRAME_ALLOCATOR_SIZE (1024 * 512)
 
 /// @{
 /// Used to optimize the initial vectors of VisibilityTestResults

+ 8 - 3
include/anki/gl/Texture.h

@@ -292,12 +292,17 @@ public:
 		glTexParameteri(target, param, value);
 	}
 
-	/// Generate new mipmaps
-	void genMipmap();
-
 	/// Read the data from the texture. Available only in GL desktop
 	void readPixels(void* data, U level = 0) const;
 
+	/// Set the range of the mipmaps
+	/// @param baseLevel The level of the base mipmap. By default is 0
+	/// @param maxLevel The level of the max mimap. Most of the time it's 1000.
+	void setMipmapsRange(U baseLevel, U maxLevel);
+
+	/// Generate mipmaps
+	void generateMipmaps();
+
 private:
 	GLuint glId = 0; ///< Identification for OGL
 	GLenum target = GL_NONE; ///< GL_TEXTURE_2D, GL_TEXTURE_3D... etc

+ 0 - 2
include/anki/renderer/Drawer.h

@@ -17,8 +17,6 @@ class Renderable;
 class RenderableDrawer
 {
 public:
-	static const U UNIFORM_BLOCK_MAX_SIZE = 256;
-
 	enum RenderingStage
 	{
 		RS_MATERIAL,

+ 10 - 0
include/anki/renderer/Ms.h

@@ -25,6 +25,13 @@ public:
 		return fai0;
 	}
 
+#if ANKI_RENDERER_USE_MRT
+	const Texture& getFai1() const
+	{
+		return fai1;
+	}
+#endif
+
 	const Texture& getDepthFai() const
 	{
 		return depthFai;
@@ -38,6 +45,9 @@ private:
 	Ez ez; /// EarlyZ pass
 	Fbo fbo;
 	Texture fai0; ///< The FAI for diffuse color, normals and specular
+#if ANKI_RENDERER_USE_MRT
+	Texture fai1;
+#endif
 	Texture depthFai; ///< The FAI for depth
 };
 

+ 13 - 3
shaders/IsLp.glsl

@@ -87,7 +87,13 @@ layout(std140)
 	Tile tiles[TILES_COUNT];
 };
 
+
+#if USE_MRT
+uniform sampler2D msFai0;
+uniform sampler2D msFai1;
+#else
 uniform highp usampler2D msFai0;
+#endif
 uniform sampler2D msDepthFai;
 
 //uniform sampler2D lightTextures[MAX_SPOT_LIGHTS];
@@ -216,15 +222,19 @@ float calcShadowFactor(in SpotTexLight light, in vec3 fragPosVspace,
 //==============================================================================
 void main()
 {
-	// Read texture first. Optimize for future out of order HW
-	uvec2 msAll = textureLod(msFai0, vTexCoords, 0.0).rg;
-
 	// get frag pos in view space
 	vec3 fragPosVspace = getFragPosVSpace();
 
 	// Decode MS
+#if USE_MRT
+	vec3 normal = unpackNormal(texture(msFai1, vTexCoords).rg);
+	vec4 diffuseAndSpec = texture(msFai0, vTexCoords);
+#else
+	uvec2 msAll = texture(msFai0, vTexCoords).rg;
+
 	vec3 normal = unpackNormal(unpackHalf2x16(msAll[1]));
 	vec4 diffuseAndSpec = unpackUnorm4x8(msAll[0]);
+#endif
 	vec2 specularAll = unpackSpecular(diffuseAndSpec.a);
 
 	// Ambient color

+ 12 - 0
shaders/MsCommonFrag.glsl

@@ -27,7 +27,12 @@ flat in lowp float vSpecularComponent;
 /// @name Fragment out
 /// @{
 #if defined(PASS_COLOR)
+#	if USE_MRT
+layout(location = 0) out vec4 fMsFai0;
+layout(location = 1) out vec2 fMsFai1;
+#	else
 layout(location = 0) out uvec2 fMsFai0;
+#	endif
 #	define fMsFai0_DEFINED
 #endif
 /// @}
@@ -151,10 +156,17 @@ void writeFais(
 	in float specularComponent, // Streangth and shininess
 	in float blurring)
 {
+#if USE_MRT
+	// Diffuse color and specular
+	fMsFai0 = vec4(diffCol, specularComponent);
+	// Normal
+	fMsFai1 = packNormal(normal);
+#else
 	// Diffuse color and specular
 	fMsFai0[0] = packUnorm4x8(vec4(diffCol, specularComponent));
 	// Normal
 	fMsFai0[1] = packHalf2x16(packNormal(normal));
+#endif
 }
 #endif
 

+ 9 - 10
shaders/Pps.glsl

@@ -19,7 +19,7 @@ layout(location = 0) out vec3 fColor;
 
 const vec2 TEX_OFFSET = vec2(1.0 / float(FBO_WIDTH), 1.0 / float(FBO_HEIGHT));
 
-vec2 KERNEL[8] = vec2[](
+const vec2 KERNEL[8] = vec2[](
 	vec2(TEX_OFFSET.x, TEX_OFFSET.y),
 	vec2(0.0, TEX_OFFSET.y),
 	vec2(-TEX_OFFSET.x, TEX_OFFSET.y),
@@ -62,16 +62,15 @@ vec3 sharpen(in sampler2D tex, in vec2 texCoords)
 {
 	const float sharpenFactor = 0.25;
 
-	vec3 col = textureLod(tex, texCoords, 0.0).rgb;
+	vec3 col = texture(tex, texCoords).rgb;
 
-	vec3 col2 = textureLod(tex, texCoords + KERNEL[0], 0.0).rgb;
+	vec3 col2 = texture(tex, texCoords + KERNEL[0]).rgb;
 	for(int i = 1; i < 8; i++)
 	{
-		col2 += textureLod(tex, texCoords + KERNEL[i], 0.0).rgb;
+		col2 += texture(tex, texCoords + KERNEL[i]).rgb;
 	}
 
-	return col * (9.0 * sharpenFactor + 1.0 - sharpenFactor) 
-		- sharpenFactor * col2;
+	return col * (8.0 * sharpenFactor + 1.0) - sharpenFactor * col2;
 }
 
 //==============================================================================
@@ -94,22 +93,22 @@ void main(void)
 #if defined(SHARPEN_ENABLED)
 	fColor = sharpen(isFai, vTexCoords);
 #else
-	fColor = textureLod(isFai, vTexCoords, 0.0).rgb;
+	fColor = texture(isFai, vTexCoords).rgb;
 #endif
 	//fColor = erosion(isFai, vTexCoords);
 
 #if defined(HDR_ENABLED)
-	vec3 hdr = textureLod(ppsHdrFai, vTexCoords, 0.0).rgb;
+	vec3 hdr = texture(ppsHdrFai, vTexCoords).rgb;
 	fColor += hdr;
 #endif
 
 #if defined(SSAO_ENABLED)
-	float ssao = textureLod(ppsSsaoFai, vTexCoords, 0.0).r;
+	float ssao = texture(ppsSsaoFai, vTexCoords).r;
 	fColor *= ssao;
 #endif
 
 #if defined(LF_ENABLED)
-	vec3 lf = textureLod(ppsLfFai, vTexCoords, 0.0).rgb;
+	vec3 lf = texture(ppsLfFai, vTexCoords).rgb;
 	fColor += lf;
 #endif
 

+ 9 - 1
shaders/PpsSsao.glsl

@@ -38,7 +38,11 @@ layout(std140, row_major) uniform commonBlock
 #define limitsOfNearPlane2 limitsOfNearPlane_.zw
 
 uniform sampler2D msDepthFai;
+#if USE_MRT
+uniform sampler2D msGFai;
+#else
 uniform highp usampler2D msGFai;
+#endif
 uniform sampler2D noiseMap; 
 /// @}
 
@@ -49,8 +53,12 @@ uniform sampler2D noiseMap;
 
 vec3 getNormal(in vec2 uv)
 {
+#if USE_MRT
+	vec3 normal = unpackNormal(texture(msGFai, uv).rg);
+#else
 	uvec2 msAll = texture(msGFai, uv).rg;
 	vec3 normal = unpackNormal(unpackHalf2x16(msAll[1]));
+#endif
 	return normal;
 }
 
@@ -61,7 +69,7 @@ vec2 getRandom(in vec2 uv)
 		float(HEIGHT) / float(NOISE_MAP_SIZE));
 
 	vec2 noise = texture(noiseMap, tmp * uv).xy;
-	//return normalize(noise * 2.0 - 1.0);r
+	//return normalize(noise * 2.0 - 1.0);
 	return noise;
 }
 

+ 7 - 2
src/gl/ShaderProgram.cpp

@@ -220,7 +220,8 @@ void ShaderProgramUniformVariable::setClientMemorySanityChecks(
 	ANKI_ASSERT(checkType<T>(getGlDataType()));
 	ANKI_ASSERT(size <= getSize() && size > 0);
 	ANKI_ASSERT(offset != -1 && arrayStride != -1 && "Uniform is not in block");
-	ANKI_ASSERT(block->getSize() <= buffSize);
+	ANKI_ASSERT(block->getSize() <= buffSize 
+		&& "The client buffer is too small");
 	ANKI_ASSERT(size <= 1 || arrayStride != 0);
 }
 
@@ -229,6 +230,7 @@ template<typename T>
 void ShaderProgramUniformVariable::setClientMemoryInternal(
 	void* buff_, U32 buffSize, const T arr[], U32 size) const
 {
+	ANKI_ASSERT(arr);
 	setClientMemorySanityChecks<T>(buffSize, size);
 	U8* buff = (U8*)buff_ + offset;
 
@@ -245,6 +247,7 @@ template<typename T, typename Vec>
 void ShaderProgramUniformVariable::setClientMemoryInternalMatrix(
 	void* buff_, U32 buffSize, const T arr[], U32 size) const
 {
+	ANKI_ASSERT(arr);
 	setClientMemorySanityChecks<T>(buffSize, size);
 	ANKI_ASSERT(matrixStride >= (GLint)sizeof(Vec));
 	U8* buff = (U8*)buff_ + offset;
@@ -252,10 +255,12 @@ void ShaderProgramUniformVariable::setClientMemoryInternalMatrix(
 	for(U32 i = 0; i < size; i++)
 	{
 		U8* subbuff = buff;
+		T matrix = arr[i];
+		matrix.transpose();
 		for(U j = 0; j < sizeof(T) / sizeof(Vec); j++)
 		{
 			Vec* ptr = (Vec*)subbuff;
-			*ptr = arr[i].getRow(j);
+			*ptr = matrix.getRow(j);
 			subbuff += matrixStride;
 		}
 		buff += arrayStride;

+ 15 - 7
src/gl/Texture.cpp

@@ -456,13 +456,6 @@ U Texture::bind() const
 	return unit;
 }
 
-//==============================================================================
-void Texture::genMipmap()
-{
-	TextureUnitsSingleton::get().bindTextureAndActivateUnit(*this);
-	glGenerateMipmap(target);
-}
-
 //==============================================================================
 void Texture::setFilteringNoBind(TextureFilteringType filterType)
 {
@@ -499,4 +492,19 @@ void Texture::readPixels(void* pixels, U level) const
 #endif
 }
 
+//==============================================================================
+void Texture::setMipmapsRange(U baseLevel, U maxLevel)
+{	
+	TextureUnitsSingleton::get().bindTextureAndActivateUnit(*this);
+	glTexParameteri(target, GL_TEXTURE_BASE_LEVEL, baseLevel);
+	glTexParameteri(target, GL_TEXTURE_MAX_LEVEL, maxLevel);
+}
+
+//==============================================================================
+void Texture::generateMipmaps()
+{
+	TextureUnitsSingleton::get().bindTextureAndActivateUnit(*this);
+	glGenerateMipmap(target);
+}
+
 } // end namespace anki

+ 5 - 2
src/renderer/Drawer.cpp

@@ -11,6 +11,9 @@
 
 namespace anki {
 
+//==============================================================================
+static const U UNIFORM_BLOCK_MAX_SIZE = 1024 * 12;
+
 //==============================================================================
 #if ANKI_ENABLE_COUNTERS
 static U64 countVerts(U32* indicesCount, I primCount)
@@ -28,10 +31,10 @@ static U64 countVerts(U32* indicesCount, I primCount)
 /// Visitor that sets a uniform
 struct SetupRenderableVariableVisitor
 {
+	Array<U32, UNIFORM_BLOCK_MAX_SIZE / sizeof(U32)> clientBlock;
 	const Frustumable* fr = nullptr;
 	Renderer* r = nullptr;
 	Renderable* renderable = nullptr;
-	Array<U8, RenderableDrawer::UNIFORM_BLOCK_MAX_SIZE> clientBlock;
 	RenderableVariable* rvar = nullptr;
 	const ShaderProgramUniformVariable* uni;
 
@@ -201,7 +204,7 @@ struct SetupRenderableVariableVisitor
 		if(uni.getUniformBlock()) \
 		{ \
 			uni.setClientMemory(&clientBlock[0], \
-				RenderableDrawer::UNIFORM_BLOCK_MAX_SIZE, \
+				sizeof(clientBlock), \
 				values, size); \
 		} \
 		else \

+ 9 - 4
src/renderer/Is.cpp

@@ -132,7 +132,8 @@ static PtrSize calcLigthsUboSize()
 static Bool useCompute()
 {
 	return GlStateCommonSingleton::get().getMajorVersion() >= 4
-		&& GlStateCommonSingleton::get().getMinorVersion() >= 3;
+		&& GlStateCommonSingleton::get().getMinorVersion() >= 3
+		&& false;
 }
 
 //==============================================================================
@@ -447,7 +448,8 @@ void Is::initInternal(const RendererInitializer& initializer)
 		<< "#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";
+		<< "#define GROUND_LIGHT " << groundLightEnabled << "\n"
+		<< "#define USE_MRT " << ANKI_RENDERER_USE_MRT << "\n";
 
 	if(sm.getPcfEnabled())
 	{
@@ -466,9 +468,9 @@ void Is::initInternal(const RendererInitializer& initializer)
 	if(useCompute())
 	{
 		pps << "#define DEPTHMAP_WIDTH " 
-			<< r->getMs().getDepthFai().getWidth() << "\n"
+			<< (r->getMs().getDepthFai().getWidth()) << "\n"
 			<< "#define DEPTHMAP_HEIGHT " 
-			<< r->getMs().getDepthFai().getHeight() << "\n"
+			<< (r->getMs().getDepthFai().getHeight()) << "\n"
 			<< "#define TILES_BLOCK_BINDING " 
 			<< TILES_BLOCK_BINDING << "\n";
 
@@ -851,6 +853,9 @@ void Is::lightPass()
 	tilesBuffer.setBinding(TILES_BLOCK_BINDING);
 
 	lightPassProg->findUniformVariable("msFai0").set(r->getMs().getFai0());
+#if ANKI_RENDERER_USE_MRT
+	lightPassProg->findUniformVariable("msFai1").set(r->getMs().getFai1());
+#endif
 	lightPassProg->findUniformVariable("msDepthFai").set(
 		r->getMs().getDepthFai());
 	lightPassProg->findUniformVariable("shadowMapArr").set(sm.sm2DArrayTex);

+ 14 - 0
src/renderer/Ms.cpp

@@ -17,14 +17,25 @@ void Ms::init(const RendererInitializer& initializer)
 {
 	try
 	{
+#if ANKI_RENDERER_USE_MRT
+		fai0.create2dFai(r->getWidth(), r->getHeight(), GL_RGBA8,
+			GL_RGBA, GL_UNSIGNED_BYTE);
+		fai1.create2dFai(r->getWidth(), r->getHeight(), GL_RG16F,
+			GL_RG, GL_FLOAT);
+#else
 		fai0.create2dFai(r->getWidth(), r->getHeight(), GL_RG32UI,
 			GL_RG_INTEGER, GL_UNSIGNED_INT);
+#endif
 		depthFai.create2dFai(r->getWidth(), r->getHeight(),
 			GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL,
 			GL_UNSIGNED_INT_24_8);
 
 		fbo.create();
+#if ANKI_RENDERER_USE_MRT
+		fbo.setColorAttachments({&fai0, &fai1});
+#else
 		fbo.setColorAttachments({&fai0});
+#endif
 		fbo.setOtherAttachment(GL_DEPTH_STENCIL_ATTACHMENT, depthFai);
 		if(!fbo.isComplete())
 		{
@@ -75,6 +86,9 @@ void Ms::run()
 			(*it).subSpatialIndices, (*it).subSpatialIndicesCount);
 	}
 
+	// Gen mips
+	//fai0.generateMipmaps();
+
 	ANKI_CHECK_GL_ERROR();
 }
 

+ 19 - 11
src/renderer/Ssao.cpp

@@ -84,33 +84,37 @@ void Ssao::initInternal(const RendererInitializer& initializer)
 	//
 	commonUbo.create(sizeof(ShaderCommonUniforms), nullptr);
 
-	std::string pps;
+	std::stringstream pps;
 
 	// main pass prog
-	pps = "#define NOISE_MAP_SIZE " + std::to_string(noiseMap->getWidth())
-		+ "\n#define WIDTH " + std::to_string(mpWidth)
-		+ "\n#define HEIGHT " + std::to_string(mpHeight) + "\n";
+	pps << "#define NOISE_MAP_SIZE " << noiseMap->getWidth()
+		<< "\n#define WIDTH " << mpWidth
+		<< "\n#define HEIGHT " << mpHeight
+		<< "\n#define USE_MRT " << ANKI_RENDERER_USE_MRT
+		<< "\n";
 	ssaoSProg.load(ShaderProgramResource::createSrcCodeToCache(
-		"shaders/PpsSsao.glsl", pps.c_str()).c_str());
+		"shaders/PpsSsao.glsl", pps.str().c_str()).c_str());
 
 	ssaoSProg->findUniformBlock("commonBlock").setBinding(0);
 
 	// blurring progs
 	const char* SHADER_FILENAME = "shaders/VariableSamplingBlurGeneric.glsl";
 
-	pps = "#define HPASS\n"
+	pps.clear();
+	pps << "#define HPASS\n"
 		"#define COL_R\n"
-		"#define IMG_DIMENSION " + std::to_string(bHeight) + "\n"
+		"#define IMG_DIMENSION " << bHeight << "\n"
 		"#define SAMPLES 7\n";
 	hblurSProg.load(ShaderProgramResource::createSrcCodeToCache(
-		SHADER_FILENAME, pps.c_str()).c_str());
+		SHADER_FILENAME, pps.str().c_str()).c_str());
 
-	pps = "#define VPASS\n"
+	pps.clear();
+	pps << "#define VPASS\n"
 		"#define COL_R\n"
-		"#define IMG_DIMENSION " + std::to_string(bWidth) + "\n"
+		"#define IMG_DIMENSION " << bWidth << "\n"
 		"#define SAMPLES 7\n";
 	vblurSProg.load(ShaderProgramResource::createSrcCodeToCache(
-		SHADER_FILENAME, pps.c_str()).c_str());
+		SHADER_FILENAME, pps.str().c_str()).c_str());
 }
 
 //==============================================================================
@@ -174,7 +178,11 @@ void Ssao::run()
 	ssaoSProg->findUniformVariable("noiseMap").set(*noiseMap);
 
 	// msGFai
+#if ANKI_RENDERER_USE_MRT
+	ssaoSProg->findUniformVariable("msGFai").set(r->getMs().getFai1());
+#else
 	ssaoSProg->findUniformVariable("msGFai").set(r->getMs().getFai0());
+#endif
 
 	// Draw
 	r->drawQuad();

+ 7 - 7
src/resource/Material.cpp

@@ -10,8 +10,6 @@
 #include <map>
 #include <fstream>
 
-#define ENABLE_UBOS 0
-
 namespace anki {
 
 //==============================================================================
@@ -269,7 +267,8 @@ void Material::parseMaterialTag(const XmlElement& materialEl)
 	// shaderProgram
 	//
 	XmlElement shaderProgramEl = materialEl.getChildElement("shaderProgram");
-	MaterialShaderProgramCreator mspc(shaderProgramEl, ENABLE_UBOS);
+	MaterialShaderProgramCreator mspc(
+		shaderProgramEl, ANKI_RENDERER_USE_MATERIAL_UBOS);
 
 	for(U32 level = 0; level < levelsOfDetail; ++level)
 	{
@@ -282,9 +281,10 @@ void Material::parseMaterialTag(const XmlElement& materialEl)
 
 			std::stringstream src;
 
-			src << "#define LOD " << level << std::endl;
-			src << "#define PASS_" << passNames[pid] << std::endl;
-			src << mspc.getShaderProgramSource() << std::endl;
+			src << "#define LOD " << level << "\n"
+				<< "#define PASS_" << passNames[pid] << "\n"
+				<< "#define USE_MRT " << ANKI_RENDERER_USE_MRT << "\n"
+				<< mspc.getShaderProgramSource() << std::endl;
 
 			std::string filename =
 				createShaderProgSourceToCache(src.str().c_str());
@@ -357,7 +357,7 @@ void Material::populateVariables(const MaterialShaderProgramCreator& mspc)
 		for(const ShaderProgramUniformVariable& v :
 			(*sProg)->getUniformVariables())
 		{
-#if ENABLE_UBOS
+#if ANKI_RENDERER_USE_MATERIAL_UBOS
 			const ShaderProgramUniformBlock* bl = v.getUniformBlock();
 			if(bl == nullptr)
 			{

+ 10 - 4
src/resource/MaterialShaderProgramCreator.cpp

@@ -249,17 +249,23 @@ void MaterialShaderProgramCreator::parseShaderTag(const XmlElement& shaderEl)
 	
 	// First the uniform block
 	std::string uniformBlock;
+	U inputsInBlockCount = 0;
 	for(Input* in : inputs)
 	{
-		if((in->shaders & shader) && in->putInBlock)
+		if(in->shaders & shader)
 		{
-			uniformBlock += in->line + "\n";
+			++inputsInBlockCount;
+		}
+
+		if(in->putInBlock)
+		{
+			uniformBlock += "\t" + in->line + "\n";
 		}
 	}
 
-	if(uniformBlock.size() > 0)
+	if(uniformBlock.size() > 0 && inputsInBlockCount > 0)
 	{
-		srcLines.push_back("layout(shared) uniform " + type + "Block {");
+		srcLines.push_back("layout(shared) uniform commonBlock {");
 		srcLines.push_back(uniformBlock);
 		srcLines.push_back("};");
 	}

+ 1 - 1
testapp/Main.cpp

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