Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
LockManager.cpp
Go to the documentation of this file.
1
2
4
5#include "Headers/GFXDevice.h"
7
8namespace Divide
9{
12
13 SyncObject::SyncObject( const U8 flag, const U64 frameIdx )
14 : _frameNumber(frameIdx)
15 , _flag(flag)
16 {
17 }
18
20 {
21 reset();
22 }
23
25 {
27 }
28
29 void LockManager::CleanExpiredSyncObjects( const RenderAPI api, const U64 frameNumber )
30 {
32
34 for ( BufferLockPoolEntry& syncObject : s_bufferLockPool )
35 {
36 if ( syncObject._ptr->_frameNumber == SyncObject::INVALID_FRAME_NUMBER )
37 {
38 continue;
39 }
40
41 bool reset = false;
42 switch (api)
43 {
44 case RenderAPI::None:
46 {
47 reset = frameNumber - syncObject._ptr->_frameNumber >= Config::MAX_FRAMES_IN_FLIGHT;
48 } break;
50 {
51 reset = syncObject._ptr->_frameNumber < frameNumber;
52 } break;
53
54 default : DIVIDE_UNEXPECTED_CALL(); break;
55 }
56
57 if (reset)
58 {
59 syncObject._ptr->reset();
60 }
61 }
62 }
63
65 {
67 s_bufferLockPool.clear();
68 }
69
70 bool LockManager::InitLockPoolEntry( const RenderAPI api, BufferLockPoolEntry& entry, const U8 flag, const U64 frameIdx )
71 {
72 switch ( api )
73 {
74 case RenderAPI::OpenGL: return glLockManager::InitLockPoolEntry( entry, flag, frameIdx );
76 case RenderAPI::None:
77 {
79
80 if ( entry._ptr == nullptr )
81 {
82 entry._ptr = std::make_unique<SyncObject>( flag, frameIdx );
83 return true;
84 }
85
86 if ( entry._ptr->_frameNumber == SyncObject::INVALID_FRAME_NUMBER )
87 {
88 entry._ptr->_frameNumber = frameIdx;
89 entry._ptr->_flag = flag;
90 return true;
91 }
92
93 return false;
94 }
95
98 break;
99 }
100
101 return true;
102 }
103
104 bool LockManager::waitForLockedRange( const size_t lockBeginBytes, const size_t lockLength )
105 {
107
108 const BufferRange testRange{ lockBeginBytes, lockLength };
109
110 bool error = false;
111
112 LockGuard<Mutex> w_lock_global( _bufferLockslock );
114
115 for ( const BufferLockInstance& lock : _bufferLocks )
116 {
117 DIVIDE_ASSERT( lock._syncObjHandle._id != SyncObjectHandle::INVALID_SYNC_ID );
118
120 const BufferLockPoolEntry& syncLockInstance = s_bufferLockPool[lock._syncObjHandle._id];
121 if ( syncLockInstance._generation != lock._syncObjHandle._generation )
122 {
123 error = !(syncLockInstance._generation > lock._syncObjHandle._generation);
124 DIVIDE_ASSERT( !error );
125 continue;
126 }
127
128 if ( !Overlaps( testRange, lock._range ) ||
129 !waitForLockedRangeLocked( syncLockInstance._ptr, testRange, lock ) )
130 {
131 _swapLocks.push_back( lock );
132 }
133 }
134
135 _bufferLocks.swap( _swapLocks );
136
137 return !error;
138 }
139
140 bool LockManager::waitForLockedRangeLocked( const SyncObject_uptr& sync, [[maybe_unused]] const BufferRange& testRange, [[maybe_unused]] const BufferLockInstance& lock )
141 {
142 sync->reset();
143 return true;
144 }
145
146 bool LockManager::lockRange( size_t lockBeginBytes, size_t lockLength, SyncObjectHandle syncObj )
147 {
149
150 DIVIDE_ASSERT( syncObj._id != SyncObjectHandle::INVALID_SYNC_ID && lockLength > 0u, "LockManager::lockRange error: Invalid lock range!" );
151
152 const BufferRange testRange{ lockBeginBytes, lockLength };
153
155 // See if we can reuse an old lock. Ignore the old fence since the new one will guard the same mem region. (Right?)
156 for ( BufferLockInstance& lock : _bufferLocks )
157 {
158 if ( Overlaps( testRange, lock._range ) )
159 {
160 Merge( lock._range, testRange );
161 lock._syncObjHandle = syncObj;
162 return true;
163 }
164 }
165
166 // No luck with our reuse search. Add a new lock.
167 _bufferLocks.emplace_back( testRange, syncObj );
168
169 return true;
170 }
171
173 {
175
177
178 // Attempt reuse
179 for ( size_t i = 0u; i < s_bufferLockPool.size(); ++i )
180 {
181 BufferLockPoolEntry& syncObject = s_bufferLockPool[i];
182
183 if ( InitLockPoolEntry( api, syncObject, flag, GFXDevice::FrameCount() ) )
184 {
185 return SyncObjectHandle{ i, ++syncObject._generation };
186 }
187 }
188
189 // We failed once, so create a new object
190 BufferLockPoolEntry newEntry{};
191 if ( !InitLockPoolEntry( api, newEntry, flag, GFXDevice::FrameCount() ) )
192 {
194 }
195
196 s_bufferLockPool.emplace_back( MOV( newEntry ) );
197 return SyncObjectHandle{ s_bufferLockPool.size() - 1u, newEntry._generation };
198 }
199
200
201}; //namespace Divide
#define MOV(...)
#define DIVIDE_ASSERT(...)
#define DIVIDE_UNEXPECTED_CALL()
#define PROFILE_SCOPE_AUTO(CATEGORY)
Definition: Profiler.h:87
static U64 FrameCount() noexcept
Definition: GFXDevice.h:340
static void CleanExpiredSyncObjects(RenderAPI api, U64 frameNumber)
Definition: LockManager.cpp:29
static void Clear()
Definition: LockManager.cpp:64
static SyncObjectHandle CreateSyncObject(RenderAPI api, U8 flag=DEFAULT_SYNC_FLAG_INTERNAL)
static Mutex s_bufferLockLock
Definition: LockManager.h:113
virtual bool waitForLockedRangeLocked(const SyncObject_uptr &sync, const BufferRange &testRange, const BufferLockInstance &lock)
bool waitForLockedRange(size_t lockBeginBytes, size_t lockLength)
Returns false if we encountered an error.
eastl::fixed_vector< BufferLockPoolEntry, 1024, true > BufferLockPool
Definition: LockManager.h:88
eastl::fixed_vector< BufferLockInstance, 64, true > _bufferLocks
Definition: LockManager.h:110
static BufferLockPool s_bufferLockPool
Definition: LockManager.h:114
bool lockRange(size_t lockBeginBytes, size_t lockLength, SyncObjectHandle syncObj)
Returns false if we encountered an error.
static bool InitLockPoolEntry(RenderAPI api, BufferLockPoolEntry &entry, U8 flag, U64 frameIdx)
Definition: LockManager.cpp:70
eastl::fixed_vector< BufferLockInstance, 64, true > _swapLocks
Definition: LockManager.h:111
static bool InitLockPoolEntry(BufferLockPoolEntry &entry, U8 flag, U64 frameIdx)
constexpr U8 MAX_FRAMES_IN_FLIGHT
Maximum number of active frames until we start waiting on a fence/sync.
Definition: config.h:100
constexpr Optick::Category::Type Graphics
Definition: Profiler.h:60
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
std::lock_guard< mutex > LockGuard
Definition: SharedMutex.h:55
void Merge(BufferRange &lhs, const BufferRange &rhs) noexcept
Definition: BufferRange.inl:49
std::mutex Mutex
Definition: SharedMutex.h:40
uint8_t U8
bool Overlaps(const BufferRange &lhs, const BufferRange &rhs) noexcept
Definition: BufferRange.inl:43
@ Vulkan
not supported yet
@ None
No rendering. Used for testing or server code.
SceneGraphNode * _flag[2]
Definition: WarScene.h:96
void efficient_clear(eastl::fixed_vector< T, nodeCount, bEnableOverflow, OverflowAllocator > &fixed_vector)
Definition: Vector.h:52
Project const SceneEntry & entry
Definition: DefaultScene.h:41
uint64_t U64
Definition: LockManager.h:83
size_t _generation
Definition: LockManager.h:85
SyncObject_uptr _ptr
Definition: LockManager.h:84
static constexpr size_t INVALID_SYNC_ID
Definition: LockManager.h:62
SyncObject(U8 flag, U64 frameIdx)
Definition: LockManager.cpp:13
virtual ~SyncObject()
Definition: LockManager.cpp:19
static constexpr U64 INVALID_FRAME_NUMBER
Definition: LockManager.h:48
virtual void reset()
Definition: LockManager.cpp:24