# Error Handling in shdrlib
shdrlib provides **rich, user-friendly error messages** across all three tiers. This guide explains how to handle errors effectively.
## Overview
Each tier has progressively more helpful error messages:
- **CORE**: Wraps raw Vulkan error codes
- **EX**: Adds context and suggestions
- **EZ**: Provides beginner-friendly explanations with step-by-step recovery
## Error Types by Tier
### EZ Tier Errors
EZ errors are designed for maximum friendliness:
```rust
use shdrlib::ez::*;
fn main() -> Result<(), EzError> {
// EZ errors include:
// - Clear explanation of what went wrong
// - Common causes
// - Step-by-step solutions
// - Links to documentation
let mut renderer = EzRenderer::new(EzConfig::default())?;
// If initialization fails, you'll see:
// ❌ Failed to initialize Vulkan renderer
//
// What happened:
// Instance creation failed: ...
//
// Common causes:
// • Vulkan runtime not installed
// • Outdated GPU drivers
// • GPU doesn't support Vulkan 1.3
//
// Try these fixes:
// 1. Update your GPU drivers
// 2. Download and install Vulkan SDK
// ...
Ok(())
}
```
### EX Tier Errors
EX errors provide context without being overwhelming:
```rust
use shdrlib::ex::*;
fn main() -> Result<(), RuntimeError> {
let runtime = RuntimeManager::new(RuntimeConfig::default())?;
// EX errors include:
// - What operation failed
// - Underlying cause
// - Actionable suggestions
// - Technical context
Ok(())
}
```
### CORE Tier Errors
CORE errors are thin wrappers around Vulkan errors:
```rust
use shdrlib::core::*;
// CORE errors expose raw Vulkan result codes
// but still provide context about the operation
```
## Error Handling Patterns
### Basic Error Propagation
The simplest approach - just propagate errors:
```rust
use shdrlib::ez::*;
fn render_frame(renderer: &mut EzRenderer) -> Result<(), EzError> {
renderer.render_frame(|frame| {
// Your rendering code
Ok(())
})?; // Propagate any errors
Ok(())
}
```
### Custom Error Handling
Handle specific errors differently:
```rust
use shdrlib::ez::*;
fn main() {
let mut renderer = match EzRenderer::new(EzConfig::default()) {
Ok(r) => r,
Err(EzError::InitializationFailed { details }) => {
eprintln!("Failed to initialize: {}", details);
eprintln!("Make sure Vulkan is installed!");
return;
}
Err(e) => {
eprintln!("Unexpected error: {}", e);
return;
}
};
// ... use renderer
}
```
### Shader Compilation Errors
Shader errors show exactly what's wrong:
```rust
use shdrlib::ez::*;
fn compile_shaders(renderer: &mut EzRenderer) -> Result<(), EzError> {
let vert = r#"
#version 450
layout(location = 0) in vec3 position;
void main() {
gl_Position = vec4(position, 1.0);
}
"#;
match renderer.add_shader(vert, ShaderStage::Vertex) {
Ok(shader) => Ok(()),
Err(EzError::ShaderCompilationFailed { details }) => {
// You'll see:
// ❌ Shader compilation failed
//
// Details:
// Line 4: undeclared identifier 'position'
//
// Debugging tips:
// • Check variable declarations
// • Verify shader version is #version 450
// ...
eprintln!("Shader error: {}", details);
Err(EzError::ShaderCompilationFailed { details })
}
Err(e) => Err(e),
}
}
```
### Validation Errors
Enable validation layers for detailed diagnostics:
```rust
use shdrlib::ez::*;
fn main() -> Result<(), EzError> {
let config = EzConfig {
enable_validation: true, // Enable validation layers
..Default::default()
};
let renderer = EzRenderer::new(config)?;
// Now you'll get validation errors if you misuse the API:
// ❌ Vulkan Validation Error
//
// Message ID: VUID-vkBeginCommandBuffer-commandBuffer-00049
// Severity: ERROR
//
// Command buffer is already in recording state
//
// What are validation errors?
// Validation layers catch API misuse before it crashes.
// These errors are CRITICAL and must be fixed!
Ok(())
}
```
## EX Tier: Advanced Error Context
The EX tier includes helper utilities for building error traces:
```rust
use shdrlib::ex::*;
use shdrlib::ex::helpers::*;
fn create_buffer_with_context() -> Result<(), RuntimeError> {
// Use with_context! macro for automatic file/line tracking
let buffer = create_buffer()
.with_context!("creating vertex buffer")?;
// If this fails, you'll see:
// ╔════════════════════════════════════════════════════════════╗
// ║ ERROR TRACEBACK ║
// ╠════════════════════════════════════════════════════════════╣
//
// ❯ creating vertex buffer
// at src/main.rs:42:9
//
// ❯ allocating device memory
// at src/memory.rs:156:13
//
// ╠════════════════════════════════════════════════════════════╣
// ║ ROOT CAUSE ║
// ╠════════════════════════════════════════════════════════════╣
//
// ERROR_OUT_OF_DEVICE_MEMORY
// The GPU has run out of video memory (VRAM)
// ...
Ok(())
}
```
## Vulkan Error Code Reference
The library includes friendly explanations for all Vulkan error codes:
```rust
use shdrlib::ex::helpers::vk_result::VkErrorInfo;
use ash::vk;
// Get detailed info about any Vulkan error
let info = VkErrorInfo::from_result(vk::Result::ERROR_OUT_OF_DEVICE_MEMORY);
println!("{}", info);
// Vulkan Error: ERROR_OUT_OF_DEVICE_MEMORY (ERROR_OUT_OF_DEVICE_MEMORY)
// The GPU has run out of video memory (VRAM)
//
// Possible causes:
// • Allocating too many buffers or textures
// • Creating large render targets
// • Not freeing resources
// • GPU has limited VRAM
//
// Suggested solutions:
// → Reduce texture sizes or use compression
// → Free unused buffers and images
// → Use memory budget queries to track usage
// → Consider streaming assets instead of loading all at once
```
## Best Practices
### 1. Always Handle Errors
Don't ignore errors - they provide critical information:
```rust
// ❌ BAD - silently ignores errors
// ✅ GOOD - handles or propagates
renderer.render_frame(|frame| Ok(()))?;
```
### 2. Enable Validation in Development
Always use validation layers during development:
```rust
let config = EzConfig {
enable_validation: cfg!(debug_assertions), // Auto-enable in debug builds
..Default::default()
};
```
### 3. Provide Context
When building libraries on top of shdrlib, add your own context:
```rust
fn load_model(path: &str) -> Result<Model, MyError> {
let buffer = create_buffer()
.map_err(|e| MyError::BufferCreation {
path: path.to_string(),
source: e,
})?;
// ...
}
```
### 4. Display Errors Nicely
For end-user applications, format errors nicely:
```rust
use shdrlib::ez::*;
fn main() {
if let Err(e) = run() {
// EZ errors already have nice formatting
eprintln!("{}", e);
std::process::exit(1);
}
}
fn run() -> Result<(), EzError> {
// Your application code
Ok(())
}
```
### 5. Log Validation Messages
Set up validation message callbacks for detailed diagnostics:
```rust
// The library automatically prints validation messages to stderr
// when validation layers are enabled.
//
// You can also set up custom callbacks at the CORE tier
// for logging to a file or custom logger.
```
## Common Error Scenarios
### Out of Memory
```
ERROR_OUT_OF_DEVICE_MEMORY
Possible causes:
• Too many textures loaded
• Buffers not being freed
• Resource leak
Solutions:
→ Free unused resources with .destroy()
→ Use smaller textures
→ Track memory usage
```
### Device Lost
```
ERROR_DEVICE_LOST
Possible causes:
• GPU driver crash (TDR timeout)
• Infinite loop in shader
• Invalid command buffer
Solutions:
→ Check for shader infinite loops
→ Enable validation layers
→ Update GPU drivers
→ Reinitialize after device loss
```
### Shader Compilation Failed
```
Shader compilation failed: Line 12: undeclared identifier
Debugging tips:
• Check line 12 in your shader
• Verify all variables are declared
• Make sure shader version is correct
```
### Window Resize
```
ERROR_OUT_OF_DATE_KHR
This is normal! Recreate your swapchain when the window resizes.
```
## Error Handling Checklist
- [ ] Enable validation layers in debug builds
- [ ] Propagate errors with `?` operator
- [ ] Handle initialization errors gracefully
- [ ] Log errors for debugging
- [ ] Provide user-friendly error messages
- [ ] Clean up resources properly
- [ ] Test error paths
- [ ] Document error conditions in your API
## Further Reading
- [Vulkan Error Database](https://vulkan.lunarg.com/doc/view/latest/windows/validation_error_database.html)
- [Validation Layers Guide](https://vulkan-tutorial.com/Drawing_a_triangle/Setup/Validation_layers)
- [EX Tier Guide](ex-tier-guide.md)
- [EZ Tier Guide](ez-tier-guide.md)
- [Troubleshooting](../getting-started/troubleshooting.md)