Browse Source

- Update README
- Add more functionality to UI
- Move GaussianBlur to the new program interface

Panagiotis Christopoulos Charitos 8 years ago
parent
commit
ec0b96bddb

+ 6 - 7
README.md

@@ -1,7 +1,6 @@
 [![AnKi logo](http://anki3d.org/wp-content/uploads/2015/11/logo_248.png)](http://anki3d.org)
 
-AnKi 3D engine is a Linux and Windows opensource game engine that runs on
-OpenGL 4.5 and Vulkan 1.0 (Experimental).
+AnKi 3D engine is a Linux and Windows opensource game engine that runs on OpenGL 4.5 and Vulkan 1.0 (Experimental).
 
 [![Video](http://img.youtube.com/vi/va7nZ2EFR4c/0.jpg)](http://www.youtube.com/watch?v=va7nZ2EFR4c)
 
@@ -11,7 +10,7 @@ OpenGL 4.5 and Vulkan 1.0 (Experimental).
 AnKi's license is BSD. This practically means that you can use the source or parts of the source on proprietary and non 
 proprietary products as long as you follow the conditions of the license.
 
-See LICENSE file for more info.
+See `LICENSE` file for more info.
 
 2 Building AnKi
 ===============
@@ -25,7 +24,7 @@ To checkout the source including the submodules type:
 
 	git clone --recurse-submodules https://github.com/godlikepanos/anki-3d-engine.git anki
 
-AnKi's build system is using CMake. A great effort was made to ease the building process that's why the number of 
+AnKi's build system is using `CMake`. A great effort was made to ease the building process that's why the number of 
 external dependencies are almost none.
 
 2.1 On Linux
@@ -46,7 +45,7 @@ To build the release version:
 	$cmake .. -DCMAKE_BUILD_TYPE=Release
 	$make
 
-To view and configure the build options you can use ccmake tool or other similar tool:
+To view and configure the build options you can use `ccmake` tool or other similar tool:
 
 	$cd path/to/anki/build
 	$ccmake .
@@ -65,7 +64,7 @@ Prerequisites:
 	- Install to a path without spaces (eg C:/mingw-w64)
 	- Append the path where mingw's binaries are located (eg C:/mingw-w64/bin) to the PATH environment variable
 
-To build the release version open PowerShell and type:
+To build the release version open `PowerShell` and type:
 
 	$cd path/to/anki
 	$mkdir build
@@ -78,7 +77,7 @@ To build the release version open PowerShell and type:
 3 Next steps
 ============
 
-Try to build with samples enabled (search for the ANKI_BUILD_SAMPLES option in your CMake GUI) and try running the 
+Try to build with `samples` enabled (search for the `ANKI_BUILD_SAMPLES` option in your CMake GUI) and try running the 
 sponza executable. Then you will be able to see sponza running in AnKi. All samples must run from within their 
 directory.
 

+ 71 - 0
programs/GaussianBlur.ankiprog

@@ -0,0 +1,71 @@
+<!-- 
+Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
+All rights reserved.
+Code licensed under the BSD License.
+http://www.anki3d.org/LICENSE
+-->
+<shaderProgram>
+	<mutators>
+		<mutator name="HORIZONTAL" values="0 1"/>
+		<mutator name="KERNEL_SIZE" values="3 5 7 9 11 13 15"/>
+		<mutator name="COLOR_COMPONENTS" values="4 3 1"/>
+	</mutators>
+
+	<shaders>
+		<shader type="vert">
+			<source><![CDATA[
+#include "shaders/Quad.vert.glsl"
+			]]></source>
+		</shader>
+
+		<shader type="frag">
+			<inputs>
+				<input name="TEXTURE_SIZE" type="uvec2" const="1"/>
+			</inputs>
+
+			<source><![CDATA[
+#include "shaders/GaussianBlurCommon.glsl"
+
+layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_tex; ///< Input FAI
+
+layout(location = 0) in vec2 in_uv;
+
+// Determine color type
+#if COLOR_COMPONENTS == 4
+#	define COL_TYPE vec4
+#	define TEX_FETCH rgba
+#elif COLOR_COMPONENTS == 3
+#	define COL_TYPE vec3
+#	define TEX_FETCH rgb
+#elif COLOR_COMPONENTS == 1
+#	define COL_TYPE float
+#	define TEX_FETCH r
+#else
+#	error See file
+#endif
+
+// Output
+layout(location = 0) out COL_TYPE out_color;
+
+void main()
+{
+#if HORIZONTAL
+	const vec2 TEXEL_SIZE = vec2(1.0 / float(TEXTURE_SIZE.x), 0.0);
+#else
+	const vec2 TEXEL_SIZE = vec2(0.0, 1.0 / float(TEXTURE_SIZE.y));
+#endif
+
+	out_color = COL_TYPE(0.0);
+	for(uint i = 0u; i < STEP_COUNT; ++i)
+	{
+		vec2 texCoordOffset = OFFSETS[i] * TEXEL_SIZE;
+		COL_TYPE col =
+			texture(u_tex, in_uv + texCoordOffset).TEX_FETCH + texture(u_tex, in_uv - texCoordOffset).TEX_FETCH;
+		out_color += WEIGHTS[i] * col;
+	}
+}
+			]]></source>
+		</shader>
+	</shaders>
+</shaderProgram>
+

+ 0 - 67
shaders/GaussianBlurGeneric.frag.glsl

@@ -1,67 +0,0 @@
-// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
-// All rights reserved.
-// Code licensed under the BSD License.
-// http://www.anki3d.org/LICENSE
-
-// Weights and offsets generated by GaussialBlur.h from Intel
-//
-// Switches: VPASS or HPASS, COL_RGBA or COL_RGB or COL_R
-// Also must define TEXTURE_SIZE and KERNEL_SIZE
-
-#include "shaders/GaussianBlurCommon.glsl"
-
-// Preprocessor switches sanity checks
-#if !defined(VPASS) && !defined(HPASS)
-#error See file
-#endif
-
-#if !(defined(COL_RGBA) || defined(COL_RGB) || defined(COL_R))
-#error See file
-#endif
-
-#if !defined(TEXTURE_SIZE)
-#error See file
-#endif
-
-layout(ANKI_TEX_BINDING(0, 0)) uniform sampler2D u_tex; ///< Input FAI
-
-layout(location = 0) in vec2 in_uv;
-
-// Determine color type
-#if defined(COL_RGBA)
-#define COL_TYPE vec4
-#elif defined(COL_RGB)
-#define COL_TYPE vec3
-#elif defined(COL_R)
-#define COL_TYPE float
-#endif
-
-// Determine tex fetch
-#if defined(COL_RGBA)
-#define TEX_FETCH rgba
-#elif defined(COL_RGB)
-#define TEX_FETCH rgb
-#elif defined(COL_R)
-#define TEX_FETCH r
-#endif
-
-// Output
-layout(location = 0) out COL_TYPE out_color;
-
-void main()
-{
-#if defined(VPASS)
-	const vec2 TEXEL_SIZE = vec2(0.0, 1.0 / TEXTURE_SIZE.y);
-#else
-	const vec2 TEXEL_SIZE = vec2(1.0 / TEXTURE_SIZE.x, 0.0);
-#endif
-
-	out_color = COL_TYPE(0.0);
-	for(uint i = 0u; i < STEP_COUNT; ++i)
-	{
-		vec2 texCoordOffset = OFFSETS[i] * TEXEL_SIZE;
-		COL_TYPE col =
-			texture(u_tex, in_uv + texCoordOffset).TEX_FETCH + texture(u_tex, in_uv - texCoordOffset).TEX_FETCH;
-		out_color += WEIGHTS[i] * col;
-	}
-}

+ 3 - 0
src/anki/Ui.h

@@ -8,3 +8,6 @@
 /// @defgroup ui User interface that is using nuklear library.
 
 #include <anki/ui/UiManager.h>
+#include <anki/ui/Font.h>
+#include <anki/ui/UiImmediateModeBuilder.h>
+#include <anki/ui/Canvas.h>

+ 45 - 16
src/anki/gr/gl/Fence.cpp

@@ -8,6 +8,7 @@
 #include <anki/gr/CommandBuffer.h>
 #include <anki/gr/gl/CommandBufferImpl.h>
 #include <anki/gr/GrManager.h>
+#include <anki/util/HighRezTimer.h>
 
 namespace anki
 {
@@ -28,32 +29,42 @@ Bool Fence::clientWait(F64 seconds)
 		return true;
 	}
 
-	if(seconds == 0.0)
-	{
-		return false;
-	}
-
 	class CheckFenceCommand final : public GlCommand
 	{
 	public:
-		FenceImpl* m_fence; // Use the ptr to impl because there is a barrier that covers racing condition.
+		FencePtr m_fence;
 		F64 m_timeout;
+		F64 m_flushTime;
 		Barrier* m_barrier;
 
-		CheckFenceCommand(FenceImpl* fence, F64 timeout, Barrier* barrier)
+		CheckFenceCommand(FencePtr fence, F64 timeout, F64 flushTime, Barrier* barrier)
 			: m_fence(fence)
 			, m_timeout(timeout)
+			, m_flushTime(flushTime)
 			, m_barrier(barrier)
 		{
 		}
 
 		Error operator()(GlState&)
 		{
-			GLenum out = glClientWaitSync(m_fence->m_fence, GL_SYNC_FLUSH_COMMANDS_BIT, m_timeout * 1e+9);
+			// Since there is a delay between flushing the cmdb and returning this result try to adjust the time we
+			// wait
+			F64 timeToWait;
+			if(m_timeout != 0.0)
+			{
+				timeToWait = m_timeout - (HighRezTimer::getCurrentTime() - m_flushTime);
+				timeToWait = max(0.0, timeToWait);
+			}
+			else
+			{
+				timeToWait = 0.0;
+			}
+
+			GLenum out = glClientWaitSync(m_fence->m_impl->m_fence, GL_SYNC_FLUSH_COMMANDS_BIT, timeToWait * 1e+9);
 
 			if(out == GL_ALREADY_SIGNALED || out == GL_CONDITION_SATISFIED)
 			{
-				m_fence->m_signaled.store(true);
+				m_fence->m_impl->m_signaled.store(true);
 			}
 			else if(out == GL_TIMEOUT_EXPIRED)
 			{
@@ -65,21 +76,39 @@ Bool Fence::clientWait(F64 seconds)
 				return ErrorCode::FUNCTION_FAILED;
 			}
 
-			m_barrier->wait();
+			if(m_barrier)
+			{
+				m_barrier->wait();
+			}
 
 			return ErrorCode::NONE;
 		}
 	};
 
-	Barrier barrier(2);
-
 	CommandBufferPtr cmdb = getManager().newInstance<CommandBuffer>(CommandBufferInitInfo());
-	cmdb->m_impl->pushBackNewCommand<CheckFenceCommand>(m_impl.get(), seconds, &barrier);
-	cmdb->flush();
 
-	barrier.wait();
+	if(seconds == 0.0)
+	{
+		// Send a cmd that will update the fence's status in case someone calls clientWait with seconds==0.0 all the
+		// time
+		cmdb->m_impl->pushBackNewCommand<CheckFenceCommand>(FencePtr(this), seconds, 0.0, nullptr);
+		cmdb->flush();
+
+		return false;
+	}
+	else
+	{
+		Barrier barrier(2);
+
+		F64 flushTime = HighRezTimer::getCurrentTime();
 
-	return m_impl->m_signaled.load();
+		cmdb->m_impl->pushBackNewCommand<CheckFenceCommand>(FencePtr(this), seconds, flushTime, &barrier);
+		cmdb->flush();
+
+		barrier.wait();
+
+		return m_impl->m_signaled.load();
+	}
 }
 
 } // end namespace anki

+ 23 - 20
src/anki/renderer/Ssao.cpp

@@ -135,16 +135,17 @@ Error SsaoHBlur::init(const ConfigSet& config)
 	m_fb = getGrManager().newInstance<Framebuffer>(fbInit);
 
 	// shader
-	ANKI_CHECK(m_r->createShaderf("shaders/GaussianBlurGeneric.frag.glsl",
-		m_frag,
-		"#define HPASS\n"
-		"#define COL_R\n"
-		"#define TEXTURE_SIZE vec2(%f, %f)\n"
-		"#define KERNEL_SIZE 9\n",
-		F32(m_ssao->m_width),
-		F32(m_ssao->m_height)));
+	ANKI_CHECK(m_r->getResourceManager().loadResource("programs/GaussianBlur.ankiprog", m_prog));
 
-	m_r->createDrawQuadShaderProgram(m_frag->getGrShader(), m_prog);
+	ShaderProgramResourceMutationInitList<3> mutators(m_prog);
+	mutators.add("HORIZONTAL", 1).add("KERNEL_SIZE", 9).add("COLOR_COMPONENTS", 1);
+	ShaderProgramResourceConstantValueInitList<1> consts(m_prog);
+	consts.add("TEXTURE_SIZE", UVec2(m_ssao->m_width, m_ssao->m_height));
+
+	const ShaderProgramResourceVariant* variant;
+	m_prog->getOrCreateVariant(mutators.m_mutations, consts.m_constantValues, variant);
+
+	m_grProg = variant->getProgram();
 
 	return ErrorCode::NONE;
 }
@@ -161,7 +162,7 @@ void SsaoHBlur::run(RenderingContext& ctx)
 
 	cmdb->setViewport(0, 0, m_ssao->m_width, m_ssao->m_height);
 	cmdb->beginRenderPass(m_fb);
-	cmdb->bindShaderProgram(m_prog);
+	cmdb->bindShaderProgram(m_grProg);
 	cmdb->bindTexture(0, 0, m_ssao->m_main.m_rt[m_r->getFrameCount() & 1]);
 	m_r->drawQuad(cmdb);
 	cmdb->endRenderPass();
@@ -177,16 +178,18 @@ void SsaoHBlur::setPostRunBarriers(RenderingContext& ctx)
 
 Error SsaoVBlur::init(const ConfigSet& config)
 {
-	ANKI_CHECK(m_r->createShaderf("shaders/GaussianBlurGeneric.frag.glsl",
-		m_frag,
-		"#define VPASS\n"
-		"#define COL_R\n"
-		"#define TEXTURE_SIZE vec2(%f, %f)\n"
-		"#define KERNEL_SIZE 9\n",
-		F32(m_ssao->m_width),
-		F32(m_ssao->m_height)));
+	// shader
+	ANKI_CHECK(m_r->getResourceManager().loadResource("programs/GaussianBlur.ankiprog", m_prog));
 
-	m_r->createDrawQuadShaderProgram(m_frag->getGrShader(), m_prog);
+	ShaderProgramResourceMutationInitList<3> mutators(m_prog);
+	mutators.add("HORIZONTAL", 0).add("KERNEL_SIZE", 9).add("COLOR_COMPONENTS", 1);
+	ShaderProgramResourceConstantValueInitList<1> consts(m_prog);
+	consts.add("TEXTURE_SIZE", UVec2(m_ssao->m_width, m_ssao->m_height));
+
+	const ShaderProgramResourceVariant* variant;
+	m_prog->getOrCreateVariant(mutators.m_mutations, consts.m_constantValues, variant);
+
+	m_grProg = variant->getProgram();
 
 	return ErrorCode::NONE;
 }
@@ -205,7 +208,7 @@ void SsaoVBlur::run(RenderingContext& ctx)
 
 	cmdb->setViewport(0, 0, m_ssao->m_width, m_ssao->m_height);
 	cmdb->beginRenderPass(m_ssao->m_main.m_fb[m_r->getFrameCount() & 1]);
-	cmdb->bindShaderProgram(m_prog);
+	cmdb->bindShaderProgram(m_grProg);
 	cmdb->bindTexture(0, 0, m_ssao->m_hblur.m_rt);
 	m_r->drawQuad(cmdb);
 	cmdb->endRenderPass();

+ 4 - 4
src/anki/renderer/Ssao.h

@@ -82,8 +82,8 @@ private:
 
 	TexturePtr m_rt;
 	FramebufferPtr m_fb;
-	ShaderResourcePtr m_frag;
-	ShaderProgramPtr m_prog;
+	ShaderProgramResourcePtr m_prog;
+	ShaderProgramPtr m_grProg;
 };
 
 /// Screen space ambient occlusion blur pass.
@@ -107,8 +107,8 @@ anki_internal:
 private:
 	Ssao* m_ssao;
 
-	ShaderResourcePtr m_frag;
-	ShaderProgramPtr m_prog;
+	ShaderProgramResourcePtr m_prog;
+	ShaderProgramPtr m_grProg;
 };
 
 /// Screen space ambient occlusion pass

+ 31 - 0
src/anki/ui/Canvas.cpp

@@ -0,0 +1,31 @@
+// Copyright (C) 2009-2017, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <anki/ui/Canvas.h>
+#include <anki/ui/Font.h>
+
+namespace anki
+{
+
+Canvas::~Canvas()
+{
+	nk_free(&m_nkCtx);
+}
+
+Error Canvas::init(FontPtr font)
+{
+	m_font = font;
+
+	nk_allocator alloc = makeNkAllocator(&getAllocator().getMemoryPool());
+	if(!nk_init(&m_nkCtx, &alloc, &m_font->getFont().handle))
+	{
+		ANKI_UI_LOGE("nk_init() failed");
+		return ErrorCode::FUNCTION_FAILED;
+	}
+
+	return ErrorCode::NONE;
+}
+
+} // end namespace anki

+ 32 - 3
src/anki/ui/Canvas.h

@@ -5,7 +5,7 @@
 
 #pragma once
 
-#include <anki/ui/Common.h>
+#include <anki/ui/UiObject.h>
 
 namespace anki
 {
@@ -13,8 +13,37 @@ namespace anki
 /// @addtogroup ui
 /// @{
 
-// TODO
+/// UI canvas.
+class Canvas : public UiObject
+{
+public:
+	Canvas(UiManager* manager)
+		: UiObject(manager)
+	{
+	}
+
+	~Canvas();
+
+	ANKI_USE_RESULT Error init(FontPtr font);
+
+	nk_context& getContext()
+	{
+		return m_nkCtx;
+	}
+
+	/// Handle input.
+	virtual void handleInput();
+
+	/// Begin building the UI.
+	void beginBuilding();
+
+	/// End building.
+	void endBuilding();
 
+private:
+	FontPtr m_font;
+	nk_context m_nkCtx = {};
+};
 /// @}
 
-} // end namespace anki
+} // end namespace anki

+ 16 - 0
src/anki/ui/Common.h

@@ -16,8 +16,24 @@ class UiManager;
 
 /// @addtogroup ui
 /// @{
+
+#define ANKI_UI_LOGI(...) ANKI_LOG("UI  ", NORMAL, __VA_ARGS__)
+#define ANKI_UI_LOGE(...) ANKI_LOG("UI  ", ERROR, __VA_ARGS__)
+#define ANKI_UI_LOGW(...) ANKI_LOG("UI  ", WARNING, __VA_ARGS__)
+#define ANKI_UI_LOGF(...) ANKI_LOG("UI  ", FATAL, __VA_ARGS__)
+
 using UiAllocator = HeapAllocator<U8>;
 
+#define ANKI_UI_OBJECT_FW(name_)                                                                                       \
+	class name_;                                                                                                       \
+	using name_##Ptr = IntrusivePtr<name_>;
+
+ANKI_UI_OBJECT_FW(Font)
+ANKI_UI_OBJECT_FW(Canvas)
+ANKI_UI_OBJECT_FW(UiImmediateModeBuilder)
+
+#undef ANKI_UI_OBJECT
+
 const I32 FONT_TEXTURE_INDEX = 1;
 
 /// Initialize a nk_allocator.

+ 1 - 1
src/anki/ui/Font.cpp

@@ -56,7 +56,7 @@ void Font::createTexture(const void* data, U32 width, U32 height)
 	ANKI_ASSERT(data && width > 0 && height > 0);
 
 	// Create and populate the buffer
-	PtrSize buffSize = width * height * 4 * 4;
+	PtrSize buffSize = width * height * 4;
 	BufferPtr buff = m_manager->getGrManager().newInstance<Buffer>(
 		buffSize, BufferUsageBit::BUFFER_UPLOAD_DESTINATION, BufferMapAccessBit::WRITE);
 	void* mapped = buff->map(0, buffSize, BufferMapAccessBit::WRITE);

+ 6 - 9
src/anki/ui/Font.h

@@ -25,11 +25,6 @@ public:
 
 	~Font();
 
-	Atomic<I32>& getRefcount()
-	{
-		return m_refcount;
-	}
-
 	/// Initialize the font.
 	ANKI_USE_RESULT Error init(const CString& filename, U32 fontHeight);
 
@@ -40,9 +35,13 @@ anki_internal:
 		return m_tex;
 	}
 
-private:
-	Atomic<I32> m_refcount = {0};
+	const nk_font& getFont() const
+	{
+		ANKI_ASSERT(m_font);
+		return *m_font;
+	}
 
+private:
 	nk_font_atlas m_atlas = {};
 	nk_font* m_font = nullptr;
 
@@ -50,8 +49,6 @@ private:
 
 	void createTexture(const void* data, U32 width, U32 height);
 };
-
-using FontPtr = IntrusivePtr<Font>;
 /// @}
 
 } // end namespace anki

+ 7 - 3
src/anki/ui/UiImmediateModeBuilder.h

@@ -13,8 +13,12 @@ namespace anki
 /// @addtogroup ui
 /// @{
 
-// TODO
-
+/// An interface that just builds the UI.
+class UiImmediateModeBuilder : public UiObject
+{
+public:
+	virtual void build(CanvasPtr ctx) = 0;
+};
 /// @}
 
-} // end namespace anki
+} // end namespace anki

+ 9 - 1
src/anki/ui/UiManager.h

@@ -42,6 +42,14 @@ public:
 		return *m_gr;
 	}
 
+	/// Create a new UI object.
+	template<typename T, typename... Args>
+	ANKI_USE_RESULT Error newInstance(IntrusivePtr<T>& ptr, Args&&... args)
+	{
+		ptr.reset(m_alloc.newInstance<T>(this));
+		return ptr->init(args...);
+	}
+
 private:
 	UiAllocator m_alloc;
 	ResourceManager* m_resources = nullptr;
@@ -49,4 +57,4 @@ private:
 };
 /// @}
 
-} // end namespace anki
+} // end namespace anki

+ 6 - 0
src/anki/ui/UiObject.h

@@ -27,8 +27,14 @@ public:
 
 	UiAllocator getAllocator() const;
 
+	Atomic<I32>& getRefcount()
+	{
+		return m_refcount;
+	}
+
 protected:
 	UiManager* m_manager;
+	Atomic<I32> m_refcount = {0};
 };
 /// @}
 

+ 13 - 9
tests/framework/Framework.cpp

@@ -223,13 +223,20 @@ void deleteTesterSingleton()
 	}
 }
 
-NativeWindow* createWindow(U width, U height)
+void initConfig(Config& cfg)
+{
+	cfg.set("width", 1920);
+	cfg.set("height", 1080);
+	cfg.set("rsrc.dataPaths", ".:../engine_data");
+}
+
+NativeWindow* createWindow(const Config& cfg)
 {
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 
 	NativeWindowInitInfo inf;
-	inf.m_width = width;
-	inf.m_height = height;
+	inf.m_width = cfg.getNumber("width");
+	inf.m_height = cfg.getNumber("height");
 	inf.m_title = "AnKi unit tests";
 	NativeWindow* win = new NativeWindow();
 
@@ -238,13 +245,10 @@ NativeWindow* createWindow(U width, U height)
 	return win;
 }
 
-GrManager* createGrManager(NativeWindow* win)
+GrManager* createGrManager(const Config& cfg, NativeWindow* win)
 {
 	GrManager* gr = new GrManager();
 
-	Config cfg;
-	cfg.set("debugContext", true);
-	cfg.set("vsync", false);
 	GrManagerInitInfo inf;
 	inf.m_allocCallback = allocAligned;
 	inf.m_cacheDirectory = "./";
@@ -255,7 +259,8 @@ GrManager* createGrManager(NativeWindow* win)
 	return gr;
 }
 
-ResourceManager* createResourceManager(GrManager* gr, PhysicsWorld*& physics, ResourceFilesystem*& resourceFs)
+ResourceManager* createResourceManager(
+	const Config& cfg, GrManager* gr, PhysicsWorld*& physics, ResourceFilesystem*& resourceFs)
 {
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 
@@ -264,7 +269,6 @@ ResourceManager* createResourceManager(GrManager* gr, PhysicsWorld*& physics, Re
 	ANKI_TEST_EXPECT_NO_ERR(physics->create(allocAligned, nullptr));
 
 	resourceFs = new ResourceFilesystem(alloc);
-	Config cfg;
 	ANKI_TEST_EXPECT_NO_ERR(resourceFs->init(cfg, "./"));
 
 	ResourceManagerInitInfo rinit;

+ 6 - 3
tests/framework/Framework.h

@@ -220,10 +220,13 @@ extern void deleteTesterSingleton();
 /// Check error code.
 #define ANKI_TEST_EXPECT_ERR(x_, y_) ANKI_TEST_EXPECT_EQ_IMPL(__FILE__, __LINE__, __func__, x_, y_)
 
-NativeWindow* createWindow(U width, U height);
+void initConfig(Config& cfg);
 
-GrManager* createGrManager(NativeWindow* win);
+NativeWindow* createWindow(const Config& cfg);
 
-ResourceManager* createResourceManager(GrManager* gr, PhysicsWorld*& physics, ResourceFilesystem*& resourceFs);
+GrManager* createGrManager(const Config& cfg, NativeWindow* win);
+
+ResourceManager* createResourceManager(
+	const Config& cfg, GrManager* gr, PhysicsWorld*& physics, ResourceFilesystem*& resourceFs);
 
 } // end namespace anki

+ 7 - 18
tests/gr/Gr.cpp

@@ -263,8 +263,13 @@ static StagingGpuMemoryManager* stagingMem = nullptr;
 
 #define COMMON_BEGIN()                                                                                                 \
 	stagingMem = new StagingGpuMemoryManager();                                                                        \
-	win = createWindow(WIDTH, HEIGHT);                                                                                 \
-	gr = createGrManager(win);                                                                                         \
+	Config cfg;                                                                                                        \
+	cfg.set("width", WIDTH);                                                                                           \
+	cfg.set("height", HEIGHT);                                                                                         \
+	cfg.set("debugContext", true);                                                                                     \
+	cfg.set("vsync", false);                                                                                           \
+	win = createWindow(cfg);                                                                                           \
+	gr = createGrManager(cfg, win);                                                                                    \
 	ANKI_TEST_EXPECT_NO_ERR(stagingMem->init(gr, Config()));                                                           \
 	TransferGpuAllocator transfAlloc;                                                                                  \
 	ANKI_TEST_EXPECT_NO_ERR(transfAlloc.init(128_MB, gr, gr->getAllocator()));                                         \
@@ -318,22 +323,6 @@ static void* setStorage(PtrSize size, CommandBufferPtr& cmdb, U set, U binding)
 
 const PixelFormat DS_FORMAT = PixelFormat(ComponentFormat::D24S8, TransformFormat::UNORM);
 
-static void createGrManager(NativeWindow*& win, GrManager*& gr)
-{
-	win = createWindow(WIDTH, HEIGHT);
-	gr = new GrManager();
-
-	Config cfg;
-	cfg.set("debugContext", true);
-	cfg.set("vsync", false);
-	GrManagerInitInfo inf;
-	inf.m_allocCallback = allocAligned;
-	inf.m_cacheDirectory = "./";
-	inf.m_config = &cfg;
-	inf.m_window = win;
-	ANKI_TEST_EXPECT_NO_ERR(gr->init(inf));
-}
-
 static ShaderProgramPtr createProgram(CString vertSrc, CString fragSrc, GrManager& gr)
 {
 	ShaderPtr vert = gr.newInstance<Shader>(ShaderType::VERTEX, vertSrc);

+ 22 - 8
tests/ui/Ui.cpp

@@ -11,9 +11,6 @@
 namespace anki
 {
 
-static const U WIDTH = 1920;
-static const U HEIGHT = 1080;
-
 static FramebufferPtr createDefaultFb(GrManager& gr)
 {
 	FramebufferInitInfo fbinit;
@@ -23,22 +20,39 @@ static FramebufferPtr createDefaultFb(GrManager& gr)
 	return gr.newInstance<Framebuffer>(fbinit);
 }
 
+class Label : public UiImmediateModeBuilder
+{
+public:
+	void build(CanvasPtr canvas)
+	{
+		nk_context* ctx = &canvas->getContext();
+		// TODO
+	}
+};
+
 ANKI_TEST(Ui, Ui)
 {
-	NativeWindow* win = createWindow(WIDTH, HEIGHT);
-	GrManager* gr = createGrManager(win);
+	Config cfg;
+	initConfig(cfg);
+	cfg.set("vsync", 1);
+
+	NativeWindow* win = createWindow(cfg);
+	GrManager* gr = createGrManager(cfg, win);
 	PhysicsWorld* physics;
 	ResourceFilesystem* fs;
-	ResourceManager* resource = createResourceManager(gr, physics, fs);
+	ResourceManager* resource = createResourceManager(cfg, gr, physics, fs);
 	UiManager* ui = new UiManager();
 
 	HeapAllocator<U8> alloc(allocAligned, nullptr);
 	ANKI_TEST_EXPECT_NO_ERR(ui->init(alloc, resource, gr));
 
 	{
+		FontPtr font;
+		ANKI_TEST_EXPECT_NO_ERR(ui->newInstance(font, "UbuntuRegular.ttf", 30));
+
 		FramebufferPtr fb = createDefaultFb(*gr);
 
-		U iterations = 100;
+		U iterations = 200;
 		while(iterations--)
 		{
 			HighRezTimer timer;
@@ -73,4 +87,4 @@ ANKI_TEST(Ui, Ui)
 	delete win;
 }
 
-} // end namespace anki
+} // end namespace anki

+ 1 - 1
thirdparty

@@ -1 +1 @@
-Subproject commit 410e112179e8bb7b501868f88d8a490e28f4eae6
+Subproject commit ae947050b6b3546b88711bc6026e41f424f93f19