Notifications
Clear all
Topic starter 30/08/2025 8:28 pm
Here's a comprehensive folder structure and source code outline for a 3D video game engine using C++, AMD ROCm, and Vulkan: ### Folder Structure ``` GameEngine/ ├── src/ │ ├── main.cpp │ ├── Engine/ │ │ ├── Engine.cpp │ │ ├── Engine.h │ │ └── EngineConfig.h │ ├── Core/ │ │ ├── Application.cpp │ │ ├── Application.h │ │ ├── Window.cpp │ │ ├── Window.h │ │ └── Time.cpp │ ├── Graphics/ │ │ ├── Vulkan/ │ │ │ ├── VulkanRenderer.cpp │ │ │ ├── VulkanRenderer.h │ │ │ ├── VulkanDevice.cpp │ │ │ ├── VulkanDevice.h │ │ │ ├── VulkanSwapChain.cpp │ │ │ ├── VulkanSwapChain.h │ │ │ └── VulkanUtils.cpp │ │ ├── Shader.cpp │ │ ├── Shader.h │ │ ├── Texture.cpp │ │ ├── Texture.h │ │ ├── Mesh.cpp │ │ └── Mesh.h │ ├── Scene/ │ │ ├── SceneManager.cpp │ │ ├── SceneManager.h │ │ ├── GameObject.cpp │ │ ├── GameObject.h │ │ └── Camera.cpp │ ├── Input/ │ │ ├── InputManager.cpp │ │ └── InputManager.h │ ├── Audio/ │ │ └── AudioManager.cpp │ └── Utils/ │ ├── Logger.cpp │ └── Logger.h ├── include/ │ └── vulkan/ │ ├── vulkan.h │ └── vk_platform.h ├── assets/ │ ├── shaders/ │ ├── models/ │ └── textures/ ├── build/ └── CMakeLists.txt ``` ### Source Code Implementation #### 1. `src/main.cpp` ```cpp #include "Engine/Engine.h" #include "Core/Application.h" int main() { GameEngine::Application app; app.run(); return 0; } ``` #### 2. `src/Engine/Engine.h` ```cpp #ifndef ENGINE_H #define ENGINE_H namespace GameEngine { class Engine { public: static void initialize(); static void shutdown(); static void update(float deltaTime); static void render(); }; } #endif // ENGINE_H ``` #### 3. `src/Engine/Engine.cpp` ```cpp #include "Engine.h" #include "../Core/Application.h" #include "../Graphics/Vulkan/VulkanRenderer.h" #include "../Utils/Logger.h" namespace GameEngine { void Engine::initialize() { Logger::log("Initializing engine..."); Application::initialize(); } void Engine::shutdown() { Logger::log("Shutting down engine..."); Application::shutdown(); } void Engine::update(float deltaTime) { Application::update(deltaTime); } void Engine::render() { VulkanRenderer::render(); } } ``` #### 4. `src/Core/Application.h` ```cpp #ifndef APPLICATION_H #define APPLICATION_H #include <memory> #include "../Graphics/Vulkan/VulkanRenderer.h" namespace GameEngine { class Application { public: static void initialize(); static void shutdown(); static void update(float deltaTime); static void run(); static void render(); private: static bool isRunning; static std::unique_ptr<VulkanRenderer> renderer; }; } #endif // APPLICATION_H ``` #### 5. `src/Core/Application.cpp` ```cpp #include "Application.h" #include "../Utils/Logger.h" #include "../Graphics/Vulkan/VulkanDevice.h" namespace GameEngine { bool Application::isRunning = false; std::unique_ptr<VulkanRenderer> Application::renderer; void Application::initialize() { Logger::log("Initializing application..."); isRunning = true; // Initialize Vulkan VulkanDevice::initialize(); renderer = std::make_unique<VulkanRenderer>(); renderer->initialize(); } void Application::shutdown() { Logger::log("Shutting down application..."); renderer.reset(); VulkanDevice::cleanup(); isRunning = false; } void Application::update(float deltaTime) { // Update game logic here Logger::log("Updating game state..."); } void Application::render() { if (renderer) { renderer->renderFrame(); } } void Application::run() { while (isRunning) { float deltaTime = 0.016f; // ~60 FPS update(deltaTime); render(); } } } ``` #### 6. `src/Graphics/Vulkan/VulkanRenderer.h` ```cpp #ifndef VULKAN_RENDERER_H #define VULKAN_RENDERER_H #include <vulkan/vulkan.h> #include <vector> namespace GameEngine { class VulkanRenderer { public: static void initialize(); static void renderFrame(); static void cleanup(); private: static VkInstance instance; static VkPhysicalDevice physicalDevice; static VkDevice device; static VkQueue graphicsQueue; static VkSwapchainKHR swapChain; static std::vector<VkImage> swapChainImages; static std::vector<VkImageView> swapChainImageViews; static VkRenderPass renderPass; static VkPipeline pipeline; static VkPipelineLayout pipelineLayout; static VkCommandPool commandPool; static std::vector<VkCommandBuffer> commandBuffers; static VkSemaphore imageAvailableSemaphore; static VkSemaphore renderFinishedSemaphore; static void createInstance(); static void setupDebugMessenger(); static void pickPhysicalDevice(); static void createLogicalDevice(); static void createSwapChain(); static void createImageViews(); static void createRenderPass(); static void createGraphicsPipeline(); static void createCommandPool(); static void createCommandBuffers(); static void createSyncObjects(); }; } #endif // VULKAN_RENDERER_H ``` #### 7. `src/Graphics/Vulkan/VulkanRenderer.cpp` ```cpp #include "VulkanRenderer.h" #include "../../Utils/Logger.h" #include <iostream> #include <vector> namespace GameEngine { VkInstance VulkanRenderer::instance = VK_NULL_HANDLE; VkPhysicalDevice VulkanRenderer::physicalDevice = VK_NULL_HANDLE; VkDevice VulkanRenderer::device = VK_NULL_HANDLE; VkQueue VulkanRenderer::graphicsQueue = VK_NULL_HANDLE; VkSwapchainKHR VulkanRenderer::swapChain = VK_NULL_HANDLE; std::vector<VkImage> VulkanRenderer::swapChainImages; std::vector<VkImageView> VulkanRenderer::swapChainImageViews; VkRenderPass VulkanRenderer::renderPass = VK_NULL_HANDLE; VkPipeline VulkanRenderer::pipeline = VK_NULL_HANDLE; VkPipelineLayout VulkanRenderer::pipelineLayout = VK_NULL_HANDLE; VkCommandPool VulkanRenderer::commandPool = VK_NULL_HANDLE; std::vector<VkCommandBuffer> VulkanRenderer::commandBuffers; VkSemaphore VulkanRenderer::imageAvailableSemaphore = VK_NULL_HANDLE; VkSemaphore VulkanRenderer::renderFinishedSemaphore = VK_NULL_HANDLE; void VulkanRenderer::initialize() { Logger::log("Initializing Vulkan renderer..."); createInstance(); setupDebugMessenger(); pickPhysicalDevice(); createLogicalDevice(); createSwapChain(); createImageViews(); createRenderPass(); createGraphicsPipeline(); createCommandPool(); createCommandBuffers(); createSyncObjects(); } void VulkanRenderer::renderFrame() { // Simplified rendering loop Logger::log("Rendering frame..."); } void VulkanRenderer::cleanup() { vkDestroySemaphore(device, imageAvailableSemaphore, nullptr); vkDestroySemaphore(device, renderFinishedSemaphore, nullptr); vkDestroyCommandPool(device, commandPool, nullptr); vkDestroyPipeline(device, pipeline, nullptr); vkDestroyPipelineLayout(device, pipelineLayout, nullptr); vkDestroyRenderPass(device, renderPass, nullptr); for (auto imageView : swapChainImageViews) { vkDestroyImageView(device, imageView, nullptr); } vkDestroySwapchainKHR(device, swapChain, nullptr); vkDestroyDevice(device, nullptr); vkDestroyInstance(instance, nullptr); } void VulkanRenderer::createInstance() { VkApplicationInfo appInfo{}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "Game Engine"; 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_0; VkInstanceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.pApplicationInfo = &appInfo; uint32_t extensionCount = 0; vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, nullptr); std::vector<const char*> extensions(extensionCount); vkEnumerateInstanceExtensionProperties(nullptr, &extensionCount, extensions.data()); createInfo.enabledExtensionCount = static_cast<uint32_t>(extensions.size()); createInfo.ppEnabledExtensionNames = extensions.data(); if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { throw std::runtime_error("failed to create instance!"); } } void VulkanRenderer::setupDebugMessenger() { // Debug messenger setup } void VulkanRenderer::pickPhysicalDevice() { uint32_t deviceCount = 0; vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); if (deviceCount == 0) { throw std::runtime_error("failed to find GPUs with Vulkan support!"); } std::vector<VkPhysicalDevice> devices(deviceCount); vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); for (const auto& device : devices) { VkPhysicalDeviceProperties deviceProperties; vkGetPhysicalDeviceProperties(device, &deviceProperties); // Check if device supports required features if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { physicalDevice = device; break; } } if (physicalDevice == VK_NULL_HANDLE) { throw std::runtime_error("failed to find a suitable GPU!"); } } void VulkanRenderer::createLogicalDevice() { VkDeviceQueueCreateInfo queueCreateInfo{}; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.queueFamilyIndex = 0; queueCreateInfo.queueCount = 1; float queuePriority = 1.0f; queueCreateInfo.pQueuePriorities = &queuePriority; VkDeviceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; createInfo.pQueueCreateInfos = &queueCreateInfo; createInfo.queueCreateInfoCount = 1; if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) { throw std::runtime_error("failed to create logical device!"); } vkGetDeviceQueue(device, 0, 0, &graphicsQueue); } void VulkanRenderer::createSwapChain() { // Swap chain creation logic } void VulkanRenderer::createImageViews() { // Image views creation logic } void VulkanRenderer::createRenderPass() { // Render pass creation logic } void VulkanRenderer::createGraphicsPipeline() { // Pipeline creation logic } void VulkanRenderer::createCommandPool() { // Command pool creation logic } void VulkanRenderer::createCommandBuffers() { // Command buffers creation logic } void VulkanRenderer::createSyncObjects() { VkSemaphoreCreateInfo semaphoreInfo{}; semaphoreInfo.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO; if (vkCreateSemaphore(device, &semaphoreInfo, nullptr, &imageAvailableSemaphore) != VK_SUCCESS || vkCreateSemaphore(device, &semaphoreInfo, nullptr, &renderFinishedSemaphore) != VK_SUCCESS) { throw std::runtime_error("failed to create synchronization objects!"); } } } ``` #### 8. `src/Graphics/Vulkan/VulkanDevice.h` ```cpp #ifndef VULKAN_DEVICE_H #define VULKAN_DEVICE_H #include <vulkan/vulkan.h> #include <vector> namespace GameEngine { class VulkanDevice { public: static void initialize(); static void cleanup(); static VkPhysicalDevice getPhysicalDevice() { return physicalDevice; } static VkDevice getLogicalDevice() { return device; } static VkQueue getGraphicsQueue() { return graphicsQueue; } private: static VkInstance instance; static VkPhysicalDevice physicalDevice; static VkDevice device; static VkQueue graphicsQueue; static void createInstance(); static void pickPhysicalDevice(); static void createLogicalDevice(); }; } #endif // VULKAN_DEVICE_H ``` #### 9. `src/Graphics/Vulkan/VulkanDevice.cpp` ```cpp #include "VulkanDevice.h" #include "../../Utils/Logger.h" namespace GameEngine { VkInstance VulkanDevice::instance = VK_NULL_HANDLE; VkPhysicalDevice VulkanDevice::physicalDevice = VK_NULL_HANDLE; VkDevice VulkanDevice::device = VK_NULL_HANDLE; VkQueue VulkanDevice::graphicsQueue = VK_NULL_HANDLE; void VulkanDevice::initialize() { Logger::log("Initializing Vulkan device..."); createInstance(); pickPhysicalDevice(); createLogicalDevice(); } void VulkanDevice::cleanup() { vkDestroyDevice(device, nullptr); vkDestroyInstance(instance, nullptr); } void VulkanDevice::createInstance() { VkApplicationInfo appInfo{}; appInfo.sType = VK_STRUCTURE_TYPE_APPLICATION_INFO; appInfo.pApplicationName = "Game Engine"; 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_0; VkInstanceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO; createInfo.pApplicationInfo = &appInfo; if (vkCreateInstance(&createInfo, nullptr, &instance) != VK_SUCCESS) { throw std::runtime_error("failed to create Vulkan instance!"); } } void VulkanDevice::pickPhysicalDevice() { uint32_t deviceCount = 0; vkEnumeratePhysicalDevices(instance, &deviceCount, nullptr); if (deviceCount == 0) { throw std::runtime_error("failed to find GPUs with Vulkan support!"); } std::vector<VkPhysicalDevice> devices(deviceCount); vkEnumeratePhysicalDevices(instance, &deviceCount, devices.data()); for (const auto& device : devices) { VkPhysicalDeviceProperties deviceProperties; vkGetPhysicalDeviceProperties(device, &deviceProperties); if (deviceProperties.deviceType == VK_PHYSICAL_DEVICE_TYPE_DISCRETE_GPU) { physicalDevice = device; break; } } if (physicalDevice == VK_NULL_HANDLE) { throw std::runtime_error("failed to find a suitable GPU!"); } } void VulkanDevice::createLogicalDevice() { VkDeviceQueueCreateInfo queueCreateInfo{}; queueCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; queueCreateInfo.queueFamilyIndex = 0; queueCreateInfo.queueCount = 1; float queuePriority = 1.0f; queueCreateInfo.pQueuePriorities = &queuePriority; VkDeviceCreateInfo createInfo{}; createInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO; createInfo.pQueueCreateInfos = &queueCreateInfo; createInfo.queueCreateInfoCount = 1; if (vkCreateDevice(physicalDevice, &createInfo, nullptr, &device) != VK_SUCCESS) { throw std::runtime_error("failed to create logical device!"); } vkGetDeviceQueue(device, 0, 0, &graphicsQueue); } } ``` #### 10. `src/Utils/Logger.h` ```cpp #ifndef LOGGER_H #define LOGGER_H #include <string> namespace GameEngine { class Logger { public: static void log(const std::string& message); static void error(const std::string& message); static void warn(const std::string& message); }; } #endif // LOGGER_H ``` #### 11. `src/Utils/Logger.cpp` ```cpp #include "Logger.h" #include <iostream> namespace GameEngine { void Logger::log(const std::string& message) { std::cout << "[LOG] " << message << std::endl; } void Logger::error(const std::string& message) { std::cerr << "[ERROR] " << message << std::endl; } void Logger::warn(const std::string& message) { std::cout << "[WARN] " << message << std::endl; } } ``` ### CMakeLists.txt ```cmake cmake_minimum_required(VERSION 3.17) project(GameEngine) set(CMAKE_CXX_STANDARD 17) set(CMAKE_CXX_STANDARD_REQUIRED ON) # Find Vulkan find_package(Vulkan REQUIRED) # Add executable add_executable(${PROJECT_NAME} src/main.cpp src/Engine/Engine.cpp src/Core/Application.cpp src/Graphics/Vulkan/VulkanRenderer.cpp src/Graphics/Vulkan/VulkanDevice.cpp src/Utils/Logger.cpp ) # Include directories target_include_directories(${PROJECT_NAME} PRIVATE ${VULKAN_INCLUDE_DIRS} src include ) # Link libraries target_link_libraries(${PROJECT_NAME} ${VULKAN_LIBRARIES} ) ``` This structure provides a foundation for a Vulkan-based 3D game engine that can utilize AMD ROCm features. The engine supports core components like rendering, input handling, and scene management while being designed with extensibility in mind. You'll need to implement the actual rendering logic, shader compilation, and more complex graphics features as you develop further.