Open3D (C++ API)  0.19.0
Loading...
Searching...
No Matches
ComputeGPU.h
Go to the documentation of this file.
1// ----------------------------------------------------------------------------
2// - Open3D: www.open3d.org -
3// ----------------------------------------------------------------------------
4// Copyright (c) 2018-2024 www.open3d.org
5// SPDX-License-Identifier: MIT
6// ----------------------------------------------------------------------------
7//
8// Generic GPU compute abstraction used by the Gaussian splatting pipeline.
9// One header covers all platforms (OpenGL on Linux/Windows, Metal on macOS).
10// Runtime shader resources are loaded from resources/gaussian_splat/.
11//
12// Typical usage:
13//
14// // One GpuComputeFrame per geometry or composite stage (RAII).
15// GpuComputeFrame frame(ctx, GpuComputeFrame::kGeometry);
16//
17// // Each dispatch: one temporary GpuComputePass expression.
18// GpuComputePass(ctx, ComputeProgramId::kGsProject, "gs_project")
19// .UBO(0, view_params_buf)
20// .SSBO(1, positions_buf)
21// .Dispatch(groups_x, 1, 1);
22// ctx.FullBarrier();
23
24#pragma once
25
26#include <cstddef>
27#include <cstdint>
28#include <vector>
29
30namespace open3d {
31namespace visualization {
32namespace rendering {
33
34// ---------------------------------------------------------------------------
35// Enums
36// ---------------------------------------------------------------------------
37
40enum class ComputeProgramId : int {
41 kGsProject = 0,
42 kGsComposite = 1,
48 kGsDepthMerge = 5,
49 kCount = 6,
50};
51
54
57constexpr const char* kGsShaderNames[] = {
58 "gaussian_project",
59 "gaussian_composite",
60 "gaussian_radix_sort_histograms",
61 "gaussian_radix_sort_scatter",
62 "gaussian_compute_dispatch_args",
63 "gaussian_depth_merge",
64};
65static_assert(std::size(kGsShaderNames) ==
66 static_cast<std::size_t>(ComputeProgramId::kCount),
67 "kGsShaderNames must match ComputeProgramId::kCount");
68
69// ---------------------------------------------------------------------------
70// GPU data layout structs
71// ---------------------------------------------------------------------------
72
78 std::uint32_t g_num_elements = 0;
79 std::uint32_t g_shift = 0;
80 std::uint32_t g_num_workgroups = 0;
81 std::uint32_t g_num_blocks_per_workgroup = 0;
82};
83static_assert(sizeof(RadixSortParams) == 16,
84 "RadixSortParams must be 16 bytes to match GLSL layout");
85
88 std::uintptr_t view_params_buf = 0;
89 std::uintptr_t positions_buf = 0;
90 std::uintptr_t scales_buf = 0;
91 std::uintptr_t rotations_buf = 0;
92 std::uintptr_t dc_opacity_buf = 0;
93 std::uintptr_t sh_buf = 0;
96 std::uintptr_t projected_composite_buf = 0;
99 std::uintptr_t tile_counts_buf = 0;
101 std::uintptr_t counters_buf = 0;
102 std::uintptr_t dispatch_args_buf = 0;
105 std::uintptr_t sort_keys_buf[2] = {0, 0};
106 std::uintptr_t sort_values_buf[2] = {0, 0};
107 std::uintptr_t histogram_buf = 0;
108 std::uintptr_t radix_params_buf = 0;
110 std::uintptr_t mask_buf = 0;
112 std::uintptr_t composite_depth_tex = 0;
115 std::uintptr_t merged_depth_u16_tex = 0;
119 std::uint64_t cached_scene_id = 0;
120 std::uint32_t cached_splat_count = 0;
123 std::uint32_t warned_gpu_error_flags = 0;
124};
125
126// ---------------------------------------------------------------------------
127// GaussianSplatGpuContext — abstract GPU backend interface
128// ---------------------------------------------------------------------------
129
133public:
134 virtual ~GaussianSplatGpuContext() = default;
135
137 virtual bool EnsureProgramsLoaded() = 0;
138
139 // --- Buffer management ------------------------------------------------
140 virtual std::uintptr_t CreateBuffer(std::size_t size,
141 const char* label = nullptr) = 0;
142 virtual void DestroyBuffer(std::uintptr_t buf) = 0;
144 virtual std::uintptr_t ResizeBuffer(std::uintptr_t buf,
145 std::size_t new_size,
146 const char* label = nullptr) = 0;
147
150 virtual std::uintptr_t CreatePrivateBuffer(std::size_t size,
151 const char* label = nullptr) {
152 return CreateBuffer(size, label);
153 }
154 virtual std::uintptr_t ResizePrivateBuffer(std::uintptr_t buf,
155 std::size_t new_size,
156 const char* label = nullptr) {
157 return ResizeBuffer(buf, new_size, label);
158 }
159 virtual void UploadBuffer(std::uintptr_t buf,
160 const void* data,
161 std::size_t size,
162 std::size_t offset) = 0;
163 virtual bool DownloadBuffer(std::uintptr_t buf,
164 void* dst,
165 std::size_t size,
166 std::size_t offset) {
167 (void)buf;
168 (void)dst;
169 (void)size;
170 (void)offset;
171 return false;
172 }
173 virtual void ClearBufferUInt32Zero(std::uintptr_t buf) = 0;
174
175 // --- Bindings ---------------------------------------------------------
176 virtual void BindSSBO(std::uint32_t binding, std::uintptr_t buf) = 0;
177 virtual void BindUBO(std::uint32_t binding, std::uintptr_t buf) = 0;
178 virtual void BindUBORange(std::uint32_t binding,
179 std::uintptr_t buf,
180 std::size_t offset,
181 std::size_t range_size) = 0;
182
183 // --- Dispatch ---------------------------------------------------------
184 virtual void UseProgram(ComputeProgramId id) = 0;
185 virtual void Dispatch(std::uint32_t groups_x,
186 std::uint32_t groups_y,
187 std::uint32_t groups_z) = 0;
188 virtual void DispatchIndirect(std::uintptr_t indirect_buf,
189 std::size_t byte_offset) = 0;
190 virtual void FullBarrier() = 0;
191
196 virtual std::uint32_t GetMaxComputeWorkGroupCount() const { return 65535u; }
197
198 // --- Textures / images ------------------------------------------------
199 virtual std::uintptr_t CreateTexture2DR32F(std::uint32_t width,
200 std::uint32_t height,
201 const char* label = nullptr) = 0;
202 virtual void DestroyTexture(std::uintptr_t tex) = 0;
203 virtual std::uintptr_t ResizeTexture2DR32F(std::uintptr_t tex,
204 std::uint32_t width,
205 std::uint32_t height,
206 const char* label = nullptr) = 0;
208 virtual std::uintptr_t ResizeTexture2DR16UI(
209 std::uintptr_t tex,
210 std::uint32_t width,
211 std::uint32_t height,
212 const char* label = nullptr) = 0;
213
217 virtual bool DownloadTextureR32F(std::uintptr_t tex,
218 std::uint32_t width,
219 std::uint32_t height,
220 std::vector<float>& out) {
221 (void)tex;
222 (void)width;
223 (void)height;
224 (void)out;
225 return false;
226 }
227
231 virtual bool DownloadTextureR16UI(std::uintptr_t tex,
232 std::uint32_t width,
233 std::uint32_t height,
234 std::vector<std::uint16_t>& out) {
235 (void)tex;
236 (void)width;
237 (void)height;
238 (void)out;
239 return false;
240 }
241
243 virtual void BindImage(std::uint32_t binding,
244 std::uintptr_t tex,
245 std::uint32_t width,
246 std::uint32_t height,
247 ImageFormat fmt) = 0;
248
249 virtual void BindSamplerTexture(std::uint32_t unit,
250 std::uintptr_t tex,
251 std::uint32_t width,
252 std::uint32_t height) = 0;
253
254 // --- Frame sync -------------------------------------------------------
257 virtual void FinishGpuWork() = 0;
258
260 virtual bool WasLastSubmitSuccessful() const { return true; }
261
264 virtual void BeginGeometryPass() {}
265 virtual void EndGeometryPass() {}
266 virtual void BeginCompositePass() {}
267 virtual void EndCompositePass() {}
268
277 virtual void WaitForGeometryPass() {}
278
281 virtual void PushDebugGroup(const char* /*label*/) {}
282 virtual void PopDebugGroup() {}
283};
284
285// ---------------------------------------------------------------------------
286// GpuComputeFrame — RAII for Begin/EndGeometryPass or Begin/EndCompositePass
287// ---------------------------------------------------------------------------
288
292public:
294
296 : ctx_(ctx), kind_(kind) {
297 if (kind_ == kGeometry) {
298 ctx_.BeginGeometryPass();
299 } else {
300 ctx_.BeginCompositePass();
301 }
302 }
304
307
309 void End() {
310 if (!ended_) {
311 ended_ = true;
312 if (kind_ == kGeometry) {
313 ctx_.EndGeometryPass();
314 } else {
315 ctx_.EndCompositePass();
316 }
317 }
318 }
319
320private:
322 Kind kind_;
323 bool ended_ = false;
324};
325
326// ---------------------------------------------------------------------------
327// GpuComputePass — RAII + builder for a single compute dispatch
328// ---------------------------------------------------------------------------
329
339public:
342 const char* label = nullptr)
343 : ctx_(ctx), label_(label) {
344 ok_ = ctx_.EnsureProgramsLoaded();
345 if (ok_) {
346 ctx_.UseProgram(pid);
347 if (label_) ctx_.PushDebugGroup(label_);
348 }
349 }
350
352 if (ok_ && label_) ctx_.PopDebugGroup();
353 }
354
357
359 [[nodiscard]] bool ok() const { return ok_; }
360
361 // --- Resource binding (fluent builder) --------------------------------
362
363 GpuComputePass& UBO(std::uint32_t binding, std::uintptr_t buf) {
364 if (ok_) ctx_.BindUBO(binding, buf);
365 return *this;
366 }
367
368 GpuComputePass& UBORange(std::uint32_t binding,
369 std::uintptr_t buf,
370 std::size_t offset,
371 std::size_t size) {
372 if (ok_) ctx_.BindUBORange(binding, buf, offset, size);
373 return *this;
374 }
375
376 GpuComputePass& SSBO(std::uint32_t binding, std::uintptr_t buf) {
377 if (ok_) ctx_.BindSSBO(binding, buf);
378 return *this;
379 }
380
381 GpuComputePass& Image(std::uint32_t binding,
382 std::uintptr_t tex,
383 std::uint32_t w,
384 std::uint32_t h,
386 if (ok_) ctx_.BindImage(binding, tex, w, h, fmt);
387 return *this;
388 }
389
390 GpuComputePass& Sampler(std::uint32_t unit,
391 std::uintptr_t tex,
392 std::uint32_t w,
393 std::uint32_t h) {
394 if (ok_) ctx_.BindSamplerTexture(unit, tex, w, h);
395 return *this;
396 }
397
398 // --- Dispatch ---------------------------------------------------------
399
400 void Dispatch(std::uint32_t gx, std::uint32_t gy, std::uint32_t gz) {
401 if (ok_) ctx_.Dispatch(gx, gy, gz);
402 }
403
404 void DispatchIndirect(std::uintptr_t buf, std::size_t byte_offset) {
405 if (ok_) ctx_.DispatchIndirect(buf, byte_offset);
406 }
407
408private:
410 const char* label_;
411 bool ok_;
412};
413
414// ---------------------------------------------------------------------------
415// Factory functions
416// ---------------------------------------------------------------------------
417
418#if !defined(__APPLE__)
419// Vulkan-only: no GL compute factory.
420#endif
421#if defined(__APPLE__)
422[[nodiscard]] std::unique_ptr<GaussianSplatGpuContext>
423CreateComputeGpuContextMetal(std::uintptr_t device_handle,
424 std::uintptr_t command_queue_handle);
425#endif
426
427} // namespace rendering
428} // namespace visualization
429} // namespace open3d
virtual void DestroyBuffer(std::uintptr_t buf)=0
virtual void EndCompositePass()
Definition ComputeGPU.h:267
virtual std::uintptr_t ResizeBuffer(std::uintptr_t buf, std::size_t new_size, const char *label=nullptr)=0
Returns a valid handle (may replace buf when the API reallocates).
virtual void DestroyTexture(std::uintptr_t tex)=0
virtual void BeginCompositePass()
Definition ComputeGPU.h:266
virtual void BindUBORange(std::uint32_t binding, std::uintptr_t buf, std::size_t offset, std::size_t range_size)=0
virtual std::uintptr_t ResizeTexture2DR32F(std::uintptr_t tex, std::uint32_t width, std::uint32_t height, const char *label=nullptr)=0
virtual void PopDebugGroup()
Definition ComputeGPU.h:282
virtual bool DownloadBuffer(std::uintptr_t buf, void *dst, std::size_t size, std::size_t offset)
Definition ComputeGPU.h:163
virtual void BindSamplerTexture(std::uint32_t unit, std::uintptr_t tex, std::uint32_t width, std::uint32_t height)=0
virtual void UploadBuffer(std::uintptr_t buf, const void *data, std::size_t size, std::size_t offset)=0
virtual void BindSSBO(std::uint32_t binding, std::uintptr_t buf)=0
virtual void Dispatch(std::uint32_t groups_x, std::uint32_t groups_y, std::uint32_t groups_z)=0
virtual std::uintptr_t ResizePrivateBuffer(std::uintptr_t buf, std::size_t new_size, const char *label=nullptr)
Definition ComputeGPU.h:154
virtual void ClearBufferUInt32Zero(std::uintptr_t buf)=0
virtual bool DownloadTextureR32F(std::uintptr_t tex, std::uint32_t width, std::uint32_t height, std::vector< float > &out)
Definition ComputeGPU.h:217
virtual std::uintptr_t CreateTexture2DR32F(std::uint32_t width, std::uint32_t height, const char *label=nullptr)=0
virtual void BindUBO(std::uint32_t binding, std::uintptr_t buf)=0
virtual void WaitForGeometryPass()
Definition ComputeGPU.h:277
virtual bool EnsureProgramsLoaded()=0
Load all compute programs (lazy, idempotent).
virtual void DispatchIndirect(std::uintptr_t indirect_buf, std::size_t byte_offset)=0
virtual std::uintptr_t CreateBuffer(std::size_t size, const char *label=nullptr)=0
virtual std::uint32_t GetMaxComputeWorkGroupCount() const
Definition ComputeGPU.h:196
virtual void BindImage(std::uint32_t binding, std::uintptr_t tex, std::uint32_t width, std::uint32_t height, ImageFormat fmt)=0
Bind a write image at the given unit with the specified format.
virtual void BeginGeometryPass()
Definition ComputeGPU.h:264
virtual void EndGeometryPass()
Definition ComputeGPU.h:265
virtual std::uintptr_t ResizeTexture2DR16UI(std::uintptr_t tex, std::uint32_t width, std::uint32_t height, const char *label=nullptr)=0
Create or resize an R16UI texture for merged-depth CPU readback.
virtual bool DownloadTextureR16UI(std::uintptr_t tex, std::uint32_t width, std::uint32_t height, std::vector< std::uint16_t > &out)
Definition ComputeGPU.h:231
virtual void UseProgram(ComputeProgramId id)=0
virtual std::uintptr_t CreatePrivateBuffer(std::size_t size, const char *label=nullptr)
Definition ComputeGPU.h:150
virtual void PushDebugGroup(const char *)
Definition ComputeGPU.h:281
virtual bool WasLastSubmitSuccessful() const
Returns whether the most recently submitted GPU work succeeded.
Definition ComputeGPU.h:260
GpuComputeFrame(const GpuComputeFrame &)=delete
~GpuComputeFrame()
Definition ComputeGPU.h:303
GpuComputeFrame(GaussianSplatGpuContext &ctx, Kind kind)
Definition ComputeGPU.h:295
GpuComputeFrame & operator=(const GpuComputeFrame &)=delete
void End()
Explicitly end the frame early (dtor becomes a no-op).
Definition ComputeGPU.h:309
GpuComputePass(const GpuComputePass &)=delete
GpuComputePass & UBORange(std::uint32_t binding, std::uintptr_t buf, std::size_t offset, std::size_t size)
Definition ComputeGPU.h:368
void DispatchIndirect(std::uintptr_t buf, std::size_t byte_offset)
Definition ComputeGPU.h:404
~GpuComputePass()
Definition ComputeGPU.h:351
GpuComputePass & operator=(const GpuComputePass &)=delete
GpuComputePass & UBO(std::uint32_t binding, std::uintptr_t buf)
Definition ComputeGPU.h:363
GpuComputePass & SSBO(std::uint32_t binding, std::uintptr_t buf)
Definition ComputeGPU.h:376
GpuComputePass(GaussianSplatGpuContext &ctx, ComputeProgramId pid, const char *label=nullptr)
Definition ComputeGPU.h:340
void Dispatch(std::uint32_t gx, std::uint32_t gy, std::uint32_t gz)
Definition ComputeGPU.h:400
GpuComputePass & Sampler(std::uint32_t unit, std::uintptr_t tex, std::uint32_t w, std::uint32_t h)
Definition ComputeGPU.h:390
bool ok() const
Returns false only when EnsureProgramsLoaded() failed (device error).
Definition ComputeGPU.h:359
GpuComputePass & Image(std::uint32_t binding, std::uintptr_t tex, std::uint32_t w, std::uint32_t h, ImageFormat fmt)
Definition ComputeGPU.h:381
int width
Definition FilePCD.cpp:53
int size
Definition FilePCD.cpp:41
int height
Definition FilePCD.cpp:54
int offset
Definition FilePCD.cpp:46
Definition DLPack.h:678
ImageFormat
Format selector for GaussianSplatGpuContext::BindImage().
Definition ComputeGPU.h:53
ComputeProgramId
Definition ComputeGPU.h:40
constexpr const char * kGsShaderNames[]
Definition ComputeGPU.h:57
Definition PinholeCameraIntrinsic.cpp:16
Per-view GPU resource handles (opaque: GL name or MTLBuffer/MTLTexture).
Definition ComputeGPU.h:87
std::uintptr_t projected_composite_buf
Definition ComputeGPU.h:96
std::uint32_t cached_splat_count
Definition ComputeGPU.h:120
std::uintptr_t scales_buf
Definition ComputeGPU.h:90
std::uintptr_t dc_opacity_buf
Definition ComputeGPU.h:92
std::uintptr_t dispatch_args_buf
Definition ComputeGPU.h:102
std::uintptr_t sort_keys_buf[2]
Definition ComputeGPU.h:105
std::uintptr_t composite_depth_tex
GS composite depth output (image binding 1); not the shared scene depth.
Definition ComputeGPU.h:112
std::uintptr_t tile_counts_buf
Definition ComputeGPU.h:99
std::uintptr_t mask_buf
Bit-packed per-splat visibility mask. Bound at binding 15.
Definition ComputeGPU.h:110
std::uintptr_t rotations_buf
Definition ComputeGPU.h:91
std::uint64_t cached_scene_id
Definition ComputeGPU.h:119
std::uintptr_t positions_buf
Definition ComputeGPU.h:89
std::uintptr_t radix_params_buf
Definition ComputeGPU.h:108
std::uint32_t warned_gpu_error_flags
Definition ComputeGPU.h:123
std::uintptr_t merged_depth_u16_tex
Definition ComputeGPU.h:115
std::uintptr_t sort_values_buf[2]
Definition ComputeGPU.h:106
std::uintptr_t view_params_buf
Definition ComputeGPU.h:88
std::uintptr_t counters_buf
GPU error/diagnostic counters (total_entries, error_flags, ...).
Definition ComputeGPU.h:101
std::uintptr_t histogram_buf
Definition ComputeGPU.h:107
std::uint32_t g_num_elements
Definition ComputeGPU.h:78
std::uint32_t g_shift
Definition ComputeGPU.h:79
std::uint32_t g_num_workgroups
Definition ComputeGPU.h:80
std::uint32_t g_num_blocks_per_workgroup
Definition ComputeGPU.h:81