From f58f3803503fe19e8153d1634bbcaf32fe45692a Mon Sep 17 00:00:00 2001
From: Tobias Frisch <tfrisch@uni-koblenz.de>
Date: Fri, 11 Aug 2023 15:13:06 +0200
Subject: [PATCH] Add log level for printing durations

Signed-off-by: Tobias Frisch <tfrisch@uni-koblenz.de>
---
 include/vkcv/Logger.hpp             | 20 +++++++++++++++++++
 projects/indirect_draw/src/main.cpp | 30 +++++++++++++++++++++++++++++
 2 files changed, 50 insertions(+)

diff --git a/include/vkcv/Logger.hpp b/include/vkcv/Logger.hpp
index 8a366b26..57e3a841 100644
--- a/include/vkcv/Logger.hpp
+++ b/include/vkcv/Logger.hpp
@@ -5,8 +5,10 @@
  * @brief Logging macro function to print line of code specific information.
  */
 
+#include <bits/chrono.h>
 #include <cstdio>
 #include <exception>
+#include <chrono>
 
 namespace vkcv {
 
@@ -14,6 +16,7 @@ namespace vkcv {
 	 * @brief Enum class to specify the level of logging.
 	 */
 	enum class LogLevel {
+		TIME,
 		RAW_INFO,
 		INFO,
 		WARNING,
@@ -29,6 +32,7 @@ namespace vkcv {
 	 */
 	constexpr auto getLogOutput(LogLevel level) {
 		switch (level) {
+		case LogLevel::TIME:
 		case LogLevel::RAW_INFO:
 		case LogLevel::INFO:
 			return stdout;
@@ -46,6 +50,8 @@ namespace vkcv {
 	 */
 	constexpr const char* getLogName(LogLevel level) {
 		switch (level) {
+		case LogLevel::TIME:
+			return "TIME";
 		case LogLevel::RAW_INFO:
 		case LogLevel::INFO:
 			return "INFO";
@@ -58,6 +64,16 @@ namespace vkcv {
 		}
 	}
 
+	inline unsigned long getLogTime() {
+		const auto time_point = std::chrono::high_resolution_clock::now();
+		static auto last_time_point = time_point;
+
+		const auto duration = (time_point - last_time_point);
+		last_time_point = time_point;
+
+		return std::chrono::duration_cast<std::chrono::milliseconds>(duration).count();
+	}
+
 #ifndef NDEBUG
 #ifndef VKCV_DEBUG_MESSAGE_LEN
 #define VKCV_DEBUG_MESSAGE_LEN 1024
@@ -78,6 +94,10 @@ namespace vkcv {
 		char output_message [VKCV_DEBUG_MESSAGE_LEN];                                \
 		snprintf(output_message, VKCV_DEBUG_MESSAGE_LEN, __VA_ARGS__);               \
 		auto output = getLogOutput(level);                                           \
+		if (level == vkcv::LogLevel::TIME) {                                         \
+			fprintf(output, "[%s]: %s (%lums)\n", vkcv::getLogName(level),           \
+					output_message, vkcv::getLogTime());                             \
+		} else                                                                       \
 		if (level != vkcv::LogLevel::RAW_INFO) {                                     \
 			fprintf(output, "[%s]: %s [%s, line %d: %s]\n", vkcv::getLogName(level), \
 					output_message, __FILE__, __LINE__, __PRETTY_FUNCTION__);        \
diff --git a/projects/indirect_draw/src/main.cpp b/projects/indirect_draw/src/main.cpp
index 6aa0f362..424f2e07 100644
--- a/projects/indirect_draw/src/main.cpp
+++ b/projects/indirect_draw/src/main.cpp
@@ -270,6 +270,8 @@ void compileMeshForIndirectDraw(vkcv::Core &core,
 int main(int argc, const char** argv) {
 	const std::string applicationName = "Indirect draw";
 
+    vkcv_log(vkcv::LogLevel::TIME, "Startup");
+
 	vkcv::Features features;
 	features.requireExtension(VK_KHR_SWAPCHAIN_EXTENSION_NAME);
     features.requireFeature([](vk::PhysicalDeviceFeatures &features){
@@ -311,6 +313,8 @@ int main(int argc, const char** argv) {
 			}
     );
 
+    vkcv_log(vkcv::LogLevel::TIME, "Features configured");
+
 	vkcv::Core core = vkcv::Core::create(
 		applicationName,
 		VK_MAKE_VERSION(0, 0, 1),
@@ -318,15 +322,23 @@ int main(int argc, const char** argv) {
 		features
 	);
 
+    vkcv_log(vkcv::LogLevel::TIME, "Core created");
+
 	vkcv::WindowHandle windowHandle = core.createWindow(applicationName,800,600,true);
 	vkcv::Window& window = core.getWindow(windowHandle);
 
+    vkcv_log(vkcv::LogLevel::TIME, "Window created");
+
     vkcv::gui::GUI gui (core, windowHandle);
 
+    vkcv_log(vkcv::LogLevel::TIME, "GUI initialized");
+
     vkcv::asset::Scene asset_scene;
 	const char* path = argc > 1 ? argv[1] : "resources/Sponza/Sponza.gltf";
 	int result = vkcv::asset::loadScene(path, asset_scene);
 
+    vkcv_log(vkcv::LogLevel::TIME, "Scene loaded");
+
 	if (result == 1) {
 		std::cout << "Loading Sponza successful!" << std::endl;
 	} else {
@@ -351,6 +363,7 @@ int main(int argc, const char** argv) {
 		return EXIT_FAILURE;
 	}
 
+    vkcv_log(vkcv::LogLevel::TIME, "Scene verified");
 
 	vkcv::ShaderProgram sponzaProgram;
 	vkcv::shader::GLSLCompiler compiler;
@@ -364,12 +377,16 @@ int main(int argc, const char** argv) {
         { vkcv::ShaderStage::COMPUTE, std::filesystem::path("resources/shaders/culling.comp") },
     }, nullptr);
 
+    vkcv_log(vkcv::LogLevel::TIME, "Shaders compiled");
+
     // vertex layout for the pipeline. (assumed to be) used by all sponza meshes.
     const std::vector<vkcv::VertexAttachment> vertexAttachments = sponzaProgram.getVertexAttachments();
 	const vkcv::VertexLayout sponzaVertexLayout {
 		{ vkcv::createVertexBinding(0, { vertexAttachments }) }
 	};
 
+    vkcv_log(vkcv::LogLevel::TIME, "Vertex layout configured");
+
     std::vector<uint8_t> compiledVertexBuffer; // IGNORED, since the vertex buffer is not interleaved!
 
     std::vector<uint8_t> compiledIndexBuffer;
@@ -382,12 +399,16 @@ int main(int argc, const char** argv) {
                                compiledIndexBuffer,
                                compiledMaterial,
                                indexedIndirectCommands);
+    
+    vkcv_log(vkcv::LogLevel::TIME, "Mesh compiled");
 
 	std::vector<std::vector<Vertex>> interleavedVertices;
     std::vector<glm::vec4> compiledBoundingBoxBuffer;
     interleaveScene(asset_scene,
                     interleavedVertices,
                     compiledBoundingBoxBuffer);
+    
+    vkcv_log(vkcv::LogLevel::TIME, "Scene interleaved");
 
 	std::vector<Vertex> compiledInterleavedVertexBuffer;
 	for(auto& vertexGroup : interleavedVertices )
@@ -435,6 +456,8 @@ int main(int argc, const char** argv) {
 			);
 	modelBuffer.fill(modelMatrix);
 
+    vkcv_log(vkcv::LogLevel::TIME, "Buffers filled");
+
 	const std::vector<vkcv::VertexBufferBinding> vertexBufferBindings = {
 			vkcv::vertexBufferBinding(vkCompiledVertexBuffer)
 	};
@@ -464,6 +487,8 @@ int main(int argc, const char** argv) {
 	setWrites.writeStorageBuffer(1, modelBuffer.getHandle());
     core.writeDescriptorSet(descriptorSet, setWrites);
 
+    vkcv_log(vkcv::LogLevel::TIME, "DescriptorSets written");
+
 	vkcv::GraphicsPipelineHandle sponzaPipelineHandle = core.createGraphicsPipeline(
 			vkcv::GraphicsPipelineConfig(
 					sponzaProgram,
@@ -478,6 +503,8 @@ int main(int argc, const char** argv) {
 		return EXIT_FAILURE;
 	}
 
+    vkcv_log(vkcv::LogLevel::TIME, "Graphics pipeline created");
+
     vkcv::DescriptorBindings cullingBindings = cullingProgram.getReflectedDescriptors().at(0);
     vkcv::DescriptorSetLayoutHandle cullingSetLayout = core.createDescriptorSetLayout(cullingBindings);
     vkcv::DescriptorSetHandle cullingDescSet = core.createDescriptorSet(cullingSetLayout);
@@ -493,6 +520,7 @@ int main(int argc, const char** argv) {
     cullingWrites.writeUniformBuffer(0, cameraPlaneBuffer.getHandle());
     core.writeDescriptorSet(cullingDescSet, cullingWrites);
 
+    vkcv_log(vkcv::LogLevel::TIME, "Culling descriptor set written");
 
     const vkcv::ComputePipelineConfig computeCullingConfig {
         cullingProgram,
@@ -504,6 +532,8 @@ int main(int argc, const char** argv) {
         return EXIT_FAILURE;
     }
 
+    vkcv_log(vkcv::LogLevel::TIME, "Compute pipeline created");
+
     vkcv::camera::CameraManager cameraManager (window);
     auto camHandle = cameraManager.addCamera(vkcv::camera::ControllerType::PILOT);
 	
-- 
GitLab