Browse Source

Android port

Panagiotis Christopoulos Charitos 12 years ago
parent
commit
c86e20f833

+ 1 - 1
CMakeLists.txt

@@ -193,7 +193,7 @@ INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/anki/Config.h" DESTINATION "${INCLUDE
 #
 # Include & lib directories
 #
-INCLUDE_DIRECTORIES("extern/tinyxml2/include" "extern/lua" "extern/png" "extern/z" "extern/bullet" "include" "${CMAKE_CURRENT_BINARY_DIR}")
+INCLUDE_DIRECTORIES("extern/tinyxml2/include" "extern/lua" "extern/z" "extern/bullet" "include" "${CMAKE_CURRENT_BINARY_DIR}")
 
 IF(${ANKI_WINDOW_BACKEND} STREQUAL "GLXX11" OR ${ANKI_WINDOW_BACKEND} STREQUAL "MACOS")
 	INCLUDE_DIRECTORIES("extern/GLEW/include")

+ 10 - 1
bench/Main.cpp

@@ -134,6 +134,7 @@ void initSubsystems()
 	initializer.get("lodDistance") = 20.0;
 	initializer.get("samples") = 16;
 
+//#if ANKI_GL == ANKI_GL_ES
 #if 1
 	initializer.get("samples") = 1;
 	initializer.get("is.maxPointLights") = 64;
@@ -141,8 +142,9 @@ void initSubsystems()
 	initializer.get("is.maxSpotLightsPerTile") = 4;
 	initializer.get("is.maxSpotTexLightsPerTile") = 4;
 	initializer.get("pps.enabled") = false;
-	initializer.get("renderingQuality") = 0.8;
+	//initializer.get("renderingQuality") = 0.25;
 	initializer.get("maxTextureSize") = 256;
+	initializer.get("mrt") = false;
 #endif
 
 	MainRendererSingleton::get().init(initializer);
@@ -334,10 +336,17 @@ static void mainLoop()
 
 		// Update
 		input.handleEvents();
+
+		if(input.getEvent(Input::WINDOW_CLOSED_EVENT) > 0)
+		{
+			break;
+		}
+
 		if(!mainLoopExtra())
 		{
 			break;
 		}
+
 		scene.update(prevUpdateTime, crntTime, renderer);
 		renderer.render(scene);
 

+ 0 - 2
include/anki/Config.h.cmake

@@ -111,8 +111,6 @@
 #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

+ 6 - 1
include/anki/core/ThreadPool.h

@@ -9,6 +9,9 @@
 
 namespace anki {
 
+/// Debug flag to disable threadpool threading capabilities
+#define ANKI_DISABLE_THREADPOOL_THREADING 0
+
 // Forward
 class ThreadPool;
 
@@ -41,7 +44,7 @@ struct ThreadJobDummy: ThreadJob
 	}
 };
 
-/// The thread that executes a ThreadJobCallback
+/// The thread that executes a ThreadJob
 class ThreadWorker
 {
 public:
@@ -109,7 +112,9 @@ public:
 	/// Wait for all jobs to finish
 	void waitForAllJobsToFinish()
 	{
+#if !ANKI_DISABLE_THREADPOOL_THREADING
 		barrier->wait();
+#endif
 	}
 
 	U32 getThreadsCount() const

+ 24 - 2
include/anki/input/Input.h

@@ -19,6 +19,14 @@ class NativeWindow;
 class Input
 {
 public:
+	enum Event
+	{
+		WINDOW_FOCUS_LOST_EVENT,
+		WINDOW_FOCUS_GAINED_EVENT,
+		WINDOW_CLOSED_EVENT,
+		EVENTS_COUNT
+	};
+
 	Input()
 	{
 		reset();
@@ -27,12 +35,12 @@ public:
 
 	/// @name Acessors
 	/// @{
-	U32 getKey(U32 i) const
+	U getKey(U32 i) const
 	{
 		return keys[i];
 	}
 
-	U32 getMouseButton(U32 i) const
+	U getMouseButton(U32 i) const
 	{
 		return mouseBtns[i];
 	}
@@ -41,6 +49,12 @@ public:
 	{
 		return mousePosNdc;
 	}
+
+	/// Get the times an event was triggered and resets the counter
+	U getEvent(Event eventId) const
+	{
+		return events[eventId];
+	}
 	/// @}
 
 	/// Initialize the platform's input system
@@ -66,6 +80,12 @@ public:
 		lockCurs = lock;
 	}
 
+	/// Add a new event
+	void addEvent(Event eventId)
+	{
+		++events[eventId];
+	}
+
 private:
 	NativeWindow* nativeWindow = nullptr;
 
@@ -84,6 +104,8 @@ private:
 
 	Vec2 mousePosNdc = Vec2(2.0); ///< The coords are in the NDC space
 
+	Array<U8, EVENTS_COUNT> events;
+
 	std::shared_ptr<InputImpl> impl;
 
 	Bool8 lockCurs = false;

+ 3 - 9
include/anki/renderer/Ms.h

@@ -8,7 +8,7 @@
 
 namespace anki {
 
-/// Material stage
+/// Material stage also known as G buffer stage. It populates the G buffer
 class Ms: public RenderingPass
 {
 public:
@@ -25,12 +25,7 @@ public:
 		return fai0[1];
 	}
 
-#if ANKI_RENDERER_USE_MRT
-	const Texture& getFai1() const
-	{
-		return fai1[1];
-	}
-#endif
+	const Texture& getFai1() const;
 
 	const Texture& getDepthFai() const
 	{
@@ -45,9 +40,8 @@ private:
 	Ez ez; /// EarlyZ pass
 	Array<Fbo, 2> fbo;
 	Array<Texture, 2> fai0; ///< The FAI for diffuse color, normals and specular
-#if ANKI_RENDERER_USE_MRT
+	/// Contains the normal and spec power on the MRT case
 	Array<Texture, 2> fai1;
-#endif
 	Array<Texture, 2> depthFai; ///< The FAI for depth
 
 	/// Create a G buffer FBO

+ 19 - 28
include/anki/renderer/Renderer.h

@@ -33,16 +33,6 @@ public:
 class Renderer
 {
 public:
-	typedef RendererInitializer Initializer;
-
-	/// The types of rendering a ModelNode
-	enum ModelNodeRenderType
-	{
-		MNRT_MS, ///< In material stage
-		MNRT_DP, ///< In a depth pass
-		MNRT_BS  ///< In blending stage
-	};
-
 	Renderer();
 	~Renderer();
 
@@ -234,7 +224,7 @@ public:
 	/// skipped
 	void clearAfterBindingFbo(const GLenum cap);
 
-protected:
+private:
 	/// @name Rendering stages
 	/// @{
 	Ms ms; ///< Material rendering stage
@@ -242,17 +232,27 @@ protected:
 	Pps pps; ///< Postprocessing rendering stage
 	Bs bs; ///< Blending stage
 	Dbg dbg; ///< Debug stage
-	/// @}
-
 	Tiler tiler;
+	/// @}
 
 	/// Width of the rendering. Don't confuse with the window width
 	U32 width;
-	/// Height of the rendering. Don't confuse with the window width
+	/// Height of the rendering. Don't confuse with the window height
 	U32 height;
-	SceneGraph* scene; ///< Current scene
-	RenderableDrawer sceneDrawer;
 	F32 lodDistance; ///< Distance that used to calculate the LOD
+	U8 samples; ///< Number of sample in multisampling
+	Bool8 useMrt; ///< Use MRT or pack things inside the G buffer
+	Bool8 isOffscreen; ///< Is offscreen renderer?
+	F32 renderingQuality; ///< Rendering quality. Relevant for offscreen 
+	U32 maxTextureSize; ///< Texture size limit. Just kept here.
+	U16 tilesXCount;
+	U16 tilesYCount;
+
+	/// @name For drawing a quad into the active framebuffer
+	/// @{
+	Vbo quadPositionsVbo; ///< The VBO for quad positions
+	Vao quadVao; ///< This VAO is used everywhere except material stage
+	/// @}
 
 	/// @name Optimization vars
 	/// Used in other stages
@@ -270,19 +270,10 @@ protected:
 	Vec2 limitsOfNearPlane2;
 	/// @}
 
-private:
-	U framesNum; ///< Frame number
-	U8 samples;
-	Bool8 useMrt; ///< Use MRT or pack things inside the G buffer
-	Bool8 isOffscreen;
-	F32 renderingQuality;
-	U32 maxTextureSize;
+	SceneGraph* scene; ///< Current scene
+	RenderableDrawer sceneDrawer;
 
-	/// @name For drawing a quad into the active framebuffer
-	/// @{
-	Vbo quadPositionsVbo; ///< The VBO for quad positions
-	Vao quadVao; ///< This VAO is used everywhere except material stage
-	/// @}
+	U framesNum; ///< Frame number
 };
 
 } // end namespace anki

+ 2 - 1
shaders/IsLp.glsl

@@ -331,8 +331,9 @@ void main()
 #endif
 
 #if 0
+	if(vInstanceId != 99999)
 	{
-		fColor += fColor * 0.1 + normal * 0.9;
+		fColor = vec3(diffColor);
 	}
 #endif
 

+ 2 - 4
shaders/MsCommonFrag.glsl

@@ -22,8 +22,6 @@ in float vTangentW;
 #	define vTangentW_DEFINED
 in vec3 vVertPosViewSpace;
 #	define vVertPosViewSpace_DEFINED
-flat in float vSpecularComponent;
-#	define vSpecularComponent_DEFINED
 #endif
 /// @}
 
@@ -110,8 +108,8 @@ vec3 getEnvironmentColor(in vec3 vertPosViewSpace, in vec3 normal,
 /// @param[in] tolerance Tolerance value
 /// @param[in] texCoords Texture coordinates
 /// @return The RGB channels of the map
-#define getDiffuseColorAndDoAlphaTesting_DEFINED
-vec3 getDiffuseColorAndDoAlphaTesting(
+#define readTextureRgbAlphaTesting_DEFINED
+vec3 readTextureRgbAlphaTesting(
 	in sampler2D map,
 	in highp vec2 texCoords,
 	in float tolerance)

+ 22 - 109
shaders/Pack.glsl

@@ -19,126 +19,39 @@ vec3 unpackNormal(in vec2 enc)
 	return normal;
 }
 
-vec2 encodeUnormFloatToVec2(in float f)
-{
-	vec2 vec = vec2(1.0, 65025.0) * f;
-	return vec2(vec.x, fract(vec.y));
-	//return unpackSnorm2x16(floatBitsToUint(f));
-}
-
-float decodeVec2ToUnormFloat(in vec2 vec)
+#if GL_ES
+uint packUnorm4x8(in vec4 v)
 {
-	//return uintBitsToFloat(packSnorm2x16(vec));
-	return dot(vec, vec2(1.0, 1.0 / 65025.0));
+	vec4 a = clamp(v, 0.0, 1.0) * 255.0;
+	return uint(a.x) | (uint(a.y) << 8) | (uint(a.z) << 16) | (uint(a.w) << 24);
 }
-
-void packAndWriteNormal(in vec3 normal, out vec4 fai)
+ 
+vec4 unpackUnorm4x8(in highp uint u)
 {
-#if 1
-	vec3 unorm = normal * 0.5 + 0.5;
-	fai = vec4(unorm.xyz, 0.0);
-#endif
+	vec4 v;
+	v.x = float(u & 0xffU);
+	v.y = float((u >> 8) & 0xffU);
+	v.z = float((u >> 16) & 0xffU);
+	v.w = float((u >> 24) & 0xffU);
 
-#if 0
-	vec3 unorm = normal * 0.5 + 0.5;
-	float maxc = max(max(unorm.x, unorm.y), unorm.z);
-	fai = vec4(unorm.xyz * maxc, maxc);
-#endif
-
-#if 0
-	vec2 enc = packNormal(normal) * 0.5 + 0.5;
-	fai = vec4(encodeUnormFloatToVec2(enc.x), encodeUnormFloatToVec2(enc.y));
-#endif
-
-#if 0
-	vec2 unorm = normal.xy * 0.5 + 0.5;
-	vec2 x = encodeUnormFloatToVec2(unorm.x);
-	vec2 y = encodeUnormFloatToVec2(unorm.y);
-	fai = vec4(x, y);
-#endif
-	//fai = packNormal(normal_);
+	return v * (1.0 / 255.0);
 }
-
-vec3 readAndUnpackNormal(in sampler2D fai, in vec2 texCoord)
-{
-#if 1
-	return normalize(texture(fai, texCoord).xyz * 2.0 - 1.0);
-#endif
-
-#if 0
-	vec4 enc = texture(fai, texCoord);
-	return normalize(enc.xyz * (2.0 / enc.w) - 1.0);
-#endif
-
-#if 0
-	vec4 enc = texture(fai, texCoord);
-	vec2 enc2 = vec2(decodeVec2ToUnormFloat(enc.xy), 
-		decodeVec2ToUnormFloat(enc.zw)) * 2.0 - 1.0;
-	return unpackNormal(enc2);
 #endif
 
-#if 0
-	vec4 enc = texture(fai, texCoord);
-	vec2 xy = vec2(decodeVec2ToUnormFloat(enc.xy),
-		decodeVec2ToUnormFloat(enc.zw)) * 2.0 - 1.0;
-	float z = sqrt(1.0 - dot(xy, xy)) ;
-	vec3 snorm = vec3(xy, z);
-	return snorm;
+// If not defined fake it to stop some compilers from complaining
+#ifndef USE_MRT
+#	define USE_MRT 1
 #endif
-	//unpackNormal(texture(fai_, texCoord_).rg)
-}
 
 #define MAX_SPECULARITY 128.0
 
-/// Pack specular stuff
-/// @param c The specular component. c.x is the color in grayscale and c.y the 
-///          specularity
-#define packSpecular_DEFINED
-float packSpecular(in vec2 c)
-{
-	return round(c[0] * 15.0) * (16.0 / 255.0) 
-		+ round(c[1] / MAX_SPECULARITY * 15.0) / 255.0;
-}
-
-/// Unpack specular
-vec2 unpackSpecular(in float f)
-{
-	float r = floor(f * (255.0 / 16.0));
-
-	return vec2(
-		r / 15.0,
-		f * (255.0 * MAX_SPECULARITY / 15.0) 
-		- r * (16.0 * MAX_SPECULARITY / 15.0));
-}
-
-#if GL_ES
-uint packUnorm4x8(in vec4 v)
-{
-	vec4 value = clamp(v, 0.0, 1.0) * 255.0;
-
-	return uint(value.x) | (uint(value.y) << 8) | (uint(value.z) << 16) |
-		(uint(value.w) << 24);
-}
- 
-vec4 unpackUnorm4x8(in uint u)
-{
-	vec4 value;
-
-	value.x = float(u & 0xffU);
-	value.y = float((u >> 8) & 0xffU);
-	value.z = float((u >> 16) & 0xffU);
-	value.w = float((u >> 24) & 0xffU);
-
-	return value * (1.0 / 255.0);
-}
-#endif
-
 // Populate the G buffer
 void writeGBuffer(
 	in vec3 diffColor, in vec3 normal, in float specColor, in float specPower,
-	out vec4 fai0
 #if USE_MRT
-	,out vec4 fai1
+	out vec4 fai0, out vec4 fai1
+#else
+	out highp uvec2 fai0
 #endif
 	)
 {
@@ -172,15 +85,15 @@ void readGBuffer(
 	normal = normalize(comp.xyz * 2.0 - 1.0);
 	specPower = comp.w * MAX_SPECULARITY;
 #else
-	uvec2 all_ = texture(fai0, texCoord).rg;
+	highp uvec2 all_ = texture(fai0, texCoord).rg;
 
 	vec4 v = unpackUnorm4x8(all_[0]);
 	diffColor = v.rgb;
-	specColor = v.a * MAX_SPECULARITY;
+	specColor = v.a;
 
 	v = unpackUnorm4x8(all_[1]);
 	normal = normalize(v.xyz * 2.0 - 1.0);
-	specPower = v.xyz;
+	specPower = v.w * MAX_SPECULARITY;
 #endif
 }
 
@@ -195,7 +108,7 @@ void readNormalFromGBuffer(
 	out vec3 normal)
 {
 #if USE_MRT
-	normal = normalize(readAndUnpackNormal(fai1, texCoord).xyz);
+	normal = normalize(texture(fai1, texCoord).xyz);
 #else
 	vec4 v = unpackUnorm4x8(texture(fai0, texCoord).g);
 	normal = normalize(v.xyz * 2.0 - 1.0);

+ 1 - 1
src/CMakeLists.txt

@@ -28,7 +28,7 @@ ENDIF()
 
 ADD_LIBRARY(anki Dummy.cpp "${_SYS_SRC}")
 
-TARGET_LINK_LIBRARIES(anki ${ANKI_LIBS} ankitinyxml2 ankilua ankibullet ankiz ankipng ${ANKI_GPERFTOOLS_LIBS} ${_SYS})
+TARGET_LINK_LIBRARIES(anki ${ANKI_LIBS} ankitinyxml2 ankilua ankibullet ankiz ${ANKI_GPERFTOOLS_LIBS} ${_SYS})
 
 SET_TARGET_PROPERTIES(anki PROPERTIES LINKER_LANGUAGE CXX)
 

+ 2 - 2
src/core/App.cpp

@@ -79,8 +79,8 @@ void App::initDirs()
 	ANKI_LOGI("Creating cache dir: %s", cachePath.c_str());
 	createDirectory(cachePath.c_str());
 #else
-	ANKI_ASSERT(gAndroidApp);
-	ANativeActivity* activity = gAndroidApp->activity;
+	//ANKI_ASSERT(gAndroidApp);
+	//ANativeActivity* activity = gAndroidApp->activity;
 
 	// Settings path
 	//settingsPath = std::string(activity->internalDataPath);

+ 7 - 2
src/core/Counters.cpp

@@ -1,5 +1,6 @@
 #include "anki/core/Counters.h"
 #include "anki/core/Timestamp.h"
+#include "anki/core/App.h"
 #include "anki/util/Array.h"
 #include <cstring>
 
@@ -46,7 +47,9 @@ CountersManager::CountersManager()
 	counterTimes.resize(C_COUNT, 0.0);
 
 	// Open and write the headers to the files
-	perframeFile.open("./perframe_counters.csv", File::OF_WRITE);
+	perframeFile.open(
+		(AppSingleton::get().getSettingsPath() + "/frame_counters.csv").c_str(), 
+		File::OF_WRITE);
 
 	perframeFile.writeText("FRAME");
 
@@ -59,7 +62,9 @@ CountersManager::CountersManager()
 	}
 
 	// Open and write the headers to the other file
-	perrunFile.open("./perrun_counters.csv", File::OF_WRITE);
+	perrunFile.open(
+		(AppSingleton::get().getSettingsPath() + "/run_counters.csv").c_str(), 
+		File::OF_WRITE);
 
 	U i = 0;
 	for(const CounterInfo& inf : cinfo)

+ 11 - 5
src/core/ThreadPool.cpp

@@ -11,17 +11,23 @@ namespace anki {
 ThreadWorker::ThreadWorker(U32 id_, Barrier* barrier_, ThreadPool* threadPool_)
 	: id(id_), barrier(barrier_), threadPool(threadPool_)
 {
+#if !ANKI_DISABLE_THREADPOOL_THREADING
 	start();
+#endif
 }
 
 //==============================================================================
 void ThreadWorker::assignNewJob(ThreadJob* job_)
 {
+#if !ANKI_DISABLE_THREADPOOL_THREADING
 	mutex.lock();
 	ANKI_ASSERT(job == nullptr && "Probably forgot to wait for all jobs");
 	job = job_;
 	mutex.unlock();
 	condVar.notify_one(); // Wake the thread
+#else
+	(*job_)(id, threadPool->getThreadsCount());
+#endif
 }
 
 //==============================================================================
@@ -65,14 +71,14 @@ ThreadPool::~ThreadPool()
 }
 
 //==============================================================================
-void ThreadPool::init(U threadsNum)
+void ThreadPool::init(U threadsCount)
 {
-	ANKI_ASSERT(threadsNum <= MAX_THREADS);
+	ANKI_ASSERT(threadsCount <= MAX_THREADS && threadsCount > 0);
 
-	barrier.reset(new Barrier(threadsNum + 1));
+	barrier.reset(new Barrier(threadsCount + 1));
 
-	jobs.resize(threadsNum);
-	for(U i = 0; i < threadsNum; i++)
+	jobs.resize(threadsCount);
+	for(U i = 0; i < threadsCount; i++)
 	{
 		jobs[i] = new ThreadWorker(i, barrier.get(), this);
 	}

+ 1 - 1
src/gl/Fbo.cpp

@@ -82,7 +82,7 @@ void Fbo::bind(const FboTarget target, Bool noReadbacks) const
 			currentRead = this;
 		}
 
-		ANKI_ASSERT(noReadbacks == false && "Dosn't make sense");
+		ANKI_ASSERT(noReadbacks == false && "Doesn't make sense");
 	}
 }
 

+ 4 - 2
src/input/CMakeLists.txt

@@ -1,9 +1,11 @@
 FILE(GLOB ANKI_INPUT_SOURCES Input.cpp)
 
-IF(ANKI_WINDOW_BACKEND STREQUAL "GLXX11" OR ANKI_WINDOW_BACKEND STREQUAL "EGLX11")
+IF(${ANKI_WINDOW_BACKEND} STREQUAL "GLXX11" OR ${ANKI_WINDOW_BACKEND} STREQUAL "EGLX11")
 	SET(ANKI_INPUT_SOURCES ${ANKI_INPUT_SOURCES} InputX11.cpp)
-ELSEIF(ANKI_WINDOW_BACKEND STREQUAL "MACOS")
+ELSEIF(${ANKI_WINDOW_BACKEND} STREQUAL "MACOS")
 	SET(ANKI_INPUT_SOURCES ${ANKI_INPUT_SOURCES} InputMacos.cpp)
+ELSEIF(${ANKI_WINDOW_BACKEND} STREQUAL "ANDROID")
+	SET(ANKI_INPUT_SOURCES ${ANKI_INPUT_SOURCES} InputAndroid.cpp)
 ELSE()
 	SET(ANKI_INPUT_SOURCES ${ANKI_INPUT_SOURCES} InputDummy.cpp)
 ENDIF()

+ 1 - 0
src/input/Input.cpp

@@ -9,6 +9,7 @@ void Input::reset(void)
 	memset(&keys[0], 0, keys.getSize() * sizeof(U32));
 	memset(&mouseBtns[0], 0, mouseBtns.getSize() * sizeof(U32));
 	mousePosNdc = Vec2(0.0);
+	memset(&events[0], 0, sizeof(events));
 }
 
 } // end namespace

+ 74 - 0
src/input/InputAndroid.cpp

@@ -0,0 +1,74 @@
+#include "anki/input/Input.h"
+#include "anki/core/NativeWindowAndroid.h"
+#include "anki/core/Logger.h"
+#include "anki/core/App.h"
+
+namespace anki {
+
+//==============================================================================
+// Other                                                                       =
+//==============================================================================
+
+//==============================================================================
+static void handleAndroidEvents(android_app* app, int32_t cmd)
+{
+	Input* input = (Input*)app->userData;
+	ANKI_ASSERT(input != nullptr);
+
+	switch(cmd)
+	{
+	case APP_CMD_TERM_WINDOW:
+	case APP_CMD_LOST_FOCUS:
+		ANKI_LOGI("New event 0x%x", cmd);
+		input->addEvent(Input::WINDOW_CLOSED_EVENT);
+		break;
+	}
+}
+
+//==============================================================================
+// Input                                                                       =
+//==============================================================================
+
+//==============================================================================
+Input::~Input()
+{}
+
+//==============================================================================
+void Input::handleEvents()
+{
+	int ident;
+	int outEvents;
+	android_poll_source* source;
+
+	memset(&events[0], 0, sizeof(events));
+
+	while((ident = ALooper_pollAll(0, NULL, &outEvents, (void**)&source)) >= 0) 
+	{
+		if(source != NULL) 
+		{
+			source->process(gAndroidApp, source);
+		}
+	}
+}
+
+//==============================================================================
+void Input::init(NativeWindow* /*nativeWindow*/)
+{
+	ANKI_ASSERT(gAndroidApp);
+	gAndroidApp->userData = this;
+    gAndroidApp->onAppCmd = handleAndroidEvents;
+}
+
+//==============================================================================
+void Input::moveCursor(const Vec2& posNdc)
+{
+	// do nothing
+}
+
+//==============================================================================
+void Input::hideCursor(Bool hide)
+{
+	// do nothing
+}
+
+} // end namespace anki

+ 1 - 1
src/renderer/Bl.cpp

@@ -5,7 +5,7 @@
 namespace anki {
 
 //==============================================================================
-void Bl::init(const Renderer::Initializer& initializer)
+void Bl::init(const RendererInitializer& initializer)
 {
 #if 0
 	enabled = initializer.pps.bl.enabled;

+ 1 - 1
src/renderer/Dbg.cpp

@@ -13,7 +13,7 @@ Dbg::~Dbg()
 {}
 
 //==============================================================================
-void Dbg::init(const Renderer::Initializer& initializer)
+void Dbg::init(const RendererInitializer& initializer)
 {
 	enabled = initializer.get("dbg.enabled");
 	enableBits(DF_ALL);

+ 1 - 1
src/renderer/Hdr.cpp

@@ -25,7 +25,7 @@ void Hdr::initFbo(Fbo& fbo, Texture& fai)
 }
 
 //==============================================================================
-void Hdr::initInternal(const Renderer::Initializer& initializer)
+void Hdr::initInternal(const RendererInitializer& initializer)
 {
 	enabled = initializer.get("pps.hdr.enabled");
 

+ 7 - 6
src/renderer/Is.cpp

@@ -345,7 +345,7 @@ struct WriteLightsJob: ThreadJob
 
 	/// XXX
 	void writeIndexToTileBuffer(
-		U lightType, U lightIndex, U i, U tileX, U tileY)
+		U lightType, U lightIndex, U indexInTileArray, U tileX, U tileY)
 	{
 		const PtrSize tileSize = is->calcTileSize();
 		PtrSize offset;
@@ -373,7 +373,7 @@ struct WriteLightsJob: ThreadJob
 		}
 
 		// Move to the array offset
-		offset += sizeof(U32) * i;
+		offset += sizeof(U32) * indexInTileArray;
 
 		// Write the lightIndex
 		*((U32*)(tileBuffer + offset)) = lightIndex;
@@ -452,7 +452,7 @@ void Is::initInternal(const RendererInitializer& initializer)
 		<< "#define MAX_SPOT_LIGHTS " << (U32)maxSpotLights << "\n"
 		<< "#define MAX_SPOT_TEX_LIGHTS " << (U32)maxSpotTexLights << "\n"
 		<< "#define GROUND_LIGHT " << groundLightEnabled << "\n"
-		<< "#define USE_MRT " << ANKI_RENDERER_USE_MRT << "\n";
+		<< "#define USE_MRT " << r->getUseMrt() << "\n";
 
 	if(sm.getPcfEnabled())
 	{
@@ -853,9 +853,10 @@ 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
+	if(r->getUseMrt())
+	{
+		lightPassProg->findUniformVariable("msFai1").set(r->getMs().getFai1());
+	}
 	lightPassProg->findUniformVariable("msDepthFai").set(
 		r->getMs().getDepthFai());
 	lightPassProg->findUniformVariable("shadowMapArr").set(sm.sm2DArrayTex);

+ 6 - 4
src/renderer/MainRenderer.cpp

@@ -15,20 +15,22 @@ MainRenderer::~MainRenderer()
 {}
 
 //==============================================================================
-void MainRenderer::init(const Renderer::Initializer& initializer_)
+void MainRenderer::init(const RendererInitializer& initializer_)
 {
 	ANKI_LOGI("Initializing main renderer...");
-	initGl();
 
-	Renderer::Initializer initializer = initializer_;
+	RendererInitializer initializer = initializer_;
 	initializer.set("offscreen", false);
 	initializer.get("width") *= initializer.get("renderingQuality");
 	initializer.get("height") *= initializer.get("renderingQuality");
 
+	initGl();
+
 	Renderer::init(initializer);
 	deformer.reset(new Deformer);
 
-	ANKI_LOGI("Main renderer initialized");
+	ANKI_LOGI("Main renderer initialized. Rendering size %dx%d", 
+		getWidth(), getHeight());
 }
 
 //==============================================================================

+ 31 - 17
src/renderer/Ms.cpp

@@ -12,30 +12,44 @@ namespace anki {
 Ms::~Ms()
 {}
 
+//==============================================================================
+const Texture& Ms::getFai1() const
+{
+	ANKI_ASSERT(r->getUseMrt());
+	return fai1[1];
+}
+
 //==============================================================================
 void Ms::createFbo(U index, U samples)
 {
-#if ANKI_RENDERER_USE_MRT
-	fai0[index].create2dFai(r->getWidth(), r->getHeight(), GL_RGBA8,
-		GL_RGBA, GL_UNSIGNED_BYTE, samples);
-	fai1[index].create2dFai(r->getWidth(), r->getHeight(), GL_RGBA8,
-		GL_RGBA, GL_UNSIGNED_BYTE, samples);
-#else
-	fai0[index].create2dFai(r->getWidth(), r->getHeight(), GL_RG32UI,
-		GL_RG_INTEGER, GL_UNSIGNED_INT, samples);
-#endif
+	if(r->getUseMrt())
+	{
+		fai0[index].create2dFai(r->getWidth(), r->getHeight(), GL_RGBA8,
+			GL_RGBA, GL_UNSIGNED_BYTE, samples);
+		fai1[index].create2dFai(r->getWidth(), r->getHeight(), GL_RGBA8,
+			GL_RGBA, GL_UNSIGNED_BYTE, samples);
+	}
+	else
+	{
+		fai0[index].create2dFai(r->getWidth(), r->getHeight(), GL_RG32UI,
+			GL_RG_INTEGER, GL_UNSIGNED_INT, samples);
+	}
+
 	depthFai[index].create2dFai(r->getWidth(), r->getHeight(),
-		GL_DEPTH24_STENCIL8, GL_DEPTH_STENCIL,
-		GL_UNSIGNED_INT_24_8, samples);
+		GL_DEPTH_COMPONENT24, GL_DEPTH_COMPONENT,
+		GL_UNSIGNED_INT, samples);
 
 	fbo[index].create();
 
-#if ANKI_RENDERER_USE_MRT
-	fbo[index].setColorAttachments({&fai0[index], &fai1[index]});
-#else
-	fbo[index].setColorAttachments({&fai0[index]});
-#endif
-	fbo[index].setOtherAttachment(GL_DEPTH_STENCIL_ATTACHMENT, depthFai[index]);
+	if(r->getUseMrt())
+	{
+		fbo[index].setColorAttachments({&fai0[index], &fai1[index]});
+	}
+	else
+	{
+		fbo[index].setColorAttachments({&fai0[index]});
+	}
+	fbo[index].setOtherAttachment(GL_DEPTH_ATTACHMENT, depthFai[index]);
 
 	if(!fbo[index].isComplete())
 	{

+ 1 - 1
src/renderer/Pps.cpp

@@ -71,7 +71,7 @@ void Pps::initInternal(const RendererInitializer& initializer)
 }
 
 //==============================================================================
-void Pps::init(const Renderer::Initializer& initializer)
+void Pps::init(const RendererInitializer& initializer)
 {
 	try
 	{

+ 11 - 2
src/renderer/Renderer.cpp

@@ -64,7 +64,16 @@ RendererInitializer::RendererInitializer()
 	newOption("renderingQuality", 1.0); // Applies only to MainRenderer
 	newOption("lodDistance", 10.0); // Distance that used to calculate the LOD
 	newOption("samples", 1);
-	newOption("useMrt", true); // Pack or not the GBuffer
+
+	if(GlStateCommonSingleton::get().getGpu() == GlStateCommon::GPU_ARM)
+	{
+		newOption("mrt", false); // Pack or not the GBuffer
+	}
+	else
+	{
+		newOption("mrt", true); // Pack or not the GBuffer
+	}
+
 	newOption("maxTextureSize", 1048576); // Cap to limit quality in resources
 	newOption("offscreen", false);
 }
@@ -91,7 +100,7 @@ void Renderer::init(const RendererInitializer& initializer)
 	lodDistance = initializer.get("lodDistance");
 	framesNum = 0;
 	samples = initializer.get("samples");
-	useMrt = initializer.get("useMrt");
+	useMrt = initializer.get("mrt");
 	isOffscreen = initializer.get("offscreen");
 	renderingQuality = initializer.get("renderingQuality");
 	maxTextureSize = initializer.get("maxTextureSize");

+ 9 - 6
src/renderer/Ssao.cpp

@@ -171,7 +171,7 @@ void Ssao::initInternal(const RendererInitializer& initializer)
 	pps << "#define NOISE_MAP_SIZE " << NOISE_TEX_SIZE
 		<< "\n#define WIDTH " << mpWidth
 		<< "\n#define HEIGHT " << mpHeight
-		<< "\n#define USE_MRT " << ANKI_RENDERER_USE_MRT
+		<< "\n#define USE_MRT " << r->getUseMrt()
 		<< "\n#define KERNEL_SIZE " << KERNEL_SIZE
 		<< "\n" << kernelStr.str() 
 		<< "\n";
@@ -266,11 +266,14 @@ void Ssao::run()
 	ssaoSProg->findUniformVariable("noiseMap").set(noiseTex);
 
 	// msGFai
-#if ANKI_RENDERER_USE_MRT
-	ssaoSProg->findUniformVariable("msGFai").set(r->getMs().getFai1());
-#else
-	ssaoSProg->findUniformVariable("msGFai").set(r->getMs().getFai0());
-#endif
+	if(r->getUseMrt())
+	{
+		ssaoSProg->findUniformVariable("msGFai").set(r->getMs().getFai1());
+	}
+	else
+	{
+		ssaoSProg->findUniformVariable("msGFai").set(r->getMs().getFai0());
+	}
 
 	// Draw
 	r->drawQuad();

+ 6 - 19
src/resource/Image.cpp

@@ -200,7 +200,7 @@ static PtrSize calcSurfaceSize(const U width, const U height,
 		break;
 	case Image::DC_S3TC:
 		out = (width / 4) * (height / 4) 
-			* (cf == Image::CF_RGB8) ? 8 : 16; // This is the block size
+			* ((cf == Image::CF_RGB8) ? 8 : 16); // This is the block size
 		break;
 	case Image::DC_ETC:
 		out = (width / 4) * (height / 4) * 8;
@@ -411,24 +411,11 @@ static void loadAnkiTexture(
 	{
 		for(U d = 0; d < depth; d++)
 		{
-			U dataSize = 0;
-			switch(preferredCompression)
-			{
-			case Image::DC_RAW:
-				dataSize = mipWidth * mipHeight 
-					* ((header.colorFormat == Image::CF_RGB8) ? 3 : 4);
-				break;
-			case Image::DC_S3TC:
-				dataSize = (mipWidth / 4) * (mipHeight / 4)
-					* ((header.colorFormat == Image::CF_RGB8) ? 8 : 16);
-				break;
-			case Image::DC_ETC:
-				dataSize = (mipWidth / 4) * (mipHeight / 4) * 8;
-				break;
-			default:
-				ANKI_ASSERT(0);
-			}
+			U dataSize = calcSurfaceSize(
+				mipWidth, mipHeight, preferredCompression, 
+				(Image::ColorFormat)header.colorFormat);
 
+			// Check if this mipmap can be skipped because of size
 			if(std::max(mipWidth, mipHeight) <= maxTextureSize)
 			{
 				U index = (mip - tmpMipLevels + mipLevels) * depth + d;
@@ -492,7 +479,7 @@ void Image::load(const char* filename, U32 maxTextureSize)
 		}
 		else if(strcmp(ext, "ankitex") == 0)
 		{
-#if 0
+#if 1
 			compression = Image::DC_RAW;
 #elif ANKI_GL == ANKI_GL_DESKTOP
 			compression = Image::DC_S3TC;

+ 3 - 1
src/resource/Material.cpp

@@ -6,6 +6,7 @@
 #include "anki/resource/TextureResource.h"
 #include "anki/util/File.h"
 #include "anki/misc/Xml.h"
+#include "anki/renderer/MainRenderer.h"
 #include <functional>
 #include <algorithm>
 #include <map>
@@ -283,7 +284,8 @@ void Material::parseMaterialTag(const XmlElement& materialEl)
 
 			src << "#define LOD " << level << "\n"
 				<< "#define PASS_" << passNames[pid] << "\n"
-				<< "#define USE_MRT " << ANKI_RENDERER_USE_MRT << "\n"
+				<< "#define USE_MRT " 
+				<< MainRendererSingleton::get().getUseMrt() << "\n"
 				<< mspc.getShaderProgramSource() << std::endl;
 
 			std::string filename =

+ 4 - 13
testapp/Main.cpp

@@ -240,16 +240,16 @@ void init()
 #if 1
 	// horse
 	horse = new ModelNode("horse", &scene, nullptr,
-		Movable::MF_NONE, "models/horse/horse.mdl");
+		Movable::MF_NONE, "models/horse/horse.ankimdl");
 	horse->setLocalTransform(Transform(Vec3(-2, 0, 0), Mat3::getIdentity(),
 		0.7));
 
 	// barrel
-	ModelNode* redBarrel = new ModelNode(
+	/*ModelNode* redBarrel = new ModelNode(
 		"red_barrel", &scene, nullptr, Movable::MF_NONE, 
 		"models/red_barrel/red_barrel.mdl");
 	redBarrel->setLocalTransform(Transform(Vec3(+2, 0, 0), Mat3::getIdentity(),
-		0.7));
+		0.7));*/
 #endif
 
 #if 0
@@ -476,7 +476,7 @@ void mainLoop()
 
 		// Sleep
 		//
-#if 1
+#if 0
 		timer.stop();
 		if(timer.getElapsedTime() < AppSingleton::get().getTimerTick())
 		{
@@ -568,16 +568,7 @@ void initSubsystems(int argc, char* argv[])
 	initializer.get("width") = win->getWidth();
 	initializer.get("height") = win->getHeight();
 	initializer.get("lodDistance") = 20.0;
-	initializer.get("samples") = 16;
-
-#if ANKI_GL == ANKI_GL_ES
 	initializer.get("samples") = 1;
-	initializer.get("pps.enabled") = false;
-	initializer.get("is.maxPointLights") = 64;
-	initializer.get("is.maxPointLightsPerTile") = 4;
-	initializer.get("is.maxSpotLightsPerTile") = 4;
-	initializer.get("is.maxSpotTexLightsPerTile") = 4;
-#endif
 
 	MainRendererSingleton::get().init(initializer);
 

+ 6 - 2
tools/texture/ankitexture.py

@@ -315,6 +315,8 @@ def create_etc_images(mips_fnames, tmp_dir, fast, color_format, convert_path):
 		else:
 			args.append("RGBA")
 
+		# Call the executable AND change the working directory so that etcpack
+		# will find convert
 		subprocess.check_call(args, stdout = subprocess.PIPE, cwd = tmp_dir)
 
 def create_dds_images(mips_fnames, tmp_dir, fast, color_format, normal):
@@ -458,7 +460,8 @@ def write_s3tc(out_file, fname, width, height, color_format):
 	if len(data) != data_size:
 		raise Exception("Failed to read DDS data")
 
-	tmp = in_file.read(128)
+	# Make sure that the file doesn't contain any more data
+	tmp = in_file.read(1)
 	if len(tmp) != 0:
 		printw("  File shouldn't contain more data")
 
@@ -493,7 +496,8 @@ def write_etc(out_file, fname, width, height, color_format):
 	if len(data) != data_size:
 		raise Exception("Failed to read PKM data")
 
-	tmp = in_file.read(data_size)
+	# Make sure that the file doesn't contain any more data
+	tmp = in_file.read(1)
 	if len(tmp) != 0:
 		printw("  File shouldn't contain more data")