Use half precision (f16) in gsplat WGSL shaders#8466
Use half precision (f16) in gsplat WGSL shaders#8466slimbuck merged 12 commits intoplaycanvas:mainfrom
Conversation
There was a problem hiding this comment.
Pull request overview
This PR introduces half-precision (f16) floating-point types throughout the gsplat WGSL shader pipeline to reduce ALU cost and varying bandwidth on devices supporting the shader-f16 WebGPU feature. The implementation uses the engine's type alias system (half, half2, half3, half4, half3x3) that automatically falls back to f32 on devices without f16 support, ensuring compatibility across all hardware.
Changes:
- Converted color pipeline, UV coordinates, spherical harmonics, quaternion/covariance computations, and fragment shader operations to half precision
- Retained f32 for position calculations, view/projection matrices, eigenvalue decomposition, and precision-sensitive operations
- Unrolled SH texture read loop in SOG format to avoid Dawn compiler issues
Reviewed changes
Copilot reviewed 10 out of 10 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| gsplatStructs.js | Changed struct fields to use half2 for UVs and half for AA factor |
| gsplatSource.js | Added half2 cast when initializing cornerUV from vertex position |
| gsplatQuatToMat3.js | Converted quaternion and matrix operations to half precision with f32 boundaries |
| gsplatEvalSH.js | Changed spherical harmonics evaluation to return half3 instead of vec3f |
| gsplatCorner.js | Implemented half-precision covariance computation with f32 promotion for projection math |
| gsplatCommon.js | Modified clipCorner to compute clip factor in f32, store as half |
| gsplat.js (vert) | Converted color pipeline to half4 with f32 conversions at user hook and output boundaries |
| sogSH.js | Unrolled SH data read loop and converted to half precision operations |
| sog.js | Changed color dequantization and SH_C0 multiply to use half3 |
| gsplat.js (frag) | Converted fragment shader to operate in half precision with f32 output |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
There was a problem hiding this comment.
Pull request overview
Copilot reviewed 11 out of 11 changed files in this pull request and generated 2 comments.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
mvaligursky
left a comment
There was a problem hiding this comment.
Seems good, but it'd be good to test on carious Samsung devices - we had multiple half conversion issues on those
Summary
Use half precision types throughout the gsplat WGSL shader pipeline to reduce ALU cost and varying bandwidth on devices that support the
shader-f16WebGPU feature. On devices without f16 support, allhalftypes automatically fall back to f32 via the engine's alias system, so there is no change in behavior.Changes
Fragment shader (
gsplat.jsfrag)gaussianUVandgaussianColorvaryings changed fromvec2f/vec4ftohalf2/half4, halving interpolation bandwidthnormExp()and alpha computation operate entirely in half precisionVertex shader - core (
gsplat.jsvert,gsplatStructs.js,gsplatSource.js,gsplatCommon.js)SplatSource.cornerUVchanged fromvec2ftohalf2SplatCorner.uvchanged fromvec2ftohalf2,aaFactorfromf32tohalfhalf4throughout; promoted to f32 only for themodifySplatColoruser hook andclipCornermathclipCornercomputes clip factor in f32 (for log/sqrt range), stores result ashalfQuaternion & covariance (
gsplatQuatToMat3.js,gsplatCorner.js)quatToMat3now returnshalf3x3and computes entirely in half precisionquatMulcomputes in half, returns f32computeCovarianceoperates inhalf3x3; result promoted to f32 at theinitCornerCovboundary for projection mathSpherical harmonics (
gsplatEvalSH.js)evalSHreturn type changed fromvec3ftohalf3, avoiding an unnecessary promotion since all SH constants and intermediates were already halfSOG format (
sog.js,sogSH.js)getColor()dequantization (mix) and SH_C0 multiply now operate in half3readSHTexel()dequantization (mix) now operates in half3 instead of f32, benefiting the 15 calls per vertex (SH band 3)Technical details
All half-precision types use the engine's alias system (
half,half2,half3,half4,half3x3) defined inhalf-types.js. WhenCAPS_SHADER_F16is not defined, these resolve to their f32 equivalents (f32,vec2f,vec3f,vec4f,mat3x3f), ensuring the shaders compile and run correctly on all devices. No native WGSL f16 types (f16,vec2h,mat3x3h, etc.) are used directly.f32 is intentionally retained for:
initCornerCov(precision-sensitive subtraction)clipCornerlog/sqrt (dynamic range)