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.
- include/tevclient.h +393 -0
- nv_sgl-0.6.0.dist-info/LICENSE +29 -0
- nv_sgl-0.6.0.dist-info/METADATA +21 -0
- nv_sgl-0.6.0.dist-info/RECORD +142 -0
- nv_sgl-0.6.0.dist-info/WHEEL +5 -0
- nv_sgl-0.6.0.dist-info/top_level.txt +1 -0
- sgl/__init__.py +15 -0
- sgl/__init__.pyi +6738 -0
- sgl/d3d12/D3D12Core.dll +0 -0
- sgl/d3d12/d3d12SDKLayers.dll +0 -0
- sgl/dxcompiler.dll +0 -0
- sgl/dxil.dll +0 -0
- sgl/gfx.dll +0 -0
- sgl/include/sgl/app/app.h +113 -0
- sgl/include/sgl/core/bitmap.h +302 -0
- sgl/include/sgl/core/crypto.h +89 -0
- sgl/include/sgl/core/data_type.h +46 -0
- sgl/include/sgl/core/dds_file.h +103 -0
- sgl/include/sgl/core/enum.h +201 -0
- sgl/include/sgl/core/error.h +161 -0
- sgl/include/sgl/core/file_stream.h +77 -0
- sgl/include/sgl/core/file_system_watcher.h +141 -0
- sgl/include/sgl/core/format.h +36 -0
- sgl/include/sgl/core/fwd.h +90 -0
- sgl/include/sgl/core/hash.h +45 -0
- sgl/include/sgl/core/input.h +522 -0
- sgl/include/sgl/core/logger.h +214 -0
- sgl/include/sgl/core/macros.h +184 -0
- sgl/include/sgl/core/maths.h +45 -0
- sgl/include/sgl/core/memory_mapped_file.h +112 -0
- sgl/include/sgl/core/memory_mapped_file_stream.h +32 -0
- sgl/include/sgl/core/memory_stream.h +74 -0
- sgl/include/sgl/core/object.h +683 -0
- sgl/include/sgl/core/platform.h +239 -0
- sgl/include/sgl/core/plugin.h +331 -0
- sgl/include/sgl/core/resolver.h +39 -0
- sgl/include/sgl/core/short_vector.h +141 -0
- sgl/include/sgl/core/static_vector.h +111 -0
- sgl/include/sgl/core/stream.h +54 -0
- sgl/include/sgl/core/string.h +276 -0
- sgl/include/sgl/core/struct.h +360 -0
- sgl/include/sgl/core/thread.h +28 -0
- sgl/include/sgl/core/timer.h +52 -0
- sgl/include/sgl/core/traits.h +15 -0
- sgl/include/sgl/core/type_utils.h +19 -0
- sgl/include/sgl/core/window.h +177 -0
- sgl/include/sgl/device/agility_sdk.h +24 -0
- sgl/include/sgl/device/blit.h +88 -0
- sgl/include/sgl/device/buffer_cursor.h +162 -0
- sgl/include/sgl/device/command.h +539 -0
- sgl/include/sgl/device/cuda_api.h +766 -0
- sgl/include/sgl/device/cuda_interop.h +39 -0
- sgl/include/sgl/device/cuda_utils.h +107 -0
- sgl/include/sgl/device/cursor_utils.h +129 -0
- sgl/include/sgl/device/device.h +668 -0
- sgl/include/sgl/device/device_resource.h +37 -0
- sgl/include/sgl/device/fence.h +91 -0
- sgl/include/sgl/device/formats.h +330 -0
- sgl/include/sgl/device/framebuffer.h +85 -0
- sgl/include/sgl/device/fwd.h +164 -0
- sgl/include/sgl/device/helpers.h +20 -0
- sgl/include/sgl/device/hot_reload.h +75 -0
- sgl/include/sgl/device/input_layout.h +74 -0
- sgl/include/sgl/device/kernel.h +69 -0
- sgl/include/sgl/device/memory_heap.h +155 -0
- sgl/include/sgl/device/native_formats.h +342 -0
- sgl/include/sgl/device/native_handle.h +73 -0
- sgl/include/sgl/device/native_handle_traits.h +65 -0
- sgl/include/sgl/device/pipeline.h +138 -0
- sgl/include/sgl/device/print.h +45 -0
- sgl/include/sgl/device/python/cursor_utils.h +853 -0
- sgl/include/sgl/device/query.h +52 -0
- sgl/include/sgl/device/raytracing.h +84 -0
- sgl/include/sgl/device/reflection.h +1254 -0
- sgl/include/sgl/device/resource.h +705 -0
- sgl/include/sgl/device/sampler.h +57 -0
- sgl/include/sgl/device/shader.h +516 -0
- sgl/include/sgl/device/shader_cursor.h +85 -0
- sgl/include/sgl/device/shader_object.h +94 -0
- sgl/include/sgl/device/shader_offset.h +67 -0
- sgl/include/sgl/device/shared_handle.h +12 -0
- sgl/include/sgl/device/slang_utils.h +54 -0
- sgl/include/sgl/device/swapchain.h +74 -0
- sgl/include/sgl/device/types.h +782 -0
- sgl/include/sgl/math/colorspace.h +56 -0
- sgl/include/sgl/math/constants.h +7 -0
- sgl/include/sgl/math/float16.h +146 -0
- sgl/include/sgl/math/matrix.h +6 -0
- sgl/include/sgl/math/matrix_math.h +746 -0
- sgl/include/sgl/math/matrix_types.h +207 -0
- sgl/include/sgl/math/python/primitivetype.h +33 -0
- sgl/include/sgl/math/quaternion.h +6 -0
- sgl/include/sgl/math/quaternion_math.h +484 -0
- sgl/include/sgl/math/quaternion_types.h +83 -0
- sgl/include/sgl/math/ray.h +47 -0
- sgl/include/sgl/math/scalar_math.h +249 -0
- sgl/include/sgl/math/scalar_types.h +107 -0
- sgl/include/sgl/math/vector.h +6 -0
- sgl/include/sgl/math/vector_math.h +1796 -0
- sgl/include/sgl/math/vector_types.h +336 -0
- sgl/include/sgl/python/nanobind.h +489 -0
- sgl/include/sgl/python/py_doc.h +11600 -0
- sgl/include/sgl/python/sgl_ext_pch.h +8 -0
- sgl/include/sgl/sgl.h +21 -0
- sgl/include/sgl/sgl_pch.h +6 -0
- sgl/include/sgl/stl/bit.h +377 -0
- sgl/include/sgl/tests/testing.h +54 -0
- sgl/include/sgl/ui/fwd.h +34 -0
- sgl/include/sgl/ui/imgui_config.h +43 -0
- sgl/include/sgl/ui/ui.h +71 -0
- sgl/include/sgl/ui/widgets.h +918 -0
- sgl/include/sgl/utils/python/slangpy.h +366 -0
- sgl/include/sgl/utils/renderdoc.h +50 -0
- sgl/include/sgl/utils/slangpy.h +153 -0
- sgl/include/sgl/utils/tev.h +93 -0
- sgl/include/sgl/utils/texture_loader.h +106 -0
- sgl/math/__init__.pyi +5083 -0
- sgl/platform/__init__.pyi +102 -0
- sgl/renderdoc/__init__.pyi +51 -0
- sgl/sgl.dll +0 -0
- sgl/sgl_ext.cp313-win_amd64.pyd +0 -0
- sgl/shaders/nvapi/nvHLSLExtns.h +2315 -0
- sgl/shaders/nvapi/nvHLSLExtnsInternal.h +758 -0
- sgl/shaders/nvapi/nvShaderExtnEnums.h +142 -0
- sgl/shaders/sgl/device/blit.slang +93 -0
- sgl/shaders/sgl/device/nvapi.slang +5 -0
- sgl/shaders/sgl/device/nvapi.slangh +7 -0
- sgl/shaders/sgl/device/print.slang +445 -0
- sgl/shaders/sgl/math/constants.slang +4 -0
- sgl/shaders/sgl/math/ray.slang +29 -0
- sgl/shaders/sgl/ui/imgui.slang +49 -0
- sgl/slang-glslang.dll +0 -0
- sgl/slang-llvm.dll +0 -0
- sgl/slang-rt.dll +0 -0
- sgl/slang.dll +0 -0
- sgl/slangpy/__init__.pyi +268 -0
- sgl/tev/__init__.pyi +108 -0
- sgl/tevclient.lib +0 -0
- sgl/thread/__init__.pyi +4 -0
- sgl/ui/__init__.pyi +1118 -0
- share/cmake/tevclient/tevclient-config-release.cmake +19 -0
- 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
|