| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384 |
- module three.gl.sync;
- public import derelict.opengl3.gl3;
- import three.gl.util;
- import std.experimental.logger;
- enum kOneSecondInNanoSeconds = GLuint64(1000000000);
- struct GlSyncManager {
- private:
- struct LockRange
- {
- size_t startOffset;
- size_t length;
-
- bool overlaps(LockRange rhs) pure const const @safe nothrow {
- 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) nothrow {
- LockRange testRange = LockRange(lockBeginOffset, lockLength);
- Lock[] swapLocks;
-
- foreach(ref lock; locks) {
- if (testRange.overlaps(lock.range)) {
- waitForSync(lock.sync);
- glCheck!glDeleteSync(lock.sync);
- }
- else {
- swapLocks ~= lock;
- }
- }
- locks = swapLocks;
- }
-
- void lockRange(size_t lockBeginOffset, size_t lockLength) nothrow {
- LockRange newRange = LockRange(lockBeginOffset, lockLength);
- GLsync syncName = glCheck!glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
- locks ~= Lock(newRange, syncName);
- }
- private:
- void waitForSync(ref GLsync sync) nothrow {
- version(LockBusyWait) {
- GLbitfield waitFlags = 0;
- GLuint64 waitDuration = 0;
- while(true) {
- GLenum waitRet = glCheck!glClientWaitSync(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(sync, 0, GL_TIMEOUT_IGNORED);
- }
- }
- }
|