mirror of
https://github.com/johndoe6345789/SDL3CPlusPlus.git
synced 2026-04-24 21:55:09 +00:00
Enhance validation and error handling across the application
- Implement early Vulkan validation to check availability and version. - Add comprehensive GPU detection and selection feedback. - Validate swap chain support and window dimensions before creation. - Introduce buffer size validation and memory checks during buffer creation. - Improve error messages with actionable troubleshooting steps. - Create scripts for rebuilding and testing the application with validation improvements.
This commit is contained in:
@@ -55,8 +55,15 @@ void Sdl3App::LoadSceneData() {
|
||||
|
||||
void Sdl3App::CreateVertexBuffer() {
|
||||
TRACE_FUNCTION();
|
||||
if (vertices_.empty()) {
|
||||
throw std::runtime_error("Cannot create vertex buffer: no vertices loaded");
|
||||
}
|
||||
VkDeviceSize bufferSize = sizeof(vertices_[0]) * vertices_.size();
|
||||
TRACE_VAR(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_);
|
||||
@@ -69,8 +76,15 @@ void Sdl3App::CreateVertexBuffer() {
|
||||
|
||||
void Sdl3App::CreateIndexBuffer() {
|
||||
TRACE_FUNCTION();
|
||||
if (indices_.empty()) {
|
||||
throw std::runtime_error("Cannot create index buffer: no indices loaded");
|
||||
}
|
||||
VkDeviceSize bufferSize = sizeof(indices_[0]) * indices_.size();
|
||||
TRACE_VAR(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_);
|
||||
|
||||
@@ -9,6 +9,36 @@ namespace sdl3cpp::app {
|
||||
|
||||
void Sdl3App::CreateInstance() {
|
||||
TRACE_FUNCTION();
|
||||
|
||||
// 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";
|
||||
@@ -58,7 +88,11 @@ void Sdl3App::CreateSurface() {
|
||||
void Sdl3App::PickPhysicalDevice() {
|
||||
TRACE_FUNCTION();
|
||||
uint32_t deviceCount = 0;
|
||||
vkEnumeratePhysicalDevices(instance_, &deviceCount, nullptr);
|
||||
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");
|
||||
}
|
||||
@@ -66,18 +100,38 @@ void Sdl3App::PickPhysicalDevice() {
|
||||
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";
|
||||
|
||||
@@ -9,6 +9,36 @@ namespace sdl3cpp::app {
|
||||
void Sdl3App::CreateSwapChain() {
|
||||
TRACE_FUNCTION();
|
||||
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);
|
||||
std::cout << "Window size: " << windowWidth << "x" << windowHeight << "\n";
|
||||
|
||||
if (windowWidth == 0 || windowHeight == 0) {
|
||||
throw std::runtime_error("Invalid window dimensions (" +
|
||||
std::to_string(windowWidth) + "x" + std::to_string(windowHeight) + ").\n" +
|
||||
"Window may be minimized or invalid.");
|
||||
}
|
||||
|
||||
std::cout << "Surface capabilities:\n";
|
||||
std::cout << " Min extent: " << support.capabilities.minImageExtent.width
|
||||
<< "x" << support.capabilities.minImageExtent.height << "\n";
|
||||
std::cout << " Max extent: " << support.capabilities.maxImageExtent.width
|
||||
<< "x" << support.capabilities.maxImageExtent.height << "\n";
|
||||
std::cout << " Min images: " << support.capabilities.minImageCount << "\n";
|
||||
std::cout << " Max images: " << support.capabilities.maxImageCount << "\n";
|
||||
std::cout.flush();
|
||||
|
||||
VkSurfaceFormatKHR surfaceFormat = ChooseSwapSurfaceFormat(support.formats);
|
||||
VkPresentModeKHR presentMode = ChooseSwapPresentMode(support.presentModes);
|
||||
|
||||
@@ -38,14 +38,39 @@ VkExtent2D ChooseSwapExtent(VkSurfaceCapabilitiesKHR capabilities, SDL_Window* w
|
||||
|
||||
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;
|
||||
|
||||
if (vkCreateBuffer(device, &bufferInfo, nullptr, &buffer) != VK_SUCCESS) {
|
||||
throw std::runtime_error("Failed to create buffer");
|
||||
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;
|
||||
@@ -54,11 +79,32 @@ void CreateBuffer(VkDevice device, VkPhysicalDevice physicalDevice, VkDeviceSize
|
||||
VkMemoryAllocateInfo allocInfo{};
|
||||
allocInfo.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO;
|
||||
allocInfo.allocationSize = memRequirements.size;
|
||||
allocInfo.memoryTypeIndex =
|
||||
FindMemoryType(physicalDevice, memRequirements.memoryTypeBits, properties);
|
||||
|
||||
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());
|
||||
}
|
||||
|
||||
if (vkAllocateMemory(device, &allocInfo, nullptr, &bufferMemory) != VK_SUCCESS) {
|
||||
throw std::runtime_error("Failed to allocate buffer memory");
|
||||
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);
|
||||
|
||||
243
tests/VALIDATION_IMPROVEMENTS.md
Normal file
243
tests/VALIDATION_IMPROVEMENTS.md
Normal file
@@ -0,0 +1,243 @@
|
||||
# Validation and Error Handling Improvements
|
||||
|
||||
## Overview
|
||||
This document describes the comprehensive validation and error handling improvements made to the SDL3CPlusPlus application to catch errors early and provide better user feedback before crashes occur.
|
||||
|
||||
## Problem
|
||||
The application was crashing with exit code 137 (SIGKILL), showing only a see-through window with no feedback on what went wrong. This made it difficult to diagnose issues.
|
||||
|
||||
## Solution
|
||||
Added extensive validation at every critical initialization stage with clear, actionable error messages.
|
||||
|
||||
---
|
||||
|
||||
## Changes Made
|
||||
|
||||
### 1. **Early Vulkan Validation** ([sdl3_app_device.cpp](src/app/sdl3_app_device.cpp))
|
||||
|
||||
#### Before:
|
||||
- Directly attempted to create Vulkan instance without checking if Vulkan is available
|
||||
- Generic error messages
|
||||
|
||||
#### After:
|
||||
- **Version Check**: Validates Vulkan is installed and checks API version before proceeding
|
||||
```cpp
|
||||
VkResult enumResult = vkEnumerateInstanceVersion(&apiVersion);
|
||||
if (enumResult != VK_SUCCESS) {
|
||||
// Provides OS-specific installation instructions
|
||||
}
|
||||
```
|
||||
- **Version Requirements**: Verifies Vulkan 1.2 or higher is available
|
||||
- **Console Output**: Displays detected Vulkan version
|
||||
```
|
||||
Vulkan Version: 1.3.xxx
|
||||
```
|
||||
- **Detailed Error Messages**: Includes OS-specific installation commands for Ubuntu/Debian, Fedora, Arch
|
||||
- **GPU-specific Guidance**: Separate instructions for NVIDIA and AMD GPUs
|
||||
|
||||
### 2. **GPU Detection and Selection** ([sdl3_app_device.cpp](src/app/sdl3_app_device.cpp))
|
||||
|
||||
#### Before:
|
||||
- Limited information about available GPUs
|
||||
- Simple unsuitable device messages
|
||||
|
||||
#### After:
|
||||
- **Comprehensive GPU Enumeration**: Lists all detected GPUs with details
|
||||
```
|
||||
=== GPU Detection ===
|
||||
GPU 0: NVIDIA GeForce RTX 3080 (VRAM: 10240 MB)
|
||||
-> SELECTED
|
||||
GPU 1: Intel UHD Graphics (VRAM: 2048 MB)
|
||||
-> UNSUITABLE (missing required features)
|
||||
==================
|
||||
```
|
||||
- **Memory Information**: Shows VRAM for each GPU
|
||||
- **Error Result Codes**: Returns Vulkan error codes for debugging
|
||||
- **Clear Selection Feedback**: Shows which GPU was selected and why others were rejected
|
||||
- **Detailed Requirements**: Lists specific missing features:
|
||||
- Graphics queue support
|
||||
- Present queue support
|
||||
- Swapchain extension support
|
||||
- Adequate swapchain formats and present modes
|
||||
|
||||
### 3. **Swap Chain Validation** ([sdl3_app_swapchain.cpp](src/app/sdl3_app_swapchain.cpp))
|
||||
|
||||
#### Before:
|
||||
- Assumed swap chain support was available
|
||||
- No validation of window dimensions
|
||||
|
||||
#### After:
|
||||
- **Surface Format Validation**: Checks if surface formats are available
|
||||
```cpp
|
||||
if (support.formats.empty()) {
|
||||
throw std::runtime_error("No surface formats available...");
|
||||
}
|
||||
```
|
||||
- **Present Mode Validation**: Verifies present modes exist
|
||||
- **Window Dimension Check**: Validates window is not minimized or has invalid size
|
||||
```cpp
|
||||
if (windowWidth == 0 || windowHeight == 0) {
|
||||
throw std::runtime_error("Invalid window dimensions...");
|
||||
}
|
||||
```
|
||||
- **Capability Reporting**: Displays surface capabilities:
|
||||
```
|
||||
Window size: 1024x768
|
||||
Surface capabilities:
|
||||
Min extent: 1x1
|
||||
Max extent: 4096x4096
|
||||
Min images: 2
|
||||
Max images: 8
|
||||
```
|
||||
|
||||
### 4. **Memory Allocation Validation** ([vulkan_api.cpp](src/app/vulkan_api.cpp))
|
||||
|
||||
#### Before:
|
||||
- Created buffers without checking available memory
|
||||
- Generic "failed to allocate" errors
|
||||
|
||||
#### After:
|
||||
- **Size Validation**: Checks buffer size is non-zero
|
||||
- **Available Memory Check**: Compares requested size against total GPU memory
|
||||
```cpp
|
||||
if (size > totalAvailable) {
|
||||
throw std::runtime_error("Requested buffer size exceeds available GPU memory");
|
||||
}
|
||||
```
|
||||
- **Error Code Reporting**: Returns specific Vulkan error codes
|
||||
- **Detailed Error Messages**: Provides size information and troubleshooting steps
|
||||
- For `VK_ERROR_OUT_OF_DEVICE_MEMORY`:
|
||||
- Close GPU-intensive applications
|
||||
- Reduce window resolution
|
||||
- Upgrade GPU or system memory
|
||||
- For `VK_ERROR_OUT_OF_HOST_MEMORY`:
|
||||
- Close other applications
|
||||
- Add more RAM
|
||||
- **Cleanup on Failure**: Properly destroys partially created resources
|
||||
```cpp
|
||||
if (allocResult != VK_SUCCESS) {
|
||||
vkDestroyBuffer(device, buffer, nullptr);
|
||||
// throw detailed error...
|
||||
}
|
||||
```
|
||||
|
||||
### 5. **Buffer Creation Validation** ([sdl3_app_buffers.cpp](src/app/sdl3_app_buffers.cpp))
|
||||
|
||||
#### Before:
|
||||
- Attempted to create buffers even if data was empty
|
||||
|
||||
#### After:
|
||||
- **Data Validation**: Checks vertices/indices are loaded before buffer creation
|
||||
```cpp
|
||||
if (vertices_.empty()) {
|
||||
throw std::runtime_error("Cannot create vertex buffer: no vertices loaded");
|
||||
}
|
||||
```
|
||||
- **Resource Reporting**: Displays buffer sizes being allocated
|
||||
```
|
||||
Creating vertex buffer: 24 vertices (1 KB)
|
||||
Creating index buffer: 36 indices (0 KB)
|
||||
```
|
||||
- **Immediate Feedback**: Uses `std::cout.flush()` to ensure messages appear immediately
|
||||
|
||||
### 6. **Enhanced Error Dialog Support**
|
||||
|
||||
All errors now:
|
||||
- Show in console with detailed information
|
||||
- Display in SDL message boxes (when available)
|
||||
- Include actionable troubleshooting steps
|
||||
- Reference specific error codes for debugging
|
||||
|
||||
---
|
||||
|
||||
## Benefits
|
||||
|
||||
1. **Early Detection**: Problems are caught before they cause crashes
|
||||
2. **Clear Feedback**: Users see exactly what went wrong and where
|
||||
3. **Actionable Guidance**: Error messages include specific steps to resolve issues
|
||||
4. **Better Diagnostics**: Includes error codes, sizes, and system capabilities
|
||||
5. **Progress Visibility**: Console output shows what the app is doing during initialization
|
||||
6. **Resource Awareness**: Validates resources before attempting allocation
|
||||
|
||||
---
|
||||
|
||||
## Testing
|
||||
|
||||
To test the improvements:
|
||||
|
||||
```bash
|
||||
cd /home/rewrich/Documents/GitHub/SDL3CPlusPlus/build/Release
|
||||
make -j$(nproc)
|
||||
./sdl3_app --json-file-in ./config/seed_runtime.json
|
||||
```
|
||||
|
||||
You should now see:
|
||||
- Vulkan version detection
|
||||
- GPU enumeration with memory information
|
||||
- Window and swap chain validation
|
||||
- Buffer creation progress
|
||||
- Clear error messages if any step fails
|
||||
|
||||
---
|
||||
|
||||
## Example Error Messages
|
||||
|
||||
### Missing Vulkan Drivers
|
||||
```
|
||||
ERROR: Vulkan is not available on this system.
|
||||
|
||||
Please install Vulkan drivers:
|
||||
- Ubuntu/Debian: sudo apt install vulkan-tools libvulkan1
|
||||
- Fedora: sudo dnf install vulkan-tools vulkan-loader
|
||||
- Arch: sudo pacman -S vulkan-tools vulkan-icd-loader
|
||||
|
||||
For NVIDIA GPUs, install: nvidia-vulkan-icd
|
||||
For AMD GPUs, install: mesa-vulkan-drivers
|
||||
```
|
||||
|
||||
### No Suitable GPU
|
||||
```
|
||||
ERROR: Failed to find a suitable GPU.
|
||||
|
||||
Found 2 GPU(s), but none meet the requirements.
|
||||
GPU 0: Intel UHD Graphics (VRAM: 2048 MB) [UNSUITABLE]
|
||||
GPU 1: AMD Radeon (VRAM: 4096 MB) [UNSUITABLE]
|
||||
|
||||
Required features:
|
||||
- Graphics queue support
|
||||
- Present queue support
|
||||
- Swapchain extension support (VK_KHR_swapchain)
|
||||
- Adequate swapchain formats and present modes
|
||||
```
|
||||
|
||||
### Out of Memory
|
||||
```
|
||||
ERROR: Failed to allocate buffer memory.
|
||||
Requested: 512 MB
|
||||
Error code: -2
|
||||
|
||||
Out of GPU memory. Try:
|
||||
- Closing other GPU-intensive applications
|
||||
- Reducing window resolution
|
||||
- Upgrading GPU or system memory
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Files Modified
|
||||
|
||||
1. [src/app/sdl3_app_device.cpp](src/app/sdl3_app_device.cpp) - Vulkan and GPU validation
|
||||
2. [src/app/sdl3_app_swapchain.cpp](src/app/sdl3_app_swapchain.cpp) - Swap chain validation
|
||||
3. [src/app/vulkan_api.cpp](src/app/vulkan_api.cpp) - Memory allocation validation
|
||||
4. [src/app/sdl3_app_buffers.cpp](src/app/sdl3_app_buffers.cpp) - Buffer creation validation
|
||||
|
||||
---
|
||||
|
||||
## Future Improvements
|
||||
|
||||
Consider adding:
|
||||
- Memory usage tracking throughout app lifecycle
|
||||
- Swap chain recreation validation
|
||||
- Shader loading validation with detailed error messages
|
||||
- Configuration file validation before initialization
|
||||
- Performance monitoring and warnings for low-memory conditions
|
||||
25
tests/rebuild_and_test.sh
Normal file
25
tests/rebuild_and_test.sh
Normal file
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
# Quick rebuild and test script
|
||||
|
||||
set -e
|
||||
|
||||
echo "==================================="
|
||||
echo " SDL3CPlusPlus - Rebuild & Test"
|
||||
echo "==================================="
|
||||
echo ""
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
BUILD_DIR="build/Release"
|
||||
|
||||
# Build
|
||||
echo "Building application..."
|
||||
cd "$BUILD_DIR"
|
||||
make -j$(nproc)
|
||||
echo "✓ Build complete"
|
||||
echo ""
|
||||
|
||||
# Test with config
|
||||
echo "Starting application with seed_runtime.json..."
|
||||
echo "Press Ctrl+C to exit, or wait for error messages"
|
||||
echo "---"
|
||||
./sdl3_app --json-file-in ./config/seed_runtime.json
|
||||
37
tests/test_validation.sh
Normal file
37
tests/test_validation.sh
Normal file
@@ -0,0 +1,37 @@
|
||||
#!/bin/bash
|
||||
# Test script for validation improvements
|
||||
|
||||
cd /home/rewrich/Documents/GitHub/SDL3CPlusPlus/build/Release
|
||||
|
||||
echo "=== Testing application startup with validation ==="
|
||||
echo ""
|
||||
|
||||
# Test 1: Check --help output
|
||||
echo "Test 1: Running with --help"
|
||||
timeout 2 ./sdl3_app --help 2>&1 || echo "(timed out or exited with code $?)"
|
||||
echo ""
|
||||
|
||||
# Test 2: Try with config file
|
||||
echo "Test 2: Running with config file (5 second timeout)"
|
||||
timeout 5 ./sdl3_app --json-file-in ./config/seed_runtime.json 2>&1 &
|
||||
PID=$!
|
||||
sleep 2
|
||||
|
||||
# Check if process is still running
|
||||
if ps -p $PID > /dev/null 2>&1; then
|
||||
echo "Process started successfully (PID: $PID)"
|
||||
kill -9 $PID 2>/dev/null
|
||||
wait $PID 2>/dev/null
|
||||
else
|
||||
echo "Process exited early"
|
||||
wait $PID 2>/dev/null
|
||||
echo "Exit code: $?"
|
||||
fi
|
||||
echo ""
|
||||
|
||||
# Test 3: Check for error in a non-existent config
|
||||
echo "Test 3: Testing with non-existent config"
|
||||
./sdl3_app --json-file-in ./config/nonexistent.json 2>&1
|
||||
echo ""
|
||||
|
||||
echo "=== Tests complete ==="
|
||||
Reference in New Issue
Block a user