20 years Weta/Pixar experience in real-time graphics, Metal shaders, and visual effects. Expert in MSL shaders, PBR rendering, tile-based deferred rendering (TBDR), and GPU debugging. Activate on 'Metal shader', 'MSL', 'compute shader', 'vertex shader', 'fragment shader', 'PBR', 'ray tracing', 'tile shader', 'GPU profiling', 'Apple GPU'. NOT for WebGL/GLSL (different architecture), general OpenGL (deprecated on Apple), CUDA (NVIDIA only), or CPU-side rendering optimization.
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Une commande directe contourne le prompt de vérification. Examinez la source avant de l'exécuter.
20 years Weta/Pixar experience in real-time graphics, Metal shaders, and visual effects. Expert in MSL shaders, PBR rendering, tile-based deferred rendering (TBDR), and GPU debugging. Activate on 'Metal shader', 'MSL', 'compute shader', 'vertex shader', 'fragment shader', 'PBR', 'ray tracing', 'tile shader', 'GPU profiling', 'Apple GPU'. NOT for WebGL/GLSL (different architecture), general OpenGL (deprecated on Apple), CUDA (NVIDIA only), or CPU-side rendering optimization.
20+ years Weta/Pixar experience specializing in Metal shaders, real-time rendering, and creative visual effects. Expert in Apple's Tile-Based Deferred Rendering (TBDR) architecture.
Decision Points
Shader Type Selection Matrix
Massive parallel data processing:
If data-independent operations → Compute shader (threadgroup size = data size)
If per-pixel operations with neighbor access → Tile shader
If simple per-vertex transformations → Vertex shader
If per-pixel lighting/materials → Fragment shader
Memory access patterns:
If reading multiple textures per pixel → Fragment shader (tile cache optimized)
If writing to multiple render targets → Fragment shader with [[color(n)]]
If sharing data between nearby threads → Tile shader with threadgroup memory
If sequential processing → Compute shader with atomic operations
If ALU-limited (heavy computation) → Compute shader (more threads)
If geometry-limited → Vertex shader with instancing/amplification
Memory/Precision Trade-off Decision Tree
Input: Variable type needed
├── Position/depth calculations?
│ └── YES: Use `float` (32-bit precision required)
├── Color/normal calculations?
│ ├── HDR/wide gamut? → `float`
│ └── Standard range? → `half` (saves 50% registers)
├── Iteration counters/indices?
│ └── Use `uint16_t` or `ushort` when possible
└── Temporary calculations?
├── Intermediate precision needed? → `float`
└── Display-bound result? → `half`
TBDR Architecture Decisions
Render target strategy:
If intermediate data not needed after pass → Memoryless texture (MTLStorageModeMemoryless)
If ping-ponging between targets → Use tile shader to avoid store/load
If multiple render targets → Group related data to minimize bandwidth
Failure Modes
1. "Bandwidth Bandit" - Excessive Memory Traffic
Detection: Frame debugger shows high memory bandwidth, low ALU utilization
Symptoms: Multiple texture fetches per fragment, storing unnecessary render targets
Fix: Use tile shaders for multi-pass effects, memoryless targets for intermediate data
// BAD: Multiple passes with full store/load
float4 pass1_result = sample_texture(tex1, uv);
// Store to render target, then load in next pass
// GOOD: Tile shader keeps data in tile memory
threadgroup float4 tile_data[64];
// Process multiple steps without memory round-trip
2. "Register Pressure Cascade" - Poor Data Type Choices
Detection: GPU occupancy drops below 50%, register spilling in shader profiler
Symptoms: Using float4 everywhere, large intermediate arrays
Fix: Use half for display-bound calculations, pack data efficiently
Detection: Fragment shader shows low efficiency in GPU profiler
Symptoms:if/else statements based on material properties or uniforms
Fix: Use function constants for compile-time specialization
// BAD: Runtime branching
if (material.has_normal_map) { /* complex normal mapping */ }
// GOOD: Function constant
constant bool has_normal_map [[function_constant(0)]];
if (has_normal_map) { /* branch eliminated at compile time */ }
Detection: Memory bandwidth higher than expected, register usage at 100%
Symptoms:float used for colors, normals, and other display-bound values
Fix: Default to half, upgrade only when precision artifacts appear
Detection: Ray tracing performance significantly below expectations
Symptoms: Using intersection query API instead of intersector
Fix: Use intersector API with explicit result handling for hardware alignment
Worked Examples
Example 1: PBR Fragment Shader Optimization
Initial novice implementation:
fragment float4 pbr_fragment(VertexOut in [[stage_in]],
constant Material& material [[buffer(0)]],
texture2d<float> albedo_tex [[texture(0)]]) {
float4 albedo = albedo_tex.sample(sampler, in.uv);
float3 normal = normalize(in.normal);
// ... complex BRDF calculation using float everywhere
return float4(final_color, 1.0);
}
Expert decision process:
Precision analysis: Color output is display-bound → use half for most calculations
Register optimization: Pack material properties, use half for intermediate values
TBDR optimization: Multiple material variants → use function constants
Optimized implementation:
constant bool use_normal_map [[function_constant(0)]];
constant bool use_metallic_roughness [[function_constant(1)]];
fragment half4 pbr_fragment(VertexOut in [[stage_in]],
constant MaterialHalf& material [[buffer(0)]],
texture2d<half> albedo_tex [[texture(0)]]) {
half4 albedo = albedo_tex.sample(sampler, in.uv);
half3 normal = normalize(half3(in.normal)); // Only convert once
if (use_normal_map) {
// Normal mapping branch eliminated at compile time
}
// BRDF calculation in half precision
half3 final_color = calculate_brdf_half(albedo.rgb, normal, material);
return half4(final_color, albedo.a);
}
Performance impact: 40% reduction in register usage, 2x occupancy increase