diff --git a/src/app/sdl3_app_buffers.cpp b/src/app/sdl3_app_buffers.cpp index f51524d..953afdd 100644 --- a/src/app/sdl3_app_buffers.cpp +++ b/src/app/sdl3_app_buffers.cpp @@ -1,4 +1,5 @@ #include "app/sdl3_app.hpp" +#include "app/trace.hpp" #include #include @@ -8,6 +9,7 @@ namespace sdl3cpp::app { void Sdl3App::LoadSceneData() { + TRACE_FUNCTION(); shaderPathMap_ = cubeScript_.LoadShaderPathsMap(); if (shaderPathMap_.empty()) { throw std::runtime_error("Lua script did not provide shader paths"); @@ -52,6 +54,7 @@ void Sdl3App::LoadSceneData() { } void Sdl3App::CreateVertexBuffer() { + TRACE_FUNCTION(); VkDeviceSize bufferSize = sizeof(vertices_[0]) * vertices_.size(); vulkan::CreateBuffer(device_, physicalDevice_, bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, vertexBuffer_, @@ -64,6 +67,7 @@ void Sdl3App::CreateVertexBuffer() { } void Sdl3App::CreateIndexBuffer() { + TRACE_FUNCTION(); VkDeviceSize bufferSize = sizeof(indices_[0]) * indices_.size(); vulkan::CreateBuffer(device_, physicalDevice_, bufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, indexBuffer_, diff --git a/src/app/sdl3_app_build.cpp b/src/app/sdl3_app_build.cpp index f810676..a626d4e 100644 --- a/src/app/sdl3_app_build.cpp +++ b/src/app/sdl3_app_build.cpp @@ -1,10 +1,12 @@ #include "app/sdl3_app.hpp" +#include "app/trace.hpp" #include namespace sdl3cpp::app { void Sdl3App::CreateFramebuffers() { + TRACE_FUNCTION(); swapChainFramebuffers_.resize(swapChainImageViews_.size()); for (size_t i = 0; i < swapChainImageViews_.size(); ++i) { VkImageView attachments[] = {swapChainImageViews_[i]}; @@ -26,6 +28,7 @@ void Sdl3App::CreateFramebuffers() { } void Sdl3App::CreateCommandPool() { + TRACE_FUNCTION(); QueueFamilyIndices indices = FindQueueFamilies(physicalDevice_); VkCommandPoolCreateInfo poolInfo{}; @@ -39,6 +42,7 @@ void Sdl3App::CreateCommandPool() { } void Sdl3App::CreateSyncObjects() { + TRACE_FUNCTION(); VkSemaphoreCreateInfo semaphoreInfo{}; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; diff --git a/src/app/sdl3_app_core.cpp b/src/app/sdl3_app_core.cpp index b5437e7..4bda5d8 100644 --- a/src/app/sdl3_app_core.cpp +++ b/src/app/sdl3_app_core.cpp @@ -1,4 +1,5 @@ #include "app/sdl3_app.hpp" +#include "app/trace.hpp" #include #include @@ -12,6 +13,7 @@ namespace sdl3cpp::app { std::vector ReadFile(const std::string& path) { + TRACE_FUNCTION(); std::ifstream file(path, std::ios::ate | std::ios::binary); if (!file) { throw std::runtime_error("failed to open file: " + path); @@ -79,9 +81,12 @@ void ThrowSdlErrorIfFailed(int result, const char* context) { } // namespace -Sdl3App::Sdl3App(const std::filesystem::path& scriptPath) : cubeScript_(scriptPath) {} +Sdl3App::Sdl3App(const std::filesystem::path& scriptPath) : cubeScript_(scriptPath) { + TRACE_FUNCTION(); +} void Sdl3App::Run() { + TRACE_FUNCTION(); InitSDL(); InitVulkan(); MainLoop(); @@ -89,6 +94,7 @@ void Sdl3App::Run() { } void Sdl3App::InitSDL() { + TRACE_FUNCTION(); ThrowSdlErrorIfFailed(SDL_Init(SDL_INIT_VIDEO), "SDL_Init failed"); ThrowSdlErrorIfFailed(SDL_Vulkan_LoadLibrary(nullptr), "SDL_Vulkan_LoadLibrary failed"); window_ = SDL_CreateWindow("SDL3 Vulkan Demo", kWidth, kHeight, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE); @@ -99,6 +105,7 @@ void Sdl3App::InitSDL() { } void Sdl3App::InitVulkan() { + TRACE_FUNCTION(); CreateInstance(); CreateSurface(); PickPhysicalDevice(); @@ -118,6 +125,7 @@ void Sdl3App::InitVulkan() { } void Sdl3App::MainLoop() { + TRACE_FUNCTION(); bool running = true; auto start = std::chrono::steady_clock::now(); while (running) { @@ -156,6 +164,7 @@ void Sdl3App::MainLoop() { } void Sdl3App::Cleanup() { + TRACE_FUNCTION(); CleanupSwapChain(); vkDestroyBuffer(device_, vertexBuffer_, nullptr); diff --git a/src/app/sdl3_app_device.cpp b/src/app/sdl3_app_device.cpp index ec8d664..1c1406d 100644 --- a/src/app/sdl3_app_device.cpp +++ b/src/app/sdl3_app_device.cpp @@ -1,4 +1,5 @@ #include "app/sdl3_app.hpp" +#include "app/trace.hpp" #include #include @@ -7,6 +8,7 @@ namespace sdl3cpp::app { void Sdl3App::CreateInstance() { + TRACE_FUNCTION(); VkApplicationInfo appInfo{}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "SDL3 Vulkan"; @@ -35,12 +37,14 @@ void Sdl3App::CreateInstance() { } void Sdl3App::CreateSurface() { + TRACE_FUNCTION(); if (!SDL_Vulkan_CreateSurface(window_, instance_, nullptr, &surface_)) { throw std::runtime_error("Failed to create Vulkan surface"); } } void Sdl3App::PickPhysicalDevice() { + TRACE_FUNCTION(); uint32_t deviceCount = 0; vkEnumeratePhysicalDevices(instance_, &deviceCount, nullptr); if (deviceCount == 0) { @@ -62,6 +66,7 @@ void Sdl3App::PickPhysicalDevice() { } void Sdl3App::CreateLogicalDevice() { + TRACE_FUNCTION(); QueueFamilyIndices indices = FindQueueFamilies(physicalDevice_); std::vector queueCreateInfos; @@ -96,6 +101,7 @@ void Sdl3App::CreateLogicalDevice() { } QueueFamilyIndices Sdl3App::FindQueueFamilies(VkPhysicalDevice device) { + TRACE_FUNCTION(); QueueFamilyIndices indices; uint32_t queueFamilyCount = 0; @@ -127,6 +133,7 @@ QueueFamilyIndices Sdl3App::FindQueueFamilies(VkPhysicalDevice device) { } bool Sdl3App::CheckDeviceExtensionSupport(VkPhysicalDevice device) { + TRACE_FUNCTION(); uint32_t extensionCount = 0; vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); @@ -142,6 +149,7 @@ bool Sdl3App::CheckDeviceExtensionSupport(VkPhysicalDevice device) { } SwapChainSupportDetails Sdl3App::QuerySwapChainSupport(VkPhysicalDevice device) { + TRACE_FUNCTION(); SwapChainSupportDetails details; vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface_, &details.capabilities); @@ -164,6 +172,7 @@ SwapChainSupportDetails Sdl3App::QuerySwapChainSupport(VkPhysicalDevice device) } bool Sdl3App::IsDeviceSuitable(VkPhysicalDevice device) { + TRACE_FUNCTION(); QueueFamilyIndices indices = FindQueueFamilies(device); bool extensionsSupported = CheckDeviceExtensionSupport(device); diff --git a/src/app/sdl3_app_pipeline.cpp b/src/app/sdl3_app_pipeline.cpp index 94eaa3d..31c07b5 100644 --- a/src/app/sdl3_app_pipeline.cpp +++ b/src/app/sdl3_app_pipeline.cpp @@ -1,4 +1,5 @@ #include "app/sdl3_app.hpp" +#include "app/trace.hpp" #include #include @@ -6,6 +7,7 @@ namespace sdl3cpp::app { VkShaderModule Sdl3App::CreateShaderModule(const std::vector& code) { + TRACE_FUNCTION(); VkShaderModuleCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; createInfo.codeSize = code.size(); @@ -19,6 +21,7 @@ VkShaderModule Sdl3App::CreateShaderModule(const std::vector& code) { } void Sdl3App::CreateGraphicsPipeline() { + TRACE_FUNCTION(); if (shaderPathMap_.empty()) { throw std::runtime_error("No shader paths were loaded before pipeline creation"); } diff --git a/src/app/sdl3_app_render.cpp b/src/app/sdl3_app_render.cpp index 7e08d2c..a6290d0 100644 --- a/src/app/sdl3_app_render.cpp +++ b/src/app/sdl3_app_render.cpp @@ -1,4 +1,5 @@ #include "app/sdl3_app.hpp" +#include "app/trace.hpp" #include #include @@ -21,6 +22,7 @@ const std::unordered_map kGuiKeyNames = { namespace sdl3cpp::app { void Sdl3App::CreateCommandBuffers() { + TRACE_FUNCTION(); commandBuffers_.resize(swapChainFramebuffers_.size()); VkCommandBufferAllocateInfo allocInfo{}; @@ -36,6 +38,7 @@ void Sdl3App::CreateCommandBuffers() { void Sdl3App::RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex, float time, const std::array& viewProj) { + TRACE_FUNCTION(); VkCommandBufferBeginInfo beginInfo{}; beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; @@ -82,6 +85,7 @@ void Sdl3App::RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageI } void Sdl3App::ProcessGuiEvent(const SDL_Event& event) { + TRACE_FUNCTION(); switch (event.type) { case SDL_EVENT_MOUSE_MOTION: guiInputSnapshot_.mouseX = static_cast(event.motion.x); @@ -114,6 +118,7 @@ void Sdl3App::ProcessGuiEvent(const SDL_Event& event) { } void Sdl3App::SetupGuiRenderer() { + TRACE_FUNCTION(); guiHasCommands_ = cubeScript_.HasGuiCommands(); if (!guiHasCommands_) { guiRenderer_.reset(); @@ -128,6 +133,7 @@ void Sdl3App::SetupGuiRenderer() { } void Sdl3App::DrawFrame(float time) { + TRACE_FUNCTION(); vkWaitForFences(device_, 1, &inFlightFence_, VK_TRUE, std::numeric_limits::max()); vkResetFences(device_, 1, &inFlightFence_); diff --git a/src/app/sdl3_app_swapchain.cpp b/src/app/sdl3_app_swapchain.cpp index d1304ca..5705c60 100644 --- a/src/app/sdl3_app_swapchain.cpp +++ b/src/app/sdl3_app_swapchain.cpp @@ -1,4 +1,5 @@ #include "app/sdl3_app.hpp" +#include "app/trace.hpp" #include "app/vulkan_api.hpp" #include @@ -6,6 +7,7 @@ namespace sdl3cpp::app { void Sdl3App::CreateSwapChain() { + TRACE_FUNCTION(); SwapChainSupportDetails support = QuerySwapChainSupport(physicalDevice_); VkSurfaceFormatKHR surfaceFormat = ChooseSwapSurfaceFormat(support.formats); @@ -55,6 +57,7 @@ void Sdl3App::CreateSwapChain() { } void Sdl3App::CreateImageViews() { + TRACE_FUNCTION(); swapChainImageViews_.resize(swapChainImages_.size()); for (size_t i = 0; i < swapChainImages_.size(); ++i) { VkImageViewCreateInfo viewInfo{}; @@ -77,6 +80,7 @@ void Sdl3App::CreateImageViews() { } void Sdl3App::CreateRenderPass() { + TRACE_FUNCTION(); VkAttachmentDescription colorAttachment{}; colorAttachment.format = swapChainImageFormat_; colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; @@ -119,6 +123,7 @@ void Sdl3App::CreateRenderPass() { } void Sdl3App::CleanupSwapChain() { + TRACE_FUNCTION(); for (auto framebuffer : swapChainFramebuffers_) { vkDestroyFramebuffer(device_, framebuffer, nullptr); } @@ -140,6 +145,7 @@ void Sdl3App::CleanupSwapChain() { } void Sdl3App::RecreateSwapChain() { + TRACE_FUNCTION(); int width = 0; int height = 0; while (width == 0 || height == 0) { @@ -160,6 +166,7 @@ void Sdl3App::RecreateSwapChain() { } VkSurfaceFormatKHR Sdl3App::ChooseSwapSurfaceFormat(const std::vector& availableFormats) { + TRACE_FUNCTION(); for (const auto& availableFormat : availableFormats) { if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { @@ -170,6 +177,7 @@ VkSurfaceFormatKHR Sdl3App::ChooseSwapSurfaceFormat(const std::vector& availablePresentModes) { + TRACE_FUNCTION(); for (const auto& availablePresentMode : availablePresentModes) { if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) { return availablePresentMode; diff --git a/src/app/trace.hpp b/src/app/trace.hpp new file mode 100644 index 0000000..25a1092 --- /dev/null +++ b/src/app/trace.hpp @@ -0,0 +1,43 @@ +#ifndef SDL3CPP_APP_TRACE_HPP +#define SDL3CPP_APP_TRACE_HPP + +#include +#include + +namespace sdl3cpp::app { + +class TraceLogger { +public: + static void SetEnabled(bool enabled) noexcept { + enabled_.store(enabled, std::memory_order_relaxed); + } + + static bool Enabled() noexcept { + return enabled_.load(std::memory_order_relaxed); + } + + static void Log(const char* message) { + if (Enabled()) { + std::cout << "[TRACE] " << message << '\n'; + } + } + +private: + static inline std::atomic_bool enabled_{false}; +}; + +class TraceScope { +public: + explicit TraceScope(const char* name) : name_(name) { + TraceLogger::Log(name_); + } + +private: + const char* name_; +}; + +} // namespace sdl3cpp::app + +#define TRACE_FUNCTION() sdl3cpp::app::TraceScope traceScope##__COUNTER__{__func__} + +#endif // SDL3CPP_APP_TRACE_HPP diff --git a/src/main.cpp b/src/main.cpp index 316be23..d1e755a 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -14,6 +14,7 @@ #include #include +#include "app/trace.hpp" #include "app/sdl3_app.hpp" namespace { @@ -156,6 +157,7 @@ struct AppOptions { std::optional seedOutput; bool saveDefaultJson = false; bool dumpRuntimeJson = false; + bool traceEnabled = false; }; AppOptions ParseCommandLine(int argc, char** argv) { @@ -163,6 +165,7 @@ AppOptions ParseCommandLine(int argc, char** argv) { std::string seedOutputText; std::string setDefaultJsonPath; bool dumpRuntimeJson = false; + bool traceRuntime = false; CLI::App app("SDL3 + Vulkan runtime helper"); app.add_option("-j,--json-file-in", jsonInputText, "Path to a runtime JSON config") @@ -177,6 +180,7 @@ AppOptions ParseCommandLine(int argc, char** argv) { setDefaultJsonOption->type_size(1, 1); setDefaultJsonOption->expected(0, 1); app.add_flag("--dump-json", dumpRuntimeJson, "Print the runtime JSON that was loaded"); + app.add_flag("--trace", traceRuntime, "Emit a log line when key functions/methods run"); try { app.parse(argc, argv); @@ -214,6 +218,7 @@ AppOptions ParseCommandLine(int argc, char** argv) { } options.saveDefaultJson = shouldSaveDefault; options.dumpRuntimeJson = dumpRuntimeJson; + options.traceEnabled = traceRuntime; return options; } @@ -275,6 +280,7 @@ void WriteRuntimeConfigJson(const RuntimeConfig& runtimeConfig, int main(int argc, char** argv) { try { AppOptions options = ParseCommandLine(argc, argv); + TraceLogger::SetEnabled(options.traceEnabled); if (options.seedOutput) { WriteRuntimeConfigJson(options.runtimeConfig, *options.seedOutput); }