use thiserror::Error;
use std::fmt;
#[derive(Error, Debug)]
pub enum RuntimeError {
#[error("Instance creation failed: {0}\n\nContext: This happens during Vulkan initialization.\nSuggestions:\n • Check that Vulkan runtime is installed\n • Update GPU drivers\n • Enable/disable validation layers")]
InstanceCreationFailed(#[from] crate::core::InstanceError),
#[error("Device creation failed: {0}\n\nContext: Failed to create logical device from physical GPU.\nSuggestions:\n • Check device extensions are supported\n • Verify required features are available\n • Try a different physical device")]
DeviceCreationFailed(#[from] crate::core::DeviceError),
#[error("No graphics queue family found on selected device\n\nContext: The selected GPU doesn't support graphics operations.\nSuggestions:\n • Verify GPU supports Vulkan graphics\n • Try a different physical device\n • Check if device is compute-only")]
NoGraphicsQueue,
#[error("No suitable physical device found (total devices: {0})\n\nContext: Found {0} physical device(s) but none met requirements.\nSuggestions:\n • Update GPU drivers\n • Relax device selection criteria\n • Check if integrated GPU is available\n • Verify Vulkan 1.3 support")]
NoSuitableDevice(usize),
#[error("Fence synchronization failed: {0}\n\nContext: Failed to synchronize with GPU using fence.\nSuggestions:\n • Check for device loss\n • Verify timeout is reasonable\n • Enable validation layers for details")]
FenceSyncFailed(#[from] crate::core::FenceError),
#[error("Semaphore creation failed: {0}\n\nContext: Failed to create synchronization primitive.\nSuggestions:\n • Check for resource exhaustion\n • Verify device is valid\n • May indicate too many simultaneous operations")]
SemaphoreCreationFailed(#[from] crate::core::SemaphoreError),
#[error("Command pool creation failed: {0}\n\nContext: Failed to create command buffer pool.\nSuggestions:\n • Verify queue family index is valid\n • Check device memory availability\n • Ensure device hasn't been lost")]
CommandPoolCreationFailed(#[from] crate::core::CommandPoolError),
#[error("Command buffer operation failed: {0}\n\nContext: Error during command buffer recording or execution.\nSuggestions:\n • Check validation layer output\n • Verify all resources are valid\n • Ensure proper synchronization\n • Check command buffer state")]
CommandBufferError(#[from] crate::core::CommandBufferError),
#[error("Queue operation failed: {0}\n\nContext: Failed to submit work to GPU or wait for completion.\nSuggestions:\n • Check for device loss\n • Verify semaphore/fence validity\n • Enable validation layers\n • Check for shader infinite loops")]
QueueError(#[from] crate::core::QueueError),
#[error("Frame presentation failed: {details}\n\nOperation: {operation}\nFrame: {frame_index}\n\nSuggestions:\n • Check if window was resized\n • Verify swapchain is valid\n • Handle ERROR_OUT_OF_DATE_KHR by recreating swapchain")]
FramePresentationFailed {
operation: String,
frame_index: usize,
details: String,
},
#[error("Resource exhaustion: {resource_type}\n\nContext: Ran out of {resource_type}.\nCurrent usage: {current_count}\nLimit: {limit}\n\nSuggestions:\n • Free unused resources\n • Check for resource leaks\n • Increase pool sizes\n • Batch operations")]
ResourceExhausted {
resource_type: String,
current_count: usize,
limit: usize,
},
#[error("{0}")]
Other(String),
}
#[derive(Error, Debug)]
pub enum ShaderManagerError {
#[error("Shader compilation failed: {0}\n\nContext: GLSL→SPIR-V compilation error.\nSuggestions:\n • Check GLSL syntax\n • Verify shader version (#version 450)\n • Review error messages above for line numbers\n • Use glslangValidator for offline validation")]
ShaderCompilationFailed(#[from] crate::core::ShaderError),
#[error("Pipeline creation failed: {0}\n\nContext: Failed to create graphics or compute pipeline.\nSuggestions:\n • Verify shader stages are compatible\n • Check descriptor set layouts match shader\n • Ensure render pass formats match\n • Enable validation layers for detailed diagnostics")]
PipelineCreationFailed(#[from] crate::core::PipelineError),
#[error("Pipeline builder error: {0}\n\nContext: Pipeline configuration is incomplete or invalid.\nSuggestions:\n • Check that all required stages are set\n • Verify color attachment formats\n • Ensure descriptor layouts are valid")]
PipelineBuilderError(#[from] PipelineError),
#[error("Invalid shader ID: {0:?}\n\nContext: Attempted to use shader that doesn't exist.\nSuggestions:\n • Verify shader was compiled successfully\n • Check shader hasn't been deleted\n • Use valid ShaderId from compile_shader()")]
InvalidShaderId(ShaderId),
#[error("Invalid pipeline ID: {0:?}\n\nContext: Attempted to use pipeline that doesn't exist.\nSuggestions:\n • Verify pipeline was created successfully\n • Check pipeline hasn't been deleted\n • Use valid PipelineId from create_pipeline()")]
InvalidPipelineId(PipelineId),
#[error("Descriptor pool creation failed: {0}\n\nContext: Failed to create descriptor set pool.\nSuggestions:\n • Check pool sizes are sufficient\n • Verify max sets count\n • Ensure device memory is available\n • Review descriptor requirements")]
DescriptorPoolCreationFailed(#[from] crate::core::DescriptorPoolError),
#[error("Descriptor operation failed: {0}\n\nContext: Error during descriptor set allocation or update.\nSuggestions:\n • Check pool isn't exhausted\n • Verify descriptor types match layout\n • Ensure buffers/images are valid\n • Reset pool if fragmented")]
DescriptorError(#[from] crate::core::DescriptorError),
#[error("Shader reflection failed for '{shader_name}'\n\nContext: Could not extract descriptor bindings from SPIR-V.\nDetails: {details}\n\nSuggestions:\n • Ensure shader uses standard descriptor bindings\n • Verify SPIR-V is valid\n • Check shader was compiled correctly")]
ReflectionFailed {
shader_name: String,
details: String,
},
}
#[derive(Error, Debug)]
pub enum PipelineError {
#[error("No vertex shader provided - vertex shader is required for graphics pipelines\n\nSuggestions:\n • Call .vertex_shader() on the pipeline builder\n • Check shader compilation succeeded\n • Verify you're building a graphics pipeline")]
NoVertexShader,
#[error("No fragment shader provided - fragment shader is required for graphics pipelines\n\nSuggestions:\n • Call .fragment_shader() on the pipeline builder\n • Fragment shaders handle pixel output\n • Check shader compilation succeeded")]
NoFragmentShader,
#[error("No compute shader provided - compute shader is required for compute pipelines\n\nSuggestions:\n • Call .compute_shader() on the pipeline builder\n • Verify shader stage is COMPUTE\n • Check shader compilation succeeded")]
NoComputeShader,
#[error("Pipeline creation failed: {0}")]
CreationFailed(#[from] crate::core::PipelineError),
#[error("Invalid descriptor set layout configuration\n\nContext: Descriptor layout doesn't match shader requirements.\nSuggestions:\n • Use shader reflection to auto-generate layouts\n • Verify binding numbers match shader\n • Check descriptor types are correct\n • Ensure set numbers are sequential")]
InvalidDescriptorLayout,
#[error("No color attachment formats specified - at least one format is required\n\nSuggestions:\n • Call .color_attachment_format() at least once\n • Common format: vk::Format::B8G8R8A8_SRGB\n • Format must match render target")]
NoColorAttachmentFormats,
#[error("Incompatible shader stages: {details}\n\nContext: Shader outputs don't match next stage inputs.\nSuggestions:\n • Check vertex shader outputs match fragment inputs\n • Verify location decorations in GLSL\n • Enable validation layers for detailed info")]
IncompatibleShaderStages { details: String },
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct ShaderId(pub(crate) usize);
impl fmt::Display for ShaderId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Shader({})", self.0)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PipelineId(pub(crate) usize);
impl fmt::Display for PipelineId {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "Pipeline({})", self.0)
}
}