Overview
Shader bugs are notoriously hard to debug—there's no printf, no breakpoints, and errors manifest as wrong pixels. rendara changes this with full shader debugging support across all major shading languages.
Supported Languages
- SPIR-V — Native Vulkan shader format
- GLSL — OpenGL Shading Language (via SPIR-V)
- HLSL — DirectX shaders (via SPIR-V or DXIL)
- WGSL — WebGPU Shading Language
Pixel-Level Debugging
The most common shader debugging workflow: click a pixel to debug.
- Capture a frame and open it in rendara
- Navigate to the draw call that renders your target
- Click on a pixel in the render target
- Select "Debug Pixel" from the context menu
rendara will show you:
- Which fragment shader invocation rendered this pixel
- All input variables (interpolated from vertex shader)
- Every line of shader code with variable values
- The final output color and why
Step-Through Debugging
rendara simulates shader execution on the CPU, allowing traditional debugging:
Controls
F10— Step over (next line)F11— Step into (enter function)Shift+F11— Step out (exit function)F5— Continue to next breakpoint
Setting Breakpoints
Click the gutter next to any line to set a breakpoint. Conditional breakpoints are supported:
// Break when this condition is true
fragColor.a < 0.5
Variable Inspection
Hover over any variable to see its current value. For vectors and matrices:
vec3 normal = normalize(v_normal);
// Hover shows: normal = vec3(0.577, 0.577, 0.577)
mat4 mvp = projection * view * model;
// Hover shows full 4x4 matrix with expandable view
dot(normal, lightDir) or length(position - cameraPos).
AI-Powered Debugging
rendara's AI can explain shader behavior in plain English:
rendara ask "why is this pixel black?"
AI: The pixel is black because the fragment shader's lighting calculation
returns 0. Looking at line 45:
float NdotL = max(dot(normal, lightDir), 0.0);
The normal vector (0, -1, 0) is pointing away from the light direction
(0, 1, 0), resulting in NdotL = 0. This causes the diffuse term to be
zero, and since there's no ambient term, the final color is black.
Suggestion: Add an ambient term or check if your normals are flipped.
Common Shader Bugs
NaN/Inf Values
Floating point errors propagate and cause visual artifacts:
// Common cause: division by zero
float attenuation = 1.0 / distance; // NaN if distance = 0
// Fix: add small epsilon
float attenuation = 1.0 / max(distance, 0.0001);
rendara highlights NaN/Inf values in red in the variable inspector.
Incorrect Normalization
// Bug: normalizing in vertex shader, interpolating, then using
// Interpolated normals are NOT unit length!
// Fix: re-normalize in fragment shader
vec3 N = normalize(v_normal);
Texture Sampling Issues
- Black textures — Check UV coordinates are in [0,1] range
- Blocky textures — Verify mip level selection, check minification filter
- Edge artifacts — Check wrap mode (repeat vs clamp)
Shader Performance Analysis
rendara analyzes shader performance and suggests optimizations:
rendara analyze frame.rdc --shader-perf
⚠ PERFORMANCE: Fragment shader "pbr.frag" (40% of frame time)
Issue: Texture sample inside loop (line 87)
for (int i = 0; i < numLights; i++) {
vec3 shadowCoord = getShadowCoord(i);
float shadow = texture(shadowMaps[i], shadowCoord).r; // ← Hot spot
}
Suggestion: Sample shadow maps outside the loop if coordinates
are independent, or use texture arrays with single sample.
Live Shader Editing
rendara supports hot-reload of shaders without recapturing:
- Modify shader code in the built-in editor
- Press
Ctrl+Sto recompile - See results immediately in the frame view