use thiserror::Error;
#[derive(Debug, Error)]
pub enum EzError {
#[error("❌ Failed to initialize Vulkan renderer\n\n\
What happened:\n\
{details}\n\n\
Common causes:\n\
• Vulkan runtime not installed (install from https://vulkan.lunarg.com/)\n\
• Outdated GPU drivers\n\
• GPU doesn't support Vulkan 1.3\n\
• Validation layers requested but not installed\n\n\
Try these fixes:\n\
1. Update your GPU drivers to the latest version\n\
2. Download and install the Vulkan SDK\n\
3. If using validation layers, install Vulkan SDK or disable them\n\
4. Run 'vulkaninfo' to check if Vulkan is working\n\n\
Need more help? Check: docs/getting-started/troubleshooting.md")]
InitializationFailed { details: String },
#[error("❌ Shader compilation failed\n\n\
What happened:\n\
Your GLSL shader code has errors and couldn't be compiled to SPIR-V.\n\n\
Details:\n\
{details}\n\n\
Debugging tips:\n\
• Check the error message above for line numbers\n\
• Verify your shader version is #version 450 or higher\n\
• Make sure all variables are declared\n\
• Check for typos in GLSL keywords\n\
• Ensure all functions return the correct type\n\n\
Common GLSL mistakes:\n\
• Missing semicolons\n\
• Using = instead of == in comparisons\n\
• Forgetting to declare uniform blocks\n\
• Wrong vector component names (use .xyzw or .rgba, not both)\n\n\
Resources:\n\
• GLSL quick reference: https://www.khronos.org/files/opengl45-quick-reference-card.pdf\n\
• Shader examples: demos/ex/README.md")]
ShaderCompilationFailed { details: String },
#[error("❌ Pipeline creation failed\n\n\
What happened:\n\
The graphics or compute pipeline couldn't be created.\n\n\
Details:\n\
{details}\n\n\
Common causes:\n\
• Shaders are incompatible (vertex output doesn't match fragment input)\n\
• Missing required shader stages\n\
• Descriptor bindings don't match shader\n\
• Render format mismatch\n\n\
Quick fixes:\n\
1. Ensure vertex shader outputs match fragment shader inputs\n\
2. Check that both vertex and fragment shaders are provided\n\
3. Verify color attachment formats are correct\n\
4. Enable validation layers for detailed error messages\n\n\
Validation layers:\n\
Add this to your config: enable_validation: true\n\
This will show exactly what's wrong!")]
PipelineCreationFailed { details: String },
#[error("❌ Invalid shader stages\n\n\
What happened:\n\
{details}\n\n\
Quick guide:\n\
• Graphics pipelines need: vertex shader (required) + fragment shader (optional but recommended)\n\
• Compute pipelines need: compute shader only\n\n\
Example:\n\
For graphics:\n\
let vert = ez.compile_shader(\"vertex.glsl\", ShaderStage::Vertex)?;\n\
let frag = ez.compile_shader(\"fragment.glsl\", ShaderStage::Fragment)?;\n\n\
For compute:\n\
let comp = ez.compile_shader(\"compute.glsl\", ShaderStage::Compute)?;")]
InvalidShaderStages { details: String },
#[error("❌ Frame rendering failed\n\n\
What happened:\n\
{details}\n\n\
This could mean:\n\
• Window was resized (this is normal, recreate swapchain)\n\
• GPU device was lost (driver crash or timeout)\n\
• Invalid rendering commands\n\n\
Recovery steps:\n\
1. If window resized: catch this error and recreate swapchain\n\
2. If device lost: reinitialize everything (full restart)\n\
3. Enable validation layers to see what command failed\n\n\
Preventing device loss:\n\
• Avoid infinite loops in shaders\n\
• Check for validation errors early\n\
• Don't exceed GPU timeouts (Windows: 2 seconds default)")]
FrameFailed { details: String },
#[error("❌ Failed to create {resource_type}\n\n\
What happened:\n\
{details}\n\n\
Common causes:\n\
• Out of GPU memory (VRAM)\n\
• Invalid parameters\n\
• Resource too large\n\n\
Tips:\n\
• Check GPU has enough free VRAM\n\
• Reduce texture sizes or buffer counts\n\
• Free resources you're not using\n\
• Monitor memory usage with GPU-Z or similar tools")]
ResourceCreationFailed {
resource_type: String,
details: String,
},
#[error("❌ Buffer operation failed: {operation}\n\n\
What happened:\n\
{details}\n\n\
Buffer operations that can fail:\n\
• Creating buffer (out of memory)\n\
• Mapping memory (wrong memory type)\n\
• Uploading data (size mismatch)\n\
• Binding buffer (wrong offset/range)\n\n\
Double-check:\n\
• Buffer size matches your data\n\
• Memory type supports your usage\n\
• Offsets are properly aligned\n\
• Buffer isn't already mapped when mapping")]
BufferOperationFailed { operation: String, details: String },
#[error("❌ Mesh operation failed\n\n\
What happened:\n\
{details}\n\n\
Common mesh issues:\n\
• Vertex/index count mismatch\n\
• Invalid vertex format\n\
• Empty mesh data\n\
• Indices out of bounds\n\n\
Mesh checklist:\n\
✓ Vertices have correct format (position, texcoord, etc.)\n\
✓ Index count is multiple of 3 (for triangles)\n\
✓ All indices are less than vertex count\n\
✓ Data types match shader expectations")]
MeshOperationFailed { details: String },
#[error("❌ Runtime error\n\n{0}\n\n\
General troubleshooting:\n\
1. Enable validation layers for detailed diagnostics\n\
2. Check if GPU drivers are up to date\n\
3. Review recent code changes\n\
4. Look for validation warnings in console\n\n\
Still stuck? Create an issue with:\n\
• Your GPU model and driver version\n\
• Full error message\n\
• Minimal code to reproduce\n\
→ https://github.com/your-repo/issues")]
RuntimeError(String),
#[error("❌ Vulkan Validation Error\n\n\
Message ID: {message_id}\n\
Severity: {severity}\n\n\
{message}\n\n\
What are validation errors?\n\
Validation layers catch Vulkan API misuse before it crashes.\n\
These errors are CRITICAL and must be fixed!\n\n\
Location: {location}\n\n\
Next steps:\n\
1. Read the message carefully - it tells you exactly what's wrong\n\
2. Fix the issue (don't just disable validation!)\n\
3. Test again with validation enabled\n\n\
Learn more: https://vulkan.lunarg.com/doc/view/latest/windows/validation_error_database.html")]
ValidationError {
message_id: String,
severity: String,
message: String,
location: String,
},
}
impl From<crate::ex::RuntimeError> for EzError {
fn from(err: crate::ex::RuntimeError) -> Self {
match err {
crate::ex::RuntimeError::InstanceCreationFailed(e) => {
EzError::InitializationFailed {
details: format!("Instance creation failed: {}", e),
}
}
crate::ex::RuntimeError::DeviceCreationFailed(e) => {
EzError::InitializationFailed {
details: format!("Device creation failed: {}", e),
}
}
crate::ex::RuntimeError::NoGraphicsQueue => {
EzError::InitializationFailed {
details: "Selected GPU doesn't have a graphics queue".to_string(),
}
}
crate::ex::RuntimeError::NoSuitableDevice(count) => {
EzError::InitializationFailed {
details: format!(
"Found {} GPU(s) but none support Vulkan 1.3 with required features",
count
),
}
}
_ => EzError::RuntimeError(err.to_string()),
}
}
}
impl From<crate::ex::ShaderManagerError> for EzError {
fn from(err: crate::ex::ShaderManagerError) -> Self {
match err {
crate::ex::ShaderManagerError::ShaderCompilationFailed(e) => {
EzError::ShaderCompilationFailed {
details: e.to_string(),
}
}
crate::ex::ShaderManagerError::PipelineCreationFailed(e) => {
EzError::PipelineCreationFailed {
details: e.to_string(),
}
}
crate::ex::ShaderManagerError::PipelineBuilderError(e) => {
EzError::PipelineCreationFailed {
details: e.to_string(),
}
}
_ => EzError::RuntimeError(err.to_string()),
}
}
}
impl From<crate::core::ShaderError> for EzError {
fn from(err: crate::core::ShaderError) -> Self {
EzError::ShaderCompilationFailed {
details: err.to_string(),
}
}
}
impl From<crate::core::PipelineError> for EzError {
fn from(err: crate::core::PipelineError) -> Self {
EzError::PipelineCreationFailed {
details: err.to_string(),
}
}
}
pub trait EzErrorDisplay {
fn display_friendly(&self) -> String;
}
impl EzErrorDisplay for EzError {
fn display_friendly(&self) -> String {
format!(
"\n\
╔══════════════════════════════════════════════════════════════════╗\n\
║ 🚨 EZ TIER ERROR 🚨 ║\n\
╠══════════════════════════════════════════════════════════════════╣\n\
\n\
{}\n\
\n\
╚══════════════════════════════════════════════════════════════════╝\n",
self
)
}
}