浏览代码

Adding async loading support for textures. Needs some work

Panagiotis Christopoulos Charitos 10 年之前
父节点
当前提交
6d7793c27a

+ 21 - 22
include/anki/resource/AsyncLoader.h

@@ -5,33 +5,33 @@
 
 #pragma once
 
-#include "anki/resource/Common.h"
-#include "anki/util/Thread.h"
+#include <anki/resource/Common.h>
+#include <anki/util/Thread.h>
 
 namespace anki {
 
 /// @addtogroup resource
 /// @{
 
-/// Asynchronous resource loader.
-class AsyncLoader
+/// Loader asynchronous task.
+class AsyncLoaderTask
 {
-public:
-	/// Loader asynchronous task.
-	class Task
-	{
-		friend class AsyncLoader;
+	friend class AsyncLoader;
 
-	public:
-		virtual ~Task()
-		{}
+public:
+	virtual ~AsyncLoaderTask()
+	{}
 
-		virtual ANKI_USE_RESULT Error operator()() = 0;
+	virtual ANKI_USE_RESULT Error operator()() = 0;
 
-	private:
-		Task* m_next = nullptr;
-	};
+private:
+	AsyncLoaderTask* m_next = nullptr;
+};
 
+/// Asynchronous resource loader.
+class AsyncLoader
+{
+public:
 	AsyncLoader();
 
 	~AsyncLoader();
@@ -40,15 +40,15 @@ public:
 
 	/// Create a new asynchronous loading task.
 	template<typename TTask, typename... TArgs>
-	ANKI_USE_RESULT Error newTask(TArgs&&... args);
+	void newTask(TArgs&&... args);
 
 private:
 	HeapAllocator<U8> m_alloc;
 	Thread m_thread;
 	Mutex m_mtx;
 	ConditionVariable m_condVar;
-	Task* m_head = nullptr;
-	Task* m_tail = nullptr;
+	AsyncLoaderTask* m_head = nullptr;
+	AsyncLoaderTask* m_tail = nullptr;
 	Bool8 m_quit = false;
 
 	/// Thread callback
@@ -59,8 +59,9 @@ private:
 	void stop();
 };
 
+//==============================================================================
 template<typename TTask, typename... TArgs>
-Error AsyncLoader::newTask(TArgs&&... args)
+void AsyncLoader::newTask(TArgs&&... args)
 {
 	TTask* newTask = m_alloc.template newInstance<TTask>(
 		std::forward<TArgs>(args)...);
@@ -85,8 +86,6 @@ Error AsyncLoader::newTask(TArgs&&... args)
 
 	// Wake up the thread
 	m_condVar.notifyOne();
-
-	return ErrorCode::NONE;
 }
 
 /// @}

+ 5 - 5
include/anki/resource/ResourceManager.h

@@ -5,10 +5,10 @@
 
 #pragma once
 
-#include "anki/resource/Common.h"
-#include "anki/util/List.h"
-#include "anki/util/Functions.h"
-#include "anki/util/String.h"
+#include <anki/resource/Common.h>
+#include <anki/util/List.h>
+#include <anki/util/Functions.h>
+#include <anki/util/String.h>
 
 namespace anki {
 
@@ -218,7 +218,7 @@ anki_internal:
 		TypeResourceManager<T>::unregisterResource(ptr);
 	}
 
-	AsyncLoader& _getAsyncLoader()
+	AsyncLoader& getAsyncLoader()
 	{
 		return *m_asyncLoader;
 	}

+ 15 - 7
shaders/FsCommonFrag.glsl

@@ -272,15 +272,23 @@ void fog(in sampler2D depthMap, in vec3 color, in float fogScale)
 
 	vec2 texCoords = gl_FragCoord.xy * screenSize;
 	float depth = texture(depthMap, texCoords).r;
-	float zNear = u_lightingUniforms.nearFarClustererDivisor.x;
-	float zFar = u_lightingUniforms.nearFarClustererDivisor.y;
-	float linearDepth = (2.0 * zNear) / (zFar + zNear - depth * (zFar - zNear));
+	float diff;
 
-	float depth2 = gl_FragCoord.z;
-	float linearDepth2 =
-		(2.0 * zNear) / (zFar + zNear - depth2 * (zFar - zNear));
+	if(depth < 1.0)
+	{
+		float zNear = u_lightingUniforms.nearFarClustererDivisor.x;
+		float zFar = u_lightingUniforms.nearFarClustererDivisor.y;
+		vec2 linearDepths = (2.0 * zNear)
+			/ (zFar + zNear - vec2(depth, gl_FragCoord.z) * (zFar - zNear));
 
-	float diff = linearDepth - linearDepth2;
+		diff = linearDepths.x - linearDepths.y;
+	}
+	else
+	{
+		// The depth buffer is cleared at this place. Set the diff to zero to
+		// avoid weird pop ups
+		diff = 0.0;
+	}
 
 	writeGBuffer(vec4(color, diff * fogScale));
 }

+ 1 - 1
src/core/Config.cpp

@@ -85,7 +85,7 @@ Config::Config()
 	newOption("gr.frameUniformsSize", 1024 * 1024 * 16);
 	newOption("gr.frameStorageSize", 1024 * 1024 * 16);
 	newOption("gr.frameVertexSize", 1024 * 1024 * 2);
-	newOption("gr.frameTransferSize", 1024 * 1024 * 16);
+	newOption("gr.frameTransferSize", 1024 * 1024 * 32);
 
 	//
 	// Resource

+ 2 - 2
src/gr/gl/GlState.cpp

@@ -164,7 +164,7 @@ void GlState::init1()
 	initDynamicBuffer(GL_SHADER_STORAGE_BUFFER, blockAlignment,
 		MAX_STORAGE_BLOCK_SIZE, BufferUsage::STORAGE);
 
-	initDynamicBuffer(GL_ARRAY_BUFFER, 8, MAX_U32, BufferUsage::VERTEX);
+	initDynamicBuffer(GL_ARRAY_BUFFER, 16, MAX_U32, BufferUsage::VERTEX);
 
 	{
 		m_transferBuffer.create(m_manager->getAllocator(),
@@ -172,7 +172,7 @@ void GlState::init1()
 
 		auto& buff = m_dynamicBuffers[BufferUsage::TRANSFER];
 		buff.m_address = &m_transferBuffer[0];
-		buff.m_alignment = 8;
+		buff.m_alignment = ANKI_SAFE_ALIGNMENT;
 		buff.m_maxAllocationSize = MAX_U32;
 	}
 }

+ 7 - 9
src/resource/AsyncLoader.cpp

@@ -3,14 +3,14 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#include "anki/resource/AsyncLoader.h"
-#include "anki/util/Logger.h"
+#include <anki/resource/AsyncLoader.h>
+#include <anki/util/Logger.h>
 
 namespace anki {
 
 //==============================================================================
 AsyncLoader::AsyncLoader()
-:	m_thread("anki_asyload")
+	: m_thread("anki_asyload")
 {}
 
 //==============================================================================
@@ -23,11 +23,11 @@ AsyncLoader::~AsyncLoader()
 		ANKI_ASSERT(m_tail != nullptr);
 		ANKI_LOGW("Stoping loading thread while there is work to do");
 
-		Task* task = m_head;
+		AsyncLoaderTask* task = m_head;
 
 		do
 		{
-			Task* next = task->m_next;
+			AsyncLoaderTask* next = task->m_next;
 			m_alloc.deleteInstance(task);
 			task = next;
 		}while(task != nullptr);
@@ -58,9 +58,7 @@ void AsyncLoader::stop()
 //==============================================================================
 Error AsyncLoader::threadCallback(Thread::Info& info)
 {
-	AsyncLoader& self = 
-		*reinterpret_cast<AsyncLoader*>(info.m_userData);
-
+	AsyncLoader& self = *reinterpret_cast<AsyncLoader*>(info.m_userData);
 	return self.threadWorker();
 }
 
@@ -71,7 +69,7 @@ Error AsyncLoader::threadWorker()
 
 	while(!err)
 	{
-		Task* task;
+		AsyncLoaderTask* task;
 
 		{
 			// Wait for something

+ 14 - 14
src/resource/ResourceManager.cpp

@@ -3,20 +3,20 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#include "anki/resource/ResourceManager.h"
-#include "anki/resource/AsyncLoader.h"
-#include "anki/resource/Animation.h"
-#include "anki/resource/Material.h"
-#include "anki/resource/Mesh.h"
-#include "anki/resource/Model.h"
-#include "anki/resource/Script.h"
-#include "anki/resource/DummyRsrc.h"
-#include "anki/resource/ShaderResource.h"
-#include "anki/resource/ParticleEmitterResource.h"
-#include "anki/resource/TextureResource.h"
-#include "anki/resource/GenericResource.h"
-#include "anki/util/Logger.h"
-#include "anki/misc/ConfigSet.h"
+#include <anki/resource/ResourceManager.h>
+#include <anki/resource/AsyncLoader.h>
+#include <anki/resource/Animation.h>
+#include <anki/resource/Material.h>
+#include <anki/resource/Mesh.h>
+#include <anki/resource/Model.h>
+#include <anki/resource/Script.h>
+#include <anki/resource/DummyRsrc.h>
+#include <anki/resource/ShaderResource.h>
+#include <anki/resource/ParticleEmitterResource.h>
+#include <anki/resource/TextureResource.h>
+#include <anki/resource/GenericResource.h>
+#include <anki/util/Logger.h>
+#include <anki/misc/ConfigSet.h>
 
 namespace anki {
 

+ 62 - 22
src/resource/TextureResource.cpp

@@ -3,12 +3,68 @@
 // Code licensed under the BSD License.
 // http://www.anki3d.org/LICENSE
 
-#include "anki/resource/TextureResource.h"
-#include "anki/resource/ImageLoader.h"
-#include "anki/resource/ResourceManager.h"
+#include <anki/resource/TextureResource.h>
+#include <anki/resource/ImageLoader.h>
+#include <anki/resource/ResourceManager.h>
+#include <anki/resource/AsyncLoader.h>
 
 namespace anki {
 
+//==============================================================================
+// Misc                                                                        =
+//==============================================================================
+
+class TexUploadTask: public AsyncLoaderTask
+{
+public:
+	UniquePtr<ImageLoader> m_loader;
+	TexturePtr m_tex;
+	GrManager* m_gr ANKI_DBG_NULLIFY_PTR;
+	U32 m_layerCount = 0;
+
+	TexUploadTask(UniquePtr<ImageLoader>& loader, TexturePtr tex,
+		GrManager* gr, U32 layerCount)
+		: m_loader(std::move(loader))
+		, m_tex(tex)
+		, m_gr(gr)
+		, m_layerCount(layerCount)
+	{}
+
+	Error operator()() final;
+};
+
+//==============================================================================
+Error TexUploadTask::operator()()
+{
+	CommandBufferPtr cmdb = m_gr->newInstance<CommandBuffer>();
+
+	// Upload the data
+	for(U layer = 0; layer < m_layerCount; layer++)
+	{
+		for(U level = 0; level < m_loader->getMipLevelsCount(); level++)
+		{
+			const auto& surf = m_loader->getSurface(level, layer);
+
+			DynamicBufferToken token;
+			void* data = m_gr->allocateFrameHostVisibleMemory(
+				surf.m_data.getSize(), BufferUsage::TRANSFER, token);
+			memcpy(data, &surf.m_data[0], surf.m_data.getSize());
+
+			cmdb->textureUpload(m_tex, level, layer, token);
+		}
+	}
+
+	// Finaly enque the GL job chain
+	// TODO This is probably a bad idea
+	cmdb->finish();
+
+	return ErrorCode::NONE;
+}
+
+//==============================================================================
+// TextureResource                                                             =
+//==============================================================================
+
 //==============================================================================
 TextureResource::~TextureResource()
 {}
@@ -137,25 +193,9 @@ Error TextureResource::load(const ResourceFilename& filename)
 	// Create the texture
 	m_tex = gr.newInstance<Texture>(init);
 
-	// Upload the data
-	for(U layer = 0; layer < layers; layer++)
-	{
-		for(U level = 0; level < init.m_mipmapsCount; level++)
-		{
-			const auto& surf = img->getSurface(level, layer);
-
-			DynamicBufferToken token;
-			void* data = gr.allocateFrameHostVisibleMemory(
-				surf.m_data.getSize(), BufferUsage::TRANSFER, token);
-			memcpy(data, &surf.m_data[0], surf.m_data.getSize());
-
-			cmdb->textureUpload(m_tex, level, layer, token);
-		}
-	}
-
-	// Finaly enque the GL job chain
-	// TODO Make asynchronous
-	cmdb->finish();
+	// Upload the data asynchronously
+	getManager().getAsyncLoader().newTask<TexUploadTask>(img, m_tex, &gr,
+		layers);
 
 	m_size = UVec3(init.m_width, init.m_height, init.m_depth);
 

+ 2 - 2
testapp/Main.cpp

@@ -43,7 +43,7 @@ App* app;
 ModelNode* horse;
 PerspectiveCamera* cam;
 
-#define PLAYER 0
+#define PLAYER 1
 #define MOUSE 1
 
 Bool profile = false;
@@ -481,7 +481,7 @@ Error initSubsystems(int argc, char* argv[])
 	config.set("is.sm.poissonEnabled", true);
 	config.set("is.sm.resolution", 1024);
 	config.set("lf.maxFlares", 32);
-	config.set("pps.enabled", false);
+	config.set("pps.enabled", true);
 	config.set("pps.bloom.enabled", true);
 	config.set("pps.bloom.renderingQuality", 0.5);
 	config.set("pps.bloom.blurringDist", 1.0);

+ 14 - 15
tests/resource/AsyncLoader.cpp

@@ -12,7 +12,7 @@
 namespace anki {
 
 //==============================================================================
-class Task: public AsyncLoader::Task
+class Task: public AsyncLoaderTask
 {
 public:
 	F32 m_sleepTime = 0.0;
@@ -21,10 +21,10 @@ public:
 	I32 m_id = -1;
 
 	Task(F32 time, Barrier* barrier, Atomic<U32>* count, I32 id = -1)
-	:	m_sleepTime(time),
-		m_barrier(barrier),
-		m_count(count),
-		m_id(id)
+		: m_sleepTime(time)
+		, m_barrier(barrier)
+		, m_count(count)
+		, m_id(id)
 	{}
 
 	Error operator()()
@@ -60,15 +60,15 @@ public:
 };
 
 //==============================================================================
-class MemTask: public AsyncLoader::Task
+class MemTask: public AsyncLoaderTask
 {
 public:
 	HeapAllocator<U8> m_alloc;
 	Barrier* m_barrier = nullptr;
 
 	MemTask(HeapAllocator<U8> alloc, Barrier* barrier)
-	:	m_alloc(alloc),
-		m_barrier(barrier)
+		: m_alloc(alloc)
+		, m_barrier(barrier)
 	{}
 
 	Error operator()()
@@ -106,7 +106,7 @@ ANKI_TEST(Resource, AsyncLoader)
 		ANKI_TEST_EXPECT_NO_ERR(a.create(alloc));
 		Barrier barrier(2);
 
-		ANKI_TEST_EXPECT_NO_ERR(a.newTask<Task>(0.0, &barrier, nullptr));
+		a.newTask<Task>(0.0, &barrier, nullptr);
 		barrier.wait();
 	}
 
@@ -126,7 +126,7 @@ ANKI_TEST(Resource, AsyncLoader)
 				pbarrier = &barrier;
 			}
 
-			ANKI_TEST_EXPECT_NO_ERR(a.newTask<Task>(0.0, pbarrier, &counter));
+			a.newTask<Task>(0.0, pbarrier, &counter);
 		}
 
 		barrier.wait();
@@ -141,7 +141,7 @@ ANKI_TEST(Resource, AsyncLoader)
 
 		for(U i = 0; i < 100; i++)
 		{
-			ANKI_TEST_EXPECT_NO_ERR(a.newTask<Task>(0.0, nullptr, nullptr));
+			a.newTask<Task>(0.0, nullptr, nullptr);
 		}
 	}
 
@@ -160,7 +160,7 @@ ANKI_TEST(Resource, AsyncLoader)
 				pbarrier = &barrier;
 			}
 
-			ANKI_TEST_EXPECT_NO_ERR(a.newTask<MemTask>(alloc, pbarrier));
+			a.newTask<MemTask>(alloc, pbarrier);
 		}
 
 		barrier.wait();
@@ -173,7 +173,7 @@ ANKI_TEST(Resource, AsyncLoader)
 
 		for(U i = 0; i < 10; i++)
 		{
-			ANKI_TEST_EXPECT_NO_ERR(a.newTask<MemTask>(alloc, nullptr));
+			a.newTask<MemTask>(alloc, nullptr);
 		}
 	}
 
@@ -193,8 +193,7 @@ ANKI_TEST(Resource, AsyncLoader)
 				pbarrier = &barrier;
 			}
 
-			ANKI_TEST_EXPECT_NO_ERR(
-				a.newTask<Task>(randRange(0.0, 0.5), pbarrier, &counter, i));
+			a.newTask<Task>(randRange(0.0, 0.5), pbarrier, &counter, i);
 		}
 
 		barrier.wait();