From 8d269b8c67756a1735b45e5cf6eeef520fdf63f4 Mon Sep 17 00:00:00 2001 From: johndoe6345789 Date: Sun, 4 Jan 2026 14:55:18 +0000 Subject: [PATCH] Remove SDL3 application rendering and swapchain management code - Deleted sdl3_app_render.cpp and sdl3_app_swapchain.cpp files, which contained the rendering and swapchain management logic for the SDL3 application. - Removed associated header files and macros that were no longer needed. - Eliminated the Vulkan API wrapper functions and the script service implementation, streamlining the codebase. - This cleanup reduces complexity and potential maintenance overhead for the SDL3 application. --- src/app/audio_player.cpp | 208 --------------- src/app/audio_player.hpp | 52 ---- src/app/sdl3_app.hpp | 152 ----------- src/app/sdl3_app_buffers.cpp | 99 ------- src/app/sdl3_app_build.cpp | 60 ----- src/app/sdl3_app_core.cpp | 284 -------------------- src/app/sdl3_app_device.cpp | 306 ---------------------- src/app/sdl3_app_pipeline.cpp | 191 -------------- src/app/sdl3_app_render.cpp | 370 --------------------------- src/app/sdl3_app_swapchain.cpp | 246 ------------------ src/app/sdl_macros.hpp | 9 - src/app/vulkan_api.cpp | 118 --------- src/app/vulkan_api.hpp | 16 -- src/services/impl/script_service.cpp | 162 ------------ src/services/impl/script_service.hpp | 52 ---- 15 files changed, 2325 deletions(-) delete mode 100644 src/app/audio_player.cpp delete mode 100644 src/app/audio_player.hpp delete mode 100644 src/app/sdl3_app.hpp delete mode 100644 src/app/sdl3_app_buffers.cpp delete mode 100644 src/app/sdl3_app_build.cpp delete mode 100644 src/app/sdl3_app_core.cpp delete mode 100644 src/app/sdl3_app_device.cpp delete mode 100644 src/app/sdl3_app_pipeline.cpp delete mode 100644 src/app/sdl3_app_render.cpp delete mode 100644 src/app/sdl3_app_swapchain.cpp delete mode 100644 src/app/sdl_macros.hpp delete mode 100644 src/app/vulkan_api.cpp delete mode 100644 src/app/vulkan_api.hpp delete mode 100644 src/services/impl/script_service.cpp delete mode 100644 src/services/impl/script_service.hpp diff --git a/src/app/audio_player.cpp b/src/app/audio_player.cpp deleted file mode 100644 index 443b924..0000000 --- a/src/app/audio_player.cpp +++ /dev/null @@ -1,208 +0,0 @@ -#include "app/audio_player.hpp" -#include "logging/logger.hpp" -#include "logging/string_utils.hpp" - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -namespace sdl3cpp::app { - -namespace { - -struct DecodedAudio { - std::vector samples; - int sampleRate = 0; - int channels = 0; -}; - -DecodedAudio DecodeOgg(const std::filesystem::path& path) { - using sdl3cpp::logging::ToString; - sdl3cpp::logging::Logger::GetInstance().TraceFunctionWithArgs("DecodeOgg", path.string()); - FILE* file = std::fopen(path.string().c_str(), "rb"); - if (!file) { - throw std::runtime_error("Failed to open audio file: " + path.string()); - } - - OggVorbis_File oggFile{}; - if (ov_open(file, &oggFile, nullptr, 0) < 0) { - std::fclose(file); - throw std::runtime_error("Failed to open OGG stream: " + path.string()); - } - - vorbis_info* info = ov_info(&oggFile, -1); - if (!info) { - ov_clear(&oggFile); - throw std::runtime_error("Audio metadata is missing"); - } - int channels = info->channels; - int rate = static_cast(info->rate); - - std::vector decoded; - decoded.reserve(static_cast(ov_pcm_total(&oggFile, -1)) * channels); - int bitstream = 0; - constexpr size_t kChunkBytes = 4096 * sizeof(int16_t); - std::vector chunk(kChunkBytes); - - while (true) { - long bytesRead = ov_read(&oggFile, chunk.data(), static_cast(chunk.size()), 0, 2, 1, &bitstream); - if (bytesRead == 0) { - break; - } - if (bytesRead < 0) { - ov_clear(&oggFile); - throw std::runtime_error("Error decoding OGG stream"); - } - size_t samples = static_cast(bytesRead) / sizeof(int16_t); - size_t oldSize = decoded.size(); - decoded.resize(oldSize + samples); - std::memcpy(decoded.data() + oldSize, chunk.data(), samples * sizeof(int16_t)); - } - - ov_clear(&oggFile); - if (decoded.empty()) { - throw std::runtime_error("Decoded audio is empty"); - } - - return DecodedAudio{std::move(decoded), rate, channels}; -} - -} // namespace - -AudioPlayer::AudioPlayer() = default; - -AudioPlayer::~AudioPlayer() { - if (stream_) { - SDL_PauseAudioStreamDevice(stream_); - SDL_DestroyAudioStream(stream_); - } -} - -void AudioPlayer::PlayBackground(const std::filesystem::path& path, bool loop) { - using sdl3cpp::logging::ToString; - sdl3cpp::logging::Logger::GetInstance().TraceFunctionWithArgs("PlayBackground", path.string() + " " + ToString(loop)); - DecodedAudio clip = DecodeOgg(path); - EnsureStream(clip.sampleRate, clip.channels); - std::scoped_lock lock(voicesMutex_); - backgroundVoice_ = AudioVoice{std::move(clip.samples), 0, loop, true}; -} - -void AudioPlayer::PlayEffect(const std::filesystem::path& path, bool loop) { - using sdl3cpp::logging::ToString; - sdl3cpp::logging::Logger::GetInstance().TraceFunctionWithArgs("PlayEffect", path.string() + " " + ToString(loop)); - DecodedAudio clip = DecodeOgg(path); - EnsureStream(clip.sampleRate, clip.channels); - std::scoped_lock lock(voicesMutex_); - effectVoices_.push_back(AudioVoice{std::move(clip.samples), 0, loop, true}); -} - -void AudioPlayer::AudioStreamCallback(void* userdata, SDL_AudioStream* stream, int additionalAmount, int totalAmount) { - auto* self = static_cast(userdata); - self->FeedStream(stream, totalAmount); -} - -void AudioPlayer::FeedStream(SDL_AudioStream* stream, int totalAmount) { - using sdl3cpp::logging::ToString; - sdl3cpp::logging::Logger::GetInstance().TraceFunctionWithArgs("FeedStream", ToString(static_cast(stream)) + " " + ToString(totalAmount)); - if (totalAmount <= 0 || !stream_) { - return; - } - size_t sampleCount = static_cast(totalAmount) / sizeof(int16_t); - if (sampleCount == 0) { - return; - } - mixBuffer_.assign(sampleCount, 0); - - std::scoped_lock lock(voicesMutex_); - if (backgroundVoice_ && backgroundVoice_->active) { - AddVoiceSamples(*backgroundVoice_, mixBuffer_, sampleCount); - if (!backgroundVoice_->active) { - backgroundVoice_.reset(); - } - } - - for (auto it = effectVoices_.begin(); it != effectVoices_.end();) { - AddVoiceSamples(*it, mixBuffer_, sampleCount); - if (!it->active) { - it = effectVoices_.erase(it); - } else { - ++it; - } - } - - outputBuffer_.resize(sampleCount); - for (size_t i = 0; i < sampleCount; ++i) { - int32_t value = mixBuffer_[i]; - if (value > std::numeric_limits::max()) { - value = std::numeric_limits::max(); - } else if (value < std::numeric_limits::min()) { - value = std::numeric_limits::min(); - } - outputBuffer_[i] = static_cast(value); - } - - SDL_PutAudioStreamData(stream, outputBuffer_.data(), static_cast(sampleCount * sizeof(int16_t))); -} - -void AudioPlayer::EnsureStream(int sampleRate, int channels) { - using sdl3cpp::logging::ToString; - sdl3cpp::logging::Logger::GetInstance().TraceFunctionWithArgs("EnsureStream", ToString(sampleRate) + " " + ToString(channels)); - if (sampleRate <= 0 || channels <= 0) { - throw std::runtime_error("Audio format is invalid"); - } - if (sampleRate_ != 0 && (sampleRate != sampleRate_ || channels != channels_)) { - throw std::runtime_error("Requested audio format does not match initialized stream"); - } - if (stream_) { - return; - } - - SDL_AudioSpec desired{}; - desired.freq = sampleRate; - desired.format = SDL_AUDIO_S16; - desired.channels = channels; - - stream_ = SDL_OpenAudioDeviceStream(SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK, &desired, &AudioPlayer::AudioStreamCallback, this); - if (!stream_) { - throw std::runtime_error("Failed to open audio stream: " + std::string(SDL_GetError())); - } - if (!SDL_ResumeAudioStreamDevice(stream_)) { - SDL_DestroyAudioStream(stream_); - stream_ = nullptr; - throw std::runtime_error("Failed to resume audio stream device: " + std::string(SDL_GetError())); - } - - sampleRate_ = sampleRate; - channels_ = channels; -} - -void AudioPlayer::AddVoiceSamples(AudioVoice& voice, std::vector& mixBuffer, size_t sampleCount) { - using sdl3cpp::logging::ToString; - sdl3cpp::logging::Logger::GetInstance().TraceFunctionWithArgs("AddVoiceSamples", ToString(voice.data.size()) + " " + ToString(mixBuffer.size()) + " " + ToString(sampleCount)); - if (voice.data.empty()) { - voice.active = false; - return; - } - size_t idx = voice.position; - for (size_t sampleIndex = 0; sampleIndex < sampleCount; ++sampleIndex) { - if (idx >= voice.data.size()) { - if (voice.loop) { - idx = 0; - } else { - voice.active = false; - break; - } - } - mixBuffer[sampleIndex] += static_cast(voice.data[idx++]); - } - voice.position = idx; -} - -} // namespace sdl3cpp::app diff --git a/src/app/audio_player.hpp b/src/app/audio_player.hpp deleted file mode 100644 index 0504932..0000000 --- a/src/app/audio_player.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SDL3CPP_APP_AUDIO_PLAYER_HPP -#define SDL3CPP_APP_AUDIO_PLAYER_HPP - -#include -#include -#include -#include -#include - -#include - -namespace sdl3cpp::app { - -class AudioPlayer { -public: - AudioPlayer(); - ~AudioPlayer(); - - AudioPlayer(const AudioPlayer&) = delete; - AudioPlayer& operator=(const AudioPlayer&) = delete; - - void PlayBackground(const std::filesystem::path& path, bool loop = true); - void PlayEffect(const std::filesystem::path& path, bool loop = false); - -private: - struct AudioVoice { - std::vector data; - size_t position = 0; - bool loop = false; - bool active = true; - }; - - static void AudioStreamCallback(void* userdata, SDL_AudioStream* stream, int additionalAmount, int totalAmount); - void FeedStream(SDL_AudioStream* stream, int totalAmount); - void EnsureStream(int sampleRate, int channels); - void AddVoiceSamples(AudioVoice& voice, std::vector& mixBuffer, size_t sampleCount); - - SDL_AudioStream* stream_ = nullptr; - int sampleRate_ = 0; - int channels_ = 0; - - std::optional backgroundVoice_; - std::vector effectVoices_; - - std::mutex voicesMutex_; - std::vector mixBuffer_; - std::vector outputBuffer_; -}; - -} // namespace sdl3cpp::app - -#endif // SDL3CPP_APP_AUDIO_PLAYER_HPP diff --git a/src/app/sdl3_app.hpp b/src/app/sdl3_app.hpp deleted file mode 100644 index 90152a2..0000000 --- a/src/app/sdl3_app.hpp +++ /dev/null @@ -1,152 +0,0 @@ -#ifndef SDL3CPP_APP_SDL3_APP_HPP -#define SDL3CPP_APP_SDL3_APP_HPP - -#include "sdl_macros.hpp" - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "app/audio_player.hpp" -#include "core/vertex.hpp" -#include "script/script_engine.hpp" -#include "script/shader_manager.hpp" -#include "gui/gui_renderer.hpp" - -namespace sdl3cpp::app { -class AudioPlayer; -} - -namespace sdl3cpp::app { - -namespace script = sdl3cpp::script; - -constexpr uint32_t kWidth = 1024; -constexpr uint32_t kHeight = 768; - -inline const std::vector kDeviceExtensions = { - VK_KHR_SWAPCHAIN_EXTENSION_NAME, -}; - -std::vector ReadFile(const std::string& path); - -struct QueueFamilyIndices { - std::optional graphicsFamily; - std::optional presentFamily; - - bool isComplete() const { - return graphicsFamily.has_value() && presentFamily.has_value(); - } -}; - -struct SwapChainSupportDetails { - VkSurfaceCapabilitiesKHR capabilities{}; - std::vector formats; - std::vector presentModes; -}; - -class Sdl3App { -public: - explicit Sdl3App(const std::filesystem::path& scriptPath, bool luaDebug = false); - void Run(); - static bool ShouldStop(); - -private: - struct RenderObject { - uint32_t indexOffset = 0; - uint32_t indexCount = 0; - int32_t vertexOffset = 0; - int computeModelMatrixRef = LUA_REFNIL; - std::string shaderKey = "default"; - }; - - void InitSDL(); - void InitVulkan(); - void MainLoop(); - void CleanupSwapChain(); - void Cleanup(); - void RecreateSwapChain(); - void CreateInstance(); - void CreateSurface(); - void PickPhysicalDevice(); - void CreateLogicalDevice(); - void CreateSwapChain(); - void CreateImageViews(); - void CreateRenderPass(); - VkShaderModule CreateShaderModule(const std::vector& code); - void CreateGraphicsPipeline(); - void CreateFramebuffers(); - void CreateCommandPool(); - void LoadSceneData(); - void CreateVertexBuffer(); - void CreateIndexBuffer(); - void CreateCommandBuffers(); - void RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex, float time, - const std::array& viewProj); - void CreateSyncObjects(); - void DrawFrame(float time); - void SetupGuiRenderer(); - void ProcessGuiEvent(const SDL_Event& event); - void PrintGpuDiagnostics(const std::string& errorContext); - - QueueFamilyIndices FindQueueFamilies(VkPhysicalDevice device); - bool CheckDeviceExtensionSupport(VkPhysicalDevice device); - SwapChainSupportDetails QuerySwapChainSupport(VkPhysicalDevice device); - bool IsDeviceSuitable(VkPhysicalDevice device); - VkSurfaceFormatKHR ChooseSwapSurfaceFormat(const std::vector& availableFormats); - VkPresentModeKHR ChooseSwapPresentMode(const std::vector& availablePresentModes); - - SDL_Window* window_ = nullptr; - VkInstance instance_ = VK_NULL_HANDLE; - VkSurfaceKHR surface_ = VK_NULL_HANDLE; - VkPhysicalDevice physicalDevice_ = VK_NULL_HANDLE; - VkDevice device_ = VK_NULL_HANDLE; - VkQueue graphicsQueue_ = VK_NULL_HANDLE; - VkQueue presentQueue_ = VK_NULL_HANDLE; - VkSwapchainKHR swapChain_ = VK_NULL_HANDLE; - std::vector swapChainImages_; - VkFormat swapChainImageFormat_; - VkExtent2D swapChainExtent_; - std::vector swapChainImageViews_; - VkRenderPass renderPass_ = VK_NULL_HANDLE; - VkPipelineLayout pipelineLayout_ = VK_NULL_HANDLE; - std::vector swapChainFramebuffers_; - VkCommandPool commandPool_ = VK_NULL_HANDLE; - std::vector commandBuffers_; - VkBuffer vertexBuffer_ = VK_NULL_HANDLE; - VkDeviceMemory vertexBufferMemory_ = VK_NULL_HANDLE; - VkBuffer indexBuffer_ = VK_NULL_HANDLE; - VkDeviceMemory indexBufferMemory_ = VK_NULL_HANDLE; - VkSemaphore imageAvailableSemaphore_ = VK_NULL_HANDLE; - VkSemaphore renderFinishedSemaphore_ = VK_NULL_HANDLE; - script::ScriptEngine scriptEngine_; - std::vector vertices_; - std::vector indices_; - std::unordered_map shaderPathMap_; - std::unordered_map graphicsPipelines_; - std::string defaultShaderKey_; - VkFence inFlightFence_ = VK_NULL_HANDLE; - bool framebufferResized_ = false; - int consecutiveSwapchainRecreations_ = 0; - bool firstFrameCompleted_ = false; - script::GuiInputSnapshot guiInputSnapshot_; - std::vector guiCommands_; - std::unique_ptr guiRenderer_; - bool guiHasCommands_ = false; - std::vector renderObjects_; - std::filesystem::path scriptDirectory_; - std::unique_ptr audioPlayer_; -}; - -} // namespace sdl3cpp::app - -#endif // SDL3CPP_APP_SDL3_APP_HPP diff --git a/src/app/sdl3_app_buffers.cpp b/src/app/sdl3_app_buffers.cpp deleted file mode 100644 index 86da105..0000000 --- a/src/app/sdl3_app_buffers.cpp +++ /dev/null @@ -1,99 +0,0 @@ -#include "app/sdl3_app.hpp" -#include "logging/logger.hpp" - -#include -#include -#include - -#include "app/vulkan_api.hpp" - -namespace sdl3cpp::app { - -void Sdl3App::LoadSceneData() { - sdl3cpp::logging::TraceGuard trace; - shaderPathMap_ = scriptEngine_.LoadShaderPathsMap(); - if (shaderPathMap_.empty()) { - throw std::runtime_error("Lua script did not provide shader paths"); - } - defaultShaderKey_ = shaderPathMap_.count("default") ? "default" : shaderPathMap_.begin()->first; - - auto sceneObjects = scriptEngine_.LoadSceneObjects(); - if (sceneObjects.empty()) { - throw std::runtime_error("Lua script did not provide any scene objects"); - } - - vertices_.clear(); - indices_.clear(); - renderObjects_.clear(); - - size_t vertexOffset = 0; - size_t indexOffset = 0; - for (const auto& sceneObject : sceneObjects) { - RenderObject renderObject{}; - renderObject.vertexOffset = static_cast(vertexOffset); - renderObject.indexOffset = static_cast(indexOffset); - renderObject.indexCount = static_cast(sceneObject.indices.size()); - renderObject.computeModelMatrixRef = sceneObject.computeModelMatrixRef; - renderObject.shaderKey = sceneObject.shaderKey; - if (shaderPathMap_.find(renderObject.shaderKey) == shaderPathMap_.end()) { - renderObject.shaderKey = defaultShaderKey_; - } - renderObjects_.push_back(renderObject); - - vertices_.insert(vertices_.end(), sceneObject.vertices.begin(), sceneObject.vertices.end()); - for (uint16_t index : sceneObject.indices) { - indices_.push_back(static_cast(index + vertexOffset)); - } - - vertexOffset += sceneObject.vertices.size(); - indexOffset += sceneObject.indices.size(); - } - - if (vertices_.empty() || indices_.empty()) { - throw std::runtime_error("Aggregated scene geometry is empty"); - } -} - -void Sdl3App::CreateVertexBuffer() { - sdl3cpp::logging::TraceGuard trace; - if (vertices_.empty()) { - throw std::runtime_error("Cannot create vertex buffer: no vertices loaded"); - } - VkDeviceSize bufferSize = sizeof(vertices_[0]) * vertices_.size(); - sdl3cpp::logging::Logger::GetInstance().TraceVariable("bufferSize", static_cast(bufferSize)); - std::cout << "Creating vertex buffer: " << vertices_.size() << " vertices (" - << (bufferSize / 1024) << " KB)\n"; - std::cout.flush(); - - vulkan::CreateBuffer(device_, physicalDevice_, bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, vertexBuffer_, - vertexBufferMemory_); - - void* data; - vkMapMemory(device_, vertexBufferMemory_, 0, bufferSize, 0, &data); - std::memcpy(data, vertices_.data(), static_cast(bufferSize)); - vkUnmapMemory(device_, vertexBufferMemory_); -} - -void Sdl3App::CreateIndexBuffer() { - sdl3cpp::logging::TraceGuard trace; - if (indices_.empty()) { - throw std::runtime_error("Cannot create index buffer: no indices loaded"); - } - VkDeviceSize bufferSize = sizeof(indices_[0]) * indices_.size(); - sdl3cpp::logging::Logger::GetInstance().TraceVariable("bufferSize", static_cast(bufferSize)); - std::cout << "Creating index buffer: " << indices_.size() << " indices (" - << (bufferSize / 1024) << " KB)\n"; - std::cout.flush(); - - vulkan::CreateBuffer(device_, physicalDevice_, bufferSize, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, - VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT, indexBuffer_, - indexBufferMemory_); - - void* data; - vkMapMemory(device_, indexBufferMemory_, 0, bufferSize, 0, &data); - std::memcpy(data, indices_.data(), static_cast(bufferSize)); - vkUnmapMemory(device_, indexBufferMemory_); -} - -} // namespace sdl3cpp::app diff --git a/src/app/sdl3_app_build.cpp b/src/app/sdl3_app_build.cpp deleted file mode 100644 index 9367ad6..0000000 --- a/src/app/sdl3_app_build.cpp +++ /dev/null @@ -1,60 +0,0 @@ -#include "app/sdl3_app.hpp" -#include "logging/logger.hpp" - -#include - -namespace sdl3cpp::app { - -void Sdl3App::CreateFramebuffers() { - sdl3cpp::logging::TraceGuard trace;; - swapChainFramebuffers_.resize(swapChainImageViews_.size()); - for (size_t i = 0; i < swapChainImageViews_.size(); ++i) { - VkImageView attachments[] = {swapChainImageViews_[i]}; - - VkFramebufferCreateInfo framebufferInfo{}; - framebufferInfo.sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO; - framebufferInfo.renderPass = renderPass_; - framebufferInfo.attachmentCount = 1; - framebufferInfo.pAttachments = attachments; - framebufferInfo.width = swapChainExtent_.width; - framebufferInfo.height = swapChainExtent_.height; - framebufferInfo.layers = 1; - - if (vkCreateFramebuffer(device_, &framebufferInfo, nullptr, &swapChainFramebuffers_[i]) != - VK_SUCCESS) { - throw std::runtime_error("Failed to create framebuffer"); - } - } -} - -void Sdl3App::CreateCommandPool() { - sdl3cpp::logging::TraceGuard trace;; - QueueFamilyIndices indices = FindQueueFamilies(physicalDevice_); - - VkCommandPoolCreateInfo poolInfo{}; - poolInfo.sType = VK_STRUCTURE_TYPE_COMMAND_POOL_CREATE_INFO; - poolInfo.queueFamilyIndex = *indices.graphicsFamily; - poolInfo.flags = VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT; - - if (vkCreateCommandPool(device_, &poolInfo, nullptr, &commandPool_) != VK_SUCCESS) { - throw std::runtime_error("Failed to create command pool"); - } -} - -void Sdl3App::CreateSyncObjects() { - sdl3cpp::logging::TraceGuard trace;; - VkSemaphoreCreateInfo semaphoreInfo{}; - semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; - - VkFenceCreateInfo fenceInfo{}; - fenceInfo.sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO; - fenceInfo.flags = VK_FENCE_CREATE_SIGNALED_BIT; - - if (vkCreateSemaphore(device_, &semaphoreInfo, nullptr, &imageAvailableSemaphore_) != VK_SUCCESS || - vkCreateSemaphore(device_, &semaphoreInfo, nullptr, &renderFinishedSemaphore_) != VK_SUCCESS || - vkCreateFence(device_, &fenceInfo, nullptr, &inFlightFence_) != VK_SUCCESS) { - throw std::runtime_error("Failed to create synchronization objects"); - } -} - -} // namespace sdl3cpp::app diff --git a/src/app/sdl3_app_core.cpp b/src/app/sdl3_app_core.cpp deleted file mode 100644 index 9b9b2fc..0000000 --- a/src/app/sdl3_app_core.cpp +++ /dev/null @@ -1,284 +0,0 @@ -#include "app/audio_player.hpp" -#include "app/sdl3_app.hpp" -#include "logging/logger.hpp" -#include "core/platform.hpp" - -#include -#include -#include -#include -#include -#include -#include - -namespace sdl3cpp::app { - -extern std::atomic g_signalReceived; - -std::vector ReadFile(const std::string& path) { - sdl3cpp::logging::TraceGuard trace;; - - // Validate file exists before attempting to open - if (!std::filesystem::exists(path)) { - throw std::runtime_error("File not found: " + path + - "\n\nPlease ensure the file exists at this location."); - } - - if (!std::filesystem::is_regular_file(path)) { - throw std::runtime_error("Path is not a regular file: " + path); - } - - std::ifstream file(path, std::ios::ate | std::ios::binary); - if (!file) { - throw std::runtime_error("Failed to open file: " + path + - "\n\nThe file exists but cannot be opened. Check file permissions."); - } - size_t size = static_cast(file.tellg()); - if (size == 0) { - throw std::runtime_error("File is empty: " + path); - } - std::vector buffer(size); - file.seekg(0); - file.read(buffer.data(), buffer.size()); - if (!file) { - throw std::runtime_error("Failed to read file contents: " + path); - } - return buffer; -} - -namespace { - -std::string BuildSdlErrorMessage(const char* context) { - std::ostringstream oss; - oss << context; - const char* sdlError = SDL_GetError(); - if (sdlError && *sdlError != '\0') { - oss << ": " << sdlError; - } else { - oss << ": (SDL_GetError returned an empty string)"; - } - - std::string platformError = sdl3cpp::platform::GetPlatformError(); - if (!platformError.empty() && platformError != "No platform error") { - oss << " [" << platformError << "]"; - } - - return oss.str(); -} - -void ThrowSdlErrorIfFailed(bool success, const char* context) { - if (!success) { - throw std::runtime_error(BuildSdlErrorMessage(context)); - } -} - -void ShowErrorDialog(const char* title, const std::string& message) { - SDL_ShowSimpleMessageBox( - SDL_MESSAGEBOX_ERROR, - title, - message.c_str(), - nullptr); -} - -} // namespace - -Sdl3App::Sdl3App(const std::filesystem::path& scriptPath, bool luaDebug) - : scriptEngine_(scriptPath, luaDebug), - scriptDirectory_(scriptPath.parent_path()) { - sdl3cpp::logging::TraceGuard trace; - auto& logger = sdl3cpp::logging::Logger::GetInstance(); - logger.TraceVariable("scriptPath", scriptPath.string()); -} - -bool Sdl3App::ShouldStop() { - return g_signalReceived.load(); -} - -void Sdl3App::Run() { - sdl3cpp::logging::TraceGuard trace;; - InitSDL(); - InitVulkan(); - MainLoop(); - Cleanup(); -} - -void Sdl3App::InitSDL() { - sdl3cpp::logging::TraceGuard trace; - auto& logger = sdl3cpp::logging::Logger::GetInstance(); - logger.TraceVariable("kWidth", static_cast(kWidth)); - logger.TraceVariable("kHeight", static_cast(kHeight)); - - try { - ThrowSdlErrorIfFailed(SDL_Init(SDL_INIT_VIDEO | SDL_INIT_AUDIO), "SDL_Init failed"); - } catch (const std::exception& e) { - ShowErrorDialog("SDL Initialization Failed", - std::string("Failed to initialize SDL subsystems.\n\nError: ") + e.what()); - throw; - } - - try { - ThrowSdlErrorIfFailed(SDL_Vulkan_LoadLibrary(nullptr), "SDL_Vulkan_LoadLibrary failed"); - } catch (const std::exception& e) { - ShowErrorDialog("Vulkan Library Load Failed", - std::string("Failed to load Vulkan library. Make sure Vulkan drivers are installed.\n\nError: ") + e.what()); - throw; - } - - window_ = SDL_CreateWindow("SDL3 Vulkan Demo", kWidth, kHeight, SDL_WINDOW_VULKAN | SDL_WINDOW_RESIZABLE); - if (!window_) { - std::string errorMsg = BuildSdlErrorMessage("SDL_CreateWindow failed"); - ShowErrorDialog("Window Creation Failed", - std::string("Failed to create application window.\n\nError: ") + errorMsg); - throw std::runtime_error(errorMsg); - } - sdl3cpp::logging::Logger::GetInstance().TraceVariable("window_", window_); - SDL_StartTextInput(window_); - try { - audioPlayer_ = std::make_unique(); - scriptEngine_.SetAudioPlayer(audioPlayer_.get()); - } catch (const std::exception& exc) { - sdl3cpp::logging::Logger::GetInstance().Warn("AudioPlayer initialization failed: " + std::string(exc.what())); - } -} - -void Sdl3App::InitVulkan() { - sdl3cpp::logging::TraceGuard trace;; - try { - CreateInstance(); - } catch (const std::exception& e) { - ShowErrorDialog("Vulkan Instance Creation Failed", e.what()); - throw; - } - - try { - CreateSurface(); - } catch (const std::exception& e) { - ShowErrorDialog("Vulkan Surface Creation Failed", e.what()); - throw; - } - - try { - PickPhysicalDevice(); - } catch (const std::exception& e) { - ShowErrorDialog("GPU Selection Failed", e.what()); - throw; - } - - try { - CreateLogicalDevice(); - } catch (const std::exception& e) { - ShowErrorDialog("Logical Device Creation Failed", e.what()); - throw; - } - - try { - CreateSwapChain(); - SetupGuiRenderer(); - CreateImageViews(); - CreateRenderPass(); - LoadSceneData(); - CreateGraphicsPipeline(); - CreateFramebuffers(); - CreateCommandPool(); - CreateVertexBuffer(); - CreateIndexBuffer(); - CreateCommandBuffers(); - CreateSyncObjects(); - } catch (const std::exception& e) { - std::string errorMsg = "Vulkan initialization failed during resource setup:\n\n"; - errorMsg += e.what(); - ShowErrorDialog("Vulkan Resource Setup Failed", errorMsg); - throw; - } -} - -void Sdl3App::MainLoop() { - sdl3cpp::logging::TraceGuard trace;; - sdl3cpp::logging::Logger::GetInstance().TraceVariable("guiHasCommands_", guiHasCommands_); - bool running = true; - auto start = std::chrono::steady_clock::now(); - auto lastProgressTime = start; - - // Launch timeout: app must complete first frame within this time - constexpr auto kLaunchTimeout = std::chrono::seconds(5); - - while (running) { - auto now = std::chrono::steady_clock::now(); - - // Check for launch timeout if first frame hasn't completed - if (!firstFrameCompleted_) { - auto elapsed = now - start; - if (elapsed > kLaunchTimeout) { - sdl3cpp::logging::Logger::GetInstance().Error("Launch timeout: Application failed to render first frame within " + std::to_string(std::chrono::duration_cast(kLaunchTimeout).count()) + " seconds. This typically indicates GPU driver issue, window manager problem, or Vulkan swapchain configuration mismatch."); - throw std::runtime_error("Launch timeout: First frame did not complete"); - } - - // Print progress indicator every second during launch - if (now - lastProgressTime > std::chrono::seconds(1)) { - auto waitTime = std::chrono::duration_cast(elapsed).count(); - sdl3cpp::logging::Logger::GetInstance().Info("Waiting for first frame... (" + std::to_string(waitTime) + "s)"); - lastProgressTime = now; - } - } - - if (ShouldStop()) { - running = false; - break; - } - SDL_Event event; - while (SDL_PollEvent(&event)) { - if (event.type == SDL_EVENT_QUIT) { - running = false; - } else if (event.type == SDL_EVENT_WINDOW_PIXEL_SIZE_CHANGED) { - framebufferResized_ = true; - } - ProcessGuiEvent(event); - } - - float mouseX = 0.0f; - float mouseY = 0.0f; - SDL_GetMouseState(&mouseX, &mouseY); - guiInputSnapshot_.mouseX = mouseX; - guiInputSnapshot_.mouseY = mouseY; - scriptEngine_.UpdateGuiInput(guiInputSnapshot_); - if (guiHasCommands_ && guiRenderer_) { - guiCommands_ = scriptEngine_.LoadGuiCommands(); - guiRenderer_->Prepare(guiCommands_, swapChainExtent_.width, swapChainExtent_.height); - } - guiInputSnapshot_.wheel = 0.0f; - guiInputSnapshot_.textInput.clear(); - - float time = std::chrono::duration(now - start).count(); - DrawFrame(time); - } - - vkDeviceWaitIdle(device_); -} - -void Sdl3App::Cleanup() { - sdl3cpp::logging::TraceGuard trace;; - CleanupSwapChain(); - - vkDestroyBuffer(device_, vertexBuffer_, nullptr); - vkFreeMemory(device_, vertexBufferMemory_, nullptr); - vkDestroyBuffer(device_, indexBuffer_, nullptr); - vkFreeMemory(device_, indexBufferMemory_, nullptr); - vkDestroySemaphore(device_, renderFinishedSemaphore_, nullptr); - vkDestroySemaphore(device_, imageAvailableSemaphore_, nullptr); - vkDestroyFence(device_, inFlightFence_, nullptr); - vkDestroyCommandPool(device_, commandPool_, nullptr); - - vkDestroyDevice(device_, nullptr); - vkDestroySurfaceKHR(instance_, surface_, nullptr); - vkDestroyInstance(instance_, nullptr); - if (window_) { - SDL_DestroyWindow(window_); - window_ = nullptr; - } - SDL_Vulkan_UnloadLibrary(); - SDL_StopTextInput(window_); - audioPlayer_.reset(); - SDL_Quit(); -} - -} // namespace sdl3cpp::app diff --git a/src/app/sdl3_app_device.cpp b/src/app/sdl3_app_device.cpp deleted file mode 100644 index 8aec820..0000000 --- a/src/app/sdl3_app_device.cpp +++ /dev/null @@ -1,306 +0,0 @@ -#include "app/sdl3_app.hpp" -#include "logging/logger.hpp" - -#include -#include -#include -#include - -namespace sdl3cpp::app { - -void Sdl3App::CreateInstance() { - sdl3cpp::logging::TraceGuard trace;; - - // Early validation: Check if Vulkan is available - uint32_t apiVersion = 0; - VkResult enumResult = vkEnumerateInstanceVersion(&apiVersion); - if (enumResult != VK_SUCCESS) { - std::string errorMsg = "Vulkan is not available on this system.\n\n"; - errorMsg += "Please install Vulkan drivers:\n"; - errorMsg += "- Ubuntu/Debian: sudo apt install vulkan-tools libvulkan1\n"; - errorMsg += "- Fedora: sudo dnf install vulkan-tools vulkan-loader\n"; - errorMsg += "- Arch: sudo pacman -S vulkan-tools vulkan-icd-loader\n"; - errorMsg += "\nFor NVIDIA GPUs, install: nvidia-vulkan-icd\n"; - errorMsg += "For AMD GPUs, install: mesa-vulkan-drivers\n"; - throw std::runtime_error(errorMsg); - } - - uint32_t major = VK_API_VERSION_MAJOR(apiVersion); - uint32_t minor = VK_API_VERSION_MINOR(apiVersion); - uint32_t patch = VK_API_VERSION_PATCH(apiVersion); - std::cout << "Vulkan Version: " << major << "." << minor << "." << patch << "\n"; - std::cout.flush(); - - if (apiVersion < VK_API_VERSION_1_2) { - std::string errorMsg = "Vulkan version is too old.\n"; - errorMsg += "Required: 1.2 or higher\n"; - errorMsg += "Found: " + std::to_string(major) + "." + std::to_string(minor); - errorMsg += "." + std::to_string(patch) + "\n\n"; - errorMsg += "Please update your GPU drivers."; - throw std::runtime_error(errorMsg); - } - - VkApplicationInfo appInfo{}; - appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; - appInfo.pApplicationName = "SDL3 Vulkan"; - appInfo.applicationVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.pEngineName = "No Engine"; - appInfo.engineVersion = VK_MAKE_VERSION(1, 0, 0); - appInfo.apiVersion = VK_API_VERSION_1_2; - - uint32_t extensionCount = 0; - const char* const* extensions = SDL_Vulkan_GetInstanceExtensions(&extensionCount); - if (!extensions) { - throw std::runtime_error("Failed to query Vulkan extensions from SDL"); - } - - std::vector extensionList(extensions, extensions + extensionCount); - sdl3cpp::logging::Logger::GetInstance().TraceVariable("extensionCount", static_cast(extensionCount)); - sdl3cpp::logging::Logger::GetInstance().TraceVariable("extensionList.size(", extensionList.size()); - - // Enable validation layers if available - std::vector layerList; - uint32_t layerCount; - vkEnumerateInstanceLayerProperties(&layerCount, nullptr); - std::vector availableLayers(layerCount); - vkEnumerateInstanceLayerProperties(&layerCount, availableLayers.data()); - - const char* validationLayer = "VK_LAYER_KHRONOS_validation"; - bool validationAvailable = false; - for (const auto& layer : availableLayers) { - if (strcmp(layer.layerName, validationLayer) == 0) { - validationAvailable = true; - break; - } - } - - if (validationAvailable) { - layerList.push_back(validationLayer); - std::cout << "Validation layer enabled: " << validationLayer << "\n"; - } else { - std::cout << "Validation layer not available: " << validationLayer << "\n"; - } - - VkInstanceCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; - createInfo.pApplicationInfo = &appInfo; - createInfo.enabledLayerCount = static_cast(layerList.size()); - createInfo.ppEnabledLayerNames = layerList.data(); - createInfo.enabledExtensionCount = static_cast(extensionList.size()); - createInfo.ppEnabledExtensionNames = extensionList.data(); - - if (vkCreateInstance(&createInfo, nullptr, &instance_) != VK_SUCCESS) { - std::string errorMsg = "Failed to create Vulkan instance. This may be due to:\n"; - errorMsg += "- Missing or outdated Vulkan drivers\n"; - errorMsg += "- Incompatible GPU\n"; - errorMsg += "- Missing required Vulkan extensions\n\n"; - errorMsg += "Required extensions (" + std::to_string(extensionList.size()) + "):\n"; - for (const auto* ext : extensionList) { - errorMsg += " - "; - errorMsg += ext; - errorMsg += "\n"; - } - throw std::runtime_error(errorMsg); - } -} - -void Sdl3App::CreateSurface() { - sdl3cpp::logging::TraceGuard trace;; - if (!SDL_Vulkan_CreateSurface(window_, instance_, nullptr, &surface_)) { - throw std::runtime_error("Failed to create Vulkan surface"); - } -} - -void Sdl3App::PickPhysicalDevice() { - sdl3cpp::logging::TraceGuard trace;; - uint32_t deviceCount = 0; - VkResult enumResult = vkEnumeratePhysicalDevices(instance_, &deviceCount, nullptr); - if (enumResult != VK_SUCCESS) { - throw std::runtime_error("Failed to enumerate physical devices (error code: " + - std::to_string(enumResult) + ")"); - } - if (deviceCount == 0) { - throw std::runtime_error("Failed to find GPUs with Vulkan support.\n\nPlease ensure:\n- You have a compatible GPU\n- Vulkan drivers are properly installed\n- Your GPU supports Vulkan 1.2 or higher"); - } - std::vector devices(deviceCount); - vkEnumeratePhysicalDevices(instance_, &deviceCount, devices.data()); - - std::string deviceInfo; - std::cout << "\n=== GPU Detection ===\n"; - for (size_t i = 0; i < devices.size(); ++i) { - VkPhysicalDeviceProperties props; - vkGetPhysicalDeviceProperties(devices[i], &props); - - VkPhysicalDeviceMemoryProperties memProps; - vkGetPhysicalDeviceMemoryProperties(devices[i], &memProps); - - uint64_t totalMemory = 0; - for (uint32_t j = 0; j < memProps.memoryHeapCount; ++j) { - if (memProps.memoryHeaps[j].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) { - totalMemory += memProps.memoryHeaps[j].size; - } - } - - deviceInfo += "\nGPU " + std::to_string(i) + ": " + props.deviceName; - deviceInfo += " (VRAM: " + std::to_string(totalMemory / (1024 * 1024)) + " MB)"; - std::cout << "GPU " << i << ": " << props.deviceName - << " (VRAM: " << (totalMemory / (1024 * 1024)) << " MB)\n"; - - if (IsDeviceSuitable(devices[i])) { - physicalDevice_ = devices[i]; - deviceInfo += " [SELECTED]"; - std::cout << " -> SELECTED\n"; - break; - } else { - deviceInfo += " [UNSUITABLE]"; - std::cout << " -> UNSUITABLE (missing required features)\n"; - } - } - std::cout << "==================\n\n"; - std::cout.flush(); - - if (physicalDevice_ == VK_NULL_HANDLE) { - std::string errorMsg = "Failed to find a suitable GPU.\n\n"; - errorMsg += "Found " + std::to_string(deviceCount) + " GPU(s), but none meet the requirements."; - errorMsg += deviceInfo; - errorMsg += "\n\nRequired features:\n"; - errorMsg += "- Graphics queue support\n"; - errorMsg += "- Present queue support\n"; - errorMsg += "- Swapchain extension support (VK_KHR_swapchain)\n"; - errorMsg += "- Adequate swapchain formats and present modes\n"; - throw std::runtime_error(errorMsg); - } -} - -void Sdl3App::CreateLogicalDevice() { - sdl3cpp::logging::TraceGuard trace;; - QueueFamilyIndices indices = FindQueueFamilies(physicalDevice_); - - std::vector queueCreateInfos; - std::set uniqueQueueFamilies = {*indices.graphicsFamily, *indices.presentFamily}; - - float queuePriority = 1.0f; - for (uint32_t queueFamily : uniqueQueueFamilies) { - VkDeviceQueueCreateInfo queueCreateInfo{}; - queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; - queueCreateInfo.queueFamilyIndex = queueFamily; - queueCreateInfo.queueCount = 1; - queueCreateInfo.pQueuePriorities = &queuePriority; - queueCreateInfos.push_back(queueCreateInfo); - } - - VkPhysicalDeviceFeatures deviceFeatures{}; - - VkDeviceCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; - createInfo.queueCreateInfoCount = static_cast(queueCreateInfos.size()); - createInfo.pQueueCreateInfos = queueCreateInfos.data(); - createInfo.pEnabledFeatures = &deviceFeatures; - createInfo.enabledExtensionCount = static_cast(kDeviceExtensions.size()); - createInfo.ppEnabledExtensionNames = kDeviceExtensions.data(); - - if (vkCreateDevice(physicalDevice_, &createInfo, nullptr, &device_) != VK_SUCCESS) { - sdl3cpp::logging::Logger::GetInstance().Error("Failed to create logical device"); - throw std::runtime_error("Failed to create logical device"); - } - - sdl3cpp::logging::Logger::GetInstance().Info("Logical device created successfully"); - vkGetDeviceQueue(device_, *indices.graphicsFamily, 0, &graphicsQueue_); - vkGetDeviceQueue(device_, *indices.presentFamily, 0, &presentQueue_); -} - -QueueFamilyIndices Sdl3App::FindQueueFamilies(VkPhysicalDevice device) { - sdl3cpp::logging::TraceGuard trace;; - QueueFamilyIndices indices; - - uint32_t queueFamilyCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, nullptr); - - std::vector queueFamilies(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(device, &queueFamilyCount, queueFamilies.data()); - - int i = 0; - for (const auto& queueFamily : queueFamilies) { - if (queueFamily.queueFlags & VK_QUEUE_GRAPHICS_BIT) { - indices.graphicsFamily = i; - } - - VkBool32 presentSupport = VK_FALSE; - vkGetPhysicalDeviceSurfaceSupportKHR(device, i, surface_, &presentSupport); - - if (presentSupport) { - indices.presentFamily = i; - } - - if (indices.isComplete()) { - break; - } - ++i; - } - - return indices; -} - -bool Sdl3App::CheckDeviceExtensionSupport(VkPhysicalDevice device) { - sdl3cpp::logging::TraceGuard trace;; - uint32_t extensionCount = 0; - vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, nullptr); - - std::vector availableExtensions(extensionCount); - vkEnumerateDeviceExtensionProperties(device, nullptr, &extensionCount, availableExtensions.data()); - - std::set requiredExtensions(kDeviceExtensions.begin(), kDeviceExtensions.end()); - - for (const auto& extension : availableExtensions) { - requiredExtensions.erase(extension.extensionName); - } - - if (!requiredExtensions.empty()) { - std::string missingList; - for (const auto& missing : requiredExtensions) { - missingList += " - " + missing + "\n"; - } - sdl3cpp::logging::Logger::GetInstance().Error("Missing required device extensions:\n" + missingList); - } - - return requiredExtensions.empty(); -} - -SwapChainSupportDetails Sdl3App::QuerySwapChainSupport(VkPhysicalDevice device) { - sdl3cpp::logging::TraceGuard trace;; - SwapChainSupportDetails details; - vkGetPhysicalDeviceSurfaceCapabilitiesKHR(device, surface_, &details.capabilities); - - uint32_t formatCount; - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface_, &formatCount, nullptr); - if (formatCount != 0) { - details.formats.resize(formatCount); - vkGetPhysicalDeviceSurfaceFormatsKHR(device, surface_, &formatCount, details.formats.data()); - } - - uint32_t presentModeCount; - vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface_, &presentModeCount, nullptr); - if (presentModeCount != 0) { - details.presentModes.resize(presentModeCount); - vkGetPhysicalDeviceSurfacePresentModesKHR(device, surface_, &presentModeCount, - details.presentModes.data()); - } - - return details; -} - -bool Sdl3App::IsDeviceSuitable(VkPhysicalDevice device) { - sdl3cpp::logging::TraceGuard trace;; - QueueFamilyIndices indices = FindQueueFamilies(device); - - bool extensionsSupported = CheckDeviceExtensionSupport(device); - bool swapChainAdequate = false; - if (extensionsSupported) { - auto details = QuerySwapChainSupport(device); - swapChainAdequate = !details.formats.empty() && !details.presentModes.empty(); - } - - return indices.isComplete() && extensionsSupported && swapChainAdequate; -} - -} // namespace sdl3cpp::app diff --git a/src/app/sdl3_app_pipeline.cpp b/src/app/sdl3_app_pipeline.cpp deleted file mode 100644 index 1b0df18..0000000 --- a/src/app/sdl3_app_pipeline.cpp +++ /dev/null @@ -1,191 +0,0 @@ -#include "app/sdl3_app.hpp" -#include "logging/logger.hpp" - -#include -#include - -namespace sdl3cpp::app { - -VkShaderModule Sdl3App::CreateShaderModule(const std::vector& code) { - sdl3cpp::logging::TraceGuard trace;; - VkShaderModuleCreateInfo createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_SHADER_MODULE_CREATE_INFO; - createInfo.codeSize = code.size(); - createInfo.pCode = reinterpret_cast(code.data()); - - VkShaderModule shaderModule; - if (vkCreateShaderModule(device_, &createInfo, nullptr, &shaderModule) != VK_SUCCESS) { - throw std::runtime_error("Failed to create shader module"); - } - return shaderModule; -} - -void Sdl3App::CreateGraphicsPipeline() { - sdl3cpp::logging::TraceGuard trace;; - if (shaderPathMap_.empty()) { - throw std::runtime_error("No shader paths were loaded before pipeline creation"); - } - - for (auto& entry : graphicsPipelines_) { - vkDestroyPipeline(device_, entry.second, nullptr); - } - graphicsPipelines_.clear(); - - VkPipelineVertexInputStateCreateInfo vertexInputInfo{}; - VkVertexInputBindingDescription bindingDescription{}; - bindingDescription.binding = 0; - bindingDescription.stride = sizeof(core::Vertex); - bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX; - - std::array attributeDescriptions{}; - attributeDescriptions[0].binding = 0; - attributeDescriptions[0].location = 0; - attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT; - attributeDescriptions[0].offset = offsetof(core::Vertex, position); - - attributeDescriptions[1].binding = 0; - attributeDescriptions[1].location = 1; - attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT; - attributeDescriptions[1].offset = offsetof(core::Vertex, color); - - vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO; - vertexInputInfo.vertexBindingDescriptionCount = 1; - vertexInputInfo.pVertexBindingDescriptions = &bindingDescription; - vertexInputInfo.vertexAttributeDescriptionCount = static_cast(attributeDescriptions.size()); - vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data(); - - VkPipelineInputAssemblyStateCreateInfo inputAssembly{}; - inputAssembly.sType = VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO; - inputAssembly.topology = VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST; - inputAssembly.primitiveRestartEnable = VK_FALSE; - - VkViewport viewport{}; - viewport.x = 0.0f; - viewport.y = 0.0f; - viewport.width = static_cast(swapChainExtent_.width); - viewport.height = static_cast(swapChainExtent_.height); - viewport.minDepth = 0.0f; - viewport.maxDepth = 1.0f; - - VkRect2D scissor{}; - scissor.offset = {0, 0}; - scissor.extent = swapChainExtent_; - - VkPipelineViewportStateCreateInfo viewportState{}; - viewportState.sType = VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO; - viewportState.viewportCount = 1; - viewportState.pViewports = &viewport; - viewportState.scissorCount = 1; - viewportState.pScissors = &scissor; - - VkPipelineRasterizationStateCreateInfo rasterizer{}; - rasterizer.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO; - rasterizer.depthClampEnable = VK_FALSE; - rasterizer.rasterizerDiscardEnable = VK_FALSE; - rasterizer.polygonMode = VK_POLYGON_MODE_FILL; - rasterizer.lineWidth = 1.0f; - rasterizer.cullMode = VK_CULL_MODE_BACK_BIT; - rasterizer.frontFace = VK_FRONT_FACE_CLOCKWISE; - rasterizer.depthBiasEnable = VK_FALSE; - - VkPipelineMultisampleStateCreateInfo multisampling{}; - multisampling.sType = VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO; - multisampling.sampleShadingEnable = VK_FALSE; - multisampling.rasterizationSamples = VK_SAMPLE_COUNT_1_BIT; - - VkPipelineColorBlendAttachmentState colorBlendAttachment{}; - colorBlendAttachment.colorWriteMask = VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | - VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT; - colorBlendAttachment.blendEnable = VK_FALSE; - - VkPipelineColorBlendStateCreateInfo colorBlending{}; - colorBlending.sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO; - colorBlending.logicOpEnable = VK_FALSE; - colorBlending.attachmentCount = 1; - colorBlending.pAttachments = &colorBlendAttachment; - - VkPushConstantRange pushRange{}; - pushRange.stageFlags = VK_SHADER_STAGE_VERTEX_BIT; - pushRange.offset = 0; - pushRange.size = sizeof(core::PushConstants); - - VkPipelineLayoutCreateInfo pipelineLayoutInfo{}; - pipelineLayoutInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO; - pipelineLayoutInfo.pushConstantRangeCount = 1; - pipelineLayoutInfo.pPushConstantRanges = &pushRange; - - if (pipelineLayout_ != VK_NULL_HANDLE) { - vkDestroyPipelineLayout(device_, pipelineLayout_, nullptr); - pipelineLayout_ = VK_NULL_HANDLE; - } - - if (vkCreatePipelineLayout(device_, &pipelineLayoutInfo, nullptr, &pipelineLayout_) != VK_SUCCESS) { - throw std::runtime_error("Failed to create pipeline layout"); - } - - VkGraphicsPipelineCreateInfo pipelineInfo{}; - pipelineInfo.sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO; - pipelineInfo.pVertexInputState = &vertexInputInfo; - pipelineInfo.pInputAssemblyState = &inputAssembly; - pipelineInfo.pViewportState = &viewportState; - pipelineInfo.pRasterizationState = &rasterizer; - pipelineInfo.pMultisampleState = &multisampling; - pipelineInfo.pColorBlendState = &colorBlending; - pipelineInfo.layout = pipelineLayout_; - pipelineInfo.renderPass = renderPass_; - pipelineInfo.subpass = 0; - - for (const auto& [key, paths] : shaderPathMap_) { - // Validate shader files exist before attempting to load - if (!std::filesystem::exists(paths.vertex)) { - throw std::runtime_error( - "Vertex shader not found: " + paths.vertex + - "\n\nShader key: " + key + - "\n\nPlease ensure shader files are compiled and present in the shaders directory."); - } - if (!std::filesystem::exists(paths.fragment)) { - throw std::runtime_error( - "Fragment shader not found: " + paths.fragment + - "\n\nShader key: " + key + - "\n\nPlease ensure shader files are compiled and present in the shaders directory."); - } - - auto vertShaderCode = ReadFile(paths.vertex); - auto fragShaderCode = ReadFile(paths.fragment); - - VkShaderModule vertShaderModule = CreateShaderModule(vertShaderCode); - VkShaderModule fragShaderModule = CreateShaderModule(fragShaderCode); - - VkPipelineShaderStageCreateInfo vertStageInfo{}; - vertStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - vertStageInfo.stage = VK_SHADER_STAGE_VERTEX_BIT; - vertStageInfo.module = vertShaderModule; - vertStageInfo.pName = "main"; - - VkPipelineShaderStageCreateInfo fragStageInfo{}; - fragStageInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO; - fragStageInfo.stage = VK_SHADER_STAGE_FRAGMENT_BIT; - fragStageInfo.module = fragShaderModule; - fragStageInfo.pName = "main"; - - VkPipelineShaderStageCreateInfo shaderStages[] = {vertStageInfo, fragStageInfo}; - - VkGraphicsPipelineCreateInfo pipelineCreateInfo = pipelineInfo; - pipelineCreateInfo.stageCount = 2; - pipelineCreateInfo.pStages = shaderStages; - - VkPipeline pipeline; - if (vkCreateGraphicsPipelines(device_, VK_NULL_HANDLE, 1, &pipelineCreateInfo, nullptr, - &pipeline) != VK_SUCCESS) { - vkDestroyShaderModule(device_, fragShaderModule, nullptr); - vkDestroyShaderModule(device_, vertShaderModule, nullptr); - throw std::runtime_error("Failed to create graphics pipeline"); - } - graphicsPipelines_.emplace(key, pipeline); - - vkDestroyShaderModule(device_, fragShaderModule, nullptr); - vkDestroyShaderModule(device_, vertShaderModule, nullptr); - } -} - -} // namespace sdl3cpp::app diff --git a/src/app/sdl3_app_render.cpp b/src/app/sdl3_app_render.cpp deleted file mode 100644 index b4f2b6c..0000000 --- a/src/app/sdl3_app_render.cpp +++ /dev/null @@ -1,370 +0,0 @@ -#include "app/sdl3_app.hpp" -#include "logging/logger.hpp" - -#include -#include -#include -#include -#include - -namespace { -const std::unordered_map kGuiKeyNames = { - {SDLK_BACKSPACE, "backspace"}, - {SDLK_DELETE, "delete"}, - {SDLK_LEFT, "left"}, - {SDLK_RIGHT, "right"}, - {SDLK_HOME, "home"}, - {SDLK_END, "end"}, - {SDLK_RETURN, "enter"}, - {SDLK_UP, "up"}, - {SDLK_DOWN, "down"}, -}; -} // namespace - -namespace sdl3cpp::app { - -void Sdl3App::PrintGpuDiagnostics(const std::string& errorContext) { - std::stringstream ss; - ss << "\n========================================\n"; - ss << "GPU DIAGNOSTIC REPORT\n"; - ss << "========================================\n"; - ss << "Error Context: " << errorContext << "\n\n"; - - // Device properties - if (physicalDevice_ != VK_NULL_HANDLE) { - VkPhysicalDeviceProperties deviceProps{}; - vkGetPhysicalDeviceProperties(physicalDevice_, &deviceProps); - - ss << "=== GPU Information ===\n"; - ss << "Device Name: " << deviceProps.deviceName << "\n"; - ss << "Driver Version: " << VK_API_VERSION_MAJOR(deviceProps.driverVersion) << "." - << VK_API_VERSION_MINOR(deviceProps.driverVersion) << "." - << VK_API_VERSION_PATCH(deviceProps.driverVersion) << "\n"; - ss << "API Version: " << VK_API_VERSION_MAJOR(deviceProps.apiVersion) << "." - << VK_API_VERSION_MINOR(deviceProps.apiVersion) << "." - << VK_API_VERSION_PATCH(deviceProps.apiVersion) << "\n"; - ss << "Vendor ID: 0x" << std::hex << deviceProps.vendorID << std::dec << "\n"; - ss << "Device ID: 0x" << std::hex << deviceProps.deviceID << std::dec << "\n"; - - VkPhysicalDeviceMemoryProperties memProps{}; - vkGetPhysicalDeviceMemoryProperties(physicalDevice_, &memProps); - - ss << "\n=== Memory Information ===\n"; - uint64_t totalVRAM = 0; - for (uint32_t i = 0; i < memProps.memoryHeapCount; i++) { - if (memProps.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) { - totalVRAM += memProps.memoryHeaps[i].size; - } - } - ss << "Total VRAM: " << (totalVRAM / 1024 / 1024) << " MB\n"; - - // Memory heaps breakdown - ss << "Memory Heaps (" << memProps.memoryHeapCount << "):\n"; - for (uint32_t i = 0; i < memProps.memoryHeapCount; i++) { - ss << " Heap " << i << ": " << (memProps.memoryHeaps[i].size / 1024 / 1024) << " MB"; - if (memProps.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) { - ss << " (Device Local)"; - } - ss << "\n"; - } - } - - // Swapchain state - ss << "\n=== Swapchain State ===\n"; - ss << "Extent: " << swapChainExtent_.width << "x" << swapChainExtent_.height << "\n"; - ss << "Image Count: " << swapChainImages_.size() << "\n"; - ss << "Format: " << swapChainImageFormat_ << "\n"; - ss << "Consecutive Recreations: " << consecutiveSwapchainRecreations_ << "\n"; - ss << "Framebuffer Resized Flag: " << (framebufferResized_ ? "true" : "false") << "\n"; - ss << "First Frame Completed: " << (firstFrameCompleted_ ? "true" : "false") << "\n"; - - // Render objects - ss << "\n=== Scene State ===\n"; - ss << "Render Objects: " << renderObjects_.size() << "\n"; - ss << "Vertices: " << vertices_.size() << "\n"; - ss << "Indices: " << indices_.size() << "\n"; - ss << "Pipelines: " << graphicsPipelines_.size() << "\n"; - ss << "GUI Renderer Active: " << (guiRenderer_ ? "true" : "false") << "\n"; - ss << "GUI Has Commands: " << (guiHasCommands_ ? "true" : "false") << "\n"; - - // Check device features that might be related - if (physicalDevice_ != VK_NULL_HANDLE) { - VkPhysicalDeviceFeatures deviceFeatures{}; - vkGetPhysicalDeviceFeatures(physicalDevice_, &deviceFeatures); - - ss << "\n=== Relevant Device Features ===\n"; - ss << "Geometry Shader: " << (deviceFeatures.geometryShader ? "supported" : "not supported") << "\n"; - ss << "Tessellation Shader: " << (deviceFeatures.tessellationShader ? "supported" : "not supported") << "\n"; - ss << "Multi Draw Indirect: " << (deviceFeatures.multiDrawIndirect ? "supported" : "not supported") << "\n"; - } - - // Queue properties - if (physicalDevice_ != VK_NULL_HANDLE) { - uint32_t queueFamilyCount = 0; - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice_, &queueFamilyCount, nullptr); - std::vector queueFamilies(queueFamilyCount); - vkGetPhysicalDeviceQueueFamilyProperties(physicalDevice_, &queueFamilyCount, queueFamilies.data()); - - ss << "\n=== Queue Families ===\n"; - for (uint32_t i = 0; i < queueFamilyCount; i++) { - ss << "Family " << i << ": " << queueFamilies[i].queueCount << " queues, flags: 0x" - << std::hex << queueFamilies[i].queueFlags << std::dec << "\n"; - } - } - - ss << "\n=== Possible Causes ===\n"; - ss << "1. GPU driver crash or hang - Check dmesg for GPU reset messages\n"; - ss << "2. Infinite loop in shader code - Review vertex/fragment shaders\n"; - ss << "3. Command buffer submission issue - Check synchronization\n"; - ss << "4. GPU overheating or hardware issue - Monitor GPU temperature\n"; - ss << "5. Driver bug - Try updating GPU drivers to latest version\n"; - ss << "6. Resource exhaustion - Check system memory and VRAM usage\n"; - - ss << "\n=== Recommended Actions ===\n"; - ss << "1. Check system logs: dmesg | grep -i 'gpu\\|radeon\\|amdgpu'\n"; - ss << "2. Update GPU drivers: sudo dnf update mesa-vulkan-drivers\n"; - ss << "3. Verify GPU health: radeontop or similar monitoring tool\n"; - ss << "4. Check for driver messages: journalctl -k | grep -i amdgpu\n"; - ss << "5. Try with different Vulkan settings or validation layers\n"; - ss << "========================================\n"; - - // sdl3cpp::logging::Logger::GetInstance().Error(ss.str()); - std::cerr << ss.str() << std::endl; -} - -void Sdl3App::CreateCommandBuffers() { - sdl3cpp::logging::TraceGuard trace;; - commandBuffers_.resize(swapChainFramebuffers_.size()); - - VkCommandBufferAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO; - allocInfo.commandPool = commandPool_; - allocInfo.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY; - allocInfo.commandBufferCount = static_cast(commandBuffers_.size()); - - if (vkAllocateCommandBuffers(device_, &allocInfo, commandBuffers_.data()) != VK_SUCCESS) { - throw std::runtime_error("Failed to allocate command buffers"); - } -} - -void Sdl3App::RecordCommandBuffer(VkCommandBuffer commandBuffer, uint32_t imageIndex, float time, - const std::array& viewProj) { - sdl3cpp::logging::TraceGuard trace;; - sdl3cpp::logging::Logger::GetInstance().TraceVariable("imageIndex", static_cast(imageIndex)); - VkCommandBufferBeginInfo beginInfo{}; - beginInfo.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO; - - vkBeginCommandBuffer(commandBuffer, &beginInfo); - - VkRenderPassBeginInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO; - renderPassInfo.renderPass = renderPass_; - renderPassInfo.framebuffer = swapChainFramebuffers_[imageIndex]; - renderPassInfo.renderArea.offset = {0, 0}; - renderPassInfo.renderArea.extent = swapChainExtent_; - - VkClearValue clearColor = {{{0.1f, 0.1f, 0.15f, 1.0f}}}; - renderPassInfo.clearValueCount = 1; - renderPassInfo.pClearValues = &clearColor; - - vkCmdBeginRenderPass(commandBuffer, &renderPassInfo, VK_SUBPASS_CONTENTS_INLINE); - - VkBuffer vertexBuffers[] = {vertexBuffer_}; - VkDeviceSize offsets[] = {0}; - vkCmdBindVertexBuffers(commandBuffer, 0, 1, vertexBuffers, offsets); - vkCmdBindIndexBuffer(commandBuffer, indexBuffer_, 0, VK_INDEX_TYPE_UINT16); - core::PushConstants pushConstants{}; - pushConstants.viewProj = viewProj; - // Temporarily disable drawing to test if hang is caused by draw commands - /* - for (const auto& object : renderObjects_) { - auto pipelineIt = graphicsPipelines_.find(object.shaderKey); - if (pipelineIt == graphicsPipelines_.end()) { - pipelineIt = graphicsPipelines_.find(defaultShaderKey_); - if (pipelineIt == graphicsPipelines_.end()) { - throw std::runtime_error("Missing pipeline for shader key"); - } - } - vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineIt->second); - pushConstants.model = scriptEngine_.ComputeModelMatrix(object.computeModelMatrixRef, time); - vkCmdPushConstants(commandBuffer, pipelineLayout_, VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(core::PushConstants), - &pushConstants); - vkCmdDrawIndexed(commandBuffer, object.indexCount, 1, object.indexOffset, object.vertexOffset, 0); - } - */ - vkCmdEndRenderPass(commandBuffer); - // Temporarily disable GUI rendering to test if it's causing the GPU hang - /* - if (guiRenderer_) { - guiRenderer_->BlitToSwapchain(commandBuffer, swapChainImages_[imageIndex]); - } - */ - vkEndCommandBuffer(commandBuffer); -} - -void Sdl3App::ProcessGuiEvent(const SDL_Event& event) { - sdl3cpp::logging::TraceGuard trace;; - switch (event.type) { - case SDL_EVENT_MOUSE_MOTION: - guiInputSnapshot_.mouseX = static_cast(event.motion.x); - guiInputSnapshot_.mouseY = static_cast(event.motion.y); - break; - case SDL_EVENT_MOUSE_BUTTON_DOWN: - case SDL_EVENT_MOUSE_BUTTON_UP: - if (event.button.button == SDL_BUTTON_LEFT) { - guiInputSnapshot_.mouseDown = (event.type == SDL_EVENT_MOUSE_BUTTON_DOWN); - } - break; - case SDL_EVENT_MOUSE_WHEEL: - guiInputSnapshot_.wheel += static_cast(event.wheel.y); - break; - case SDL_EVENT_TEXT_INPUT: - guiInputSnapshot_.textInput.append(event.text.text); - break; - case SDL_EVENT_KEY_DOWN: - case SDL_EVENT_KEY_UP: { - SDL_Keycode key = event.key.key; - auto it = kGuiKeyNames.find(key); - if (it != kGuiKeyNames.end()) { - guiInputSnapshot_.keyStates[it->second] = (event.type == SDL_EVENT_KEY_DOWN); - } - break; - } - default: - break; - } -} - -void Sdl3App::SetupGuiRenderer() { - sdl3cpp::logging::TraceGuard trace;; - guiHasCommands_ = scriptEngine_.HasGuiCommands(); - if (!guiHasCommands_) { - guiRenderer_.reset(); - return; - } - if (!guiRenderer_) { - guiRenderer_ = - std::make_unique(device_, physicalDevice_, swapChainImageFormat_, - scriptEngine_.GetScriptDirectory()); - } - guiRenderer_->Resize(swapChainExtent_.width, swapChainExtent_.height, swapChainImageFormat_); -} - -void Sdl3App::DrawFrame(float time) { - sdl3cpp::logging::TraceGuard trace;; - sdl3cpp::logging::Logger::GetInstance().Debug("Drawing frame at time " + std::to_string(time)); - - // Use reasonable timeout instead of infinite wait (5 seconds) - constexpr uint64_t kFenceTimeout = 5000000000ULL; // 5 seconds in nanoseconds - VkResult fenceResult = vkWaitForFences(device_, 1, &inFlightFence_, VK_TRUE, kFenceTimeout); - if (fenceResult == VK_TIMEOUT) { - sdl3cpp::logging::Logger::GetInstance().Error("Fence wait timeout: GPU appears to be hung"); - PrintGpuDiagnostics("Fence wait timeout after 5 seconds"); - throw std::runtime_error("Fence wait timeout: GPU appears to be hung"); - } else if (fenceResult != VK_SUCCESS) { - sdl3cpp::logging::Logger::GetInstance().Error("Fence wait failed with code: " + std::to_string(fenceResult)); - PrintGpuDiagnostics("Fence wait failed with error code " + std::to_string(fenceResult)); - throw std::runtime_error("Fence wait failed"); - } - vkResetFences(device_, 1, &inFlightFence_); - - uint32_t imageIndex; - // Use reasonable timeout for image acquisition (5 seconds) - VkResult result = vkAcquireNextImageKHR(device_, swapChain_, kFenceTimeout, - imageAvailableSemaphore_, VK_NULL_HANDLE, &imageIndex); - - if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized_) { - consecutiveSwapchainRecreations_++; - std::string logMsg = "Swapchain recreation triggered (attempt " + std::to_string(consecutiveSwapchainRecreations_) + ")"; - if (result == VK_ERROR_OUT_OF_DATE_KHR) { - logMsg += " - OUT_OF_DATE"; - } else if (result == VK_SUBOPTIMAL_KHR) { - logMsg += " - SUBOPTIMAL"; - } else if (framebufferResized_) { - logMsg += " - RESIZE_EVENT"; - } - sdl3cpp::logging::Logger::GetInstance().Info(logMsg); - - // Detect infinite swapchain recreation loop - constexpr int kMaxConsecutiveRecreations = 10; - if (consecutiveSwapchainRecreations_ > kMaxConsecutiveRecreations) { - throw std::runtime_error( - "Swapchain recreation loop detected: " + std::to_string(consecutiveSwapchainRecreations_) + - " consecutive recreations. This may indicate a driver issue or window manager problem.\n" - "Try running with a different window manager or updating your GPU drivers."); - } - - RecreateSwapChain(); - return; - } else if (result == VK_TIMEOUT) { - std::cerr << "\nERROR: Image acquisition timeout: GPU appears to be hung\n"; - PrintGpuDiagnostics("Image acquisition timeout after 5 seconds"); - throw std::runtime_error("Image acquisition timeout: GPU appears to be hung"); - } else if (result != VK_SUCCESS) { - throw std::runtime_error("Failed to acquire swap chain image"); - } - sdl3cpp::logging::Logger::GetInstance().TraceVariable("imageIndex", static_cast(imageIndex)); - - float aspect = static_cast(swapChainExtent_.width) / static_cast(swapChainExtent_.height); - auto viewProj = scriptEngine_.GetViewProjectionMatrix(aspect); - - vkResetCommandBuffer(commandBuffers_[imageIndex], 0); - RecordCommandBuffer(commandBuffers_[imageIndex], imageIndex, time, viewProj); - - VkSemaphore waitSemaphores[] = {imageAvailableSemaphore_}; - VkSemaphore signalSemaphores[] = {renderFinishedSemaphore_}; - VkPipelineStageFlags waitStages[] = {VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT}; - - VkSubmitInfo submitInfo{}; - submitInfo.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; - submitInfo.waitSemaphoreCount = 1; - submitInfo.pWaitSemaphores = waitSemaphores; - submitInfo.pWaitDstStageMask = waitStages; - submitInfo.commandBufferCount = 1; - submitInfo.pCommandBuffers = &commandBuffers_[imageIndex]; - submitInfo.signalSemaphoreCount = 1; - submitInfo.pSignalSemaphores = signalSemaphores; - - if (vkQueueSubmit(graphicsQueue_, 1, &submitInfo, inFlightFence_) != VK_SUCCESS) { - throw std::runtime_error("Failed to submit draw command buffer"); - } - - VkPresentInfoKHR presentInfo{}; - presentInfo.sType = VK_STRUCTURE_TYPE_PRESENT_INFO_KHR; - presentInfo.waitSemaphoreCount = 1; - presentInfo.pWaitSemaphores = signalSemaphores; - presentInfo.swapchainCount = 1; - presentInfo.pSwapchains = &swapChain_; - presentInfo.pImageIndices = &imageIndex; - - result = vkQueuePresentKHR(presentQueue_, &presentInfo); - if (result == VK_ERROR_OUT_OF_DATE_KHR || result == VK_SUBOPTIMAL_KHR || framebufferResized_) { - consecutiveSwapchainRecreations_++; - std::cout << "Swapchain recreation after present (attempt " << consecutiveSwapchainRecreations_ << ")\n"; - - constexpr int kMaxConsecutiveRecreations = 10; - if (consecutiveSwapchainRecreations_ > kMaxConsecutiveRecreations) { - throw std::runtime_error( - "Swapchain recreation loop detected after present: " + std::to_string(consecutiveSwapchainRecreations_) + - " consecutive recreations."); - } - - RecreateSwapChain(); - } else if (result != VK_SUCCESS) { - throw std::runtime_error("Failed to present swap chain image"); - } else { - // Successfully presented a frame - reset counter - if (consecutiveSwapchainRecreations_ > 0) { - std::cout << "Frame presented successfully after " << consecutiveSwapchainRecreations_ - << " swapchain recreation(s)\n"; - } - consecutiveSwapchainRecreations_ = 0; - - if (!firstFrameCompleted_) { - firstFrameCompleted_ = true; - std::cout << "First frame completed successfully\n"; - } - } -} - -} // namespace sdl3cpp::app diff --git a/src/app/sdl3_app_swapchain.cpp b/src/app/sdl3_app_swapchain.cpp deleted file mode 100644 index 5c58f29..0000000 --- a/src/app/sdl3_app_swapchain.cpp +++ /dev/null @@ -1,246 +0,0 @@ -#include "app/sdl3_app.hpp" -#include "app/vulkan_api.hpp" -#include "logging/logger.hpp" - -#include - -namespace sdl3cpp::app { - -void Sdl3App::CreateSwapChain() { - sdl3cpp::logging::TraceGuard trace;; - SwapChainSupportDetails support = QuerySwapChainSupport(physicalDevice_); - - // Validate swap chain support - if (support.formats.empty()) { - throw std::runtime_error("No surface formats available for swap chain.\n" - "This may indicate GPU driver issues or incompatible surface."); - } - if (support.presentModes.empty()) { - throw std::runtime_error("No present modes available for swap chain.\n" - "This may indicate GPU driver issues or incompatible surface."); - } - - // Validate window dimensions - int windowWidth = 0, windowHeight = 0; - SDL_GetWindowSize(window_, &windowWidth, &windowHeight); - sdl3cpp::logging::Logger::GetInstance().Info("Window size: " + std::to_string(windowWidth) + "x" + std::to_string(windowHeight)); - - if (windowWidth == 0 || windowHeight == 0) { - sdl3cpp::logging::Logger::GetInstance().Error("Invalid window dimensions (" + std::to_string(windowWidth) + "x" + std::to_string(windowHeight) + "). Window may be minimized or invalid."); - throw std::runtime_error("Invalid window dimensions (" + - std::to_string(windowWidth) + "x" + std::to_string(windowHeight) + ").\n" + - "Window may be minimized or invalid."); - } - - sdl3cpp::logging::Logger::GetInstance().Debug("Surface capabilities - Min extent: " + std::to_string(support.capabilities.minImageExtent.width) + "x" + std::to_string(support.capabilities.minImageExtent.height) + - ", Max extent: " + std::to_string(support.capabilities.maxImageExtent.width) + "x" + std::to_string(support.capabilities.maxImageExtent.height) + - ", Min images: " + std::to_string(support.capabilities.minImageCount) + - ", Max images: " + std::to_string(support.capabilities.maxImageCount)); - - VkSurfaceFormatKHR surfaceFormat = ChooseSwapSurfaceFormat(support.formats); - VkPresentModeKHR presentMode = ChooseSwapPresentMode(support.presentModes); - VkExtent2D extent = vulkan::ChooseSwapExtent(support.capabilities, window_); - - uint32_t imageCount = support.capabilities.minImageCount + 1; - if (support.capabilities.maxImageCount > 0 && imageCount > support.capabilities.maxImageCount) { - imageCount = support.capabilities.maxImageCount; - } - sdl3cpp::logging::Logger::GetInstance().TraceVariable("imageCount", static_cast(imageCount)); - - VkSwapchainCreateInfoKHR createInfo{}; - createInfo.sType = VK_STRUCTURE_TYPE_SWAPCHAIN_CREATE_INFO_KHR; - createInfo.surface = surface_; - createInfo.minImageCount = imageCount; - createInfo.imageFormat = surfaceFormat.format; - createInfo.imageColorSpace = surfaceFormat.colorSpace; - createInfo.imageExtent = extent; - createInfo.imageArrayLayers = 1; - createInfo.imageUsage = VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT; - - QueueFamilyIndices indices = FindQueueFamilies(physicalDevice_); - uint32_t queueFamilyIndices[] = {*indices.graphicsFamily, *indices.presentFamily}; - if (indices.graphicsFamily != indices.presentFamily) { - createInfo.imageSharingMode = VK_SHARING_MODE_CONCURRENT; - createInfo.queueFamilyIndexCount = 2; - createInfo.pQueueFamilyIndices = queueFamilyIndices; - } else { - createInfo.imageSharingMode = VK_SHARING_MODE_EXCLUSIVE; - } - - createInfo.preTransform = support.capabilities.currentTransform; - createInfo.compositeAlpha = VK_COMPOSITE_ALPHA_OPAQUE_BIT_KHR; - createInfo.presentMode = presentMode; - createInfo.clipped = VK_TRUE; - - if (vkCreateSwapchainKHR(device_, &createInfo, nullptr, &swapChain_) != VK_SUCCESS) { - throw std::runtime_error("Failed to create swap chain"); - } - - vkGetSwapchainImagesKHR(device_, swapChain_, &imageCount, nullptr); - swapChainImages_.resize(imageCount); - vkGetSwapchainImagesKHR(device_, swapChain_, &imageCount, swapChainImages_.data()); - - swapChainImageFormat_ = surfaceFormat.format; - swapChainExtent_ = extent; -} - -void Sdl3App::CreateImageViews() { - sdl3cpp::logging::TraceGuard trace;; - swapChainImageViews_.resize(swapChainImages_.size()); - for (size_t i = 0; i < swapChainImages_.size(); ++i) { - VkImageViewCreateInfo viewInfo{}; - viewInfo.sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO; - viewInfo.image = swapChainImages_[i]; - viewInfo.viewType = VK_IMAGE_VIEW_TYPE_2D; - viewInfo.format = swapChainImageFormat_; - viewInfo.components = {VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, - VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY}; - viewInfo.subresourceRange.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT; - viewInfo.subresourceRange.baseMipLevel = 0; - viewInfo.subresourceRange.levelCount = 1; - viewInfo.subresourceRange.baseArrayLayer = 0; - viewInfo.subresourceRange.layerCount = 1; - - if (vkCreateImageView(device_, &viewInfo, nullptr, &swapChainImageViews_[i]) != VK_SUCCESS) { - throw std::runtime_error("Failed to create image views"); - } - } -} - -void Sdl3App::CreateRenderPass() { - sdl3cpp::logging::TraceGuard trace;; - VkAttachmentDescription colorAttachment{}; - colorAttachment.format = swapChainImageFormat_; - colorAttachment.samples = VK_SAMPLE_COUNT_1_BIT; - colorAttachment.loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR; - colorAttachment.storeOp = VK_ATTACHMENT_STORE_OP_STORE; - colorAttachment.stencilLoadOp = VK_ATTACHMENT_LOAD_OP_DONT_CARE; - colorAttachment.stencilStoreOp = VK_ATTACHMENT_STORE_OP_DONT_CARE; - colorAttachment.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED; - colorAttachment.finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR; - - VkAttachmentReference colorAttachmentRef{}; - colorAttachmentRef.attachment = 0; - colorAttachmentRef.layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL; - - VkSubpassDescription subpass{}; - subpass.pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS; - subpass.colorAttachmentCount = 1; - subpass.pColorAttachments = &colorAttachmentRef; - - VkSubpassDependency dependency{}; - dependency.srcSubpass = VK_SUBPASS_EXTERNAL; - dependency.dstSubpass = 0; - dependency.srcStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.srcAccessMask = 0; - dependency.dstStageMask = VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT; - dependency.dstAccessMask = VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT; - - VkRenderPassCreateInfo renderPassInfo{}; - renderPassInfo.sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO; - renderPassInfo.attachmentCount = 1; - renderPassInfo.pAttachments = &colorAttachment; - renderPassInfo.subpassCount = 1; - renderPassInfo.pSubpasses = &subpass; - renderPassInfo.dependencyCount = 1; - renderPassInfo.pDependencies = &dependency; - - if (vkCreateRenderPass(device_, &renderPassInfo, nullptr, &renderPass_) != VK_SUCCESS) { - throw std::runtime_error("Failed to create render pass"); - } -} - -void Sdl3App::CleanupSwapChain() { - sdl3cpp::logging::TraceGuard trace;; - for (auto framebuffer : swapChainFramebuffers_) { - vkDestroyFramebuffer(device_, framebuffer, nullptr); - } - vkFreeCommandBuffers(device_, commandPool_, - static_cast(commandBuffers_.size()), commandBuffers_.data()); - for (auto& entry : graphicsPipelines_) { - vkDestroyPipeline(device_, entry.second, nullptr); - } - graphicsPipelines_.clear(); - if (pipelineLayout_ != VK_NULL_HANDLE) { - vkDestroyPipelineLayout(device_, pipelineLayout_, nullptr); - pipelineLayout_ = VK_NULL_HANDLE; - } - vkDestroyRenderPass(device_, renderPass_, nullptr); - for (auto imageView : swapChainImageViews_) { - vkDestroyImageView(device_, imageView, nullptr); - } - vkDestroySwapchainKHR(device_, swapChain_, nullptr); -} - -void Sdl3App::RecreateSwapChain() { - sdl3cpp::logging::TraceGuard trace;; - int width = 0; - int height = 0; - - // Escape hatch: Maximum 100 attempts (10 seconds at 100ms/iteration) - constexpr int kMaxAttempts = 100; - int attempts = 0; - - while (width == 0 || height == 0) { - // Escape hatch 1: Check for signal (Ctrl+C) - if (ShouldStop()) { - sdl3cpp::logging::Logger::GetInstance().Warn("Received stop signal while waiting for valid window dimensions"); - throw std::runtime_error("Application shutdown requested"); - } - - // Escape hatch 2: Timeout after maximum attempts - if (attempts >= kMaxAttempts) { - sdl3cpp::logging::Logger::GetInstance().Error("Timeout waiting for valid window dimensions after " + std::to_string(attempts) + " attempts. Window size stuck at: " + std::to_string(width) + "x" + std::to_string(height)); - throw std::runtime_error("Window resize timeout: dimensions remain 0x0"); - } - - SDL_GetWindowSize(window_, &width, &height); - - if (width == 0 || height == 0) { - // Use SDL_WaitEventTimeout instead of SDL_WaitEvent to avoid blocking indefinitely - SDL_Event event; - SDL_WaitEventTimeout(&event, 100); // 100ms timeout - attempts++; - - // Log periodically for debugging - if (attempts % 10 == 0) { - sdl3cpp::logging::Logger::GetInstance().Debug("Still waiting for valid window dimensions (attempt " + std::to_string(attempts) + "/" + std::to_string(kMaxAttempts) + "): " + std::to_string(width) + "x" + std::to_string(height)); - } - } - } - - sdl3cpp::logging::Logger::GetInstance().Info("Window resize resolved: " + std::to_string(width) + "x" + std::to_string(height)); - vkDeviceWaitIdle(device_); - CleanupSwapChain(); - CreateSwapChain(); - CreateImageViews(); - SetupGuiRenderer(); - CreateRenderPass(); - CreateGraphicsPipeline(); - CreateFramebuffers(); - CreateCommandBuffers(); - framebufferResized_ = false; -} - -VkSurfaceFormatKHR Sdl3App::ChooseSwapSurfaceFormat(const std::vector& availableFormats) { - sdl3cpp::logging::TraceGuard trace;; - for (const auto& availableFormat : availableFormats) { - if (availableFormat.format == VK_FORMAT_B8G8R8A8_SRGB && - availableFormat.colorSpace == VK_COLOR_SPACE_SRGB_NONLINEAR_KHR) { - return availableFormat; - } - } - return availableFormats[0]; -} - -VkPresentModeKHR Sdl3App::ChooseSwapPresentMode(const std::vector& availablePresentModes) { - sdl3cpp::logging::TraceGuard trace;; - for (const auto& availablePresentMode : availablePresentModes) { - if (availablePresentMode == VK_PRESENT_MODE_MAILBOX_KHR) { - return availablePresentMode; - } - } - return VK_PRESENT_MODE_FIFO_KHR; -} - -} // namespace sdl3cpp::app diff --git a/src/app/sdl_macros.hpp b/src/app/sdl_macros.hpp deleted file mode 100644 index bbca670..0000000 --- a/src/app/sdl_macros.hpp +++ /dev/null @@ -1,9 +0,0 @@ -#ifndef SDL3CPP_APP_SDL_MACROS_HPP -#define SDL3CPP_APP_SDL_MACROS_HPP - -// SDL macros required for core library functionality -#ifndef SDL_MAIN_HANDLED -#define SDL_MAIN_HANDLED -#endif - -#endif // SDL3CPP_APP_SDL_MACROS_HPP \ No newline at end of file diff --git a/src/app/vulkan_api.cpp b/src/app/vulkan_api.cpp deleted file mode 100644 index b38f86b..0000000 --- a/src/app/vulkan_api.cpp +++ /dev/null @@ -1,118 +0,0 @@ -#include "app/vulkan_api.hpp" -#include "logging/logger.hpp" - -#include -#include - -namespace sdl3cpp::app::vulkan { - -namespace { - -uint32_t FindMemoryType(VkPhysicalDevice physicalDevice, uint32_t typeFilter, VkMemoryPropertyFlags properties) { - VkPhysicalDeviceMemoryProperties memProperties; - vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProperties); - - for (uint32_t i = 0; i < memProperties.memoryTypeCount; ++i) { - if ((typeFilter & (1 << i)) && - (memProperties.memoryTypes[i].propertyFlags & properties) == properties) { - sdl3cpp::logging::Logger::GetInstance().Debug("Found suitable memory type: " + std::to_string(i)); - return i; - } - } - - sdl3cpp::logging::Logger::GetInstance().Error("Failed to find suitable memory type"); - throw std::runtime_error("Failed to find suitable memory type"); -} - -} // namespace - -VkExtent2D ChooseSwapExtent(VkSurfaceCapabilitiesKHR capabilities, SDL_Window* window) { - int width = 0; - int height = 0; - SDL_GetWindowSize(window, &width, &height); - - return VkExtent2D{ - static_cast(std::clamp(width, static_cast(capabilities.minImageExtent.width), - static_cast(capabilities.maxImageExtent.width))), - static_cast(std::clamp(height, static_cast(capabilities.minImageExtent.height), - static_cast(capabilities.maxImageExtent.height))) - }; -} - -void CreateBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkDeviceSize size, VkBufferUsageFlags usage, - VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) { - sdl3cpp::logging::Logger::GetInstance().Debug("Creating buffer with size " + std::to_string(size) + " bytes"); - // Validate buffer size - if (size == 0) { - sdl3cpp::logging::Logger::GetInstance().Error("Cannot create buffer with size 0"); - throw std::runtime_error("Cannot create buffer with size 0"); - } - - // Check available memory before allocating - VkPhysicalDeviceMemoryProperties memProps; - vkGetPhysicalDeviceMemoryProperties(physicalDevice, &memProps); - - uint64_t totalAvailable = 0; - for (uint32_t i = 0; i < memProps.memoryHeapCount; ++i) { - if (memProps.memoryHeaps[i].flags & VK_MEMORY_HEAP_DEVICE_LOCAL_BIT) { - totalAvailable += memProps.memoryHeaps[i].size; - } - } - - if (size > totalAvailable) { - throw std::runtime_error("Requested buffer size (" + - std::to_string(size / (1024 * 1024)) + " MB) exceeds available GPU memory (" + - std::to_string(totalAvailable / (1024 * 1024)) + " MB)"); - } - - VkBufferCreateInfo bufferInfo{}; - bufferInfo.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; - bufferInfo.size = size; - bufferInfo.usage = usage; - bufferInfo.sharingMode = VK_SHARING_MODE_EXCLUSIVE; - - VkResult createResult = vkCreateBuffer(device, &bufferInfo, nullptr, &buffer); - if (createResult != VK_SUCCESS) { - throw std::runtime_error("Failed to create buffer (error code: " + - std::to_string(createResult) + ", size: " + - std::to_string(size / 1024) + " KB)"); - } - - VkMemoryRequirements memRequirements; - vkGetBufferMemoryRequirements(device, buffer, &memRequirements); - - VkMemoryAllocateInfo allocInfo{}; - allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO; - allocInfo.allocationSize = memRequirements.size; - - try { - allocInfo.memoryTypeIndex = - FindMemoryType(physicalDevice, memRequirements.memoryTypeBits, properties); - } catch (const std::exception& e) { - vkDestroyBuffer(device, buffer, nullptr); - throw std::runtime_error(std::string("Failed to find suitable memory type: ") + e.what()); - } - - VkResult allocResult = vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory); - if (allocResult != VK_SUCCESS) { - vkDestroyBuffer(device, buffer, nullptr); - std::string errorMsg = "Failed to allocate buffer memory.\n"; - errorMsg += "Requested: " + std::to_string(memRequirements.size / (1024 * 1024)) + " MB\n"; - errorMsg += "Error code: " + std::to_string(allocResult) + "\n"; - if (allocResult == VK_ERROR_OUT_OF_DEVICE_MEMORY) { - errorMsg += "\nOut of GPU memory. Try:\n"; - errorMsg += "- Closing other GPU-intensive applications\n"; - errorMsg += "- Reducing window resolution\n"; - errorMsg += "- Upgrading GPU or system memory"; - } else if (allocResult == VK_ERROR_OUT_OF_HOST_MEMORY) { - errorMsg += "\nOut of system memory. Try:\n"; - errorMsg += "- Closing other applications\n"; - errorMsg += "- Adding more RAM to your system"; - } - throw std::runtime_error(errorMsg); - } - - vkBindBufferMemory(device, buffer, bufferMemory, 0); -} - -} // namespace sdl3cpp::app::vulkan diff --git a/src/app/vulkan_api.hpp b/src/app/vulkan_api.hpp deleted file mode 100644 index 881c615..0000000 --- a/src/app/vulkan_api.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef SDL3CPP_APP_VULKAN_API_HPP -#define SDL3CPP_APP_VULKAN_API_HPP - -#include -#include - -namespace sdl3cpp::app::vulkan { - -VkExtent2D ChooseSwapExtent(VkSurfaceCapabilitiesKHR capabilities, SDL_Window* window); - -void CreateBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkDeviceSize size, VkBufferUsageFlags usage, - VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory); - -} // namespace sdl3cpp::app::vulkan - -#endif // SDL3CPP_APP_VULKAN_API_HPP diff --git a/src/services/impl/script_service.cpp b/src/services/impl/script_service.cpp deleted file mode 100644 index 9e1506f..0000000 --- a/src/services/impl/script_service.cpp +++ /dev/null @@ -1,162 +0,0 @@ -#include "script_service.hpp" -#include "../../script/script_engine.hpp" -#include "../../logging/logging.hpp" -#include - -namespace sdl3cpp::services::impl { - -ScriptService::ScriptService(const std::filesystem::path& scriptPath) - : scriptPath_(scriptPath) { - logging::Logger::GetInstance().Trace("ScriptService::ScriptService: Created"); -} - -ScriptService::~ScriptService() { - logging::Logger::GetInstance().Trace("ScriptService::~ScriptService: Destroyed"); - if (initialized_) { - Shutdown(); - } -} - -void ScriptService::Initialize() { - logging::Logger::GetInstance().Trace("ScriptService::Initialize: Entering"); - - if (initialized_) { - throw std::runtime_error("Script service already initialized"); - } - - try { - scriptEngine_ = std::make_unique(scriptPath_); - initialized_ = true; - logging::Logger::GetInstance().Trace("ScriptService::Initialize: Exiting"); - } catch (const std::exception& e) { - logging::Logger::GetInstance().Trace("ScriptService::Initialize: Exiting with error"); - throw std::runtime_error(std::string("Failed to initialize script engine: ") + e.what()); - } -} - -void ScriptService::Shutdown() noexcept { - logging::Logger::GetInstance().Trace("ScriptService::Shutdown: Entering"); - - if (scriptEngine_) { - scriptEngine_.reset(); - } - initialized_ = false; - - logging::Logger::GetInstance().Trace("ScriptService::Shutdown: Exiting"); -} - -std::vector ScriptService::LoadSceneObjects() { - logging::Logger::GetInstance().Trace("ScriptService::LoadSceneObjects: Entering"); - - if (!initialized_) { - throw std::runtime_error("Script service not initialized"); - } - - auto result = scriptEngine_->LoadSceneObjects(); - logging::Logger::GetInstance().Trace("ScriptService::LoadSceneObjects: Exiting"); - return result; -} - -std::array ScriptService::ComputeModelMatrix(int functionRef, float time) { - logging::TraceGuard trace("ScriptService::ComputeModelMatrix"); - - if (!initialized_) { - throw std::runtime_error("Script service not initialized"); - } - - return scriptEngine_->ComputeModelMatrix(functionRef, time); -} - -std::array ScriptService::GetViewProjectionMatrix(float aspect) { - logging::Logger::GetInstance().Trace("ScriptService::GetViewProjectionMatrix: Entering"); - - if (!initialized_) { - throw std::runtime_error("Script service not initialized"); - } - - auto result = scriptEngine_->GetViewProjectionMatrix(aspect); - logging::Logger::GetInstance().Trace("ScriptService::GetViewProjectionMatrix: Exiting"); - return result; -} - -std::unordered_map ScriptService::LoadShaderPathsMap() { - logging::TraceGuard trace("ScriptService::LoadShaderPathsMap"); - - if (!initialized_) { - throw std::runtime_error("Script service not initialized"); - } - - return scriptEngine_->LoadShaderPathsMap(); -} - -std::vector ScriptService::LoadGuiCommands() { - logging::TraceGuard trace("ScriptService::LoadGuiCommands"); - - if (!initialized_) { - throw std::runtime_error("Script service not initialized"); - } - - return scriptEngine_->LoadGuiCommands(); -} - -void ScriptService::UpdateGuiInput(const script::GuiInputSnapshot& input) { - logging::TraceGuard trace("ScriptService::UpdateGuiInput"); - - if (!initialized_) { - throw std::runtime_error("Script service not initialized"); - } - - scriptEngine_->UpdateGuiInput(input); -} - -bool ScriptService::HasGuiCommands() const { - logging::TraceGuard trace("ScriptService::HasGuiCommands"); - - if (!initialized_) { - return false; - } - - return scriptEngine_->HasGuiCommands(); -} - -script::PhysicsBridge& ScriptService::GetPhysicsBridge() { - logging::TraceGuard trace("ScriptService::GetPhysicsBridge"); - - if (!initialized_) { - throw std::runtime_error("Script service not initialized"); - } - - return scriptEngine_->GetPhysicsBridge(); -} - -void ScriptService::SetAudioPlayer(app::AudioPlayer* audioPlayer) { - logging::TraceGuard trace("ScriptService::SetAudioPlayer"); - - if (!initialized_) { - throw std::runtime_error("Script service not initialized"); - } - - scriptEngine_->SetAudioPlayer(audioPlayer); -} - -std::filesystem::path ScriptService::GetScriptDirectory() const { - logging::TraceGuard trace("ScriptService::GetScriptDirectory"); - - if (!initialized_) { - throw std::runtime_error("Script service not initialized"); - } - - return scriptEngine_->GetScriptDirectory(); -} - -std::string ScriptService::GetLuaError() { - logging::TraceGuard trace("ScriptService::GetLuaError"); - - if (!initialized_) { - return "Script service not initialized"; - } - - return scriptEngine_->GetLuaError(); -} - -} // namespace sdl3cpp::services::impl \ No newline at end of file diff --git a/src/services/impl/script_service.hpp b/src/services/impl/script_service.hpp deleted file mode 100644 index c87bceb..0000000 --- a/src/services/impl/script_service.hpp +++ /dev/null @@ -1,52 +0,0 @@ -#pragma once - -#include "../interfaces/i_script_service.hpp" -#include "../../di/lifecycle.hpp" -#include -#include - -namespace sdl3cpp::script { -class ScriptEngine; -} - -namespace sdl3cpp::services::impl { - -/** - * @brief Script service implementation. - * - * Wraps ScriptEngine to provide Lua script execution and integration - * with scene, shaders, GUI, physics, and audio systems. - */ -class ScriptService : public IScriptService, - public di::IInitializable, - public di::IShutdownable { -public: - explicit ScriptService(const std::filesystem::path& scriptPath); - ~ScriptService() override; - - // IInitializable interface - void Initialize() override; - - // IShutdownable interface - void Shutdown() noexcept override; - - // IScriptService interface - std::vector LoadSceneObjects() override; - std::array ComputeModelMatrix(int functionRef, float time) override; - std::array GetViewProjectionMatrix(float aspect) override; - std::unordered_map LoadShaderPathsMap() override; - std::vector LoadGuiCommands() override; - void UpdateGuiInput(const script::GuiInputSnapshot& input) override; - bool HasGuiCommands() const override; - script::PhysicsBridge& GetPhysicsBridge() override; - void SetAudioPlayer(app::AudioPlayer* audioPlayer) override; - std::filesystem::path GetScriptDirectory() const override; - std::string GetLuaError() override; - -private: - std::filesystem::path scriptPath_; - std::unique_ptr scriptEngine_; - bool initialized_ = false; -}; - -} // namespace sdl3cpp::services::impl \ No newline at end of file