Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
build*/
.build/
DerivedData/
*.spz
*.ply
*.glb
.DS_Store
.argent/
.idea/
.gradle/
local.properties
Expand Down
39 changes: 39 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Changelog

Notable changes to the SplatKit iOS SDK and the shared C++ engine it ships.
The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); alphas may break APIs.

## Unreleased

### Added

- `SplatMetalView.renderPolicy` and `deviceCapabilities`, with `SKRenderPolicy`, `SKDeviceCapabilities` and `-[SKSplatEngine applyRenderPolicy:reason:warnings:]`.
Each request is re-validated on the render thread; Metal applies the sort depth with GPU sort and the sub-pixel threshold under tight culling, and every other field falls back with a warning.
An invalid request or a preparation failure keeps the previous policy.
- Shared engine: `resolveRenderPolicy`, `SplatEngine::setRenderPolicy` and a capability query on `SplatRenderer`.
- Benchmarks log 30-second windows and final p99 frame and GPU times; `TimingSummary` reports p99.

### Changed

- Benchmarks reject durations outside `(0, 3600]` seconds and treat a zero GPU time as unavailable, not as a free frame.

### Removed

- The `SPLATKIT_METAL_MIN_PIXEL_RADIUS` and `SPLATKIT_METAL_DEPTH_KEY_BITS` environment variables; set `renderPolicy` instead.

## [0.1.0-alpha.2] - 2026-09-12

### Fixed

- GCC portability of the offline LOD writer and portable residency test budgets.
- Hosts without Metal raster support report skipped tests instead of failures.

## [0.1.0-alpha.1] - 2026-09-12

### Added

- Native Metal SDK for iOS 17 and A14/M1 or newer, distributed as a SwiftPM device and simulator XCFramework.
- GPU visibility and radix sorting, experimental LOD and hybrid screen tiles, asynchronous loading and first-frame readiness.

[0.1.0-alpha.2]: https://github.com/Xget7/splatkit-ios/releases/tag/v0.1.0-alpha.2
[0.1.0-alpha.1]: https://github.com/Xget7/splatkit-ios/releases/tag/v0.1.0-alpha.1
42 changes: 30 additions & 12 deletions CONTEXT.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,61 +16,79 @@ The splats of a world decoded into memory, structure of arrays, in the engine's
_Avoid_: point cloud, dataset, buffer

**World**:
What a host asks the engine to show: a source of splats plus, optionally, a collider. A world is one file today and a tileset tomorrow; the host does not know which.
What a host asks the engine to show: a source of splats plus, optionally, a collider.
A world is one file or a tileset streamed in tiles.
_Avoid_: scene, model, asset, map

**Collider**:
The triangle mesh the walk camera collides with; the world's floor and walls for navigation only, never drawn.
_Avoid_: mesh, geometry, nav mesh

**Source**:
Where a world's bytes come from: a file, an asset, a content provider or a URL. Fetching a source puts its bytes on disk; it says nothing about how they are drawn.
Where a world's bytes come from: a file, an asset, a content provider or a URL.
Fetching a source puts its bytes on disk; it says nothing about how they are drawn.
_Avoid_: URI (that is the wire format of a source), download

### Drawing

**Frame**:
One presented image. The engine draws a frame only when something changed.
One presented image.
The engine draws a frame only when something changed.

**Sort**:
Ordering the splats back to front from the camera, on the CPU, so blending is correct.
Ordering splats by camera depth in the direction required by compositing.
_Avoid_: depth sort, z-order

**Cull**:
Dropping the sorted splats outside the camera's frustum, widened by a margin, before drawing.
Rejecting splats outside the view or below the configured visibility threshold.

**Render scale**:
The size of the render target relative to the surface, 0.1 to 2. Below 1 the frame is upscaled, above 1 supersampled.
The size of the render target relative to the surface, 0.1 to 2.
Below 1 the frame is upscaled, above 1 supersampled.
_Avoid_: resolution, resolution mode, quality (that is the preset)

**Preset**:
A named quality setting (low, medium, high, ultra) that fixes the render scale, the harmonics degree and the splat budget together.
A named set of starting values for the render scale, the harmonics degree and the budgets: `RenderQuality` on Android, the builder presets in React Native.
Individual settings override it.
_Avoid_: mode, profile, level

**Splat budget**:
Selection capacity; zero disables reduction.
_Avoid_: limit, cap, max splats

**Render policy**:
Per-view renderer choices, such as sort depth and the sub-pixel threshold, resolved against the device capabilities.
A supported choice applies, an unsupported one falls back with a warning, and an invalid request is rejected while the previous policy stays.
_Avoid_: settings, config, quality (that is the preset)

**Capabilities**:
What one backend on one device can apply from a render policy, and the limits it accepts.

### Level of detail

**Node**:
One entry of the in-memory hierarchy over a cloud: a leaf is a splat of the file, an interior node is one splat standing in for its children.
One entry of the hierarchy over a cloud: a leaf is a splat of the file, an interior node is one splat standing in for its children.

**Tree**:
Offline/load-time hierarchy.
The hierarchy of nodes, built at load time or read from an offline `.lodsplat` file.
_Avoid_: LOD, octree (a tree of nodes is not an octree of tiles)

**Selection**:
Covering cut; capacity≠quality.
The nodes drawn this frame: a cut that covers the world within the splat budget.
A larger budget is not a quality guarantee.

### Scale

**Tile**:
A cube of the world at one level, stored as its own spz file, with its splats in spatial order.
_Avoid_: chunk, cell, block, node (a node is inside a cloud, a tile is a cloud)

**Screen tile**:
A rectangular group of image pixels composited together; unrelated to a world's streaming tiles.

**Level**:
How coarse a tile is: level 0 is the file's splats, each level up stands in for the eight tiles below it with fewer, larger splats. Made offline, never on the phone.
How coarse a tile is: level 0 is the file's splats, each level up stands in for the eight tiles below it with fewer, larger splats.
Made offline, never on the phone.
_Avoid_: LOD, mip, layer

**Tileset**:
Expand All @@ -82,5 +100,5 @@ Loading and dropping tiles by what the camera can see while walking, so memory h
_Avoid_: downloading (that is fetching a source), lazy loading

**Residency budget**:
The most tile bytes held in memory at once; what streaming evicts against.
The most splats held resident at once; what streaming evicts against.
_Avoid_: cache size, memory limit
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ MIT-licensed sources include the shared C++ engine/core.
## Install

Add `https://github.com/Xget7/splatkit-ios` in Xcode Package Dependencies and select product `SplatKit`.
Choose exact version `0.1.0-alpha.2`.
Choose exact version `0.1.0-alpha.2`; `main` may be ahead of that release, as the [changelog](CHANGELOG.md) lists.
The package downloads the release XCFramework for arm64 devices and arm64/x86_64 simulators.

```swift
Expand All @@ -33,4 +33,4 @@ Requires Xcode, CMake and Python 3.9+; builds fetch pinned dependencies.
No signing credentials or scene downloads are needed for synthetic native tests.
LOD, hybrid tiles and 16-bit sorting remain experimental; quality acceptance and sustained 30/60 FPS are not guaranteed.
Simulator/Mac checks are not phone benchmarks.
RN GPU controls remain pending.
[react-native-splatkit](https://github.com/Xget7/react-native-splatkit) drives `renderPolicy` from its `policy` prop; iOS device validation is pending.
Loading
Loading