Ver Fonte

Porting to Android. First demo runs very slow but with out compressed textures

Panagiotis Christopoulos Charitos há 12 anos atrás
pai
commit
fc5e20fe20

+ 2 - 0
AndroidManifest.xml

@@ -21,4 +21,6 @@
 	</application>
 	<uses-feature android:glEsVersion="0x00030000"/>
 	<uses-sdk android:minSdkVersion="18"/>
+	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
+	<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"></uses-permission>
 </manifest>

+ 19 - 8
CMakeLists.txt

@@ -6,6 +6,8 @@ PROJECT(anki)
 # Configuration
 #
 
+SET(ANKI_BUILD_TYPE "Release" CACHE STRING "Like CMAKE_BUILD_TYPE (Release or Debug)")
+
 OPTION(ANKI_BUILD_TOOLS "Build tools" ON)
 OPTION(ANKI_BUILD_TESTS "Build unit tests" OFF)
 OPTION(ANKI_BUILD_TESTAPP "Build test application" ON)
@@ -22,9 +24,6 @@ ELSE()
 	SET(_ANKI_ENABLE_COUNTERS 0)
 ENDIF()
 
-# Because we want different compiler flags for each platform
-SET(ANKI_CPU "X86" CACHE STRING "The CPU arch (X86 or ARM)")
-
 # Address space
 SET(ANKI_CPU_ADDR_SPACE "0" CACHE STRING 
 	"The CPU architecture (0 or 32 or 64). If zero go native")
@@ -53,7 +52,13 @@ ENDIF()
 
 SET(ANKI_WINDOW_BACKEND "${_WIN_BACKEND}" CACHE STRING "The window backend (GLXX11 or EGLX11 or EGLFBDEV or MACOS or or ANDROID or DUMMY)")
 
-SET(ANKI_GCC_TO_STRING_WORKAROUND "0" CACHE STRING "Enable workaround for C++11 GCC bug (0 or 1)")
+OPTION(ANKI_GCC_TO_STRING_WORKAROUND "Enable workaround for C++11 GCC bug" OFF)
+IF(ANKI_GCC_TO_STRING_WORKAROUND)
+	SET(_ANKI_GCC_TO_STRING_WORKAROUND 1)
+ELSE()
+	SET(_ANKI_GCC_TO_STRING_WORKAROUND 0)
+ENDIF()
+
 
 # Extra directories
 SET(ANKI_EXTRA_INCLUDE_DIRS CACHE STRING "Some extra include paths (Needed for some weird builds)")
@@ -77,14 +82,14 @@ IF(NOT ANKI_CPU_ADDR_SPACE STREQUAL "0")
 ENDIF()
 
 # static libstdc++
-#SET(CXX_FLAGS "${CXX_FLAGS} -static-libstdc++ ")
+SET(CXX_FLAGS "${CXX_FLAGS} -static-libstdc++ ")
 
 # SSE
-IF(${ANKI_CPU} STREQUAL "X86")
+IF(NOT ${ANKI_WINDOW_BACKEND} STREQUAL "ANDROID")
 	SET(COMPILER_FLAGS "${COMPILER_FLAGS} -msse4 ")
 ENDIF()
 
-IF(${CMAKE_BUILD_TYPE} STREQUAL "Debug")
+IF(${ANKI_BUILD_TYPE} STREQUAL "Debug")
 	# Debug
 
 	SET(COMPILER_FLAGS "${COMPILER_FLAGS} -g3 -O0 ")
@@ -93,6 +98,11 @@ ELSE()
 
 	SET(COMPILER_FLAGS "${COMPILER_FLAGS} -ffast-math -O4 -flto ")
 
+	# Add this because Android compiler complains
+	IF(ANDROID)
+		SET(COMPILER_FLAGS "${COMPILER_FLAGS} -fno-data-sections ")
+	ENDIF()
+
 	SET(CXX_FLAGS "${CXX_FLAGS} -fno-rtti ")
 ENDIF()
 
@@ -144,6 +154,7 @@ ADD_SUBDIRECTORY(extern)
 # Doxygen
 #
 FIND_PACKAGE(Doxygen)
+
 IF(DOXYGEN_FOUND)
 	CONFIGURE_FILE(${CMAKE_CURRENT_SOURCE_DIR}/docs/doxyfile ${CMAKE_CURRENT_BINARY_DIR}/doxyfile @ONLY)
 	
@@ -170,7 +181,7 @@ SET(ANKI_VERSION_MAJOR 0)
 SET(ANKI_VERSION_MINOR 1)
 MESSAGE("++ AnKi version: ${ANKI_VERSION_MAJOR}.${ANKI_VERSION_MINOR}")
 
-IF(${CMAKE_BUILD_TYPE} STREQUAL Debug)
+IF(${ANKI_BUILD_TYPE} STREQUAL "Debug")
 	SET(ANKI_DEBUG 1)
 ELSE()
 	SET(ANKI_DEBUG 0)

+ 5 - 1
bench/CMakeLists.txt

@@ -1,2 +1,6 @@
-ADD_LIBRARY(ankibench SHARED Main.cpp)
+IF(ANDROID)
+	ADD_LIBRARY(ankibench SHARED Main.cpp)
+ELSE()
+	ADD_EXECUTABLE(ankibench Main.cpp)
+ENDIF()
 TARGET_LINK_LIBRARIES(ankibench anki) 

+ 205 - 38
bench/Main.cpp

@@ -28,28 +28,65 @@
 #include "anki/core/NativeWindow.h"
 #include "anki/core/Counters.h"
 #include "anki/Scene.h"
-#include <android_native_app_glue.h>
-#include <android/log.h>
+#include "anki/event/LightEvent.h"
+#include "anki/event/MovableEvent.h"
 
 using namespace anki;
 
 //==============================================================================
-void initSubsystems(android_app* app)
+struct LogFile 
 {
-	U glmajor = 3, glminor = 0;
+	ANKI_HAS_SLOTS(LogFile)
 
-	// App
-	AppSingleton::get().init(app);
+	void handler(const Logger::Info& info)
+	{
+		const char* x;
+		switch(info.type)
+		{
+		case Logger::LMT_NORMAL:
+			x = "Info";
+			break;
+		case Logger::LMT_ERROR:
+			x = "Error";
+			break;
+		case Logger::LMT_WARNING:
+			x = "Warn";
+			break;
+		}
+
+		file.writeText("(%s:%d %s) %s: %s\n", 
+			info.file, info.line, info.func, x, info.msg);
+	}
+	ANKI_SLOT(handler, const Logger::Info&)
+
+	File file;
+};
+
+static LogFile logfile;
+
+//==============================================================================
+void initSubsystems()
+{
+#if ANKI_OS == ANKI_OS_ANDROID
+	// Log file
+	logfile.file.open("/sdcard/anki.log", File::OF_WRITE);
+	ANKI_CONNECT(&LoggerSingleton::get(), messageRecieved, &logfile, handler);
+#endif
 
-	// Util
-	File::setAndroidAssetManager(app->activity->assetManager);
+	// App
+	AppSingleton::get().init();
 
 	// Window
 	NativeWindowInitializer nwinit;
 	nwinit.width = 1280;
 	nwinit.height = 720;
-	nwinit.majorVersion = glmajor;
-	nwinit.minorVersion = glminor;
+#if ANKI_GL == ANKI_GL_ES
+	nwinit.majorVersion = 3;
+	nwinit.minorVersion = 0;
+#else
+	nwinit.majorVersion = 4;
+	nwinit.minorVersion = 3;
+#endif
 	nwinit.depthBits = 0;
 	nwinit.stencilBits = 0;
 	nwinit.fullscreenDesktopRez = true;
@@ -57,7 +94,8 @@ void initSubsystems(android_app* app)
 	NativeWindowSingleton::get().create(nwinit);
 
 	// GL stuff
-	GlStateCommonSingleton::get().init(glmajor, glminor, nwinit.debugContext);
+	GlStateCommonSingleton::get().init(
+		nwinit.majorVersion, nwinit.minorVersion, nwinit.debugContext);
 
 	// Input
 	InputSingleton::get().init(&NativeWindowSingleton::get());
@@ -98,11 +136,11 @@ void initSubsystems(android_app* app)
 
 #if ANKI_GL == ANKI_GL_ES
 	initializer.samples = 1;
-	initializer.pps.enabled = false;
 	initializer.is.maxPointLights = 64;
 	initializer.is.maxPointLightsPerTile = 4;
 	initializer.is.maxSpotLightsPerTile = 4;
 	initializer.is.maxSpotTexLightsPerTile = 4;
+	initializer.pps.enabled = false;
 #endif
 
 	MainRendererSingleton::get().init(initializer);
@@ -115,6 +153,95 @@ void initSubsystems(android_app* app)
 }
 
 //==============================================================================
+void initScene()
+{
+	SceneGraph& scene = SceneGraphSingleton::get();
+
+	scene.setAmbientColor(Vec4(0.1, 0.05, 0.05, 0.0) * 2);
+
+	PerspectiveCamera* cam = new PerspectiveCamera(
+		"main_camera", &scene, nullptr, Movable::MF_NONE);
+
+	const F32 ang = 45.0;
+	cam->setAll(
+		MainRendererSingleton::get().getAspectRatio() * toRad(ang),
+		toRad(ang), 0.5, 500.0);
+	cam->setLocalTransform(Transform(Vec3(18.0, 5.2, 0.0),
+		Mat3(Euler(toRad(-10.0), toRad(90.0), toRad(0.0))),
+		1.0));
+	scene.setActiveCamera(cam);
+
+#if 1
+	F32 x = 8.5; 
+	F32 y = 2.25;
+	F32 z = 2.49;
+	Array<Vec3, 4> vaseLightPos = {{Vec3(x, y, -z - 1.4), Vec3(x, y, z),
+		Vec3(-x - 2.3, y, z), Vec3(-x - 2.3, y, -z - 1.4)}};
+	for(U i = 0; i < vaseLightPos.getSize(); i++)
+	{
+		Vec3 lightPos = vaseLightPos[i];
+
+		PointLight* point =
+			new PointLight(("vase_plight" + std::to_string(i)).c_str(),
+			&scene, nullptr, Movable::MF_NONE, 
+			(i != 100) ? "textures/lens_flare/flares0.ankitex" : nullptr);
+		point->setRadius(2.0);
+		point->setLocalOrigin(lightPos);
+		point->setDiffuseColor(Vec4(3.0, 0.2, 0.0, 0.0));
+		point->setSpecularColor(Vec4(1.0, 1.0, 0.0, 0.0));
+		point->setLensFlaresStretchMultiplier(Vec2(10.0, 1.0));
+		point->setLensFlaresAlpha(1.0);
+
+		LightEventData eventData;
+		eventData.light = point;
+		eventData.radiusMultiplier = 0.2;
+		eventData.intensityMultiplier = Vec4(-1.2, 0.0, 0.0, 0.0);
+		eventData.specularIntensityMultiplier = Vec4(0.1, 0.1, 0.0, 0.0);
+		auto event = scene.getEventManager().newLightEvent(0.0, 0.8, eventData);
+		event->enableBits(Event::EF_REANIMATE);
+
+		MovableEventData moveData;
+		moveData.movableSceneNode = point;
+		moveData.posMin = Vec3(-0.5, 0.0, -0.5);
+		moveData.posMax = Vec3(0.5, 0.0, 0.5);
+		auto mevent = scene.getEventManager().newMovableEvent(0.0, 2.0, moveData);
+		mevent->enableBits(Event::EF_REANIMATE);
+
+		ParticleEmitter* pe = new ParticleEmitter(
+			("pe" + std::to_string(i)).c_str(), &scene, nullptr,
+			Movable::MF_NONE, "particles/smoke.ankipart");
+		pe->setLocalOrigin(lightPos);
+
+		pe = new ParticleEmitter(
+			("pef" + std::to_string(i)).c_str(), &scene, nullptr,
+			Movable::MF_NONE, "particles/fire.ankipart");
+		pe->setLocalOrigin(lightPos);
+	}
+#endif
+
+	scene.load("maps/sponza/master.scene");
+
+	PointLight* pl = new PointLight("pl0", &scene, nullptr, Movable::MF_NONE);
+	pl->setRadius(12.5);
+	pl->setDiffuseColor(Vec4(0.5, 0.3, 0.2, 1.0));
+	pl->setSpecularColor(Vec4(0.1, 0.0, 0.0, 1.0));
+	pl->setLocalOrigin(Vec3(10, 2.0, -0.8));
+
+	pl = new PointLight("pl1", &scene, nullptr, Movable::MF_NONE);
+	pl->setRadius(12.5);
+	pl->setDiffuseColor(Vec4(0.5, 0.3, 0.2, 1.0));
+	pl->setSpecularColor(Vec4(0.1, 0.0, 0.0, 1.0));
+	pl->setLocalOrigin(Vec3(0, 2.0, -0.8));
+
+	pl = new PointLight("pl2", &scene, nullptr, Movable::MF_NONE);
+	pl->setRadius(12.5);
+	pl->setDiffuseColor(Vec4(0.5, 0.3, 0.2, 1.0));
+	pl->setSpecularColor(Vec4(0.1, 0.0, 0.0, 1.0));
+	pl->setLocalOrigin(Vec3(-11, 2.0, -0.8));
+}
+
+//==============================================================================
+#if ANKI_OS == ANKI_OS_ANDROID
 static void handleEvents(android_app* app, int32_t cmd) 
 {
 	switch(cmd) 
@@ -136,9 +263,53 @@ static void handleEvents(android_app* app, int32_t cmd)
 		break;
 	}
 }
+#endif
 
 //==============================================================================
-void mainLoop()
+static Bool mainLoopExtra()
+{
+	const F32 dist = 0.2;
+	const F32 ang = toRad(3.0);
+	const F32 scale = 0.01;
+	const F32 mouseSensivity = 9.0;
+
+	Input& in = InputSingleton::get();
+
+	Movable* mover = SceneGraphSingleton::get().getActiveCamera().getMovable();
+
+	if(in.getKey(KC_UP)) mover->rotateLocalX(ang);
+	if(in.getKey(KC_DOWN)) mover->rotateLocalX(-ang);
+	if(in.getKey(KC_LEFT)) mover->rotateLocalY(ang);
+	if(in.getKey(KC_RIGHT)) mover->rotateLocalY(-ang);
+
+	if(in.getKey(KC_A)) mover->moveLocalX(-dist);
+	if(in.getKey(KC_D)) mover->moveLocalX(dist);
+	if(in.getKey(KC_Z)) mover->moveLocalY(dist);
+	if(in.getKey(KC_SPACE)) mover->moveLocalY(-dist);
+	if(in.getKey(KC_W)) mover->moveLocalZ(-dist);
+	if(in.getKey(KC_S)) mover->moveLocalZ(dist);
+	if(in.getKey(KC_Q)) mover->rotateLocalZ(ang);
+	if(in.getKey(KC_E)) mover->rotateLocalZ(-ang);
+
+	if(in.getMousePosition() != Vec2(0.0))
+	{
+		F32 angY = -ang * in.getMousePosition().x() * mouseSensivity *
+			MainRendererSingleton::get().getAspectRatio();
+
+		mover->rotateLocalY(angY);
+		mover->rotateLocalX(ang * in.getMousePosition().y() * mouseSensivity);
+	}
+
+	if(InputSingleton::get().getKey(KC_ESCAPE))
+	{
+		return false;
+	}
+
+	return true;
+}
+
+//==============================================================================
+static void mainLoop()
 {
 	ANKI_LOGI("Entering main loop");
 
@@ -161,9 +332,12 @@ void mainLoop()
 
 		// Update
 		input.handleEvents();
-		scene.update(
-			prevUpdateTime, crntTime, MainRendererSingleton::get());
-		renderer.render(SceneGraphSingleton::get());
+		if(!mainLoopExtra())
+		{
+			break;
+		}
+		scene.update(prevUpdateTime, crntTime, renderer);
+		renderer.render(scene);
 
 		window.swapBuffers();
 		ANKI_COUNTERS_RESOLVE_FRAME();
@@ -186,35 +360,24 @@ void mainLoop()
 }
 
 //==============================================================================
-void loopUntilWindowIsReady(android_app* app)
-{
-	while(app->window == nullptr) 
-	{
-		int ident;
-		int events;
-		android_poll_source* source;
-
-		while((ident=ALooper_pollAll(0, NULL, &events, (void**)&source)) >= 0) 
-		{
-			if (source != NULL) 
-			{
-				source->process(app, source);
-			}
-		}
-	}
-}
-
-//==============================================================================
+#if ANKI_OS == ANKI_OS_ANDROID
 void android_main(android_app* app)
 {
 	app_dummy();
 
+	// First thing to do
+	gAndroidApp = app;
+
 	app->onAppCmd = handleEvents;
-	loopUntilWindowIsReady(app);
+#else
+int main(int, char**)
+{
+#endif
 
 	try
 	{
-		initSubsystems(app);
+		initSubsystems();
+		initScene();
 		mainLoop();
 
 		ANKI_LOGI("Exiting...");
@@ -225,5 +388,9 @@ void android_main(android_app* app)
 	}
 
 	ANKI_LOGI("Bye!!");
-	exit(1);
+#if ANKI_OS == ANKI_OS_ANDROID
+	exit(0);
+#else
+	return 0;
+#endif
 }

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

@@ -105,7 +105,7 @@
 
 // General config
 #define ANKI_MAX_MULTIDRAW_PRIMITIVES 64
-#define ANKI_MAX_INSTANCES 64
+#define ANKI_MAX_INSTANCES 32
 
 // Renderer and rendering related config options
 #define ANKI_RENDERER_TILES_X_COUNT 16
@@ -154,7 +154,7 @@
 /// @}
 
 // Workaround some GCC C++11 problems
-#if ${ANKI_GCC_TO_STRING_WORKAROUND}
+#if ${_ANKI_GCC_TO_STRING_WORKAROUND}
 #	include <sstream>
 
 namespace std {

+ 5 - 13
include/anki/core/App.h

@@ -10,6 +10,10 @@
 
 namespace anki {
 
+#if ANKI_OS == ANKI_OS_ANDROID
+extern android_app* gAndroidApp;
+#endif
+
 /// The core class of the engine.
 ///
 /// - It initializes the window
@@ -24,7 +28,7 @@ public:
 	{}
 
 	/// Initialize the app
-	void init(void* systemSpecificData);
+	void init();
 
 	/// @name Accessors
 	/// @{
@@ -50,14 +54,6 @@ public:
 	{
 		return cachePath;
 	}
-
-#if ANKI_OS == ANKI_OS_ANDROID
-	android_app& getAndroidApp()
-	{
-		ANKI_ASSERT(andApp);
-		return *andApp;
-	}
-#endif
 	/// @}
 
 	/// What it does:
@@ -77,10 +73,6 @@ private:
 	std::string cachePath;
 	F32 timerTick;
 
-#if ANKI_OS == ANKI_OS_ANDROID
-	android_app* andApp = nullptr;
-#endif
-
 	void initDirs();
 };
 

+ 7 - 0
include/anki/renderer/Is.h

@@ -38,6 +38,11 @@ public:
 	{
 		return fai;
 	}
+
+	void setDrawToDefaultFbo(Bool x)
+	{
+		drawToDefaultFbo = x;
+	}
 	/// @}
 
 private:
@@ -102,6 +107,8 @@ private:
 	U8 maxSpotTexLightsPerTile;
 	/// @}
 
+	Bool8 drawToDefaultFbo = false;
+
 	/// Called by init
 	void initInternal(const RendererInitializer& initializer);
 

+ 7 - 8
include/anki/resource/ResourceManager.inl.h

@@ -10,9 +10,6 @@ void TypeResourceManager<Type>::
 	allocAndLoadRsrc(const char* filename, Type*& newInstance)
 {
 	newInstance = nullptr;
-	std::string newFname;
-
-	newFname = ResourceManagerSingleton::get().fixResourcePath(filename);
 
 	// Alloc
 	try
@@ -21,17 +18,17 @@ void TypeResourceManager<Type>::
 	}
 	catch(const std::exception& e)
 	{
-		throw ANKI_EXCEPTION("Constructor failed for: " + newFname) << e;
+		throw ANKI_EXCEPTION("Constructor failed for: " + filename) << e;
 	}
 
 	// Load
 	try
 	{
-		newInstance->load(newFname.c_str());
+		newInstance->load(filename);
 	}
 	catch(std::exception& e)
 	{
-		throw ANKI_EXCEPTION("Cannot load: " + newFname) << e;
+		throw ANKI_EXCEPTION("Cannot load: " + filename) << e;
 	}
 }
 
@@ -55,15 +52,17 @@ typename TypeResourceManager<Type>::Hook& TypeResourceManager<Type>::
 		hook = new Hook;
 		hook->uuid = filename;
 		hook->referenceCounter = 1;
+		std::string newFname =
+			ResourceManagerSingleton::get().fixResourcePath(filename);
 
 		try
 		{
-			allocAndLoadRsrc(filename, hook->resource);
+			allocAndLoadRsrc(newFname.c_str(), hook->resource);
 		}
 		catch(std::exception& e)
 		{
 			delete hook;
-			throw ANKI_EXCEPTION("Cannot load: " + filename) << e;
+			throw ANKI_EXCEPTION("Cannot load: " + newFname) << e;
 		}
 
 		hooks.push_back(hook);

+ 13 - 5
include/anki/resource/ShaderProgramResource.h

@@ -5,6 +5,9 @@
 
 namespace anki {
 
+/// @addtogroup Resource
+/// @{
+
 /// Shader program resource
 class ShaderProgramResource: public ShaderProgram
 {
@@ -22,15 +25,20 @@ public:
 
 	/// Used by @ref Material and @ref Renderer to create custom shaders in
 	/// the cache
-	/// @param sProgFPathName The file pathname of the shader prog
+	/// @param filename The file pathname of the shader prog
 	/// @param preAppendedSrcCode The source code we want to write on top
 	///        of the shader prog
+	/// @param filenamePrefix Add that at the base filename for additional 
+	///        ways to identify the file in the cache
 	/// @return The file pathname of the new shader prog. Its
-	///         $HOME/.anki/cache/newFNamePrefix_fName
-	static std::string createSrcCodeToCache(const char* sProgFPathName,
-		const char* preAppendedSrcCode);
+	///         $HOME/.anki/cache/ + filenamePrefix + hash + .glsl
+	static std::string createSrcCodeToCache(
+		const char* filename,
+		const char* preAppendedSrcCode,
+		const char* filenamePrefix);
 }; 
+/// @}
 
-} // end namespace
+} // end namespace anki
 
 #endif

+ 6 - 13
include/anki/util/File.h

@@ -4,11 +4,6 @@
 #include "anki/util/StringList.h"
 #include <string>
 
-// Forward
-#if ANKI_OS == ANKI_OS_ANDROID
-struct AAssetManager;
-#endif
-
 namespace anki {
 
 /// @addtogroup util
@@ -74,6 +69,12 @@ public:
 	///                     Endianness enums
 	void open(const char* filename, U16 openMask);
 
+	/// Return true if the file is oppen
+	Bool isOpen() const
+	{
+		return file != nullptr;
+	}
+
 	/// Close the file
 	void close();
 
@@ -124,12 +125,6 @@ public:
 	/// File exists?
 	static Bool fileExists(const char* filename);
 
-#if ANKI_OS == ANKI_OS_ANDROID
-	static void setAndroidAssetManager(AAssetManager* manager)
-	{
-		andAssetManager = manager;
-	}
-#endif
 	/// @}
 
 private:
@@ -148,8 +143,6 @@ private:
 	void openZipFile(const char* archive, const char* archived, U16 flags);
 
 #if ANKI_OS == ANKI_OS_ANDROID
-	static AAssetManager* andAssetManager;
-
 	/// Open an Android file
 	void openAndFile(const char* filename, U16 flags);
 #endif

+ 3 - 3
shaders/BsCommonFrag.glsl

@@ -5,9 +5,9 @@
 #pragma anki include "shaders/MsBsCommon.glsl"
 
 #define vTexCoords_DEFINED
-in vec2 vTexCoord;
+in highp vec2 vTexCoord;
 #define vInstanceId_DEFINED
-flat in uint vInstanceId;
+flat in highp uint vInstanceId;
 
 #if defined(PASS_COLOR)
 layout(location = 0) out vec4 fColor;
@@ -29,7 +29,7 @@ void writeFais(in vec4 color)
 #define particleAlpha_DEFINED
 void particleAlpha(in sampler2D tex, in float alpha)
 {
-	vec4 color = DEFAULT_FLOAT_PRECISION vec4(texture(tex, vTexCoord));
+	vec4 color = texture(tex, vTexCoord);
 	color.w *= alpha;
 	writeFais(color);
 }

+ 5 - 6
shaders/CommonFrag.glsl

@@ -2,15 +2,14 @@
 #define ANKI_SHADERS_COMMON_FRAG_GLSL
 
 #ifndef DEFAULT_FLOAT_PRECISION
-precision highp float;
-#else
-precision DEFAULT_FLOAT_PRECISION float;
+#define DEFAULT_FLOAT_PRECISION highp
 #endif
 
 #ifndef DEFAULT_INT_PRECISION
-precision highp int;
-#else
-precision DEFAULT_FLOAT_PRECISION int;
+#define DEFAULT_INT_PRECISION highp
 #endif
 
+precision DEFAULT_FLOAT_PRECISION float;
+precision DEFAULT_FLOAT_PRECISION int;
+
 #endif

+ 6 - 7
shaders/MsCommonFrag.glsl

@@ -19,7 +19,7 @@ in float vTangentW;
 #	define vTangentW_DEFINED
 in vec3 vVertPosViewSpace;
 #	define vVertPosViewSpace_DEFINED
-flat in lowp float vSpecularComponent;
+flat in float vSpecularComponent;
 #	define vSpecularComponent_DEFINED
 #endif
 /// @}
@@ -58,8 +58,7 @@ vec3 getNormalFromTexture(in vec3 normal, in vec3 tangent, in float tangentW,
 	return normalize(normal);
 #	else
 	// First read the texture
-	vec3 nAtTangentspace = 
-		(DEFAULT_FLOAT_PRECISION vec3(texture(map, texCoords)).rgb - 0.5) * 2.0;
+	vec3 nAtTangentspace = (texture(map, texCoords).rgb - 0.5) * 2.0;
 
 	vec3 n = normalize(normal);
 	vec3 t = normalize(tangent);
@@ -100,7 +99,7 @@ vec3 getEnvironmentColor(in vec3 vertPosViewSpace, in vec3 normal,
 	float m = 2.0 * length(r);
 	vec2 semTexCoords = r.xy / m + 0.5;
 
-	vec3 semCol = DEFAULT_FLOAT_PRECISION vec3(texture(map, semTexCoords)).rgb;
+	vec3 semCol = texture(map, semTexCoords).rgb;
 	return semCol;
 }
 #endif
@@ -118,7 +117,7 @@ vec3 getDiffuseColorAndDoAlphaTesting(
 	in float tolerance)
 {
 #if defined(PASS_COLOR)
-	vec4 col = DEFAULT_FLOAT_PRECISION vec4(texture(map, texCoords));
+	vec4 col = vec4(texture(map, texCoords));
 	if(col.a < tolerance)
 	{
 		discard;
@@ -128,7 +127,7 @@ vec3 getDiffuseColorAndDoAlphaTesting(
 #	if LOD > 0
 	return vec3(0.0);
 #	else
-	float a = DEFAULT_FLOAT_PRECISION float(texture(map, texCoords).a);
+	float a = float(texture(map, texCoords).a);
 	if(a < tolerance)
 	{
 		discard;
@@ -143,7 +142,7 @@ vec3 getDiffuseColorAndDoAlphaTesting(
 #	define readRgbFromTexture_DEFINED
 vec3 readRgbFromTexture(in sampler2D tex, in highp vec2 texCoords)
 {
-	return DEFAULT_FLOAT_PRECISION vec3(texture(tex, texCoords)).rgb;
+	return vec3(texture(tex, texCoords)).rgb;
 }
 #endif
 

+ 11 - 11
shaders/MsCommonVert.glsl

@@ -3,24 +3,24 @@
 
 /// @name Attributes
 /// @{
-layout(location = 0) in vec3 position;
-layout(location = 3) in vec2 texCoord;
+layout(location = 0) in highp vec3 position;
+layout(location = 3) in highp vec2 texCoord;
 #if defined(PASS_COLOR)
-layout(location = 1) in vec3 normal;
-layout(location = 2) in vec4 tangent;
+layout(location = 1) in mediump vec3 normal;
+layout(location = 2) in mediump vec4 tangent;
 #endif
 /// @}
 
 /// @name Varyings
 /// @{
-out vec2 vTexCoords;
+out highp vec2 vTexCoords;
 #if defined(PASS_COLOR)
 out mediump vec3 vNormal;
 out mediump vec3 vTangent;
 out mediump float vTangentW;
 out mediump vec3 vVertPosViewSpace; ///< For env mapping. AKA view vector
 /// Calculate it per vertex instead of per fragment
-flat out lowp float vSpecularComponent; 
+flat out float vSpecularComponent; 
 #endif
 /// @}
 
@@ -44,9 +44,9 @@ void setVaryings2(
 	in mat3 normalMat)
 {
 #if defined(PASS_COLOR)
-	vNormal = mediump vec3(normalMat * normal);
-	vTangent = mediump vec3(normalMat * vec3(tangent));
-	vTangentW = mediump float(tangent.w);
+	vNormal = vec3(normalMat * normal);
+	vTangent = vec3(normalMat * vec3(tangent));
+	vTangentW = float(tangent.w);
 #endif
 
 	setVaryings1(modelViewProjectionMat);
@@ -57,7 +57,7 @@ void setVaryings2(
 #define setVertPosViewSpace_DEFINED
 void setVertPosViewSpace(in mat4 modelViewMat)
 {
-	vVertPosViewSpace = mediump vec3(modelViewMat * vec4(position, 1.0));
+	vVertPosViewSpace = vec3(modelViewMat * vec4(position, 1.0));
 }
 #endif
 
@@ -66,7 +66,7 @@ void setVertPosViewSpace(in mat4 modelViewMat)
 #define prepackSpecular_DEFINED
 void prepackSpecular(in vec2 specular)
 {
-	vSpecularComponent = lowp float(packSpecular(specular));
+	vSpecularComponent = float(packSpecular(specular));
 }
 #endif
 

+ 3 - 3
src/CMakeLists.txt

@@ -12,16 +12,16 @@ ENDFOREACH()
 
 # Set the platform libraries
 IF(${ANKI_WINDOW_BACKEND} STREQUAL "GLXX11")
-	SET(_SYS GL ankiglew)
+	SET(_SYS GL ankiglew pthread)
 ELSEIF(${ANKI_WINDOW_BACKEND} STREQUAL "MACOS")
 	FIND_PACKAGE(OpenGL REQUIRED)
-	SET(_SYS ${OPENGL_LIBRARIES} ankiglew)
+	SET(_SYS ${OPENGL_LIBRARIES} ankiglew pthread)
 ELSEIF(${ANKI_WINDOW_BACKEND} STREQUAL "ANDROID")
 	SET(_SYS GLESv3 EGL log android)
 	INCLUDE_DIRECTORIES("${ANDROID_NDK}/sources/android/native_app_glue")
 	SET(_SYS_SRC "${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c")
 ELSEIF(${ANKI_WINDOW_BACKEND} STREQUAL "EGLFBDEV")
-	SET(_SYS GLESv2 EGL mali)
+	SET(_SYS GLESv2 EGL mali pthread)
 ELSE()
 	MESSAGE(FATAL_ERROR "Unrecognized ANKI_WINDOW_BACKEND: ${ANKI_WINDOW_BACKEND}")
 ENDIF()

+ 10 - 8
src/core/App.cpp

@@ -21,6 +21,11 @@
 
 namespace anki {
 
+#if ANKI_OS == ANKI_OS_ANDROID
+/// The one and only android hack
+android_app* gAndroidApp = nullptr;
+#endif
+
 //==============================================================================
 /// Bad things signal handler
 /*static void handler(int sig)
@@ -38,13 +43,8 @@ namespace anki {
 }*/
 
 //==============================================================================
-void App::init(void* systemSpecificData)
+void App::init()
 {
-#if ANKI_OS == ANKI_OS_ANDROID
-	ANKI_ASSERT(systemSpecificData);
-	andApp = (android_app*)systemSpecificData;
-#endif
-
 	// Install signal handlers
 	/*signal(SIGSEGV, handler);
 	signal(SIGBUS, handler);
@@ -79,10 +79,12 @@ void App::initDirs()
 	ANKI_LOGI("Creating cache dir: %s", cachePath.c_str());
 	createDirectory(cachePath.c_str());
 #else
-	ANativeActivity* activity = andApp->activity;
+	ANKI_ASSERT(gAndroidApp);
+	ANativeActivity* activity = gAndroidApp->activity;
 
 	// Settings path
-	settingsPath = std::string(activity->internalDataPath);
+	//settingsPath = std::string(activity->internalDataPath);
+	settingsPath = std::string("/sdcard/.anki/");
 	if(!directoryExists(settingsPath.c_str()))
 	{
 		ANKI_LOGI("Creating settings dir: %s", settingsPath.c_str());

+ 24 - 1
src/core/NativeWindowAndroid.cpp

@@ -7,6 +7,27 @@
 
 namespace anki {
 
+//==============================================================================
+static void loopUntilWindowIsReady(android_app& app)
+{
+	while(app.window == nullptr) 
+	{
+		int ident;
+		int events;
+		android_poll_source* source;
+
+		const U timeoutMs = 5;
+		while((ident = 
+			ALooper_pollAll(timeoutMs, NULL, &events, (void**)&source)) >= 0) 
+		{
+			if (source != NULL) 
+			{
+				source->process(&app, source);
+			}
+		}
+	}
+}
+
 //==============================================================================
 // NativeWindowImpl                                                            =
 //==============================================================================
@@ -22,7 +43,9 @@ void NativeWindowImpl::create(NativeWindowInitializer& init)
 
 	ANKI_LOGI("Creating native window");
 
-	android_app& andApp = AppSingleton::get().getAndroidApp();
+	ANKI_ASSERT(gAndroidApp);
+	android_app& andApp = *gAndroidApp;
+	loopUntilWindowIsReady(andApp);
 
 	// EGL init
 	//

+ 17 - 15
src/gl/ShaderProgram.cpp

@@ -534,11 +534,12 @@ void ShaderProgram::destroy()
 GLuint ShaderProgram::createAndCompileShader(const char* sourceCode,
 	const char* preproc, GLenum type)
 {
-	GLuint glId = 0;
+	GLuint shader = 0;
 	const char* sourceStrs[1] = {nullptr};
 
 	// create the shader
-	glId = glCreateShader(type);
+	shader = glCreateShader(type);
+	ANKI_ASSERT(shader);
 
 	// attach the source
 	std::string fullSrc = preproc;
@@ -546,11 +547,11 @@ GLuint ShaderProgram::createAndCompileShader(const char* sourceCode,
 	sourceStrs[0] = fullSrc.c_str();
 
 	// compile
-	glShaderSource(glId, 1, sourceStrs, NULL);
-	glCompileShader(glId);
+	glShaderSource(shader, 1, sourceStrs, NULL);
+	glCompileShader(shader);
 
-	GLint success;
-	glGetShaderiv(glId, GL_COMPILE_STATUS, &success);
+	GLint success = GL_FALSE;
+	glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
 
 	if(!success)
 	{
@@ -559,9 +560,9 @@ GLuint ShaderProgram::createAndCompileShader(const char* sourceCode,
 		GLint charsWritten = 0;
 		Vector<char> infoLog;
 
-		glGetShaderiv(glId, GL_INFO_LOG_LENGTH, &infoLen);
+		glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);
 		infoLog.resize(infoLen + 1);
-		glGetShaderInfoLog(glId, infoLen, &charsWritten, &infoLog[0]);
+		glGetShaderInfoLog(shader, infoLen, &charsWritten, &infoLog[0]);
 		infoLog[charsWritten] = '\0';
 
 		std::stringstream err;
@@ -583,9 +584,10 @@ GLuint ShaderProgram::createAndCompileShader(const char* sourceCode,
 		// Throw
 		throw ANKI_EXCEPTION(err.str());
 	}
-	ANKI_ASSERT(glId != 0);
+	ANKI_ASSERT(shader != 0);
+	ANKI_CHECK_GL_ERROR();
 
-	return glId;
+	return shader;
 }
 
 //==============================================================================
@@ -595,19 +597,19 @@ void ShaderProgram::link() const
 	glLinkProgram(glId);
 
 	// check if linked correctly
-	GLint success;
+	GLint success = GL_FALSE;
 	glGetProgramiv(glId, GL_LINK_STATUS, &success);
 
 	if(!success)
 	{
-		int info_len = 0;
+		int infoLen = 0;
 		int charsWritten = 0;
 		std::string infoLogTxt;
 
-		glGetProgramiv(glId, GL_INFO_LOG_LENGTH, &info_len);
+		glGetProgramiv(glId, GL_INFO_LOG_LENGTH, &infoLen);
 
-		infoLogTxt.resize(info_len + 1);
-		glGetProgramInfoLog(glId, info_len, &charsWritten, &infoLogTxt[0]);
+		infoLogTxt.resize(infoLen + 1);
+		glGetProgramInfoLog(glId, infoLen, &charsWritten, &infoLogTxt[0]);
 		throw ANKI_EXCEPTION("Link error log follows:\n" 
 			+ infoLogTxt);
 	}

+ 2 - 2
src/renderer/Hdr.cpp

@@ -61,7 +61,7 @@ void Hdr::initInternal(const Renderer::Initializer& initializer)
 		"#define IMG_DIMENSION " + std::to_string(height) + "\n"
 		"#define SAMPLES 7\n";
 	hblurSProg.load(ShaderProgramResource::createSrcCodeToCache(
-		SHADER_FILENAME, pps.c_str()).c_str());
+		SHADER_FILENAME, pps.c_str(), "r_").c_str());
 
 	pps =
 		"#define VPASS\n"
@@ -70,7 +70,7 @@ void Hdr::initInternal(const Renderer::Initializer& initializer)
 		"#define IMG_DIMENSION " + std::to_string(width) + "\n"
 		"#define SAMPLES 7\n";
 	vblurSProg.load(ShaderProgramResource::createSrcCodeToCache(
-		SHADER_FILENAME, pps.c_str()).c_str());
+		SHADER_FILENAME, pps.c_str(), "r_").c_str());
 
 	// Set timestamps
 	parameterUpdateTimestamp = getGlobTimestamp();

+ 11 - 3
src/renderer/Is.cpp

@@ -465,7 +465,7 @@ void Is::initInternal(const RendererInitializer& initializer)
 
 	// point light
 	lightPassProg.load(ShaderProgramResource::createSrcCodeToCache(
-		"shaders/IsLp.glsl", pps.str().c_str()).c_str());
+		"shaders/IsLp.glsl", pps.str().c_str(), "r_").c_str());
 
 #if ANKI_GL == ANKI_GL_DESKTOP
 	if(useCompute())
@@ -478,7 +478,7 @@ void Is::initInternal(const RendererInitializer& initializer)
 			<< TILES_BLOCK_BINDING << "\n";
 
 		rejectProg.load(ShaderProgramResource::createSrcCodeToCache(
-			"shaders/IsRejectLights.glsl", pps.str().c_str()).c_str());
+			"shaders/IsRejectLights.glsl", pps.str().c_str(), "r_").c_str());
 	}
 #endif
 
@@ -867,7 +867,15 @@ void Is::lightPass()
 //==============================================================================
 void Is::setState()
 {
-	fbo.bind();
+	if(drawToDefaultFbo)
+	{
+		Fbo::bindDefault();
+	}
+	else
+	{
+		fbo.bind();
+	}
+
 	r->clearAfterBindingFbo(
 		GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
 	GlStateSingleton::get().setViewport(

+ 2 - 2
src/renderer/Lf.cpp

@@ -78,13 +78,13 @@ void Lf::initInternal(const RendererInitializer& initializer)
 		+ std::to_string(r->getPps().getHdr().getFai().getHeight()) + ".0)\n";
 
 	pseudoProg.load(ShaderProgramResource::createSrcCodeToCache(
-		"shaders/PpsLfPseudoPass.glsl", pps.c_str()).c_str());
+		"shaders/PpsLfPseudoPass.glsl", pps.c_str(), "r_").c_str());
 
 	// Load program 2
 	pps = "#define MAX_FLARES "
 		+ std::to_string(maxFlaresPerLight * maxLightsWithFlares) + "\n";
 	std::string fname = ShaderProgramResource::createSrcCodeToCache(
-		"shaders/PpsLfSpritePass.glsl", pps.c_str());
+		"shaders/PpsLfSpritePass.glsl", pps.c_str(), "r_");
 	realProg.load(fname.c_str());
 
 	ublock = &realProg->findUniformBlock("flaresBlock");

+ 1 - 0
src/renderer/MainRenderer.cpp

@@ -83,6 +83,7 @@ void MainRenderer::render(SceneGraph& scene)
 	Bool drawToDefaultFbo = renderingQuality > 0.9 && !dbg.getEnabled();
 
 	pps.setDrawToDefaultFbo(drawToDefaultFbo);
+	is.setDrawToDefaultFbo(drawToDefaultFbo && !pps.getEnabled());
 
 	Renderer::render(scene);
 

+ 1 - 1
src/renderer/Pps.cpp

@@ -70,7 +70,7 @@ void Pps::initInternal(const RendererInitializer& initializer)
 	pps += "#define FBO_HEIGHT " + std::to_string(r->getHeight()) + "\n";
 
 	prog.load(ShaderProgramResource::createSrcCodeToCache(
-		"shaders/Pps.glsl", pps.c_str()).c_str());
+		"shaders/Pps.glsl", pps.c_str(), "r_").c_str());
 }
 
 //==============================================================================

+ 3 - 3
src/renderer/Ssao.cpp

@@ -176,7 +176,7 @@ void Ssao::initInternal(const RendererInitializer& initializer)
 		<< "\n" << kernelStr.str() 
 		<< "\n";
 	ssaoSProg.load(ShaderProgramResource::createSrcCodeToCache(
-		"shaders/PpsSsao.glsl", pps.str().c_str()).c_str());
+		"shaders/PpsSsao.glsl", pps.str().c_str(), "r_").c_str());
 
 	ssaoSProg->findUniformBlock("commonBlock").setBinding(0);
 
@@ -189,7 +189,7 @@ void Ssao::initInternal(const RendererInitializer& initializer)
 		"#define IMG_DIMENSION " << bHeight << "\n"
 		"#define SAMPLES 7\n";
 	hblurSProg.load(ShaderProgramResource::createSrcCodeToCache(
-		SHADER_FILENAME, pps.str().c_str()).c_str());
+		SHADER_FILENAME, pps.str().c_str(), "r_").c_str());
 
 	pps.clear();
 	pps << "#define VPASS\n"
@@ -197,7 +197,7 @@ void Ssao::initInternal(const RendererInitializer& initializer)
 		"#define IMG_DIMENSION " << bWidth << "\n"
 		"#define SAMPLES 7\n";
 	vblurSProg.load(ShaderProgramResource::createSrcCodeToCache(
-		SHADER_FILENAME, pps.str().c_str()).c_str());
+		SHADER_FILENAME, pps.str().c_str(), "r_").c_str());
 }
 
 //==============================================================================

+ 1 - 1
src/renderer/Tiler.cpp

@@ -213,7 +213,7 @@ void Tiler::initInternal(Renderer* r_)
 		"#define RENDERER_HEIGHT " + std::to_string(r->getHeight()) + "\n";
 
 	prog.load(ShaderProgramResource::createSrcCodeToCache(
-		"shaders/TilerMinMax.glsl", pps.c_str()).c_str());
+		"shaders/TilerMinMax.glsl", pps.c_str(), "r_").c_str());
 
 	depthMapUniform = &(prog->findUniformVariable("depthMap"));
 

+ 2 - 2
src/resource/Material.cpp

@@ -326,8 +326,8 @@ std::string Material::createShaderProgSourceToCache(const std::string& source)
 	if(!File::fileExists(newfPathName.c_str()))
 	{
 		// If not create it
-		File f(newfPathName.c_str(), File::OF_READ);
-		f.writeText(source.c_str());
+		File f(newfPathName.c_str(), File::OF_WRITE);
+		f.writeText("%s\n", source.c_str());
 	}
 
 	return newfPathName;

+ 23 - 17
src/resource/ShaderProgramResource.cpp

@@ -1,5 +1,6 @@
 #include "anki/resource/ShaderProgramResource.h"
 #include "anki/resource/ShaderProgramPrePreprocessor.h"
+#include "anki/resource/ResourceManager.h"
 #include "anki/core/App.h" // To get cache dir
 #include "anki/util/File.h"
 #include "anki/util/Exception.h"
@@ -44,7 +45,7 @@ void ShaderProgramResource::load(const char* filename, const char* extraSrc)
 		}
 	}
 
-	// XXX Fix that nonsense
+	// Create the program
 	if(pars.getShaderSource(ST_VERTEX).size() != 0)
 	{
 		std::string vertSrc = extraSrc + pars.getShaderSource(ST_VERTEX);
@@ -78,36 +79,41 @@ void ShaderProgramResource::load(const char* filename, const char* extraSrc)
 
 //==============================================================================
 std::string ShaderProgramResource::createSrcCodeToCache(
-	const char* sProgFPathName, const char* preAppendedSrcCode)
+	const char* filename, const char* preAppendedSrcCode, 
+	const char* filenamePrefix)
 {
+	ANKI_ASSERT(filename && preAppendedSrcCode && filenamePrefix);
+
 	if(strlen(preAppendedSrcCode) < 1)
 	{
-		return sProgFPathName;
+		return filename;
 	}
 
 	// Create suffix
 	std::hash<std::string> stringHash;
-	std::size_t h = stringHash(std::string(sProgFPathName) 
-		+ preAppendedSrcCode);
+	std::size_t h = stringHash(std::string(filename) + preAppendedSrcCode);
 	std::string suffix = std::to_string(h);
 
-	//
-	std::string newfPathName = AppSingleton::get().getCachePath()
-		+ "/" + suffix + ".glsl";
+	// Compose cached filename
+	std::string newFilename = AppSingleton::get().getCachePath()
+		+ "/" + filenamePrefix + suffix + ".glsl";
 
-	if(File::fileExists(newfPathName.c_str()))
+	if(File::fileExists(newFilename.c_str()))
 	{
-		return newfPathName;
+		return newFilename;
 	}
 
-	std::string src_;
-	File(sProgFPathName, File::OF_READ).readAllText(src_);
-	std::string src = preAppendedSrcCode + src_;
+	// Read file and append code
+	std::string src;
+	File(ResourceManagerSingleton::get().fixResourcePath(filename).c_str(), 
+		File::OF_READ).readAllText(src);
+	src = preAppendedSrcCode + src;
 
-	File f(newfPathName.c_str(), File::OF_READ);
-	f.writeText(src.c_str());
+	// Write cached file
+	File f(newFilename.c_str(), File::OF_WRITE);
+	f.writeText("%s\n", src.c_str());
 
-	return newfPathName;
+	return newFilename;
 }
 
-} // end namespace
+} // end namespace anki

+ 2 - 0
src/scene/SceneGraph.cpp

@@ -139,6 +139,8 @@ void SceneGraph::unregisterNode(SceneNode* node)
 //==============================================================================
 void SceneGraph::update(F32 prevUpdateTime, F32 crntTime, Renderer& renderer)
 {
+	ANKI_ASSERT(mainCam);
+
 	ANKI_COUNTER_START_TIMER(C_SCENE_UPDATE_TIME);
 
 	ThreadPool& threadPool = ThreadPoolSingleton::get();

+ 9 - 6
src/util/File.cpp

@@ -1,12 +1,12 @@
 #include "anki/util/File.h"
 #include "anki/util/Exception.h"
 #include "anki/util/Assert.h"
-#include "anki/core/Logger.h" // XXX
 #include <fstream>
 #include <cstring>
 #include <cstdarg>
 #include <contrib/minizip/unzip.h>
 #if ANKI_OS == ANKI_OS_ANDROID
+#	include <android_native_app_glue.h>
 #	include <android/asset_manager.h>
 #endif
 
@@ -17,7 +17,7 @@ namespace anki {
 //==============================================================================
 
 #if ANKI_OS == ANKI_OS_ANDROID
-AAssetManager* File::andAssetManager = nullptr;
+extern android_app* gAndroidApp;
 #endif
 
 //==============================================================================
@@ -197,10 +197,13 @@ void File::openAndFile(const char* filename, U16 flags_)
 	}
 
 	// Open file
-	ANKI_ASSERT(andAssetManager != nullptr 
-		&& "You should call setAndroidAssetManager() on engine initialization");
+	ANKI_ASSERT(gAndroidApp != nullptr && gAndroidApp->activity 
+		&& gAndroidApp->activity->assetManager);
+
 	file = AAssetManager_open(
-		andAssetManager, filename + 1, AASSET_MODE_STREAMING);
+		gAndroidApp->activity->assetManager, 
+		filename + 1, 
+		AASSET_MODE_STREAMING);
 
 	if(file == nullptr)
 	{
@@ -538,7 +541,7 @@ void File::seek(PtrSize offset, SeekOrigin origin)
 #if ANKI_OS == ANKI_OS_ANDROID
 	else if(flags & FT_SPECIAL)
 	{
-		if(AAsset_seek((AAsset*)file, offset, origin) != 0)
+		if(AAsset_seek((AAsset*)file, offset, origin) == (off_t)-1)
 		{
 			throw ANKI_EXCEPTION("AAsset_seek() failed");
 		}

+ 1 - 1
testapp/Main.cpp

@@ -515,7 +515,7 @@ void initSubsystems(int argc, char* argv[])
 #endif
 
 	// App
-	AppSingleton::get().init(nullptr);
+	AppSingleton::get().init();
 
 	// Window
 	NativeWindowInitializer nwinit;