refactor: Enhance service architecture by introducing IPlatformService and updating dependencies

- Removed core/platform.hpp and core/vulkan_utils.cpp, integrating their functionality into new platform_service implementations.
- Updated service registrations to utilize IPlatformService for improved modularity.
- Refactored event bus usage across services to leverage IEventBus interface.
- Enhanced buffer management in BufferService with detailed logging and error handling.
- Updated GUI rendering services to utilize buffer service for resource management.
- Cleaned up includes and improved overall code organization for better maintainability.
This commit is contained in:
2026-01-04 17:43:18 +00:00
parent 1e6be869e0
commit 00a359d85f
23 changed files with 254 additions and 220 deletions

View File

@@ -1,72 +0,0 @@
#include "core/platform.hpp"
#include <cstdlib>
#ifdef _WIN32
#include <windows.h>
#endif
namespace sdl3cpp::platform {
std::optional<std::filesystem::path> GetUserConfigDirectory() {
#ifdef _WIN32
if (const char* appData = std::getenv("APPDATA")) {
return std::filesystem::path(appData) / "sdl3cpp";
}
#else
if (const char* xdgConfig = std::getenv("XDG_CONFIG_HOME")) {
return std::filesystem::path(xdgConfig) / "sdl3cpp";
}
if (const char* home = std::getenv("HOME")) {
return std::filesystem::path(home) / ".config" / "sdl3cpp";
}
#endif
return std::nullopt;
}
#ifdef _WIN32
namespace {
std::string FormatWin32Error(DWORD errorCode) {
if (errorCode == ERROR_SUCCESS) {
return "ERROR_SUCCESS";
}
LPSTR buffer = nullptr;
DWORD length = FormatMessageA(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
nullptr,
errorCode,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
reinterpret_cast<LPSTR>(&buffer),
0,
nullptr
);
std::string message;
if (length > 0 && buffer != nullptr) {
message = std::string(buffer, length);
// Remove trailing newlines
while (!message.empty() && (message.back() == '\n' || message.back() == '\r')) {
message.pop_back();
}
LocalFree(buffer);
} else {
message = "(FormatMessage failed)";
}
return message;
}
} // anonymous namespace
#endif
std::string GetPlatformError() {
#ifdef _WIN32
DWORD win32Error = ::GetLastError();
if (win32Error != ERROR_SUCCESS) {
return "Win32 error " + std::to_string(win32Error) + ": " + FormatWin32Error(win32Error);
}
return "No platform error";
#else
return "No platform error";
#endif
}
} // namespace sdl3cpp::platform

View File

@@ -1,27 +0,0 @@
#ifndef SDL3CPP_CORE_PLATFORM_HPP
#define SDL3CPP_CORE_PLATFORM_HPP
#include <filesystem>
#include <optional>
#include <string>
namespace sdl3cpp::platform {
// Platform detection
#ifdef _WIN32
constexpr bool IsWindows = true;
constexpr bool IsUnix = false;
#else
constexpr bool IsWindows = false;
constexpr bool IsUnix = true;
#endif
// Get user configuration directory (platform-specific)
std::optional<std::filesystem::path> GetUserConfigDirectory();
// Format platform-specific error messages
std::string GetPlatformError();
} // namespace sdl3cpp::platform
#endif // SDL3CPP_CORE_PLATFORM_HPP

View File

@@ -1,114 +0,0 @@
#include "vulkan_utils.hpp"
#include <algorithm>
#include <stdexcept>
#include <string>
namespace sdl3cpp::vulkan::utils {
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) {
return i;
}
}
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<uint32_t>(std::clamp(width, static_cast<int>(capabilities.minImageExtent.width),
static_cast<int>(capabilities.maxImageExtent.width))),
static_cast<uint32_t>(std::clamp(height, static_cast<int>(capabilities.minImageExtent.height),
static_cast<int>(capabilities.maxImageExtent.height)))
};
}
void CreateBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkDeviceSize size, VkBufferUsageFlags usage,
VkMemoryPropertyFlags properties, VkBuffer& buffer, VkDeviceMemory& bufferMemory) {
// Validate buffer size
if (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::vulkan::utils

View File

@@ -1,13 +0,0 @@
#pragma once
#include <vulkan/vulkan.h>
#include <SDL3/SDL.h>
namespace sdl3cpp::vulkan::utils {
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::vulkan::utils