yum-mirror/slang

Making it easier to work with shaders

git clone https://git.yummers.dev/yum-mirror/slang

Theresa FoleyImprove performance of AST deserialization (#7935)631a4c37a

master
2.4 KiB97 linesraw
1// slang-relative-ptr.h
2#ifndef SLANG_RELATIVE_PTR_H
3#define SLANG_RELATIVE_PTR_H
4
5// This file implements a smart pointer type `RelativePtr<T>`
6// that, rather than storing the actual *address* of a value
7// of type `T`, stores the relative offset (in bytes) between
8// the target `T*` and the address of the `RelativePtr<T>`
9// itself.
10//
11// This kind of pointer representation can be useful when
12// implementing "memory-mappable" data structures that can
13// still conveniently represent complicated object graphs.
14
15#include "slang-basic.h"
16
17namespace Slang
18{
19namespace detail
20{
21struct RelativePtr32Traits
22{
23    using Offset = Int32;
24    using UOffset = UInt32;
25};
26
27struct RelativePtr64Traits
28{
29    using Offset = Int64;
30    using UOffset = UInt64;
31};
32} // namespace detail
33
34template<typename T, typename Traits>
35struct RelativePtr
36{
37public:
38    using This = RelativePtr<T, Traits>;
39    using Value = T;
40    using RawPtr = T*;
41    using Offset = typename Traits::Offset;
42    using UOffset = typename Traits::UOffset;
43
44    SLANG_FORCE_INLINE RelativePtr() = default;
45    SLANG_FORCE_INLINE RelativePtr(RelativePtr const& ptr) { set(ptr); }
46    SLANG_FORCE_INLINE RelativePtr(RelativePtr&& ptr) { set(ptr); }
47    SLANG_FORCE_INLINE RelativePtr(T* ptr) { set(ptr); }
48
49    SLANG_FORCE_INLINE void operator=(RelativePtr const& ptr) { set(ptr); }
50    SLANG_FORCE_INLINE void operator=(RelativePtr&& ptr) { set(ptr); }
51    SLANG_FORCE_INLINE void operator=(T* ptr) { set(ptr); }
52
53    T* get() const
54    {
55        if (_offset == 0)
56        {
57            return nullptr;
58        }
59
60        intptr_t thisAddr = intptr_t(this);
61        intptr_t targetAddr = thisAddr + intptr_t(_offset);
62
63        return (T*)(targetAddr);
64    }
65
66    void set(T* ptr)
67    {
68        if (ptr == nullptr)
69        {
70            _offset = 0;
71            return;
72        }
73
74        intptr_t thisAddr = intptr_t(this);
75        intptr_t targetAddr = intptr_t(ptr);
76        intptr_t offsetVal = targetAddr - thisAddr;
77
78        _offset = Offset(offsetVal);
79        SLANG_ASSERT(intptr_t(_offset) == offsetVal);
80    }
81
82    SLANG_FORCE_INLINE operator T*() const { return get(); }
83    SLANG_FORCE_INLINE T* operator->() const { return get(); }
84
85private:
86    Offset _offset = 0;
87};
88
89template<typename T>
90using RelativePtr32 = RelativePtr<T, detail::RelativePtr32Traits>;
91
92template<typename T>
93using RelativePtr64 = RelativePtr<T, detail::RelativePtr64Traits>;
94
95} // namespace Slang
96
97#endif