diff --git a/config/Sources.cmake b/config/Sources.cmake index 7632d7d8f788b53a22ce1a5b513f469a83b00f4d..4f673e00d1e42e733534480d6085affd651a8c04 100644 --- a/config/Sources.cmake +++ b/config/Sources.cmake @@ -29,6 +29,8 @@ set(vkcv_sources ${vkcv_source}/vkcv/ImageManager.hpp ${vkcv_source}/vkcv/ImageManager.cpp + + ${vkcv_include}/vkcv/Logger.hpp ${vkcv_include}/vkcv/SwapChain.hpp ${vkcv_source}/vkcv/SwapChain.cpp diff --git a/include/vkcv/Logger.hpp b/include/vkcv/Logger.hpp new file mode 100644 index 0000000000000000000000000000000000000000..bc8758f195fe35a5c16e181d56ea9ac2abdb2b92 --- /dev/null +++ b/include/vkcv/Logger.hpp @@ -0,0 +1,60 @@ +#pragma once + +#include <iostream> + +namespace vkcv { + + enum class LogLevel { + INFO, + WARNING, + ERROR + }; + + constexpr auto getLogOutput(LogLevel level) { + switch (level) { + case LogLevel::INFO: + return stdout; + default: + return stderr; + } + } + + constexpr const char* getLogName(LogLevel level) { + switch (level) { + case LogLevel::INFO: + return "INFO"; + case LogLevel::WARNING: + return "WARNING"; + case LogLevel::ERROR: + return "ERROR"; + default: + return "UNKNOWN"; + } + } + +#ifndef NDEBUG + +#define vkcv_log(level, ...) { \ + char output_message [1024]; \ + \ + sprintf( \ + output_message, \ + __VA_ARGS__ \ + ); \ + \ + std::fprintf( \ + getLogOutput(level), \ + "[%s]: %s [%s, line %d: %s]\n", \ + vkcv::getLogName(level), \ + output_message, \ + __FILE__, \ + __LINE__, \ + __PRETTY_FUNCTION__ \ + ); \ +} + +#else +#define vkcv_log(level, ...) {} +#endif + +} diff --git a/modules/asset_loader/src/vkcv/asset/asset_loader.cpp b/modules/asset_loader/src/vkcv/asset/asset_loader.cpp index e660b442d0b9a0208f95c9d753ef19e926bcac44..2f84bcd548b17af6d8162078969ae153e33c71b6 100644 --- a/modules/asset_loader/src/vkcv/asset/asset_loader.cpp +++ b/modules/asset_loader/src/vkcv/asset/asset_loader.cpp @@ -7,6 +7,8 @@ #define STBI_ONLY_JPEG #include <stb_image.h> +#include <vkcv/Logger.hpp> + namespace vkcv::asset { /** @@ -39,11 +41,12 @@ uint8_t convertTypeToInt(const fx::gltf::Accessor::Type type) { * @param path path to file that is responsible for error */ void print_what (const std::exception& e, const std::string &path) { - fprintf(stderr, "ERROR loading file %s: %s\n", path.c_str(), e.what()); + vkcv_log(vkcv::LogLevel::ERROR, "Loading file %s: %s", + path.c_str(), e.what()); + try { std::rethrow_if_nested(e); } catch (const std::exception& nested) { - std::cerr << "nested: "; print_what(nested, path); } } @@ -121,7 +124,7 @@ int loadMesh(const std::string &path, Mesh &mesh) { const size_t off = indexBufferView.byteOffset; const void *const ptr = ((char*)indexBuffer.data.data()) + off; if (!memcpy(indexBufferData.data(), ptr, indexBufferView.byteLength)) { - std::cerr << "ERROR copying index buffer data.\n"; + vkcv_log(vkcv::LogLevel::ERROR, "Copying index buffer data"); return 0; } } @@ -136,7 +139,7 @@ int loadMesh(const std::string &path, Mesh &mesh) { const size_t off = 0; const void *const ptr = ((char*)vertexBuffer.data.data()) + off; if (!memcpy(vertexBufferData.data(), ptr, vertexBuffer.byteLength)) { - std::cerr << "ERROR copying vertex buffer data.\n"; + vkcv_log(vkcv::LogLevel::ERROR, "Copying vertex buffer data"); return 0; } } @@ -150,9 +153,8 @@ int loadMesh(const std::string &path, Mesh &mesh) { case fx::gltf::Accessor::ComponentType::UnsignedInt: indexType = UINT32; break; default: - std::cerr << "ERROR: Index type not supported: " << - static_cast<uint16_t>(indexAccessor.componentType) << - std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Index type (%u) not supported", + static_cast<uint16_t>(indexAccessor.componentType)); return 0; } diff --git a/src/vkcv/CommandResources.cpp b/src/vkcv/CommandResources.cpp index 71c990c3c222f2318c2f5744ff6295f667d9e6f8..5efb49595394da534ce751b49f39fe8219be0496 100644 --- a/src/vkcv/CommandResources.cpp +++ b/src/vkcv/CommandResources.cpp @@ -1,6 +1,7 @@ #include "vkcv/CommandResources.hpp" #include <iostream> +#include "vkcv/Logger.hpp" namespace vkcv { @@ -62,7 +63,7 @@ namespace vkcv { return queueManager.getPresentQueue(); } else { - std::cerr << "getQueueForSubmit error: unknown queue type" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Unknown queue type"); return queueManager.getGraphicsQueues().front(); // graphics is the most general queue } } diff --git a/src/vkcv/CommandStreamManager.cpp b/src/vkcv/CommandStreamManager.cpp index 9d0a236a4eaa5a166be77d143370a018b9ea7e73..481e44c129c07b9a66f3c1e0cd2bffbebac2f55b 100644 --- a/src/vkcv/CommandStreamManager.cpp +++ b/src/vkcv/CommandStreamManager.cpp @@ -1,6 +1,8 @@ #include "vkcv/CommandStreamManager.hpp" #include "vkcv/Core.hpp" +#include "vkcv/Logger.hpp" + namespace vkcv { CommandStreamManager::CommandStreamManager() noexcept : m_core(nullptr){} @@ -14,7 +16,7 @@ namespace vkcv { void CommandStreamManager::init(Core* core) { if (!core) { - std::cerr << "Error: CommandStreamManager::init requires valid core pointer" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Requires valid core pointer"); } m_core = core; } @@ -57,7 +59,7 @@ namespace vkcv { const size_t id = handle.getId(); if (id >= m_commandStreams.size()) { - std::cerr << "Error: CommandStreamManager::recordCommandsToStream requires valid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Requires valid handle"); return; } @@ -71,7 +73,7 @@ namespace vkcv { const size_t id = handle.getId(); if (id >= m_commandStreams.size()) { - std::cerr << "Error: CommandStreamManager::addFinishCallbackToStream requires valid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Requires valid handle"); return; } @@ -86,7 +88,7 @@ namespace vkcv { const size_t id = handle.getId(); if (id >= m_commandStreams.size()) { - std::cerr << "Error: CommandStreamManager::submitCommandStreamSynchronous requires valid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Requires valid handle"); return; } CommandStream& stream = m_commandStreams[id]; @@ -111,7 +113,7 @@ namespace vkcv { vk::CommandBuffer CommandStreamManager::getStreamCommandBuffer(const CommandStreamHandle handle) { const size_t id = handle.getId(); if (id >= m_commandStreams.size()) { - std::cerr << "Error: CommandStreamManager::submitCommandStreamSynchronous requires valid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Requires valid handle"); return nullptr; } return m_commandStreams[id].cmdBuffer; diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp index 9ed83d2a224119bd20fcfc81c5720b425de06bb6..bff4ed84d0c98b736e13ee103eb1c030ef65ba8b 100644 --- a/src/vkcv/Core.cpp +++ b/src/vkcv/Core.cpp @@ -16,6 +16,8 @@ #include "ImageLayoutTransitions.hpp" #include "vkcv/CommandStreamManager.hpp" +#include "vkcv/Logger.hpp" + namespace vkcv { @@ -125,7 +127,7 @@ namespace vkcv } if (result != vk::Result::eSuccess) { - std::cerr << vk::to_string(result) << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "%s", vk::to_string(result).c_str()); return Result::ERROR; } @@ -149,7 +151,7 @@ namespace vkcv } if (acquireSwapchainImage() != Result::SUCCESS) { - std::cerr << "Acquire failed!" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Acquire failed"); m_currentSwapchainImageIndex = std::numeric_limits<uint32_t>::max(); } @@ -234,7 +236,7 @@ namespace vkcv 1); if(m_Context.m_Device.createFramebuffer(&createInfo, nullptr, &framebuffer) != vk::Result::eSuccess) { - std::cout << "FAILED TO CREATE TEMPORARY FRAMEBUFFER!" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Failed to create temporary framebuffer"); return; } @@ -325,7 +327,7 @@ namespace vkcv } if (result != vk::Result::eSuccess) { - std::cout << "Error: swapchain present failed... " << vk::to_string(result) << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Swapchain present failed (%s)", vk::to_string(result).c_str()); } } diff --git a/src/vkcv/DescriptorManager.cpp b/src/vkcv/DescriptorManager.cpp index 99e9928d21ad7e501634c93b59694d3c5faeaf6c..c0fb34ac3f75ecea5db6c36a65f5d97739bccb20 100644 --- a/src/vkcv/DescriptorManager.cpp +++ b/src/vkcv/DescriptorManager.cpp @@ -1,5 +1,7 @@ #include "DescriptorManager.hpp" +#include "vkcv/Logger.hpp" + namespace vkcv { DescriptorManager::DescriptorManager(vk::Device device) noexcept: @@ -53,7 +55,7 @@ namespace vkcv vk::DescriptorSetLayoutCreateInfo layoutInfo({}, setBindings); if(m_Device.createDescriptorSetLayout(&layoutInfo, nullptr, &set.layout) != vk::Result::eSuccess) { - std::cout << "FAILED TO CREATE DESCRIPTOR SET LAYOUT" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Failed to create descriptor set layout"); return DescriptorSetHandle(); }; @@ -69,10 +71,10 @@ namespace vkcv result = m_Device.allocateDescriptorSets(&allocInfo, &set.vulkanHandle); } if (result != vk::Result::eSuccess) { - std::cout << "FAILED TO ALLOCATE DESCRIPTOR SET" << std::endl; - std::cout << vk::to_string(result) << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Failed to create descriptor set (%s)", + vk::to_string(result).c_str()); + m_Device.destroy(set.layout); - return DescriptorSetHandle(); } }; @@ -239,7 +241,7 @@ namespace vkcv case DescriptorType::IMAGE_STORAGE: return vk::DescriptorType::eStorageImage; default: - std::cerr << "Error: DescriptorManager::convertDescriptorTypeFlag, unknown DescriptorType" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Unknown DescriptorType"); return vk::DescriptorType::eUniformBuffer; } } @@ -266,7 +268,7 @@ namespace vkcv void DescriptorManager::destroyDescriptorSetById(uint64_t id) { if (id >= m_DescriptorSets.size()) { - std::cerr << "Error: DescriptorManager::destroyResourceDescriptionById invalid id" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Invalid id"); return; } @@ -282,7 +284,7 @@ namespace vkcv vk::DescriptorPool pool; if (m_Device.createDescriptorPool(&m_PoolInfo, nullptr, &pool) != vk::Result::eSuccess) { - std::cout << "FAILED TO ALLOCATE DESCRIPTOR POOL." << std::endl; + vkcv_log(vkcv::LogLevel::WARNING, "Failed to allocate descriptor pool"); pool = nullptr; }; m_Pools.push_back(pool); diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp index cdfd32b009a8007b606c86bf087b3f921b2bb89f..9c11da144412415bd7664161b2519d9f0e10af72 100644 --- a/src/vkcv/ImageManager.cpp +++ b/src/vkcv/ImageManager.cpp @@ -6,6 +6,7 @@ #include "ImageManager.hpp" #include "vkcv/Core.hpp" #include "ImageLayoutTransitions.hpp" +#include "vkcv/Logger.hpp" #include <algorithm> @@ -206,7 +207,7 @@ namespace vkcv { const uint64_t id = handle.getId(); if (id >= m_images.size()) { - std::cerr << "Error: ImageManager::getVulkanImage invalid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Invalid handle"); return nullptr; } @@ -219,7 +220,7 @@ namespace vkcv { const uint64_t id = handle.getId(); if (id >= m_images.size()) { - std::cerr << "Error: ImageManager::getVulkanDeviceMemory invalid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Invalid handle"); return nullptr; } @@ -232,7 +233,7 @@ namespace vkcv { const uint64_t id = handle.getId(); if (id >= m_images.size()) { - std::cerr << "Error: ImageManager::getVulkanImageView invalid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Invalid handle"); return nullptr; } @@ -245,7 +246,7 @@ namespace vkcv { const uint64_t id = handle.getId(); if (id >= m_images.size()) { - std::cerr << "Error: ImageManager::switchImageLayout invalid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Invalid handle"); return; } @@ -280,7 +281,7 @@ namespace vkcv { const uint64_t id = handle.getId(); if (id >= m_images.size()) { - std::cerr << "Error: ImageManager::switchImageLayout invalid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Invalid handle"); return; } @@ -295,7 +296,7 @@ namespace vkcv { const uint64_t id = handle.getId(); if (id >= m_images.size()) { - std::cerr << "Error: ImageManager::fillImage invalid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Invalid handle"); return; } @@ -369,7 +370,7 @@ namespace vkcv { const uint64_t id = handle.getId(); if (id >= m_images.size()) { - std::cerr << "Error: ImageManager::getImageWidth invalid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Invalid handle"); return 0; } @@ -382,7 +383,7 @@ namespace vkcv { const uint64_t id = handle.getId(); if (id >= m_images.size()) { - std::cerr << "Error: ImageManager::getImageHeight invalid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Invalid handle"); return 0; } @@ -395,7 +396,7 @@ namespace vkcv { const uint64_t id = handle.getId(); if (id >= m_images.size()) { - std::cerr << "Error: ImageManager::getImageDepth invalid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Invalid handle"); return 0; } @@ -407,7 +408,7 @@ namespace vkcv { void ImageManager::destroyImageById(uint64_t id) { if (id >= m_images.size()) { - std::cerr << "Error: ImageManager::destroyImageById invalid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Invalid handle"); return; } @@ -436,7 +437,7 @@ namespace vkcv { const uint64_t id = handle.getId(); if (id >= m_images.size()) { - std::cerr << "Error: ImageManager::destroyImageById invalid handle" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Invalid handle"); return vk::Format::eUndefined; } diff --git a/src/vkcv/PipelineManager.cpp b/src/vkcv/PipelineManager.cpp index 28a64a243b9a7a8fc9372409ef3783901219c868..15f77f13f81bea54a346a46d02e65f2dc7eed42e 100644 --- a/src/vkcv/PipelineManager.cpp +++ b/src/vkcv/PipelineManager.cpp @@ -1,5 +1,6 @@ #include "PipelineManager.hpp" #include "vkcv/Image.hpp" +#include "vkcv/Logger.hpp" namespace vkcv { @@ -20,15 +21,25 @@ namespace vkcv // currently assuming default 32 bit formats, no lower precision or normalized variants supported vk::Format vertexFormatToVulkanFormat(const VertexFormat format) { switch (format) { - case VertexFormat::FLOAT: return vk::Format::eR32Sfloat; - case VertexFormat::FLOAT2: return vk::Format::eR32G32Sfloat; - case VertexFormat::FLOAT3: return vk::Format::eR32G32B32Sfloat; - case VertexFormat::FLOAT4: return vk::Format::eR32G32B32A32Sfloat; - case VertexFormat::INT: return vk::Format::eR32Sint; - case VertexFormat::INT2: return vk::Format::eR32G32Sint; - case VertexFormat::INT3: return vk::Format::eR32G32B32Sint; - case VertexFormat::INT4: return vk::Format::eR32G32B32A32Sint; - default: std::cerr << "Warning: Unknown vertex format" << std::endl; return vk::Format::eUndefined; + case VertexFormat::FLOAT: + return vk::Format::eR32Sfloat; + case VertexFormat::FLOAT2: + return vk::Format::eR32G32Sfloat; + case VertexFormat::FLOAT3: + return vk::Format::eR32G32B32Sfloat; + case VertexFormat::FLOAT4: + return vk::Format::eR32G32B32A32Sfloat; + case VertexFormat::INT: + return vk::Format::eR32Sint; + case VertexFormat::INT2: + return vk::Format::eR32G32Sint; + case VertexFormat::INT3: + return vk::Format::eR32G32B32Sint; + case VertexFormat::INT4: + return vk::Format::eR32G32B32A32Sint; + default: + vkcv_log(vkcv::LogLevel::WARNING, "Unknown vertex format"); + return vk::Format::eUndefined; } } @@ -40,7 +51,7 @@ namespace vkcv const bool existsFragmentShader = config.m_ShaderProgram.existsShader(ShaderStage::FRAGMENT); if (!(existsVertexShader && existsFragmentShader)) { - std::cout << "Core::createGraphicsPipeline requires vertex and fragment shader code" << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "Requires vertex and fragment shader code"); return PipelineHandle(); } diff --git a/src/vkcv/QueueManager.cpp b/src/vkcv/QueueManager.cpp index e4d1a2d3a3302fc435c4c278322c08f51f19be6b..308c2c066204afbdc09c2bffac96b914eaf47c71 100644 --- a/src/vkcv/QueueManager.cpp +++ b/src/vkcv/QueueManager.cpp @@ -4,7 +4,7 @@ #include <iostream> #include "vkcv/QueueManager.hpp" - +#include "vkcv/Logger.hpp" namespace vkcv { @@ -95,7 +95,8 @@ namespace vkcv { found = true; } } - std::cerr << "Warning: not enough \"" << vk::to_string(qFlag) << "\"-Queues." << std::endl; + + vkcv_log(vkcv::LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str()); } break; case vk::QueueFlagBits::eCompute: @@ -116,7 +117,8 @@ namespace vkcv { found = true; } } - std::cerr << "Warning: not enough \"" << vk::to_string(qFlag) << "\"-Queues." << std::endl; + + vkcv_log(vkcv::LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str()); } break; case vk::QueueFlagBits::eTransfer: @@ -137,7 +139,8 @@ namespace vkcv { found = true; } } - std::cerr << "Warning: not enough \"" << vk::to_string(qFlag) << "\"-Queues." << std::endl; + + vkcv_log(vkcv::LogLevel::WARNING, "Not enough %s queues", vk::to_string(qFlag).c_str()); } break; default: diff --git a/src/vkcv/ShaderProgram.cpp b/src/vkcv/ShaderProgram.cpp index d22573d28d9a56908a373d6e3bbe0be9e87000ed..ef70b818aa10a6648ea3ddfa6571defa40e4d7cb 100644 --- a/src/vkcv/ShaderProgram.cpp +++ b/src/vkcv/ShaderProgram.cpp @@ -5,6 +5,7 @@ */ #include "vkcv/ShaderProgram.hpp" +#include "vkcv/Logger.hpp" namespace vkcv { /** @@ -17,7 +18,7 @@ namespace vkcv { { std::ifstream file(shaderPath.string(), std::ios::ate | std::ios::binary); if (!file.is_open()) { - std::cout << "The file could not be opened." << std::endl; + vkcv_log(vkcv::LogLevel::ERROR, "The file could not be opened"); return std::vector<char>{}; } size_t fileSize = (size_t)file.tellg(); @@ -60,7 +61,8 @@ namespace vkcv { default: break; } - std::cout << "Shader Program Reflection: unknown Vertex Format" << std::endl; + + vkcv_log(vkcv::LogLevel::WARNING, "Unknown vertex format"); return VertexFormat::FLOAT; } @@ -72,14 +74,15 @@ namespace vkcv { bool ShaderProgram::addShader(ShaderStage shaderStage, const std::filesystem::path &shaderPath) { - if(m_Shaders.find(shaderStage) != m_Shaders.end()) - std::cout << "Found existing shader stage. Overwriting." << std::endl; + if(m_Shaders.find(shaderStage) != m_Shaders.end()) { + vkcv_log(vkcv::LogLevel::WARNING, "Overwriting existing shader stage"); + } const std::vector<char> shaderCode = readShaderCode(shaderPath); - if (shaderCode.empty()) - return false; - else - { + + if (shaderCode.empty()) { + return false; + } else { Shader shader{shaderCode, shaderStage}; m_Shaders.insert(std::make_pair(shaderStage, shader)); return true; diff --git a/src/vkcv/VertexLayout.cpp b/src/vkcv/VertexLayout.cpp index 3a524d97865a06db3e8dbe22a390cafaee3a0226..354eac51c1b67fb899565b330f12cbdb6bb62f34 100644 --- a/src/vkcv/VertexLayout.cpp +++ b/src/vkcv/VertexLayout.cpp @@ -3,6 +3,7 @@ // #include "vkcv/VertexLayout.hpp" +#include "vkcv/Logger.hpp" namespace vkcv { uint32_t getFormatSize(VertexFormat format) { @@ -24,10 +25,9 @@ namespace vkcv { case VertexFormat::INT4: return 16; default: - break; + vkcv_log(vkcv::LogLevel::WARNING, "No format given"); + return 0; } - std::cout << "VertexLayout: No format given" << std::endl; - return 0; } VertexInputAttachment::VertexInputAttachment(uint32_t location, uint32_t binding, std::string name, VertexFormat format, uint32_t offset) noexcept: