Browse Source

Fixes. Refresh the way of setting the name of threads. The logger now shows the tread name instead of an ID

Panagiotis Christopoulos Charitos 3 years ago
parent
commit
65de8eb999

+ 5 - 0
AnKi/Config.h.cmake

@@ -233,6 +233,9 @@ inline int __builtin_ctzll(unsigned long long x)
 #endif
 #endif
 
 
 // Define the main() function.
 // Define the main() function.
+namespace anki {
+void preMainInit();
+}
 #if ANKI_OS_ANDROID
 #if ANKI_OS_ANDROID
 extern "C" {
 extern "C" {
 struct android_app;
 struct android_app;
@@ -250,6 +253,7 @@ void cleanupGetAndroidCommandLineArguments(void* ptr);
 	extern "C" void android_main(android_app* app) \
 	extern "C" void android_main(android_app* app) \
 	{ \
 	{ \
 		anki::g_androidApp = app; \
 		anki::g_androidApp = app; \
+		preMainInit(); \
 		char** argv; \
 		char** argv; \
 		int argc; \
 		int argc; \
 		void* cleanupToken = anki::getAndroidCommandLineArguments(argc, argv); \
 		void* cleanupToken = anki::getAndroidCommandLineArguments(argc, argv); \
@@ -261,6 +265,7 @@ void cleanupGetAndroidCommandLineArguments(void* ptr);
 	int myMain(int argc, char* argv[]); \
 	int myMain(int argc, char* argv[]); \
 	int main(int argc, char* argv[]) \
 	int main(int argc, char* argv[]) \
 	{ \
 	{ \
+		preMainInit(); \
 		return myMain(argc, argv); \
 		return myMain(argc, argv); \
 	}
 	}
 #endif
 #endif

+ 0 - 2
AnKi/Core/App.cpp

@@ -174,8 +174,6 @@ Error App::initInternal(AllocAlignedCallback allocCb, void* allocCbUserData)
 
 
 	setSignalHandlers();
 	setSignalHandlers();
 
 
-	Thread::setNameOfCurrentThread("AnKiMain");
-
 	initMemoryCallbacks(allocCb, allocCbUserData);
 	initMemoryCallbacks(allocCb, allocCbUserData);
 	m_heapAlloc = HeapAllocator<U8>(m_allocCb, m_allocCbData, "Core");
 	m_heapAlloc = HeapAllocator<U8>(m_allocCb, m_allocCbData, "Core");
 
 

+ 2 - 2
AnKi/Core/NativeWindowAndroid.cpp

@@ -38,7 +38,7 @@ void NativeWindow::deleteInstance(NativeWindow* window)
 	}
 	}
 }
 }
 
 
-void NativeWindow::setWindowTitle(CString title)
+void NativeWindow::setWindowTitle([[maybe_unused]] CString title)
 {
 {
 	// Nothing
 	// Nothing
 }
 }
@@ -67,7 +67,7 @@ NativeWindowAndroid::~NativeWindowAndroid()
 	m_nativeWindow = nullptr;
 	m_nativeWindow = nullptr;
 }
 }
 
 
-Error NativeWindowAndroid::init(const NativeWindowInitInfo& init)
+Error NativeWindowAndroid::init([[maybe_unused]] const NativeWindowInitInfo& init)
 {
 {
 	ANKI_CORE_LOGI("Initializing Android window");
 	ANKI_CORE_LOGI("Initializing Android window");
 
 

+ 1 - 1
AnKi/Core/StdinListener.h

@@ -20,7 +20,7 @@ class StdinListener
 {
 {
 public:
 public:
 	StdinListener()
 	StdinListener()
-		: m_thrd("anki_stdin")
+		: m_thrd("Stdin")
 	{
 	{
 	}
 	}
 
 

+ 5 - 5
AnKi/Gr/Vulkan/GrManagerImpl.cpp

@@ -244,10 +244,10 @@ Error GrManagerImpl::initInstance()
 				ANKI_VK_LOGV("\t%s", layer.layerName);
 				ANKI_VK_LOGV("\t%s", layer.layerName);
 				CString layerName = layer.layerName;
 				CString layerName = layer.layerName;
 
 
-				static constexpr char* validationName = "VK_LAYER_KHRONOS_validation";
-				if((m_config->getGrValidation() || m_config->getGrDebugPrintf()) && layerName == validationName)
+				static constexpr const Char* kValidationName = "VK_LAYER_KHRONOS_validation";
+				if((m_config->getGrValidation() || m_config->getGrDebugPrintf()) && layerName == kValidationName)
 				{
 				{
-					layersToEnable.emplaceBack(validationName);
+					layersToEnable.emplaceBack(kValidationName);
 				}
 				}
 			}
 			}
 		}
 		}
@@ -1088,8 +1088,8 @@ Error GrManagerImpl::initDevice(const GrManagerInitInfo& init)
 		}
 		}
 	}
 	}
 
 
-	VkPhysicalDeviceMaintenance4FeaturesKHR maintenance4Features = {
-		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES_KHR};
+	VkPhysicalDeviceMaintenance4FeaturesKHR maintenance4Features = {};
+	maintenance4Features.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MAINTENANCE_4_FEATURES_KHR;
 	if(!!(m_extensions & VulkanExtensions::MAINTENANCE_4))
 	if(!!(m_extensions & VulkanExtensions::MAINTENANCE_4))
 	{
 	{
 		maintenance4Features.maintenance4 = true;
 		maintenance4Features.maintenance4 = true;

+ 9 - 3
AnKi/Importer/GltfImporter.cpp

@@ -716,8 +716,13 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 							   [[maybe_unused]] ThreadHiveSemaphore* signalSemaphore) {
 							   [[maybe_unused]] ThreadHiveSemaphore* signalSemaphore) {
 				Ctx& self = *static_cast<Ctx*>(userData);
 				Ctx& self = *static_cast<Ctx*>(userData);
 
 
+				Error err = self.m_importer->m_errorInThread.load();
+
 				// LOD 0
 				// LOD 0
-				Error err = self.m_importer->writeMesh(*self.m_mesh, 0, self.m_importer->computeLodFactor(0));
+				if(!err)
+				{
+					err = self.m_importer->writeMesh(*self.m_mesh, 0, self.m_importer->computeLodFactor(0));
+				}
 
 
 				// LOD 1
 				// LOD 1
 				if(!err && self.m_importer->m_lodCount > 1 && !self.m_importer->skipMeshLod(*self.m_mesh, 1))
 				if(!err && self.m_importer->m_lodCount > 1 && !self.m_importer->skipMeshLod(*self.m_mesh, 1))
@@ -754,7 +759,7 @@ Error GltfImporter::visitNode(const cgltf_node& node, const Transform& parentTrf
 				self.m_importer->m_alloc.deleteInstance(&self);
 				self.m_importer->m_alloc.deleteInstance(&self);
 			};
 			};
 
 
-			if(m_hive)
+			if(m_hive != nullptr)
 			{
 			{
 				m_hive->submitTask(callback, ctx);
 				m_hive->submitTask(callback, ctx);
 			}
 			}
@@ -1153,7 +1158,8 @@ StringAuto GltfImporter::computeModelResourceFilename(const cgltf_mesh& mesh) co
 
 
 	for(U i = 0; i < mesh.primitives_count; ++i)
 	for(U i = 0; i < mesh.primitives_count; ++i)
 	{
 	{
-		list.pushBackSprintf("_%s", mesh.primitives[i].material->name);
+		const Char* mtlName = (mesh.primitives[i].material) ? mesh.primitives[i].material->name : "UnamedMtl";
+		list.pushBackSprintf("_%s", mtlName);
 	}
 	}
 
 
 	StringAuto joined(m_alloc);
 	StringAuto joined(m_alloc);

+ 1 - 1
AnKi/Resource/AsyncLoader.cpp

@@ -10,7 +10,7 @@
 namespace anki {
 namespace anki {
 
 
 AsyncLoader::AsyncLoader()
 AsyncLoader::AsyncLoader()
-	: m_thread("anki_asyload")
+	: m_thread("AsyncLoad")
 {
 {
 }
 }
 
 

+ 2 - 1
AnKi/Resource/ImageResource.cpp

@@ -276,7 +276,8 @@ Error ImageResource::load(LoadingContext& ctx)
 			unflatten3dArrayIndex(ctx.m_layerCount, ctx.m_faces, ctx.m_loader.getMipmapCount(), i, layer, face, mip);
 			unflatten3dArrayIndex(ctx.m_layerCount, ctx.m_faces, ctx.m_loader.getMipmapCount(), i, layer, face, mip);
 
 
 			TextureBarrierInfo& barrier = barriers[barrierCount++];
 			TextureBarrierInfo& barrier = barriers[barrierCount++];
-			barrier = {ctx.m_tex.get(), TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION};
+			barrier = {ctx.m_tex.get(), TextureUsageBit::NONE, TextureUsageBit::TRANSFER_DESTINATION,
+					   TextureSubresourceInfo()};
 
 
 			if(ctx.m_texType == TextureType::_3D)
 			if(ctx.m_texType == TextureType::_3D)
 			{
 			{

+ 2 - 1
AnKi/Util/CMakeLists.txt

@@ -16,7 +16,8 @@ set(sources
 	Serializer.cpp
 	Serializer.cpp
 	Xml.cpp
 	Xml.cpp
 	F16.cpp
 	F16.cpp
-	Process.cpp)
+	Process.cpp
+	Thread.cpp)
 
 
 if(LINUX OR ANDROID OR MACOS)
 if(LINUX OR ANDROID OR MACOS)
 	set(sources ${sources}
 	set(sources ${sources}

+ 1 - 0
AnKi/Util/FilesystemPosix.cpp

@@ -249,6 +249,7 @@ Error getApplicationPath(StringAuto& out)
 {
 {
 #if ANKI_OS_ANDROID
 #if ANKI_OS_ANDROID
 	ANKI_ASSERT(0 && "getApplicationPath() doesn't work on Android");
 	ANKI_ASSERT(0 && "getApplicationPath() doesn't work on Android");
+	(void)out;
 #else
 #else
 	DynamicArrayAuto<Char> buff(out.getAllocator(), 1024);
 	DynamicArrayAuto<Char> buff(out.getAllocator(), 1024);
 
 

+ 28 - 24
AnKi/Util/Logger.cpp

@@ -19,7 +19,7 @@
 
 
 namespace anki {
 namespace anki {
 
 
-inline constexpr Array<const char*, U(LoggerMessageType::COUNT)> MSG_TEXT = {"I", "V", "E", "W", "F"};
+inline constexpr Array<const Char*, U(LoggerMessageType::COUNT)> kMessageTypeTxt = {"I", "V", "E", "W", "F"};
 
 
 Logger::Logger()
 Logger::Logger()
 {
 {
@@ -65,8 +65,8 @@ void Logger::removeMessageHandler(void* data, LoggerMessageHandlerCallback callb
 	}
 	}
 }
 }
 
 
-void Logger::write(const char* file, int line, const char* func, const char* subsystem, LoggerMessageType type,
-				   ThreadId tid, const char* msg)
+void Logger::write(const Char* file, int line, const Char* func, const Char* subsystem, LoggerMessageType type,
+				   const Char* threadName, const Char* msg)
 {
 {
 	// Note: m_verbosityEnabled is not accessed in a thread-safe way. It doesn't really matter though
 	// Note: m_verbosityEnabled is not accessed in a thread-safe way. It doesn't really matter though
 	if(type == LoggerMessageType::VERBOSE && !m_verbosityEnabled)
 	if(type == LoggerMessageType::VERBOSE && !m_verbosityEnabled)
@@ -74,10 +74,10 @@ void Logger::write(const char* file, int line, const char* func, const char* sub
 		return;
 		return;
 	}
 	}
 
 
-	const char* baseFile = strrchr(file, (ANKI_OS_WINDOWS) ? '\\' : '/');
+	const Char* baseFile = strrchr(file, (ANKI_OS_WINDOWS) ? '\\' : '/');
 	baseFile = (baseFile) ? baseFile + 1 : file;
 	baseFile = (baseFile) ? baseFile + 1 : file;
 
 
-	LoggerMessageInfo inf = {baseFile, line, func, type, msg, subsystem, tid};
+	LoggerMessageInfo inf = {baseFile, line, func, type, msg, subsystem, threadName};
 
 
 	m_mutex.lock();
 	m_mutex.lock();
 
 
@@ -95,8 +95,8 @@ void Logger::write(const char* file, int line, const char* func, const char* sub
 	}
 	}
 }
 }
 
 
-void Logger::writeFormated(const char* file, int line, const char* func, const char* subsystem, LoggerMessageType type,
-						   ThreadId tid, const char* fmt, ...)
+void Logger::writeFormated(const Char* file, int line, const Char* func, const Char* subsystem, LoggerMessageType type,
+						   const Char* threadName, const Char* fmt, ...)
 {
 {
 	Array<Char, 256> buffer;
 	Array<Char, 256> buffer;
 	va_list args;
 	va_list args;
@@ -110,7 +110,7 @@ void Logger::writeFormated(const char* file, int line, const char* func, const c
 	}
 	}
 	else if(len < I(sizeof(buffer)))
 	else if(len < I(sizeof(buffer)))
 	{
 	{
-		write(file, line, func, subsystem, type, tid, &buffer[0]);
+		write(file, line, func, subsystem, type, threadName, &buffer[0]);
 		va_end(args);
 		va_end(args);
 	}
 	}
 	else
 	else
@@ -121,10 +121,10 @@ void Logger::writeFormated(const char* file, int line, const char* func, const c
 		va_start(args, fmt);
 		va_start(args, fmt);
 
 
 		const PtrSize newSize = len + 1;
 		const PtrSize newSize = len + 1;
-		char* newBuffer = static_cast<char*>(malloc(newSize));
+		Char* newBuffer = static_cast<Char*>(malloc(newSize));
 		len = vsnprintf(newBuffer, newSize, fmt, args);
 		len = vsnprintf(newBuffer, newSize, fmt, args);
 
 
-		write(file, line, func, subsystem, type, tid, newBuffer);
+		write(file, line, func, subsystem, type, threadName, newBuffer);
 
 
 		free(newBuffer);
 		free(newBuffer);
 		va_end(args);
 		va_end(args);
@@ -137,9 +137,9 @@ void Logger::defaultSystemMessageHandler(void*, const LoggerMessageInfo& info)
 	// More info about terminal colors:
 	// More info about terminal colors:
 	// https://stackoverflow.com/questions/4842424/list-of-ansi-color-escape-sequences
 	// https://stackoverflow.com/questions/4842424/list-of-ansi-color-escape-sequences
 	FILE* out = nullptr;
 	FILE* out = nullptr;
-	const char* terminalColor = nullptr;
-	const char* terminalColorBg = nullptr;
-	const char* endTerminalColor = "\033[0m";
+	const Char* terminalColor = nullptr;
+	const Char* terminalColorBg = nullptr;
+	const Char* endTerminalColor = "\033[0m";
 
 
 	switch(info.m_type)
 	switch(info.m_type)
 	{
 	{
@@ -172,7 +172,8 @@ void Logger::defaultSystemMessageHandler(void*, const LoggerMessageInfo& info)
 		ANKI_ASSERT(0);
 		ANKI_ASSERT(0);
 	}
 	}
 
 
-	const char* fmt = "%s[%s][%s][%" PRIx64 "]%s%s %s (%s:%d %s)%s\n";
+	static_assert(Thread::kThreadNameMaxLength == 15, "See file");
+	constexpr const Char* fmt = "%s[%s][%s][%-15s]%s%s %s (%s:%d %s)%s\n";
 	if(!runningFromATerminal())
 	if(!runningFromATerminal())
 	{
 	{
 		terminalColor = "";
 		terminalColor = "";
@@ -180,8 +181,8 @@ void Logger::defaultSystemMessageHandler(void*, const LoggerMessageInfo& info)
 		endTerminalColor = "";
 		endTerminalColor = "";
 	}
 	}
 
 
-	fprintf(out, fmt, terminalColorBg, MSG_TEXT[U(info.m_type)], info.m_subsystem ? info.m_subsystem : "N/A ",
-			info.m_tid, endTerminalColor, terminalColor, info.m_msg, info.m_file, info.m_line, info.m_func,
+	fprintf(out, fmt, terminalColorBg, kMessageTypeTxt[U(info.m_type)], info.m_subsystem ? info.m_subsystem : "N/A ",
+			info.m_threadName, endTerminalColor, terminalColor, info.m_msg, info.m_file, info.m_line, info.m_func,
 			endTerminalColor);
 			endTerminalColor);
 #elif ANKI_OS_WINDOWS
 #elif ANKI_OS_WINDOWS
 	WORD attribs = 0;
 	WORD attribs = 0;
@@ -226,8 +227,10 @@ void Logger::defaultSystemMessageHandler(void*, const LoggerMessageInfo& info)
 		SetConsoleTextAttribute(consoleHandle, attribs);
 		SetConsoleTextAttribute(consoleHandle, attribs);
 
 
 		// Print
 		// Print
-		fprintf(out, "[%s][%s] %s (%s:%d %s)\n", MSG_TEXT[info.m_type], info.m_subsystem ? info.m_subsystem : "N/A ",
-				info.m_msg, info.m_file, info.m_line, info.m_func);
+		static_assert(Thread::kThreadNameMaxLength == 15, "See file");
+		fprintf(out, "[%s][%s][%-15s] %s (%s:%d %s)\n", kMessageTypeTxt[info.m_type],
+				info.m_subsystem ? info.m_subsystem : "N/A ", info.m_threadName, info.m_msg, info.m_file, info.m_line,
+				info.m_func);
 
 
 		// Restore state
 		// Restore state
 		SetConsoleTextAttribute(consoleHandle, savedAttribs);
 		SetConsoleTextAttribute(consoleHandle, savedAttribs);
@@ -254,9 +257,10 @@ void Logger::defaultSystemMessageHandler(void*, const LoggerMessageInfo& info)
 		ANKI_ASSERT(0);
 		ANKI_ASSERT(0);
 	}
 	}
 
 
-	__android_log_print(andMsgType, "AnKi", "[%s][%s] %s (%s:%d %s)\n", MSG_TEXT[info.m_type],
-						info.m_subsystem ? info.m_subsystem : "N/A ", info.m_msg, info.m_file, info.m_line,
-						info.m_func);
+	static_assert(Thread::kThreadNameMaxLength == 15, "See file");
+	__android_log_print(andMsgType, "AnKi", "[%s][%s][%-15s] %s (%s:%d %s)\n", kMessageTypeTxt[info.m_type],
+						info.m_subsystem ? info.m_subsystem : "N/A ", info.m_threadName, info.m_msg, info.m_file,
+						info.m_line, info.m_func);
 #else
 #else
 	FILE* out = NULL;
 	FILE* out = NULL;
 
 
@@ -279,7 +283,7 @@ void Logger::defaultSystemMessageHandler(void*, const LoggerMessageInfo& info)
 		ANKI_ASSERT(0);
 		ANKI_ASSERT(0);
 	}
 	}
 
 
-	fprintf(out, "[%s][%s][%" PRIx64 "] %s (%s:%d %s)\n", MSG_TEXT[info.m_type],
+	fprintf(out, "[%s][%s][%" PRIx64 "] %s (%s:%d %s)\n", kMessageTypeTxt[info.m_type],
 			info.m_subsystem ? info.m_subsystem : "N/A ", info.m_tid, info.m_msg, info.m_file, info.m_line,
 			info.m_subsystem ? info.m_subsystem : "N/A ", info.m_tid, info.m_msg, info.m_file, info.m_line,
 			info.m_func);
 			info.m_func);
 
 
@@ -291,8 +295,8 @@ void Logger::fileMessageHandler(void* pfile, const LoggerMessageInfo& info)
 {
 {
 	File* file = reinterpret_cast<File*>(pfile);
 	File* file = reinterpret_cast<File*>(pfile);
 
 
-	Error err = file->writeTextf("[%s] %s (%s:%d %s)\n", MSG_TEXT[info.m_type], info.m_msg, info.m_file, info.m_line,
-								 info.m_func);
+	Error err = file->writeTextf("[%s] %s (%s:%d %s)\n", kMessageTypeTxt[info.m_type], info.m_msg, info.m_file,
+								 info.m_line, info.m_func);
 
 
 	if(!err)
 	if(!err)
 	{
 	{

+ 10 - 10
AnKi/Util/Logger.h

@@ -34,13 +34,13 @@ enum class LoggerMessageType : U8
 class LoggerMessageInfo
 class LoggerMessageInfo
 {
 {
 public:
 public:
-	const char* m_file;
+	const Char* m_file;
 	I32 m_line;
 	I32 m_line;
-	const char* m_func;
+	const Char* m_func;
 	LoggerMessageType m_type;
 	LoggerMessageType m_type;
-	const char* m_msg;
-	const char* m_subsystem;
-	ThreadId m_tid;
+	const Char* m_msg;
+	const Char* m_subsystem;
+	const Char* m_threadName;
 };
 };
 
 
 /// The message handler callback.
 /// The message handler callback.
@@ -69,13 +69,13 @@ public:
 	void addFileMessageHandler(File* file);
 	void addFileMessageHandler(File* file);
 
 
 	/// Send a message.
 	/// Send a message.
-	void write(const char* file, int line, const char* func, const char* subsystem, LoggerMessageType type,
-			   ThreadId tid, const char* msg);
+	void write(const Char* file, int line, const Char* func, const Char* subsystem, LoggerMessageType type,
+			   const Char* threadName, const Char* msg);
 
 
 	/// Send a formated message.
 	/// Send a formated message.
 	ANKI_CHECK_FORMAT(7, 8)
 	ANKI_CHECK_FORMAT(7, 8)
-	void writeFormated(const char* file, int line, const char* func, const char* subsystem, LoggerMessageType type,
-					   ThreadId tid, const char* fmt, ...);
+	void writeFormated(const Char* file, int line, const Char* func, const Char* subsystem, LoggerMessageType type,
+					   const Char* threadName, const Char* fmt, ...);
 
 
 	/// Enable or disable logger verbosity.
 	/// Enable or disable logger verbosity.
 	void enableVerbosity(Bool enable)
 	void enableVerbosity(Bool enable)
@@ -118,7 +118,7 @@ using LoggerSingleton = Singleton<Logger>;
 	do \
 	do \
 	{ \
 	{ \
 		LoggerSingleton::get().writeFormated(ANKI_FILE, __LINE__, ANKI_FUNC, subsystem_, LoggerMessageType::t, \
 		LoggerSingleton::get().writeFormated(ANKI_FILE, __LINE__, ANKI_FUNC, subsystem_, LoggerMessageType::t, \
-											 Thread::getCurrentThreadId(), __VA_ARGS__); \
+											 Thread::getCurrentThreadName(), __VA_ARGS__); \
 	} while(false);
 	} while(false);
 /// @}
 /// @}
 
 

+ 6 - 0
AnKi/Util/System.cpp

@@ -6,6 +6,7 @@
 #include <AnKi/Util/System.h>
 #include <AnKi/Util/System.h>
 #include <AnKi/Util/Logger.h>
 #include <AnKi/Util/Logger.h>
 #include <AnKi/Util/StringList.h>
 #include <AnKi/Util/StringList.h>
+#include <AnKi/Util/Thread.h>
 #include <cstdio>
 #include <cstdio>
 
 
 #if ANKI_POSIX
 #if ANKI_POSIX
@@ -211,4 +212,9 @@ void cleanupGetAndroidCommandLineArguments(void* ptr)
 }
 }
 #endif
 #endif
 
 
+void preMainInit()
+{
+	Thread::setCurrentThreadName("Main");
+}
+
 } // end namespace anki
 } // end namespace anki

+ 3 - 0
AnKi/Util/System.h

@@ -49,6 +49,9 @@ std::tm getLocalTime();
 /// Takes the return value of getAndroidCommandLineArguments() for cleanup.
 /// Takes the return value of getAndroidCommandLineArguments() for cleanup.
 void cleanupGetAndroidCommandLineArguments(void* ptr);
 void cleanupGetAndroidCommandLineArguments(void* ptr);
 #endif
 #endif
+
+/// Some common code to be called before main.
+void preMainInit();
 /// @}
 /// @}
 
 
 } // end namespace anki
 } // end namespace anki

+ 39 - 0
AnKi/Util/Thread.cpp

@@ -0,0 +1,39 @@
+// Copyright (C) 2009-2022, Panagiotis Christopoulos Charitos and contributors.
+// All rights reserved.
+// Code licensed under the BSD License.
+// http://www.anki3d.org/LICENSE
+
+#include <AnKi/Util/Thread.h>
+
+namespace anki {
+
+thread_local Array<Char, Thread::kThreadNameMaxLength + 1> Thread::m_nameTls = {};
+
+Thread::Thread(const Char* name)
+{
+	if(name)
+	{
+		PtrSize len = strlen(name);
+		len = min<PtrSize>(len, kThreadNameMaxLength);
+		memcpy(&m_name[0], &name[0], len);
+		m_name[len] = '\0';
+	}
+	else
+	{
+		memcpy(&m_name[0], kDefaultThreadName, strlen(kDefaultThreadName) + 1);
+	}
+}
+
+const Char* Thread::getCurrentThreadName()
+{
+	if(m_nameTls[0] == '\0')
+	{
+		return kDefaultThreadName;
+	}
+	else
+	{
+		return &m_nameTls[0];
+	}
+}
+
+} // end namespace anki

+ 9 - 19
AnKi/Util/Thread.h

@@ -22,9 +22,6 @@
 
 
 namespace anki {
 namespace anki {
 
 
-// Forward
-class CString;
-
 /// @addtogroup util_thread
 /// @addtogroup util_thread
 /// @{
 /// @{
 
 
@@ -53,22 +50,11 @@ using ThreadCallback = Error (*)(ThreadCallbackInfo&);
 class Thread
 class Thread
 {
 {
 public:
 public:
+	static constexpr U32 kThreadNameMaxLength = 15;
+
 	/// Create a thread with or without a name
 	/// Create a thread with or without a name
 	/// @param[in] name The name of the new thread. Can be nullptr.
 	/// @param[in] name The name of the new thread. Can be nullptr.
-	Thread(const char* name)
-	{
-		if(name)
-		{
-			PtrSize len = std::strlen(name);
-			len = std::min<PtrSize>(len, sizeof(m_name) - 1);
-			memcpy(&m_name[0], &name[0], len);
-			m_name[len] = '\0';
-		}
-		else
-		{
-			m_name[0] = '\0';
-		}
-	}
+	Thread(const Char* name);
 
 
 	Thread(const Thread&) = delete;
 	Thread(const Thread&) = delete;
 
 
@@ -106,7 +92,9 @@ public:
 	void pinToCores(const ThreadCoreAffinityMask& coreAffintyMask);
 	void pinToCores(const ThreadCoreAffinityMask& coreAffintyMask);
 
 
 	/// Name the current thread.
 	/// Name the current thread.
-	static void setNameOfCurrentThread(const CString& name);
+	static void setCurrentThreadName(const Char* name);
+
+	static const Char* getCurrentThreadName();
 
 
 private:
 private:
 	/// The system native type.
 	/// The system native type.
@@ -117,7 +105,9 @@ private:
 	Error m_returnCode = Error::NONE;
 	Error m_returnCode = Error::NONE;
 #endif
 #endif
 	void* m_userData = nullptr; ///< The user date to pass to the callback.
 	void* m_userData = nullptr; ///< The user date to pass to the callback.
-	Array<char, 32> m_name; ///< The name of the thread.
+	Array<Char, kThreadNameMaxLength + 1> m_name = {}; ///< The name of the thread.
+	static thread_local Array<Char, kThreadNameMaxLength + 1> m_nameTls;
+	static constexpr const Char* kDefaultThreadName = "AnKiUnnamed"; ///< the name of an unnamed thread.
 	ThreadCallback m_callback = nullptr; ///< The callback.
 	ThreadCallback m_callback = nullptr; ///< The callback.
 
 
 #if ANKI_EXTRA_CHECKS
 #if ANKI_EXTRA_CHECKS

+ 12 - 4
AnKi/Util/ThreadHive.cpp

@@ -4,11 +4,14 @@
 // http://www.anki3d.org/LICENSE
 // http://www.anki3d.org/LICENSE
 
 
 #include <AnKi/Util/ThreadHive.h>
 #include <AnKi/Util/ThreadHive.h>
+#include <AnKi/Util/String.h>
 #include <cstring>
 #include <cstring>
 #include <cstdio>
 #include <cstdio>
 
 
 namespace anki {
 namespace anki {
 
 
+Atomic<U32> ThreadHive::m_uuid = {0};
+
 #define ANKI_ENABLE_HIVE_DEBUG_PRINT 0
 #define ANKI_ENABLE_HIVE_DEBUG_PRINT 0
 
 
 #if ANKI_ENABLE_HIVE_DEBUG_PRINT
 #if ANKI_ENABLE_HIVE_DEBUG_PRINT
@@ -25,9 +28,9 @@ public:
 	ThreadHive* m_hive;
 	ThreadHive* m_hive;
 
 
 	/// Constructor
 	/// Constructor
-	Thread(U32 id, ThreadHive* hive, Bool pinToCore)
+	Thread(U32 id, ThreadHive* hive, Bool pinToCore, CString threadName)
 		: m_id(id)
 		: m_id(id)
-		, m_thread("anki_threadhive")
+		, m_thread(threadName.cstr())
 		, m_hive(hive)
 		, m_hive(hive)
 	{
 	{
 		ANKI_ASSERT(hive);
 		ANKI_ASSERT(hive);
@@ -60,13 +63,18 @@ public:
 ThreadHive::ThreadHive(U32 threadCount, GenericMemoryPoolAllocator<U8> alloc, Bool pinToCores)
 ThreadHive::ThreadHive(U32 threadCount, GenericMemoryPoolAllocator<U8> alloc, Bool pinToCores)
 	: m_slowAlloc(alloc)
 	: m_slowAlloc(alloc)
 	, m_alloc(alloc.getMemoryPool().getAllocationCallback(), alloc.getMemoryPool().getAllocationCallbackUserData(),
 	, m_alloc(alloc.getMemoryPool().getAllocationCallback(), alloc.getMemoryPool().getAllocationCallbackUserData(),
-			  1024 * 4)
+			  4_KB)
 	, m_threadCount(threadCount)
 	, m_threadCount(threadCount)
 {
 {
 	m_threads = reinterpret_cast<Thread*>(m_slowAlloc.allocate(sizeof(Thread) * threadCount));
 	m_threads = reinterpret_cast<Thread*>(m_slowAlloc.allocate(sizeof(Thread) * threadCount));
+
+	const U32 uuid = m_uuid.fetchAdd(1);
+
 	for(U32 i = 0; i < threadCount; ++i)
 	for(U32 i = 0; i < threadCount; ++i)
 	{
 	{
-		::new(&m_threads[i]) Thread(i, this, pinToCores);
+		Array<Char, 32> threadName;
+		snprintf(&threadName[0], threadName.getSize(), "Hive#%u/#%u", uuid, i);
+		::new(&m_threads[i]) Thread(i, this, pinToCores, &threadName[0]);
 	}
 	}
 }
 }
 
 

+ 2 - 0
AnKi/Util/ThreadHive.h

@@ -151,6 +151,8 @@ private:
 	Mutex m_mtx;
 	Mutex m_mtx;
 	ConditionVariable m_cvar;
 	ConditionVariable m_cvar;
 
 
+	static Atomic<U32> m_uuid;
+
 	void threadRun(U32 threadId);
 	void threadRun(U32 threadId);
 
 
 	/// Wait for more tasks.
 	/// Wait for more tasks.

+ 7 - 4
AnKi/Util/ThreadPool.cpp

@@ -5,6 +5,7 @@
 
 
 #include <AnKi/Util/ThreadPool.h>
 #include <AnKi/Util/ThreadPool.h>
 #include <AnKi/Util/Logger.h>
 #include <AnKi/Util/Logger.h>
+#include <AnKi/Util/String.h>
 #include <cstdlib>
 #include <cstdlib>
 #include <new>
 #include <new>
 
 
@@ -23,9 +24,9 @@ public:
 	Bool m_quit = false;
 	Bool m_quit = false;
 
 
 	/// Constructor
 	/// Constructor
-	ThreadPoolThread(U32 id, ThreadPool* threadpool, Bool pinToCore)
+	ThreadPoolThread(U32 id, ThreadPool* threadpool, Bool pinToCore, CString threadName)
 		: m_id(id)
 		: m_id(id)
-		, m_thread("anki_threadpool")
+		, m_thread(threadName.cstr())
 		, m_task(nullptr)
 		, m_task(nullptr)
 		, m_threadpool(threadpool)
 		, m_threadpool(threadpool)
 	{
 	{
@@ -80,9 +81,11 @@ ThreadPool::ThreadPool(U32 threadCount, Bool pinToCores)
 		ANKI_UTIL_LOGF("Out of memory");
 		ANKI_UTIL_LOGF("Out of memory");
 	}
 	}
 
 
-	while(threadCount-- != 0)
+	for(U32 i = 0; i < threadCount; ++i)
 	{
 	{
-		::new(&m_threads[threadCount]) detail::ThreadPoolThread(threadCount, this, pinToCores);
+		Array<Char, 64> threadName;
+		snprintf(&threadName[0], threadName.getSize(), "ThreadPool#%u", i);
+		::new(&m_threads[i]) detail::ThreadPoolThread(i, this, pinToCores, &threadName[0]);
 	}
 	}
 }
 }
 
 

+ 15 - 6
AnKi/Util/ThreadPosix.cpp

@@ -27,10 +27,7 @@ void Thread::start(void* userData, ThreadCallback callback, const ThreadCoreAffi
 		Thread* thread = static_cast<Thread*>(ud);
 		Thread* thread = static_cast<Thread*>(ud);
 
 
 		// Set thread name
 		// Set thread name
-		if(thread->m_name[0] != '\0')
-		{
-			setNameOfCurrentThread(&thread->m_name[0]);
-		}
+		setCurrentThreadName(&thread->m_name[0]);
 
 
 		// Call the callback
 		// Call the callback
 		ThreadCallbackInfo info;
 		ThreadCallbackInfo info;
@@ -96,9 +93,21 @@ void Thread::pinToCores(const ThreadCoreAffinityMask& coreAffintyMask)
 	}
 	}
 }
 }
 
 
-void Thread::setNameOfCurrentThread(const CString& name)
+void Thread::setCurrentThreadName(const Char* name)
 {
 {
-	pthread_setname_np(pthread_self(), name.cstr());
+	// Copy the string first and limit its size
+	const PtrSize len = min<PtrSize>(strlen(name), kThreadNameMaxLength);
+	if(len > 0)
+	{
+		memcpy(&m_nameTls[0], name, len);
+		m_nameTls[len] = '\0';
+	}
+	else
+	{
+		memcpy(&m_nameTls[0], kDefaultThreadName, strlen(kDefaultThreadName) + 1);
+	}
+
+	pthread_setname_np(pthread_self(), &m_nameTls[0]);
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 24 - 7
AnKi/Util/ThreadWindows.cpp

@@ -16,11 +16,7 @@ DWORD ANKI_WINAPI Thread::threadCallback(LPVOID ud)
 	ANKI_ASSERT(ud != nullptr);
 	ANKI_ASSERT(ud != nullptr);
 	Thread* thread = reinterpret_cast<Thread*>(ud);
 	Thread* thread = reinterpret_cast<Thread*>(ud);
 
 
-	// Set thread name
-	if(thread->m_name[0] != '\0')
-	{
-		// TODO
-	}
+	setCurrentThreadName(&thread->m_name[0]);
 
 
 	// Call the callback
 	// Call the callback
 	ThreadCallbackInfo info;
 	ThreadCallbackInfo info;
@@ -104,9 +100,30 @@ void Thread::pinToCores(const ThreadCoreAffinityMask& coreAffintyMask)
 	}
 	}
 }
 }
 
 
-void Thread::setNameOfCurrentThread(const CString& name)
+void Thread::setCurrentThreadName(const Char* name)
 {
 {
-	// TODO
+	// Copy the string first and limit its size
+	const PtrSize len = min<PtrSize>(strlen(name), kThreadNameMaxLength);
+	if(len > 0)
+	{
+		memcpy(&m_nameTls[0], name, len);
+		m_nameTls[len] = '\0';
+	}
+	else
+	{
+		memcpy(&m_nameTls[0], kDefaultThreadName, strlen(kDefaultThreadName) + 1);
+	}
+
+	// Convert to wstring
+	Array<WChar, kThreadNameMaxLength + 1> wstring;
+	mbstowcs(&wstring[0], &m_nameTls[0], wstring.getSize());
+
+	// Set it
+	const HRESULT r = SetThreadDescription(GetCurrentThread(), &wstring[0]);
+	if(r < 0)
+	{
+		ANKI_UTIL_LOGE("SetThreadDescription() failed. Ignoring error");
+	}
 }
 }
 
 
 } // end namespace anki
 } // end namespace anki

+ 6 - 0
AnKi/Util/Win32Minimal.h

@@ -47,6 +47,9 @@ typedef const CHAR* PCZZSTR;
 typedef CHAR* LPSTR;
 typedef CHAR* LPSTR;
 typedef struct HINSTANCE__* HINSTANCE;
 typedef struct HINSTANCE__* HINSTANCE;
 typedef HINSTANCE HMODULE;
 typedef HINSTANCE HMODULE;
+typedef wchar_t WCHAR;
+typedef const WCHAR* PCWSTR;
+typedef WCHAR *NWPSTR, *LPWSTR, *PWSTR;
 ANKI_DECLARE_HANDLE(HWND);
 ANKI_DECLARE_HANDLE(HWND);
 
 
 typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
 typedef struct _SECURITY_ATTRIBUTES SECURITY_ATTRIBUTES, *LPSECURITY_ATTRIBUTES;
@@ -73,6 +76,9 @@ ANKI_WINBASEAPI DWORD_PTR ANKI_WINAPI SetThreadAffinityMask(HANDLE hThread, DWOR
 ANKI_WINBASEAPI DWORD ANKI_WINAPI WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
 ANKI_WINBASEAPI DWORD ANKI_WINAPI WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds);
 ANKI_WINBASEAPI BOOL ANKI_WINAPI CloseHandle(HANDLE hObject);
 ANKI_WINBASEAPI BOOL ANKI_WINAPI CloseHandle(HANDLE hObject);
 ANKI_WINBASEAPI DWORD ANKI_WINAPI GetCurrentThreadId(VOID);
 ANKI_WINBASEAPI DWORD ANKI_WINAPI GetCurrentThreadId(VOID);
+ANKI_WINBASEAPI HRESULT ANKI_WINAPI SetThreadDescription(HANDLE hThread, PCWSTR lpThreadDescription);
+ANKI_WINBASEAPI HRESULT ANKI_WINAPI GetThreadDescription(HANDLE hThread, PWSTR* ppszThreadDescription);
+ANKI_WINBASEAPI HANDLE ANKI_WINAPI GetCurrentThread();
 
 
 ANKI_WINBASEAPI VOID ANKI_WINAPI InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
 ANKI_WINBASEAPI VOID ANKI_WINAPI InitializeCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
 ANKI_WINBASEAPI VOID ANKI_WINAPI EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);
 ANKI_WINBASEAPI VOID ANKI_WINAPI EnterCriticalSection(LPCRITICAL_SECTION lpCriticalSection);

+ 2 - 1
Tools/GltfImporter/Main.cpp

@@ -184,7 +184,8 @@ static Error parseCommandLineArgs(int argc, char** argv, CmdLineArgs& info)
 	return Error::NONE;
 	return Error::NONE;
 }
 }
 
 
-int main(int argc, char** argv)
+ANKI_MAIN_FUNCTION(myMain)
+int myMain(int argc, char** argv)
 {
 {
 	CmdLineArgs cmdArgs;
 	CmdLineArgs cmdArgs;
 	if(parseCommandLineArgs(argc, argv, cmdArgs))
 	if(parseCommandLineArgs(argc, argv, cmdArgs))