| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879 |
- module three.gl.sync;
- public import derelict.opengl3.gl3;
- import three.gl.util;
- struct GlSyncManager {
- private:
- struct LockRange
- {
- size_t startOffset;
- size_t length;
-
- bool overlaps(LockRange rhs) const {
- return startOffset < (rhs.startOffset + rhs.length) && rhs.startOffset < (startOffset + length);
- }
- }
-
- struct Lock
- {
- LockRange range;
- GLsync sync;
- }
-
- Lock[] locks;
- public:
- void construct() pure @safe nothrow @nogc {
- }
-
- void destruct() pure @safe nothrow @nogc {
- }
-
- void waitForLockedRange(size_t lockBeginOffset, size_t lockLength) {
- LockRange testRange = LockRange(lockBeginOffset, lockLength);
- Lock[] swapLocks;
-
- foreach(ref lock; locks) {
- if (testRange.overlaps(lock.range)) {
- version(LockBusyWait) {
- GLbitfield waitFlags = 0;
- GLuint64 waitDuration = 0;
- while(true) {
- GLenum waitRet = glCheck!glClientWaitSync(lock.sync, waitFlags, waitDuration);
- if (waitRet == GL_ALREADY_SIGNALED || waitRet == GL_CONDITION_SATISFIED) {
- return;
- }
-
- if (waitRet == GL_WAIT_FAILED) {
- assert(!"Not sure what to do here. Probably raise an exception or something.");
- return;
- }
-
- // After the first time, need to start flushing, and wait for a looong time.
- waitFlags = GL_SYNC_FLUSH_COMMANDS_BIT;
- waitDuration = kOneSecondInNanoSeconds;
- }
- }
- else {
- glCheck!glWaitSync(lock.sync, 0, GL_TIMEOUT_IGNORED);
- }
-
- glCheck!glDeleteSync(lock.sync);
- }
- else {
- swapLocks ~= lock;
- }
- }
-
- import std.algorithm : swap;
- swap(locks, swapLocks);
- }
-
- void lockRange(size_t lockBeginOffset, size_t lockLength) {
- LockRange newRange = LockRange(lockBeginOffset, lockLength);
- GLsync syncName = glCheck!glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
- locks ~= Lock(newRange, syncName);
- }
- }
|