nv-sgl 0.6.0__cp313-cp313-win_amd64.whl

Sign up to get free protection for your applications and to get access to all the features.
Files changed (142) hide show
  1. include/tevclient.h +393 -0
  2. nv_sgl-0.6.0.dist-info/LICENSE +29 -0
  3. nv_sgl-0.6.0.dist-info/METADATA +21 -0
  4. nv_sgl-0.6.0.dist-info/RECORD +142 -0
  5. nv_sgl-0.6.0.dist-info/WHEEL +5 -0
  6. nv_sgl-0.6.0.dist-info/top_level.txt +1 -0
  7. sgl/__init__.py +15 -0
  8. sgl/__init__.pyi +6738 -0
  9. sgl/d3d12/D3D12Core.dll +0 -0
  10. sgl/d3d12/d3d12SDKLayers.dll +0 -0
  11. sgl/dxcompiler.dll +0 -0
  12. sgl/dxil.dll +0 -0
  13. sgl/gfx.dll +0 -0
  14. sgl/include/sgl/app/app.h +113 -0
  15. sgl/include/sgl/core/bitmap.h +302 -0
  16. sgl/include/sgl/core/crypto.h +89 -0
  17. sgl/include/sgl/core/data_type.h +46 -0
  18. sgl/include/sgl/core/dds_file.h +103 -0
  19. sgl/include/sgl/core/enum.h +201 -0
  20. sgl/include/sgl/core/error.h +161 -0
  21. sgl/include/sgl/core/file_stream.h +77 -0
  22. sgl/include/sgl/core/file_system_watcher.h +141 -0
  23. sgl/include/sgl/core/format.h +36 -0
  24. sgl/include/sgl/core/fwd.h +90 -0
  25. sgl/include/sgl/core/hash.h +45 -0
  26. sgl/include/sgl/core/input.h +522 -0
  27. sgl/include/sgl/core/logger.h +214 -0
  28. sgl/include/sgl/core/macros.h +184 -0
  29. sgl/include/sgl/core/maths.h +45 -0
  30. sgl/include/sgl/core/memory_mapped_file.h +112 -0
  31. sgl/include/sgl/core/memory_mapped_file_stream.h +32 -0
  32. sgl/include/sgl/core/memory_stream.h +74 -0
  33. sgl/include/sgl/core/object.h +683 -0
  34. sgl/include/sgl/core/platform.h +239 -0
  35. sgl/include/sgl/core/plugin.h +331 -0
  36. sgl/include/sgl/core/resolver.h +39 -0
  37. sgl/include/sgl/core/short_vector.h +141 -0
  38. sgl/include/sgl/core/static_vector.h +111 -0
  39. sgl/include/sgl/core/stream.h +54 -0
  40. sgl/include/sgl/core/string.h +276 -0
  41. sgl/include/sgl/core/struct.h +360 -0
  42. sgl/include/sgl/core/thread.h +28 -0
  43. sgl/include/sgl/core/timer.h +52 -0
  44. sgl/include/sgl/core/traits.h +15 -0
  45. sgl/include/sgl/core/type_utils.h +19 -0
  46. sgl/include/sgl/core/window.h +177 -0
  47. sgl/include/sgl/device/agility_sdk.h +24 -0
  48. sgl/include/sgl/device/blit.h +88 -0
  49. sgl/include/sgl/device/buffer_cursor.h +162 -0
  50. sgl/include/sgl/device/command.h +539 -0
  51. sgl/include/sgl/device/cuda_api.h +766 -0
  52. sgl/include/sgl/device/cuda_interop.h +39 -0
  53. sgl/include/sgl/device/cuda_utils.h +107 -0
  54. sgl/include/sgl/device/cursor_utils.h +129 -0
  55. sgl/include/sgl/device/device.h +668 -0
  56. sgl/include/sgl/device/device_resource.h +37 -0
  57. sgl/include/sgl/device/fence.h +91 -0
  58. sgl/include/sgl/device/formats.h +330 -0
  59. sgl/include/sgl/device/framebuffer.h +85 -0
  60. sgl/include/sgl/device/fwd.h +164 -0
  61. sgl/include/sgl/device/helpers.h +20 -0
  62. sgl/include/sgl/device/hot_reload.h +75 -0
  63. sgl/include/sgl/device/input_layout.h +74 -0
  64. sgl/include/sgl/device/kernel.h +69 -0
  65. sgl/include/sgl/device/memory_heap.h +155 -0
  66. sgl/include/sgl/device/native_formats.h +342 -0
  67. sgl/include/sgl/device/native_handle.h +73 -0
  68. sgl/include/sgl/device/native_handle_traits.h +65 -0
  69. sgl/include/sgl/device/pipeline.h +138 -0
  70. sgl/include/sgl/device/print.h +45 -0
  71. sgl/include/sgl/device/python/cursor_utils.h +853 -0
  72. sgl/include/sgl/device/query.h +52 -0
  73. sgl/include/sgl/device/raytracing.h +84 -0
  74. sgl/include/sgl/device/reflection.h +1254 -0
  75. sgl/include/sgl/device/resource.h +705 -0
  76. sgl/include/sgl/device/sampler.h +57 -0
  77. sgl/include/sgl/device/shader.h +516 -0
  78. sgl/include/sgl/device/shader_cursor.h +85 -0
  79. sgl/include/sgl/device/shader_object.h +94 -0
  80. sgl/include/sgl/device/shader_offset.h +67 -0
  81. sgl/include/sgl/device/shared_handle.h +12 -0
  82. sgl/include/sgl/device/slang_utils.h +54 -0
  83. sgl/include/sgl/device/swapchain.h +74 -0
  84. sgl/include/sgl/device/types.h +782 -0
  85. sgl/include/sgl/math/colorspace.h +56 -0
  86. sgl/include/sgl/math/constants.h +7 -0
  87. sgl/include/sgl/math/float16.h +146 -0
  88. sgl/include/sgl/math/matrix.h +6 -0
  89. sgl/include/sgl/math/matrix_math.h +746 -0
  90. sgl/include/sgl/math/matrix_types.h +207 -0
  91. sgl/include/sgl/math/python/primitivetype.h +33 -0
  92. sgl/include/sgl/math/quaternion.h +6 -0
  93. sgl/include/sgl/math/quaternion_math.h +484 -0
  94. sgl/include/sgl/math/quaternion_types.h +83 -0
  95. sgl/include/sgl/math/ray.h +47 -0
  96. sgl/include/sgl/math/scalar_math.h +249 -0
  97. sgl/include/sgl/math/scalar_types.h +107 -0
  98. sgl/include/sgl/math/vector.h +6 -0
  99. sgl/include/sgl/math/vector_math.h +1796 -0
  100. sgl/include/sgl/math/vector_types.h +336 -0
  101. sgl/include/sgl/python/nanobind.h +489 -0
  102. sgl/include/sgl/python/py_doc.h +11600 -0
  103. sgl/include/sgl/python/sgl_ext_pch.h +8 -0
  104. sgl/include/sgl/sgl.h +21 -0
  105. sgl/include/sgl/sgl_pch.h +6 -0
  106. sgl/include/sgl/stl/bit.h +377 -0
  107. sgl/include/sgl/tests/testing.h +54 -0
  108. sgl/include/sgl/ui/fwd.h +34 -0
  109. sgl/include/sgl/ui/imgui_config.h +43 -0
  110. sgl/include/sgl/ui/ui.h +71 -0
  111. sgl/include/sgl/ui/widgets.h +918 -0
  112. sgl/include/sgl/utils/python/slangpy.h +366 -0
  113. sgl/include/sgl/utils/renderdoc.h +50 -0
  114. sgl/include/sgl/utils/slangpy.h +153 -0
  115. sgl/include/sgl/utils/tev.h +93 -0
  116. sgl/include/sgl/utils/texture_loader.h +106 -0
  117. sgl/math/__init__.pyi +5083 -0
  118. sgl/platform/__init__.pyi +102 -0
  119. sgl/renderdoc/__init__.pyi +51 -0
  120. sgl/sgl.dll +0 -0
  121. sgl/sgl_ext.cp313-win_amd64.pyd +0 -0
  122. sgl/shaders/nvapi/nvHLSLExtns.h +2315 -0
  123. sgl/shaders/nvapi/nvHLSLExtnsInternal.h +758 -0
  124. sgl/shaders/nvapi/nvShaderExtnEnums.h +142 -0
  125. sgl/shaders/sgl/device/blit.slang +93 -0
  126. sgl/shaders/sgl/device/nvapi.slang +5 -0
  127. sgl/shaders/sgl/device/nvapi.slangh +7 -0
  128. sgl/shaders/sgl/device/print.slang +445 -0
  129. sgl/shaders/sgl/math/constants.slang +4 -0
  130. sgl/shaders/sgl/math/ray.slang +29 -0
  131. sgl/shaders/sgl/ui/imgui.slang +49 -0
  132. sgl/slang-glslang.dll +0 -0
  133. sgl/slang-llvm.dll +0 -0
  134. sgl/slang-rt.dll +0 -0
  135. sgl/slang.dll +0 -0
  136. sgl/slangpy/__init__.pyi +268 -0
  137. sgl/tev/__init__.pyi +108 -0
  138. sgl/tevclient.lib +0 -0
  139. sgl/thread/__init__.pyi +4 -0
  140. sgl/ui/__init__.pyi +1118 -0
  141. share/cmake/tevclient/tevclient-config-release.cmake +19 -0
  142. share/cmake/tevclient/tevclient-config.cmake +108 -0
@@ -0,0 +1,683 @@
1
+ // SPDX-License-Identifier: Apache-2.0
2
+
3
+ #pragma once
4
+
5
+ #include "sgl/core/macros.h"
6
+ #include "sgl/core/format.h"
7
+
8
+ #include <atomic>
9
+ #include <type_traits>
10
+ #include <utility>
11
+ #include <string>
12
+ #include <cstdint>
13
+
14
+ extern "C" {
15
+ struct _object;
16
+ typedef _object PyObject;
17
+ };
18
+
19
+ /// Enable/disable object lifetime tracking.
20
+ /// When enabled, each object derived from Object will have its
21
+ /// lifetime tracked. This is useful for debugging memory leaks.
22
+ #define SGL_ENABLE_OBJECT_TRACKING 0
23
+
24
+ /// Enable/disable reference tracking.
25
+ /// When enabled, all references to an object that has reference tracking
26
+ /// enabled using set_enable_ref_tracking() are tracked. Each time the reference
27
+ /// count is increased, the current stack trace is stored. This helps identify
28
+ /// owners of objects that are not properly releasing their references.
29
+ /// Optionally all references can be tracked by setting SGL_TRACK_ALL_REFS.
30
+ #define SGL_ENABLE_REF_TRACKING 0
31
+
32
+ #if SGL_ENABLE_REF_TRACKING
33
+ #if !SGL_ENABLE_OBJECT_TRACKING
34
+ #error "SGL_ENABLE_REF_TRACKING requires SGL_ENABLE_OBJECT_TRACKING"
35
+ #endif
36
+ #include "platform.h"
37
+ #include <map>
38
+ #include <mutex>
39
+ static constexpr bool SGL_TRACK_ALL_REFS{false};
40
+ #endif
41
+
42
+
43
+ namespace sgl {
44
+
45
+ /**
46
+ * \brief Object base class with intrusive reference counting
47
+ *
48
+ * The Object class provides a convenient foundation of a class hierarchy that
49
+ * will ease lifetime and ownership-related issues whenever Python bindings are
50
+ * involved.
51
+ *
52
+ * Internally, its constructor sets the `m_state` field to `1`, which indicates
53
+ * that the instance is owned by C++. Bits 2..63 of this field are used to
54
+ * store the actual reference count value. The `inc_ref()` and `dec_ref()`
55
+ * functions can be used to increment or decrement this reference count. When
56
+ * `dec_ref()` removes the last reference, the instance will be deallocated
57
+ * using a `delete` expression handled using a polymorphic destructor.
58
+ *
59
+ * When a subclass of `Object` is constructed to Python or returned from C++ to
60
+ * Python, nanobind will invoke `Object::set_self_py()`, which hands ownership
61
+ * over to Python/nanobind. Any remaining references will be moved from the
62
+ * `m_state` field to the Python reference count. In this mode, `inc_ref()` and
63
+ * `dec_ref()` wrap Python reference counting primitives (`Py_INCREF()` /
64
+ * `Py_DECREF()`) which must be made available by calling the function
65
+ * `object_init_py` once during module initialization. Note that the `m_state`
66
+ * field is also used to store a pointer to the `PyObject *`. Python instance
67
+ * pointers are always aligned (i.e. bit 1 is zero), which disambiguates
68
+ * between the two possible configurations.
69
+ *
70
+ * Within C++, the RAII helper class `ref` (defined below) can be used to keep
71
+ * instances alive. This removes the need to call the `inc_ref()` / `dec_ref()`
72
+ * functions explicitly.
73
+ *
74
+ * ```
75
+ * {
76
+ * ref<MyClass> inst = new MyClass();
77
+ * inst->my_function();
78
+ * ...
79
+ * } // end of scope, 'inst' automatically deleted if no longer referenced
80
+ * ```
81
+ *
82
+ * A separate optional file ``object_py.h`` provides a nanobind type caster
83
+ * to bind functions taking/returning values of type `ref<T>`.
84
+ */
85
+ class SGL_API Object {
86
+ public:
87
+ #if SGL_ENABLE_OBJECT_TRACKING
88
+ /// Default constructor.
89
+ Object();
90
+ /// Destructor.
91
+ virtual ~Object();
92
+ #else
93
+ /// Default constructor.
94
+ Object() = default;
95
+ /// Destructor.
96
+ virtual ~Object() = default;
97
+ #endif
98
+
99
+ /// Copy constructor.
100
+ /// Note: We don't copy the reference counter, so that the new object
101
+ /// starts with a reference count of 0.
102
+ Object(const Object&) { }
103
+
104
+ /// Copy assignment.
105
+ /// Note: We don't copy the reference counter, but leave the reference
106
+ /// counts of the two objects unchanged. This results in the same semantics
107
+ /// that we would get if we used `std::shared_ptr` where the reference
108
+ /// counter is stored in a separate place from the object.
109
+ Object& operator=(const Object&) { return *this; }
110
+
111
+ /// Make the object non-movable.
112
+ Object(Object&&) = delete;
113
+ Object& operator=(Object&&) = delete;
114
+
115
+ /// Return the name of the class.
116
+ /// Note: This reports the actual class name if \c SGL_OBJECT() is used.
117
+ virtual const char* class_name() const { return "Object"; }
118
+
119
+ /// Increase the object's reference count.
120
+ void inc_ref() const noexcept;
121
+
122
+ /// Decrease the object's reference count and potentially deallocate it.
123
+ void dec_ref(bool dealloc = true) const noexcept;
124
+
125
+ /// Return current reference count.
126
+ uint64_t ref_count() const;
127
+
128
+ /// Return the Python object associated with this instance (or NULL)
129
+ PyObject* self_py() const noexcept;
130
+
131
+ /// Set the Python object associated with this instance
132
+ void set_self_py(PyObject* self) noexcept;
133
+
134
+ /// Return a string representation of this object.
135
+ /// This is used for debugging purposes.
136
+ virtual std::string to_string() const;
137
+
138
+ #if SGL_ENABLE_OBJECT_TRACKING
139
+ /// Report all objects that are currently alive.
140
+ static void report_alive_objects();
141
+
142
+ /// Report references of this object.
143
+ void report_refs() const;
144
+ #endif
145
+
146
+ #if SGL_ENABLE_REF_TRACKING
147
+ void inc_ref_tracked(uint64_t ref_id) const;
148
+ void dec_ref_tracked(uint64_t ref_id, bool dealloc = true) const noexcept;
149
+
150
+ /// Enable/disable reference tracking of this object.
151
+ void set_enable_ref_tracking(bool enable);
152
+ #endif
153
+
154
+ private:
155
+ mutable std::atomic<uintptr_t> m_state{1};
156
+
157
+ #if SGL_ENABLE_REF_TRACKING
158
+ struct RefTracker {
159
+ uint32_t count{1};
160
+ platform::StackTrace stack_trace;
161
+ // RefTracker(StackTrace stack_trace_)
162
+ // : count(1)
163
+ // , stack_trace(std::move(stack_trace))
164
+ // {
165
+ // }
166
+ };
167
+ mutable std::map<uint64_t, RefTracker> m_ref_trackers;
168
+ mutable std::mutex m_ref_trackers_mutex;
169
+ bool m_enable_ref_tracking = SGL_TRACK_ALL_REFS;
170
+ #endif
171
+ };
172
+
173
+ /// Macro to declare the object class name.
174
+ #define SGL_OBJECT(class_) \
175
+ public: \
176
+ const char* class_name() const override \
177
+ { \
178
+ return #class_; \
179
+ }
180
+
181
+ /**
182
+ * \brief Install Python reference counting handlers
183
+ *
184
+ * The `Object` class is designed so that the dependency on Python is
185
+ * *optional*: the code compiles in ordinary C++ projects, in which case the
186
+ * Python reference counting functionality will simply not be used.
187
+ *
188
+ * Python binding code must invoke `object_init_py` and provide functions that
189
+ * can be used to increase/decrease the Python reference count of an instance
190
+ * (i.e., `Py_INCREF` / `Py_DECREF`).
191
+ */
192
+ SGL_API void
193
+ object_init_py(void (*object_inc_ref_py)(PyObject*) noexcept, void (*object_dec_ref_py)(PyObject*) noexcept);
194
+
195
+
196
+ #if SGL_ENABLE_REF_TRACKING
197
+ namespace detail {
198
+ inline uint64_t next_ref_id()
199
+ {
200
+ static std::atomic<uint64_t> s_next_id = 0;
201
+ return s_next_id.fetch_add(1);
202
+ }
203
+ } // namespace detail
204
+ #endif
205
+
206
+
207
+ /**
208
+ * \brief Reference counting helper.
209
+ *
210
+ * The \a ref template is a simple wrapper to store a pointer to an object. It
211
+ * takes care of increasing and decreasing the object's reference count as
212
+ * needed. When the last reference goes out of scope, the associated object
213
+ * will be deallocated.
214
+ *
215
+ * This class follows similar semantics to the ``std::shared_ptr`` class from
216
+ * the STL. In particular, we avoid implicit conversion to and from raw
217
+ * pointers.
218
+ */
219
+ template<typename T>
220
+ class ref {
221
+ public:
222
+ /// Default constructor (nullptr).
223
+ ref() { }
224
+
225
+ /// Construct a reference from a nullptr.
226
+ ref(std::nullptr_t) { }
227
+
228
+ /// Construct a reference from a convertible pointer.
229
+ template<typename T2 = T>
230
+ explicit ref(T2* ptr)
231
+ : m_ptr(ptr)
232
+ {
233
+ static_assert(
234
+ std::is_base_of_v<Object, T2>,
235
+ "Cannot create reference to object not inheriting from Object class."
236
+ );
237
+ static_assert(
238
+ std::is_convertible_v<T2*, T*>,
239
+ "Cannot create reference to object from unconvertible pointer type."
240
+ );
241
+ if (m_ptr)
242
+ inc_ref(reinterpret_cast<const Object*>(m_ptr));
243
+ }
244
+
245
+ /// Copy constructor.
246
+ ref(const ref& r)
247
+ : m_ptr(r.m_ptr)
248
+ {
249
+ if (m_ptr)
250
+ inc_ref(reinterpret_cast<const Object*>(m_ptr));
251
+ }
252
+
253
+ /// Construct a reference from a convertible reference.
254
+ template<typename T2 = T>
255
+ ref(const ref<T2>& r)
256
+ : m_ptr(r.m_ptr)
257
+ {
258
+ static_assert(
259
+ std::is_base_of_v<Object, T>,
260
+ "Cannot create reference to object not inheriting from Object class."
261
+ );
262
+ static_assert(
263
+ std::is_convertible_v<T2*, T*>,
264
+ "Cannot create reference to object from unconvertible reference."
265
+ );
266
+ if (m_ptr)
267
+ inc_ref(reinterpret_cast<const Object*>(m_ptr));
268
+ }
269
+
270
+ /// Construct a reference from a pointer.
271
+ explicit ref(T* ptr)
272
+ : m_ptr(ptr)
273
+ {
274
+ if (m_ptr)
275
+ inc_ref(reinterpret_cast<const Object*>(m_ptr));
276
+ }
277
+
278
+ /// Move constructor.
279
+ ref(ref&& r) noexcept
280
+ : m_ptr(r.m_ptr)
281
+ #if SGL_ENABLE_REF_TRACKING
282
+ , m_ref_id(r.m_ref_id)
283
+ #endif
284
+ {
285
+ r.m_ptr = nullptr;
286
+ #if SGL_ENABLE_REF_TRACKING
287
+ r.m_ref_id = uint64_t(-1);
288
+ #endif
289
+ }
290
+
291
+ /// Construct a reference by moving from a convertible reference.
292
+ template<typename T2>
293
+ explicit ref(ref<T2>&& r) noexcept
294
+ : m_ptr(r.m_ptr)
295
+ #if SGL_ENABLE_REF_TRACKING
296
+ , m_ref_id(r.m_ref_id)
297
+ #endif
298
+ {
299
+ static_assert(
300
+ std::is_base_of_v<Object, T>,
301
+ "Cannot create reference to object not inheriting from Object class."
302
+ );
303
+ static_assert(
304
+ std::is_convertible_v<T2*, T*>,
305
+ "Cannot create reference to object from unconvertible reference."
306
+ );
307
+ r.m_ptr = nullptr;
308
+ #if SGL_ENABLE_REF_TRACKING
309
+ r.m_ref_id = uint64_t(-1);
310
+ #endif
311
+ }
312
+
313
+ /// Destructor.
314
+ ~ref()
315
+ {
316
+ if (m_ptr)
317
+ dec_ref(reinterpret_cast<const Object*>(m_ptr));
318
+ }
319
+
320
+ /// Assign another reference into the current one.
321
+ ref& operator=(const ref& r) noexcept
322
+ {
323
+ if (r != *this) {
324
+ if (r.m_ptr)
325
+ inc_ref(reinterpret_cast<const Object*>(r.m_ptr));
326
+ T* prev_ptr = m_ptr;
327
+ m_ptr = r.m_ptr;
328
+ if (prev_ptr)
329
+ dec_ref(reinterpret_cast<const Object*>(prev_ptr));
330
+ }
331
+ return *this;
332
+ }
333
+
334
+ /// Assign another convertible reference into the current one.
335
+ template<typename T2>
336
+ ref& operator=(const ref<T2>& r) noexcept
337
+ {
338
+ static_assert(
339
+ std::is_convertible_v<T2*, T*>,
340
+ "Cannot assign reference to object from unconvertible reference."
341
+ );
342
+ if (r != *this) {
343
+ if (r.m_ptr)
344
+ inc_ref(reinterpret_cast<const Object*>(r.m_ptr));
345
+ T* prev_ptr = m_ptr;
346
+ m_ptr = r.m_ptr;
347
+ if (prev_ptr)
348
+ dec_ref(reinterpret_cast<const Object*>(prev_ptr));
349
+ }
350
+ return *this;
351
+ }
352
+
353
+ /// Move another reference into the current one.
354
+ ref& operator=(ref&& r) noexcept
355
+ {
356
+ if (static_cast<void*>(&r) != this) {
357
+ if (m_ptr)
358
+ dec_ref(reinterpret_cast<const Object*>(m_ptr));
359
+ m_ptr = r.m_ptr;
360
+ r.m_ptr = nullptr;
361
+ #if SGL_ENABLE_REF_TRACKING
362
+ m_ref_id = r.m_ref_id;
363
+ r.m_ref_id = uint64_t(-1);
364
+ #endif
365
+ }
366
+ return *this;
367
+ }
368
+
369
+ /// Move another convertible reference into the current one.
370
+ template<typename T2>
371
+ ref& operator=(ref<T2>&& r) noexcept
372
+ {
373
+ static_assert(std::is_convertible_v<T2*, T*>, "Cannot move reference to object from unconvertible reference.");
374
+ if (static_cast<void*>(&r) != this) {
375
+ if (m_ptr)
376
+ dec_ref(reinterpret_cast<const Object*>(m_ptr));
377
+ m_ptr = r.m_ptr;
378
+ r.m_ptr = nullptr;
379
+ #if SGL_ENABLE_REF_TRACKING
380
+ m_ref_id = r.m_ref_id;
381
+ r.m_ref_id = uint64_t(-1);
382
+ #endif
383
+ }
384
+ return *this;
385
+ }
386
+
387
+ /// Overwrite this reference with a pointer to another object
388
+ template<typename T2 = T>
389
+ void reset(T2* ptr = nullptr) noexcept
390
+ {
391
+ static_assert(std::is_convertible_v<T2*, T*>, "Cannot assign reference to object from unconvertible pointer.");
392
+ if (ptr != m_ptr) {
393
+ if (ptr)
394
+ inc_ref(reinterpret_cast<const Object*>(ptr));
395
+ T* prevPtr = m_ptr;
396
+ m_ptr = ptr;
397
+ if (prevPtr)
398
+ dec_ref(reinterpret_cast<const Object*>(prevPtr));
399
+ }
400
+ }
401
+
402
+ /// Compare this reference to another reference.
403
+ template<typename T2 = T>
404
+ bool operator==(const ref<T2>& r) const
405
+ {
406
+ static_assert(
407
+ std::is_convertible_v<T2*, T*> || std::is_convertible_v<T*, T2*>,
408
+ "Cannot compare references of non-convertible types."
409
+ );
410
+ return m_ptr == r.m_ptr;
411
+ }
412
+
413
+ /// Compare this reference to another reference.
414
+ template<typename T2 = T>
415
+ bool operator!=(const ref<T2>& r) const
416
+ {
417
+ static_assert(
418
+ std::is_convertible_v<T2*, T*> || std::is_convertible_v<T*, T2*>,
419
+ "Cannot compare references of non-convertible types."
420
+ );
421
+ return m_ptr != r.m_ptr;
422
+ }
423
+
424
+ /// Compare this reference to another reference.
425
+ template<typename T2 = T>
426
+ bool operator<(const ref<T2>& r) const
427
+ {
428
+ static_assert(
429
+ std::is_convertible_v<T2*, T*> || std::is_convertible_v<T*, T2*>,
430
+ "Cannot compare references of non-convertible types."
431
+ );
432
+ return m_ptr < r.m_ptr;
433
+ }
434
+
435
+ /// Compare this reference to a pointer.
436
+ template<typename T2 = T>
437
+ bool operator==(const T2* ptr) const
438
+ {
439
+ static_assert(std::is_convertible_v<T2*, T*>, "Cannot compare reference to pointer of non-convertible types.");
440
+ return m_ptr == ptr;
441
+ }
442
+
443
+ /// Compare this reference to a pointer.
444
+ template<typename T2 = T>
445
+ bool operator!=(const T2* ptr) const
446
+ {
447
+ static_assert(std::is_convertible_v<T2*, T*>, "Cannot compare reference to pointer of non-convertible types.");
448
+ return m_ptr != ptr;
449
+ }
450
+
451
+ /// Compare this reference to a null pointer.
452
+ bool operator==(std::nullptr_t) const { return m_ptr == nullptr; }
453
+
454
+ /// Compare this reference to a null pointer.
455
+ bool operator!=(std::nullptr_t) const { return m_ptr != nullptr; }
456
+
457
+ /// Compare this reference to a null pointer.
458
+ bool operator<(std::nullptr_t) const { return m_ptr < nullptr; }
459
+
460
+ /// Access the object referenced by this reference.
461
+ T* operator->() const { return m_ptr; }
462
+
463
+ /// Return a C++ reference to the referenced object.
464
+ T& operator*() const { return *m_ptr; }
465
+
466
+ /// Return a pointer to the referenced object.
467
+ T* get() const { return m_ptr; }
468
+
469
+ /// Return a pointer to the referenced object.
470
+ operator T*() const { return m_ptr; }
471
+
472
+ /// Check if the object is defined
473
+ operator bool() const { return m_ptr != nullptr; }
474
+
475
+ /// Swap this reference with another reference.
476
+ void swap(ref& r) noexcept
477
+ {
478
+ std::swap(m_ptr, r.m_ptr);
479
+ #if SGL_ENABLE_REF_TRACKING
480
+ std::swap(m_ref_id, r.m_ref_id);
481
+ #endif
482
+ }
483
+
484
+ private:
485
+ inline void inc_ref(const Object* object)
486
+ {
487
+ #if SGL_ENABLE_REF_TRACKING
488
+ object->inc_ref_tracked(m_ref_id);
489
+ #else
490
+ object->inc_ref();
491
+ #endif
492
+ }
493
+
494
+ inline void dec_ref(const Object* object)
495
+ {
496
+ #if SGL_ENABLE_REF_TRACKING
497
+ object->dec_ref_tracked(m_ref_id);
498
+ #else
499
+ object->dec_ref(true);
500
+ #endif
501
+ }
502
+
503
+ T* m_ptr{nullptr};
504
+ #if SGL_ENABLE_REF_TRACKING
505
+ uint64_t m_ref_id{detail::next_ref_id()};
506
+ #endif
507
+
508
+ template<typename T2>
509
+ friend class ref;
510
+ };
511
+
512
+ template<class T, class... Args>
513
+ ref<T> make_ref(Args&&... args)
514
+ {
515
+ return ref<T>(new T(std::forward<Args>(args)...));
516
+ }
517
+
518
+ template<class T, class U>
519
+ ref<T> static_ref_cast(const ref<U>& r) noexcept
520
+ {
521
+ return ref<T>(static_cast<T*>(r.get()));
522
+ }
523
+
524
+ template<class T, class U>
525
+ ref<T> dynamic_ref_cast(const ref<U>& r) noexcept
526
+ {
527
+ return ref<T>(dynamic_cast<T*>(r.get()));
528
+ }
529
+
530
+ template<typename T>
531
+ struct is_ref : std::false_type { };
532
+
533
+ template<typename T>
534
+ struct is_ref<ref<T>> : std::true_type { };
535
+
536
+ template<typename T>
537
+ struct is_ref<const ref<T>> : std::true_type { };
538
+
539
+ template<typename T>
540
+ inline constexpr bool is_ref_v = is_ref<T>::value;
541
+
542
+ static_assert(is_ref_v<Object> == false);
543
+ static_assert(is_ref_v<ref<Object>> == true);
544
+
545
+ template<class T>
546
+ struct remove_ref {
547
+ using type = T;
548
+ };
549
+
550
+ template<class T>
551
+ struct remove_ref<ref<T>> {
552
+ using type = T;
553
+ };
554
+
555
+ template<class T>
556
+ struct remove_ref<const ref<T>> {
557
+ using type = T;
558
+ };
559
+
560
+ static_assert(std::is_same_v<remove_ref<Object>::type, Object> == true);
561
+ static_assert(std::is_same_v<remove_ref<ref<Object>>::type, Object> == true);
562
+ static_assert(std::is_same_v<remove_ref<const ref<Object>>::type, Object> == true);
563
+
564
+
565
+ /**
566
+ * \brief Breakable reference counting helper for avoding reference cycles.
567
+ *
568
+ * This helper represents a strong reference (ref<T>) that can be broken.
569
+ * This is accomplished by storing both a strong reference and a raw pointer.
570
+ * When the strong reference is broken, we access the referenced object through
571
+ * the raw pointer.
572
+ *
573
+ * This helper can be used in scenarios where some object holds nested objects
574
+ * that themselves hold a reference to the parent object. In such cases, the
575
+ * nested objects should hold a breakable reference to the parent object.
576
+ * When the nested objects are created, we can immediately break the strong
577
+ * reference to the parent object. This allows the parent object to be destroyed
578
+ * when all of the external references to it are released.
579
+ *
580
+ * This helper can be used in place of a \a ref, but it cannot be reassigned.
581
+ */
582
+ template<typename T>
583
+ class breakable_ref {
584
+ public:
585
+ breakable_ref(const ref<T>& r)
586
+ : m_strong_ref(r)
587
+ , m_weak_ref(m_strong_ref.get())
588
+ {
589
+ }
590
+ breakable_ref(ref<T>&& r)
591
+ : m_strong_ref(std::forward<ref<T>>(r))
592
+ , m_weak_ref(m_strong_ref.get())
593
+ {
594
+ }
595
+
596
+ breakable_ref() = delete;
597
+ breakable_ref& operator=(const ref<T>&) = delete;
598
+ breakable_ref& operator=(ref<T>&&) = delete;
599
+
600
+ T* get() const { return m_weak_ref; }
601
+ T* operator->() const { return get(); }
602
+ T& operator*() const { return *get(); }
603
+ operator ref<T>() const { return ref<T>(get()); }
604
+ operator T*() const { return get(); }
605
+ operator bool() const { return get() != nullptr; }
606
+
607
+ void break_strong_reference() { m_strong_ref.reset(); }
608
+
609
+ private:
610
+ ref<T> m_strong_ref;
611
+ T* m_weak_ref = nullptr;
612
+ };
613
+
614
+ /**
615
+ * \brief Helper class to protect objects from being deleted before the constructor has finished.
616
+ *
617
+ * When objects are constructed, they have a reference count of zero.
618
+ * If during the constructor, a reference to the object is taken and later released,
619
+ * the object will be deleted before the constructor has finished.
620
+ *
621
+ * This helper class will take the initial reference to the object during construction,
622
+ * and avoid any other references to the object from deallocating it before the constructor
623
+ * has finished.
624
+ *
625
+ * \tparam T Object type.
626
+ */
627
+ template<typename T>
628
+ class ConstructorRefGuard {
629
+ public:
630
+ SGL_NON_COPYABLE_AND_MOVABLE(ConstructorRefGuard);
631
+
632
+ explicit ConstructorRefGuard(T* obj)
633
+ : m_obj(obj)
634
+ {
635
+ m_obj->inc_ref();
636
+ }
637
+
638
+ ~ConstructorRefGuard() { m_obj->dec_ref(false); }
639
+
640
+ private:
641
+ T* m_obj;
642
+ };
643
+
644
+
645
+ } // namespace sgl
646
+
647
+ template<typename T>
648
+ struct fmt::formatter<sgl::ref<T>> : formatter<const void*> {
649
+ template<typename FormatContext>
650
+ auto format(const sgl::ref<T>& ref, FormatContext& ctx) const
651
+ {
652
+ return formatter<const void*>::format(ref.get(), ctx);
653
+ }
654
+ };
655
+
656
+ template<typename T>
657
+ struct fmt::formatter<sgl::breakable_ref<T>> : formatter<const void*> {
658
+ template<typename FormatContext>
659
+ auto format(const sgl::breakable_ref<T>& ref, FormatContext& ctx) const
660
+ {
661
+ return formatter<const void*>::format(ref.get(), ctx);
662
+ }
663
+ };
664
+
665
+ namespace std {
666
+ template<typename T>
667
+ void swap(::sgl::ref<T>& x, ::sgl::ref<T>& y) noexcept
668
+ {
669
+ return x.swap(y);
670
+ }
671
+
672
+ template<typename T>
673
+ struct less<::sgl::ref<T>> {
674
+ bool operator()(const ::sgl::ref<T>& a, const ::sgl::ref<T>& b) const { return a.get() < b.get(); }
675
+ };
676
+
677
+ template<typename T>
678
+ struct hash<::sgl::ref<T>> {
679
+ constexpr int operator()(const ::sgl::ref<T>& r) const { return std::hash<T*>()(r.get()); }
680
+ };
681
+
682
+
683
+ } // namespace std