You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
A layered strategy for Metashade source code node reimplementation, starting with trivial arithmetic nodes, using the safe math experiment as a forcing function, and connecting to the ASWF generic implementation gap.
Builds on the multi-environment infrastructure from #13.
The Landscape
MaterialX's stdlib has three implementation tiers, each with different Metashade opportunities:
380 inline sourcecode implementations (genglsl) -- trivial expressions like {{in1}} + {{in2}}, duplicated identically across 3 targets (genglsl/genosl/genmdl) and ~16 type variants each. Only ~60 unique expression patterns.
87 file-based source code nodes (listed in source_code_nodes.txt) -- dedicated .glsl/.osl files for BSDFs, noise, image sampling, compositing blends, etc. These have genuinely different implementations per target.
198 nodegraph implementations -- target-independent compositions of simpler nodes. Already generic, no reimplementation needed.
The 380 inline implementations collapse into ~60 unique patterns. The arithmetic subset (add, subtract, multiply, divide, modulo) accounts for 69 NodeDefs across type variants.
Why start here:
Identical across all targets -- {{in1}} + {{in2}} is the same in GLSL, MDL, and OSL
Metashade already generates these correctly via ArithmeticType._rhs_binary_operator() in metashade/targets/_clike/dtypes.py
The existing test_metashade_add_color3 test proves the pattern works end-to-end
convert_*, combine*, extract* -- type constructors / swizzles
constant, remap, smoothstep -- simple expressions
Compositing ops (plus, screen, difference, mix) -- one-liner blending math
Layer 2: Safe Math as a Forcing Function
Safe math is not just a feature -- it's the experiment that proves Metashade can do something MaterialX's sourcecode mechanism cannot: transform operator semantics globally.
The divide node is interesting: it needs to replace an inline expression with a function call. The Metashade-generated .glsl file would define the safe_div function, and the .mtlx implementation would reference it. This is a promotion from inline to file-based, which the override mechanism supports since loadLibraries with the environment loaded first will find the file-based implementation before the inline one from stdlib.
Unlike ASWF templates which are syntactic macros, Metashade has semantic awareness -- it knows that color3 / float and float / float share logic but matrix44 / matrix44 needs mx_matrix_mul(mx_inverse(...))
The safe math hook demonstrates behavioral genericity -- same safety guarantee across all targets from one place
The data tells a compelling story
380 inline implementations x 3 targets = ~1140 lines of duplicated XML for ~60 unique patterns
Metashade reimplements all 60 patterns from a single Python codebase
Safe math, half-precision, and optimization are free riders from the same infrastructure
Overview
A layered strategy for Metashade source code node reimplementation, starting with trivial arithmetic nodes, using the safe math experiment as a forcing function, and connecting to the ASWF generic implementation gap.
Builds on the multi-environment infrastructure from #13.
The Landscape
MaterialX's stdlib has three implementation tiers, each with different Metashade opportunities:
sourcecodeimplementations (genglsl) -- trivial expressions like{{in1}} + {{in2}}, duplicated identically across 3 targets (genglsl/genosl/genmdl) and ~16 type variants each. Only ~60 unique expression patterns.source_code_nodes.txt) -- dedicated.glsl/.oslfiles for BSDFs, noise, image sampling, compositing blends, etc. These have genuinely different implementations per target.Layer 1: Arithmetic Node Reimplementation (Foundation)
The 380 inline implementations collapse into ~60 unique patterns. The arithmetic subset (
add,subtract,multiply,divide,modulo) accounts for 69 NodeDefs across type variants.Why start here:
{{in1}} + {{in2}}is the same in GLSL, MDL, and OSLArithmeticType._rhs_binary_operator()inmetashade/targets/_clike/dtypes.pytest_metashade_add_color3test proves the pattern works end-to-endBroader trivial set beyond pure arithmetic:
abs,floor,ceil,sign,clamp,min,max,pow,sqrt,exp,log-- map to intrinsic functionsifgreater,ifequal,switch-- ternary expressionsconvert_*,combine*,extract*-- type constructors / swizzlesconstant,remap,smoothstep-- simple expressionsplus,screen,difference,mix) -- one-liner blending mathLayer 2: Safe Math as a Forcing Function
Safe math is not just a feature -- it's the experiment that proves Metashade can do something MaterialX's
sourcecodemechanism cannot: transform operator semantics globally.The hook architecture
Injection points in Metashade
_rhs_binary_operator(self, rhs, op)in_clike/dtypes.py-- central dispatch for all binary ops on scalars_per_element_or_scalar(self, rhs, op)in_rtsl/dtypes.py-- vector division/multiplicationFloatIntrinsicsMixin.pow(),.sqrt()inglsl/_intrinsics.py-- intrinsics with NaN riskWhat safe math means concretely
For division:
For power/sqrt:
Connection to multi-environment system (#13)
The safe math experiment becomes a Metashade environment:
The divide node is interesting: it needs to replace an inline expression with a function call. The Metashade-generated
.glslfile would define thesafe_divfunction, and the.mtlximplementation would reference it. This is a promotion from inline to file-based, which the override mechanism supports sinceloadLibrarieswith the environment loaded first will find the file-based implementation before the inline one from stdlib.Usage:
Layer 3: Source Code Node Reimplementation (Medium-term)
After arithmetic, move to the 87 file-based source code nodes, tiered by complexity:
Tier A: Near-trivial
mx_premult_color4,mx_unpremult_color4-- simple alpha mathmx_luminance_color3/4-- dot product with weightsmx_displacement_float/vector3-- simple scalingmx_rotate_vector2/3-- rotation matrix mathTier B: Medium complexity, high value
mx_burn_*,mx_dodge_*-- compositing blend modes (division-based, safe math relevant!)mx_ramplr_*,mx_ramptb_*,mx_splitlr_*,mx_splittb_*-- texture coordinate interpolationmx_hsvtorgb_*,mx_rgbtohsv_*-- color space conversionmx_roughness_anisotropy,mx_roughness_dual-- PBR utilityTier C: Complex, high value
mx_generalized_schlick_bsdf,mx_dielectric_bsdf,mx_conductor_bsdf,mx_oren_nayar_diffuse_bsdf,mx_sheen_bsdf, etc.mx_noise2d/3d_*,mx_fractal2d/3d_*,mx_worleynoise2d/3d_*,mx_cellnoise*mx_image_*,mx_hextiledimage_*Tier D: adsklib custom nodes
noise1d,hashnoise2d,pore_impulse,backface_util-- custom source nodes with manual GLSL/OSL duplicationwood3dprocedural -- 1600+ line XML nodegraphLayer 4: The Generic Implementation Story (ASWF)
Current ASWF state
The gap Metashade fills
The community solved interface genericity (templates) but explicitly punted on implementation genericity. Metashade is uniquely positioned:
color3 / floatandfloat / floatshare logic butmatrix44 / matrix44needsmx_matrix_mul(mx_inverse(...))The data tells a compelling story
Proposed Execution Order
dividefor all types with safe math hook; deploy assafe_math/environmentpow,sqrt,exp,log,clamp)