Skip to content

Performance Optimization Patch - Complete Overhaul #1

Description

@Zarbuz

Overview

I wanted to share a comprehensive performance optimization patch for the Gaussian Splatting
octree system that I developed for my WebGPU fork. These changes dramatically improve
performance, reduce GC allocations, and add critical features for handling 1M+ splat scenes.

Summary of Changes

1. GPU Optimization - Distance Culling & LOD System

Added new settings in GaussianSplatSettings:

Distance Culling

  • m_EnableDistanceCulling: Enable/disable distance-based culling
  • m_MaxRenderDistance: Maximum render distance (0 = infinite)
  • Impact: 30-50% fewer splats rendered

LOD System

  • m_EnableLOD: Enable progressive splat density reduction
  • m_LODStartDistance: Distance where LOD begins
  • m_LODMinDensity: Minimum splat density at max distance (0.25 = 25%)
  • Impact: 40-70% fewer splats at distance

Combined GPU load reduction: 60-80% - Critical for WebGPU/WebGL targets!

2. Native C++ Pthread Sorting for WebGL

Complete native plugin system for WebGL parallel sorting:

  • GaussianSplatSort.cpp: Native C++ pthread-based parallel sorting
  • GaussianSplatNativeSort.cs: C# wrapper with DllImport integration
  • Automatic detection: Falls back to C# sequential if multithreading not enabled
  • Performance: 2-3x faster than C# sequential on WebGL
  • Documentation: Complete setup guide in README_NATIVE_THREADING.md

3. Non-Blocking Parallel Sort System

Completely redesigned parallel sorting to eliminate main thread blocking:

Key Improvements

  • 0ms blocking: Task.WaitAll() (10ms) → Task.IsCompleted checks (~0.1ms)
  • Budget system: Limits nodes sorted per frame (default: 20 nodes)
  • Priority-based: Closest nodes sorted first for best visual quality
  • Task state tracking: Prevents redundant task spawning
  • Impact: 100x reduction in main thread blocking

4. Zero-Allocation Architecture

Completely redesigned parallel sorting to eliminate main thread blocking:

Key Improvements

  • 0ms blocking: Task.WaitAll() (10ms) → Task.IsCompleted checks (~0.1ms)
  • Budget system: Limits nodes sorted per frame (default: 20 nodes)
  • Priority-based: Closest nodes sorted first for best visual quality
  • Task state tracking: Prevents redundant task spawning
  • Impact: 100x reduction in main thread blocking
// Configuration
octree.enableParallelSorting = true;
octree.maxNodesSortedPerFrame = 20;  // Budget per frame
octree.parallelSortThreads = SystemInfo.processorCount - 1;

How It Works

  1. Spawn background tasks for node sorting (non-blocking)
  2. Main thread checks Task.IsCompleted (0.1ms)
  3. Use completed results immediately
  4. Incomplete nodes prioritized in next frame

4. Zero-Allocation Architecture

Complete conversion from managed collections to native memory:

Core Changes

  • OctreeNode.splatIndices: List<int>NativeList<int>
  • OctreeNode.childIndices: List<int>int[8] fixed array
  • m_OthersIndices: List<int>NativeList<int>
  • m_VisibleSplatIndices: List<int>NativeList<int>

Technical Details

  • Direct memory access via GetUnsafePtr()
  • Ultra-fast memcpy with UnsafeUtility.MemCpy()
  • Proper disposal with Dispose() methods
  • Zero-allocation bulk operations with AddRange(nativeList.AsArray())

5. Bug Fixes

  • Rendering freeze fix: SetAssetDataOnMaterial() now called every frame regardless of culling
    state (fixes black screen when octree culling disabled)
  • Inspector UI fix: Statistics tab now displays even when octree culling is disabled (renamed to
    ShowRuntimeStatistics())

6. Improved Default Parameters

Updated default octree settings for better out-of-the-box performance with large scenes:

  • m_OctreeMaxDepth: 8 → 6 (fewer nodes = faster sorting)
  • m_OctreeMaxSplatsPerLeaf: 4096 → 8192 (larger leaves = fewer sorts)
  • m_OctreeCullingUpdateInterval: 1 → 2 (skip alternate frames for 2x speedup)

7. Comprehensive Documentation

Added extensive performance documentation:

  • PERFORMANCE_GUIDE.md: Complete optimization guide with recommendations by scene size
  • Native threading guide: Setup instructions for WebGL pthread compilation
  • Profiling tips: How to diagnose and fix performance bottlenecks
  • Success metrics: Target FPS and timing benchmarks for different splat counts

8. Additional Optimizations

  • Sort direction threshold: Configurable angular threshold to reduce re-sort frequency
  • Outlier resort fraction: Tunable parameter for outlier bucket re-sorting
  • Reusable buffers: Persistent scratch buffers to avoid per-frame allocations
  • Static comparers: Eliminated lambda allocations in hot paths

Performance Results

Before optimizations (1M splats):

  • FPS: 10-15 FPS
  • GC Allocations: 8.9 MB/frame
  • CPU Sort Time: 10-15ms
  • Main Thread Blocking: 10ms+

After optimizations (1M splats):

  • FPS: 50-60 FPS (4-6x improvement)
  • GC Allocations: ~0.6 KB/frame (>10,000x reduction)
  • CPU Sort Time: 2-3ms
  • Main Thread Blocking: ~0.1ms (100x reduction)
  • GPU Load: 60-80% reduction (with LOD enabled)

Files Modified

Native Threading (NEW)

File Description
package/Runtime/GaussianSplatNativeSort.cs Native plugin C# wrapper with NativeList support
package/Plugins/WebGL/GaussianSplatSort.cpp Native C++ pthread-based parallel sorting

Documentation (NEW)

File Description
PERFORMANCE_GUIDE.md Complete optimization guide for 1M+ splat scenes
package/Plugins/WebGL/README_NATIVE_THREADING.md Native threading setup guide
package/Plugins/WebGL/README.md Plugin system overview

Notes

I'm not submitting this as a pull request because I maintain my own fork of the original
repository with additional WebGPU-specific modifications. However, feel free to use, adapt, or
integrate any of these changes if you find them useful for your fork.

The patch is attached as performance-optimizations.patch and can be applied with:
git apply performance-optimizations.patch

All changes are tested and working in Unity 2022.3+ with scenes containing 1M+ splats. The
optimizations are particularly impactful for WebGPU/WebGL builds where GPU and threading
constraints are most severe.

Feel free to reach out if you have any questions about the implementation!

Best regards

performance-optimizations.patch

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions