typed_pipeline_metadata_plan - mark-ik/graphshell GitHub Wiki
The wgpu backend identifies shader pipelines using string tuples like
("ps_text_run", "ALPHA_PASS,GLYPH_TRANSFORM,TEXTURE_2D"). This caused the
DPR=2 text bug — a wildcard match arm silently selected the wrong shader
variant. Replacing these stringly-typed keys with a flat enum gives us
compiler exhaustiveness checks that prevent this bug class entirely.
A single enum rather than factored ShaderName + ShaderConfig enums, because
the config flags are NOT freely combinable — each shader only uses specific
configs. A product space would create hundreds of invalid combinations. The flat
enum makes every valid variant explicit and every invalid variant unrepresentable.
The enum covers the ~35 shader variants actually generated under wgpu feature flags (DITHERING + DEBUG). No GL-only variants (TEXTURE_RECT, ADVANCED_BLEND, DUAL_SOURCE_BLENDING, ANTIALIASING, REPETITION) are included.
// Brush shaders (opaque + alpha)
BrushSolid, BrushSolidAlpha,
BrushImage, BrushImageAlpha,
BrushBlend, BrushBlendAlpha,
BrushMixBlend, BrushMixBlendAlpha,
BrushLinearGradient, BrushLinearGradientAlpha,
BrushOpacity, BrushOpacityAlpha,
BrushYuvImage, BrushYuvImageAlpha,
// Text (the two variants that matter)
PsTextRun, PsTextRunGlyphTransform,
// Quads
PsQuadTextured,
PsQuadGradient, PsQuadRadialGradient, PsQuadConicGradient,
PsQuadMask, PsQuadMaskFastPath,
// Prim
PsSplitComposite,
// Clip
CsClipRectangle, CsClipRectangleFastPath, CsClipBoxShadow,
// Cache tasks
CsBorderSolid, CsBorderSegment, CsLineDecoration,
CsFastLinearGradient,
CsLinearGradient, CsRadialGradient, CsConicGradient,
CsBlurColor,
CsScale,
// Debug
DebugColor, DebugFont,
// Utility (texture cache ops)
PsClear, PsCopy,
// Debug overdraw variants (compiled but rarely used at runtime)
BrushSolidDebugOverdraw, BrushBlendDebugOverdraw, BrushMixBlendDebugOverdraw,
BrushLinearGradientDebugOverdraw, BrushOpacityDebugOverdraw, BrushOpacityAntialiasing,
BrushOpacityAlphaAntialiasing, BrushOpacityAntialiasingDebugOverdraw,
BrushImageDebugOverdraw, BrushImageAlphaRepetition, BrushImageRepetition,
BrushImageRepetitionDebugOverdraw, BrushImageAlphaRepetitionDebugOverdraw,
BrushYuvImageDebugOverdraw,
PsTextRunDebugOverdraw, CsBlurAlpha,
This is large. Pragmatic approach: start with only the variants actually used
at runtime (the first ~35 above). DEBUG_OVERDRAW and ANTIALIASING/REPETITION
variants can map via from_shader_key() → None and be compiled but not
indexed in the typed cache. They're only used with DebugFlags::SHOW_OVERDRAW
which the wgpu path doesn't support yet.
Core variants (what we actually type): ~38 variants.
WGSL_SHADERS: HashMap<(&str, &str), WgslShaderSource> stays unchanged (no
build.rs changes). The enum provides:
-
shader_key(self) -> (&'static str, &'static str)— enum → string pair -
from_shader_key(name, config) -> Option<Self>— string pair → enum (None for debug-overdraw etc.) -
instance_layout(self) -> Option<&'static [InstanceField]>— replaces the string match in create_all_pipelines
-
Define
WgpuShaderVariantnearWgpuBlendMode/WgpuDepthState(~line 51)- Derive
Debug, Clone, Copy, PartialEq, Eq, Hash -
shader_key(),from_shader_key(),instance_layout()methods -
all()→ const array for test coverage
- Derive
-
Change
shadersHashMap (line 230):HashMap<WgpuShaderVariant, ShaderEntry>(was(&str, &str)) -
Change
pipelinesHashMap (line 231-232):HashMap<(WgpuShaderVariant, WgpuBlendMode, WgpuDepthState, wgpu::TextureFormat), WgpuProgram> -
Change
draw_instanced()signature (line 1551):variant: WgpuShaderVariantreplacesshader_name: &str, config: &strPipeline key:(variant, blend_mode, depth_state, target_format)Shader lookup:self.shaders.get(&variant) -
Update
create_all_pipelines()(line 2352): Iterate WGSL_SHADERS, callfrom_shader_key(), skip None, store by variant. Replace string-match instance layout withvariant.instance_layout(). -
Update
create_pipeline_for_blend()(line 2269):variant: WgpuShaderVariantreplacesname: &str, config: &str. Label:format!("{:?}", variant).
- Add
WgpuShaderVariantto public re-exports (line 39).
-
Change
batch_key_to_pipeline_key()(line 2199): ReturnWgpuShaderVariantinstead of(&str, &str).BatchKind::TextRun(glyph_format) => match glyph_format { GlyphFormat::TransformedAlpha | GlyphFormat::TransformedSubpixel => WgpuShaderVariant::PsTextRunGlyphTransform, _ => WgpuShaderVariant::PsTextRun, }
-
Update
draw_batch!macro (~line 2005):let variant = Self::batch_key_to_pipeline_key(...)→ pass todraw_instanced. -
Update
pattern_to_shaderclosure (~line 2439): ReturnWgpuShaderVariantinstead of(&str, &str). -
Update all direct
draw_instancedcalls (~13 call sites): Replace string pairs with enum variants:-
"cs_clip_rectangle", ""→CsClipRectangle -
"cs_clip_rectangle", "FAST_PATH"→CsClipRectangleFastPath -
"cs_clip_box_shadow", "TEXTURE_2D"→CsClipBoxShadow -
"cs_blur", "COLOR_TARGET"→CsBlurColor -
"cs_scale", "TEXTURE_2D"→CsScale -
"cs_border_solid", ""→CsBorderSolid -
"cs_border_segment", ""→CsBorderSegment -
"cs_line_decoration", ""→CsLineDecoration -
"cs_fast_linear_gradient", ""→CsFastLinearGradient -
"cs_linear_gradient", "DITHERING"→CsLinearGradient -
"cs_radial_gradient", "DITHERING"→CsRadialGradient -
"cs_conic_gradient", "DITHERING"→CsConicGradient
-
-
Update
draw_cs!anddraw_cs_blend!macros (~line 2575): Change$shader:expr, $config:exprto$variant:expr.
-
Define the enum in wgpu_device.rs with shader_key/from_shader_key/instance_layout. Re-export in device/mod.rs. Build succeeds — nothing uses it yet.
-
Migrate WgpuDevice internals: change shaders + pipelines HashMaps, draw_instanced signature, create_all_pipelines, create_pipeline_for_blend. This breaks the call sites temporarily.
-
Migrate renderer call sites: batch_key_to_pipeline_key return type, draw_batch macro, pattern_to_shader, all direct draw_instanced calls, draw_cs/draw_cs_blend macros.
-
Build and verify.
Steps 2-3 are effectively one atomic commit since changing draw_instanced's signature breaks all callers. Can do as a single commit.
-
cargo build --bin servoshellfrom servo-graphshell (full compile) -
SERVO_WGPU_BACKEND=1 cargo run --bin servoshell— visual check that text, images, solid backgrounds, gradients all render correctly at DPR=1 and DPR=2 - No string shader names remain in renderer/mod.rs draw paths (grep check)