Writing Code for VDE
This skill covers all aspects of writing code for the Vulkan Display Engine, from coding conventions to CMake integration.
When to use this skill
- •Adding new classes or functions to the engine
- •Understanding project coding standards
- •Adding source files and updating CMakeLists.txt
- •Organizing headers and implementation files
- •Writing API documentation
- •Following include patterns
Coding Conventions
Naming Conventions
Namespaces:
- •All code must be in the
vde::namespace - •Nested namespaces for API categories:
vde::api::
Classes and Types:
- •PascalCase for classes, structs, and enums
- •Examples:
Window,VulkanContext,GameCamera,EntityHandle
Functions and Methods:
- •camelCase for functions and methods
- •Examples:
shouldClose(),pollEvents(),createEntity()
Constants:
- •UPPER_SNAKE_CASE for global constants
- •kPrefix for class-level constants
- •Examples:
MAX_FRAMES_IN_FLIGHT,kDefaultResolution
Member Variables:
- •
m_prefix for private/protected members - •camelCase after prefix
- •Examples:
m_width,m_window,m_vulkanContext
Parameters and Local Variables:
- •camelCase without prefix
- •Examples:
width,height,entityHandle
File Organization
Public Headers:
- •Location:
include/vde/for core engine,include/vde/api/for game API - •One class per header file
- •Filename matches class name:
Window.h,GameCamera.h - •Use
#pragma oncefor header guards - •Must include complete documentation
Implementation Files:
- •Location:
src/for core engine,src/api/for game API - •One implementation per source file
- •Filename matches header:
Window.cpp,GameCamera.cpp - •Include corresponding header first
Example Structure:
include/vde/
Core.h # Core types and macros
Window.h # Public header
VulkanContext.h
api/
Game.h
Entity.h
src/
Window.cpp # Implementation
VulkanContext.cpp
api/
Game.cpp
Entity.cpp
Include Order
In .cpp files, organize includes in this exact order:
- •Corresponding header (e.g.,
#include <vde/Window.h>inWindow.cpp) - •Other VDE headers (
#include <vde/...>) - •Third-party headers (Vulkan, GLFW, GLM, etc.)
- •Standard library (
<vector>,<memory>, etc.)
Example:
#include <vde/Window.h> // 1. Corresponding header #include <vde/VulkanContext.h> // 2. Other vde headers #include <vde/api/Entity.h> #include <GLFW/glfw3.h> // 3. Third-party #include <glm/glm.hpp> #include <stdexcept> // 4. Standard library #include <vector>
In .h files:
- •Include only what's needed in the header
- •Forward declare when possible
- •Use
<vde/...>for all VDE includes
Documentation
Use Doxygen-style comments for all public API:
File Headers:
#pragma once /** * @file Window.h * @brief Window management for Vulkan Display Engine * * Provides platform-independent window creation and input handling * using GLFW as the underlying implementation. */
Class Documentation:
/**
* @brief Window class for managing a GLFW window with Vulkan support
*
* Provides functionality for:
* - Window creation and destruction
* - Resolution changes and fullscreen toggle
* - Event polling
* - Resize callbacks
*/
class Window {
Function Documentation:
/** * @brief Construct a window with specified dimensions * @param width Window width in pixels * @param height Window height in pixels * @param title Window title * @throws std::runtime_error if window creation fails */ Window(uint32_t width, uint32_t height, const char* title);
Required Tags:
- •
@brief- Brief description - •
@param- For each parameter - •
@return- For non-void functions - •
@throws- For functions that can throw exceptions
Adding New Source Files
Step 1: Create the Files
For Core Engine Components:
include/vde/MyNewClass.h src/MyNewClass.cpp
For Game API Components:
include/vde/api/MyNewClass.h src/api/MyNewClass.cpp
Step 2: Update CMakeLists.txt
Open CMakeLists.txt in the project root and add your files to the appropriate lists.
Add Implementation File:
Find the VDE_SOURCES section and add your .cpp file:
set(VDE_SOURCES
src/Window.cpp
src/VulkanContext.cpp
src/Camera.cpp
# ... existing files ...
src/MyNewClass.cpp # Add your implementation here
# Game API
src/api/Entity.cpp
src/api/MyNewAPIClass.cpp # Or here for API files
)
Add Public Header:
Find the VDE_PUBLIC_HEADERS section and add your .h file:
set(VDE_PUBLIC_HEADERS
include/vde/Core.h
include/vde/Window.h
# ... existing headers ...
include/vde/MyNewClass.h # Add your header here
# Game API headers
include/vde/api/GameAPI.h
include/vde/api/MyNewAPIClass.h # Or here for API headers
)
Important Notes:
- •Keep files organized by category (core engine vs. game API)
- •Use forward slashes (
/) in paths, even on Windows - •Paths are relative to the project root
- •Headers must be in
VDE_PUBLIC_HEADERSto be installed - •Source files must be in
VDE_SOURCESto be compiled
Step 3: Rebuild the Project
After updating CMakeLists.txt, rebuild:
# Visual Studio build cmake --build build --config Debug --clean-first # Or Ninja build cmake --build build_ninja --clean-first
CMake will automatically detect the changes and include your new files.
Adding Headers-Only Components
For header-only utilities or templates:
- •Create the header in
include/vde/orinclude/vde/api/ - •Add it to
VDE_PUBLIC_HEADERSin CMakeLists.txt - •Do NOT add a
.cppfile or entry inVDE_SOURCES
Example:
set(VDE_PUBLIC_HEADERS
# ... existing headers ...
include/vde/MathUtils.h # Header-only utility
)
Code Style Guidelines
Formatting
- •Indentation: 4 spaces (no tabs)
- •Braces: Opening brace on same line for functions, control structures
- •Line length: Prefer 100 characters max, but not strict
Example:
void MyClass::myFunction(int param) {
if (param > 0) {
// Do something
} else {
// Do something else
}
}
Modern C++ Practices
- •Use C++20 features where appropriate
- •Prefer RAII for resource management
- •Use smart pointers (
std::unique_ptr,std::shared_ptr) over raw pointers - •Use
constwherever possible - •Avoid macros except for header guards (use
#pragma once)
Example:
class ResourceManager {
public:
std::unique_ptr<Texture> createTexture(const std::string& path);
private:
std::vector<std::unique_ptr<Buffer>> m_buffers;
};
Error Handling
- •Use exceptions for error handling in public API
- •Throw
std::runtime_erroror derived exceptions - •Document exceptions with
@throwsin Doxygen comments
Example:
/**
* @brief Load texture from file
* @param path File path to texture
* @return Loaded texture
* @throws std::runtime_error if file cannot be loaded
*/
Texture loadTexture(const std::string& path) {
if (!fileExists(path)) {
throw std::runtime_error("Texture file not found: " + path);
}
// Load texture...
}
CMake Integration Details
Understanding the Build Structure
The VDE project uses CMake with these key components:
Library Target:
# Creates the 'vde' library target
add_library(vde STATIC ${VDE_SOURCES} ${VDE_PUBLIC_HEADERS})
Include Directories:
# Public includes (available to library users)
target_include_directories(vde PUBLIC
$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>
$<INSTALL_INTERFACE:include>
)
# Private includes (only for library implementation)
target_include_directories(vde PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/src
${CMAKE_CURRENT_SOURCE_DIR}/third_party/stb
)
Dependencies:
# Public dependencies (exposed to library users)
target_link_libraries(vde PUBLIC
Vulkan::Vulkan
glfw
glm::glm
)
# Private dependencies (internal use only)
target_link_libraries(vde PRIVATE
glslang::glslang
glslang::SPIRV
)
When to Modify CMakeLists.txt
You MUST update CMakeLists.txt when:
- •Adding new
.cppsource files → updateVDE_SOURCES - •Adding new public
.hheaders → updateVDE_PUBLIC_HEADERS - •Adding new external dependencies → update
target_link_libraries
You do NOT need to update CMakeLists.txt when:
- •Modifying existing files
- •Adding private headers in
src/(not public API) - •Changing function implementations
Adding External Dependencies
If you need to add a new external library:
- •Add FetchContent declaration:
FetchContent_Declare(
mylibrary
GIT_REPOSITORY https://github.com/user/mylibrary.git
GIT_TAG v1.0.0
)
FetchContent_MakeAvailable(mylibrary)
- •Link the library:
target_link_libraries(vde PRIVATE # or PUBLIC if exposed in headers
mylibrary::mylibrary
)
Quick Reference Checklist
When adding a new class to VDE:
- • Create
include/vde/ClassName.h(orinclude/vde/api/ClassName.h) - • Create
src/ClassName.cpp(orsrc/api/ClassName.cpp) - • Add
#pragma onceto header - • Add file and class Doxygen documentation
- • Use
vde::namespace (orvde::api::) - • Follow naming conventions (PascalCase class, camelCase methods, m_ members)
- • Add header to
VDE_PUBLIC_HEADERSin CMakeLists.txt - • Add source to
VDE_SOURCESin CMakeLists.txt - • Include corresponding header first in .cpp file
- • Follow include order in implementation
- • Document public methods with @brief, @param, @return, @throws
- • Rebuild project with
cmake --build build --config Debug - • Run tests to verify:
./scripts/build-and-test.ps1
Common Patterns
Creating a New Engine Component
// include/vde/MyComponent.h
#pragma once
/**
* @file MyComponent.h
* @brief Brief description of component
*/
#include <vde/Core.h>
#include <memory>
namespace vde {
/**
* @brief Component description
*/
class MyComponent {
public:
MyComponent();
~MyComponent();
/**
* @brief Do something
* @param value Input parameter
* @return Result value
*/
int doSomething(int value);
private:
int m_value;
};
} // namespace vde
// src/MyComponent.cpp
#include <vde/MyComponent.h>
#include <stdexcept>
namespace vde {
MyComponent::MyComponent()
: m_value(0) {
}
MyComponent::~MyComponent() = default;
int MyComponent::doSomething(int value) {
if (value < 0) {
throw std::runtime_error("Value must be non-negative");
}
m_value = value;
return m_value * 2;
}
} // namespace vde
Creating a New Game API Component
// include/vde/api/MyFeature.h
#pragma once
/**
* @file MyFeature.h
* @brief Feature for game developers
*/
#include <vde/api/GameTypes.h>
namespace vde::api {
/**
* @brief Feature description
*/
class MyFeature {
public:
/**
* @brief Initialize feature
* @param settings Configuration settings
*/
void initialize(const Settings& settings);
private:
bool m_initialized = false;
};
} // namespace vde::api
See Also
- •add-component - Guide for adding complex engine systems
- •build-tool-workflows - Build and test commands
- •create-tests - Writing unit tests for your code
- •vulkan-patterns - Vulkan-specific coding patterns
- •architecture - Project structure and organization