Skip to content

Commit

Permalink
Make options run time. Allow both sort types again.
Browse files Browse the repository at this point in the history
  • Loading branch information
schwa committed Oct 14, 2024
1 parent cba83f0 commit 8fe40f0
Show file tree
Hide file tree
Showing 6 changed files with 61 additions and 58 deletions.
57 changes: 27 additions & 30 deletions Sources/GaussianSplatSupport/GaussianSplatViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,18 @@ import SwiftUISupport
import Traces

public struct GaussianSplatConfiguration {
public enum SortMethod {
case gpuBitonic
case cpuRadix
}

public var debugMode: Bool
public var metalFXRate: Float
public var discardRate: Float
public var gpuCounters: GPUCounters?
public var clearColor: MTLClearColor // TODO: make this a SwiftUI Color
public var skyboxTexture: MTLTexture?
public var verticalAngleOfView: Angle

public enum SortMethod {
case gpuBitonic
case cpuRadix
}

public var sortMethod: SortMethod

public init(debugMode: Bool = false, metalFXRate: Float = 2, discardRate: Float = 0.0, gpuCounters: GPUCounters? = nil, clearColor: MTLClearColor = .init(red: 0, green: 0, blue: 0, alpha: 1), skyboxTexture: MTLTexture? = nil, verticalAngleOfView: Angle = .degrees(90), sortMethod: SortMethod = .gpuBitonic) {
Expand All @@ -50,21 +49,10 @@ public struct GaussianSplatConfiguration {
@MainActor
public class GaussianSplatViewModel <Splat> where Splat: SplatProtocol {
@ObservationIgnored
public let device: MTLDevice
private let device: MTLDevice

@ObservationIgnored
public var configuration: GaussianSplatConfiguration

@ObservationIgnored
private var resources: GaussianSplatResources?

@ObservationIgnored
public var frame: Int = 0 {
didSet {
// try! sceneChanged()
}
}

public var scene: SceneGraph {
didSet {
if oldValue.currentCameraNode?.transform != scene.currentCameraNode?.transform {
Expand All @@ -80,16 +68,6 @@ public class GaussianSplatViewModel <Splat> where Splat: SplatProtocol {

public var loadProgress = Progress()

@ObservationIgnored
private var logger: Logger?

@ObservationIgnored
private var cpuSorter: AsyncSortManager<Splat>?

@ObservationIgnored
private var cpuSorterTask: Task<Void, Never>?

// TODO: bang and try!
public var splatCloud: SplatCloud<SplatC> {
get {
scene.firstNode(label: "splats")!.content as! SplatCloud<SplatC>
Expand All @@ -101,6 +79,25 @@ public class GaussianSplatViewModel <Splat> where Splat: SplatProtocol {
}
}

@ObservationIgnored
public var frame: Int = 0 {
didSet {
try! updatePass()
}
}

@ObservationIgnored
private var resources: GaussianSplatResources?

@ObservationIgnored
private var logger: Logger?

@ObservationIgnored
private var cpuSorter: AsyncSortManager<Splat>?

@ObservationIgnored
private var cpuSorterTask: Task<Void, Never>?

// MARK: -

public init(device: MTLDevice, splatResource: SplatResource, splatCloud: SplatCloud<SplatC>, configuration: GaussianSplatConfiguration, logger: Logger? = nil) throws where Splat == SplatC {
Expand Down Expand Up @@ -158,7 +155,7 @@ public class GaussianSplatViewModel <Splat> where Splat: SplatProtocol {
}

let fullRedraw = true
let sortEnabled = (frame <= 1 || frame.isMultiple(of: 15))
let sortEnabled = configuration.sortMethod == .gpuBitonic && (frame <= 1 || frame.isMultiple(of: 15))
self.pass = try GroupPass(id: "FullPass") {
GroupPass(id: "GaussianSplatRenderGroup", enabled: fullRedraw, renderPassDescriptor: offscreenRenderPassDescriptor1) {
if configuration.sortMethod == .gpuBitonic {
Expand Down Expand Up @@ -264,7 +261,7 @@ public class GaussianSplatViewModel <Splat> where Splat: SplatProtocol {
}

public func requestSort() {
guard let cpuSorter else {
guard configuration.sortMethod == .cpuRadix, let cpuSorter else {
return
}
guard let splatsNode = scene.firstNode(label: "splats"), let splatCloud = splatsNode.content as? SplatCloud<Splat> else {
Expand Down
2 changes: 1 addition & 1 deletion Sources/GaussianSplatSupport/SplatCloud+Support.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public extension SplatCloud where Splat == SplatC {
convenience init(device: MTLDevice, data: Data) throws {
let splatArray = data.withUnsafeBytes { buffer in
buffer.withMemoryRebound(to: SplatB.self) { splats in
return convert_b_to_c(splats)
convert_b_to_c(splats)
}
}
let splats = try device.makeTypedBuffer(data: splatArray, options: .storageModeShared).labelled("Splats")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import GaussianSplatSupport
import SwiftUI

struct GaussianSplatConfigurationView: View {

@Binding
var configuration: GaussianSplatConfiguration

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -103,20 +103,13 @@ extension GaussianSplatViewModel where Splat == SplatC {
fatalError("Not an even multiple of \(MemoryLayout<SplatB>.stride)")
}
let splatCount = contentLength / MemoryLayout<SplatB>.stride
print("Content length: \(contentLength), splat count: \(splatCount)")

try self.init(device: device, splatResource: splatResource, splatCapacity: splatCount, configuration: configuration, logger: logger)
}

func streamingLoad(url: URL) async throws {
// assert(MemoryLayout<SplatB>.stride == MemoryLayout<SplatB>.size)
//
let session = URLSession.shared

loadProgress.totalUnitCount = Int64(splatCloud.capacity)

// Start loading splats into a new splat cloud with the right capacity...
// splatCloud = try SplatCloud<Splat>(device: device, capacity: splatCount)
let request = URLRequest(url: url)
let (byteStream, bytesResponse) = try await session.bytes(for: request)
guard let bytesResponse = bytesResponse as? HTTPURLResponse else {
Expand All @@ -132,7 +125,6 @@ extension GaussianSplatViewModel where Splat == SplatC {
}
}
.chunks(ofCount: 2048)

for try await splats in splatStream {
try splatCloud.append(splats: splats)
self.requestSort()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,14 +120,15 @@ public struct GaussianSplatLobbyView: View {
#endif
case .render:
GaussianSplatLoadingView(url: source.url, splatResource: source, bounds: source.bounds, initialConfiguration: configuration, progressiveLoad: progressiveLoad)
.overlay(alignment: .topLeading) {
Button("Back") {
mode = .config
.toolbar {
ToolbarItem(placement: .navigation) {
Button("Back") {
mode = .config
}
#if os(macOS)
.buttonStyle(.link)
#endif
}
#if os(macOS)
.buttonStyle(.link)
#endif
.padding()
}
.environment(\.gpuCounters, configuration.gpuCounters)
}
Expand All @@ -152,7 +153,6 @@ public struct GaussianSplatLobbyView: View {
let texture = try! textureLoader.newTexture(cgImage: cgImage, options: nil)
texture.label = "Skybox Gradient"
configuration.skyboxTexture = texture
print("Set skyboxTexture to \(texture)")
}
else {
configuration.skyboxTexture = nil
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,9 +44,10 @@ internal struct GaussianSplatView: View {
}

internal var body: some View {
@Bindable
var viewModel = viewModel

Group {
@Bindable
var viewModel = viewModel
GaussianSplatRenderView<SplatC>()
#if os(iOS)
.ignoresSafeArea()
Expand All @@ -55,25 +56,21 @@ internal struct GaussianSplatView: View {
.environment(\.gpuCounters, gpuCounters)
}
.background(.black)
.overlay(alignment: .topTrailing) {
.toolbar {
Button(systemImage: "gear") {
showOptions.toggle()
}
.buttonStyle(.borderless)
.padding()
.popover(isPresented: $showOptions) {
OptionsView(options: $options)
OptionsView(options: $options, configuration: $viewModel.configuration)
.padding()
}
}
.overlay(alignment: .top) {
VStack {
if options.showInfo {
VStack {
Text(viewModel.splatResource.name).font(.title)
Link(viewModel.splatResource.url.absoluteString, destination: viewModel.splatResource.url)
Text(viewModel.splatCloud.capacity, format: .number)
}
InfoView()
.padding()
.background(.thinMaterial)
.cornerRadius(8)
Expand Down Expand Up @@ -108,7 +105,7 @@ internal struct GaussianSplatView: View {
}
}

struct OptionsView: View {
private struct OptionsView: View {
struct Options {
var showInfo: Bool = true
var showTraces: Bool = true
Expand All @@ -118,11 +115,29 @@ struct OptionsView: View {
@Binding
var options: Options

@Binding
var configuration: GaussianSplatConfiguration

var body: some View {
Form {
Toggle("Show Info", isOn: $options.showInfo)
Toggle("Show Traces", isOn: $options.showTraces)
Toggle("Show Counters", isOn: $options.showCounters)
GaussianSplatConfigurationView(configuration: $configuration)
}
}
}

private struct InfoView: View {
@Environment(GaussianSplatViewModel<SplatC>.self)
private var viewModel

var body: some View {
VStack {
Text(viewModel.splatResource.name).font(.title)
Link(viewModel.splatResource.url.absoluteString, destination: viewModel.splatResource.url)
Text(viewModel.splatCloud.capacity, format: .number)
Text("\(viewModel.configuration.sortMethod)")
}
}
}

0 comments on commit 8fe40f0

Please sign in to comment.