Torque3D Documentation / _generateds / gfxGLCircularVolatileBuffer.h

gfxGLCircularVolatileBuffer.h

Engine/source/gfx/gl/gfxGLCircularVolatileBuffer.h

More...

Classes:

Detailed Description

  1
  2#ifndef GL_CIRCULAR_VOLATILE_BUFFER_H
  3#define GL_CIRCULAR_VOLATILE_BUFFER_H
  4
  5#include "gfx/gl/gfxGLDevice.h"
  6#include "gfx/gl/gfxGLUtils.h"
  7
  8class GLFenceRange 
  9{
 10public:
 11   GLFenceRange() : mStart(0), mEnd(0), mSync(0)
 12   {         
 13     
 14   }
 15
 16   ~GLFenceRange()
 17   {
 18      //the order of creation/destruction of static variables is indetermined... depends on detail of the build
 19      //looks like for some reason on windows + sdl + opengl the order make invalid / wrong the process TODO: Refactor -LAR
 20      //AssertFatal( mSync == 0, "");
 21   }
 22
 23   void init(U32 start, U32 end)
 24   {  
 25      PROFILE_SCOPE(GFXGLQueryFence_issue);
 26      mStart = start;
 27      mEnd = end;
 28      mSync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
 29   }
 30
 31   bool checkOverlap(U32 start, U32 end) 
 32   {         
 33      if( mStart < end && start < mEnd )
 34         return true;
 35
 36      return false;
 37   }
 38
 39   void wait()
 40   {   
 41      PROFILE_SCOPE(GFXGLQueryFence_block);
 42      GLbitfield waitFlags = 0;
 43      GLuint64 waitDuration = 0;
 44      while( 1 ) 
 45      {
 46         GLenum waitRet = glClientWaitSync( mSync, waitFlags, waitDuration );
 47         if( waitRet == GL_ALREADY_SIGNALED || waitRet == GL_CONDITION_SATISFIED ) 
 48         {
 49            break;
 50         }
 51
 52         if( waitRet == GL_WAIT_FAILED ) 
 53         {
 54            AssertFatal(0, "GLSync failed.");
 55            break;
 56         }
 57         
 58         waitFlags = GL_SYNC_FLUSH_COMMANDS_BIT;
 59         waitDuration = scOneSecondInNanoSeconds;
 60      }     
 61
 62      glDeleteSync(mSync);
 63      mSync = 0;
 64   }
 65
 66   void swap( GLFenceRange &r )
 67   {
 68      GLFenceRange temp;
 69      temp = *this;
 70      *this = r;
 71      r = temp;
 72   }
 73
 74protected:
 75   U32 mStart, mEnd;
 76   GLsync mSync;
 77   static const GLuint64 scOneSecondInNanoSeconds = 1000000000;
 78
 79   GLFenceRange( const GLFenceRange &);
 80   GLFenceRange& operator=(const GLFenceRange &r)
 81   {
 82      mStart = r.mStart;
 83      mEnd = r.mEnd;
 84      mSync = r.mSync;
 85      return *this;
 86   }
 87};
 88
 89class GLOrderedFenceRangeManager
 90{
 91public:
 92
 93   ~GLOrderedFenceRangeManager( )
 94   {
 95      //the order of creation/destruction of static variables is indetermined... depends on detail of the build
 96      //looks like for some reason on windows + sdl + opengl the order make invalid / wrong the process TODO: Refactor -LAR
 97      //waitAllRanges( );
 98   }
 99
100   void protectOrderedRange( U32 start, U32 end )
101   {
102      mFenceRanges.increment();
103      GLFenceRange &range = mFenceRanges.last();
104      range.init( start, end );
105   }
106
107   void waitFirstRange( U32 start, U32 end )
108   {
109      if( !mFenceRanges.size() || !mFenceRanges[0].checkOverlap( start, end ) )
110         return;
111         
112      mFenceRanges[0].wait();
113      mFenceRanges.pop_front();
114   }
115
116   void waitOverlapRanges( U32 start, U32 end )
117   {
118      for( U32 i = 0; i < mFenceRanges.size(); ++i )
119      {
120         if( !mFenceRanges[i].checkOverlap( start, end ) )
121            continue;
122         
123         mFenceRanges[i].wait();
124         mFenceRanges.erase(i);
125      }
126   }
127
128   void waitAllRanges()
129   {
130      for( int i = 0; i < mFenceRanges.size(); ++i )            
131         mFenceRanges[i].wait();      
132
133      mFenceRanges.clear();
134   }
135
136protected:
137   Vector<GLFenceRange> mFenceRanges;
138};
139
140class GLCircularVolatileBuffer
141{
142public:
143   GLCircularVolatileBuffer(GLuint binding) 
144      : mBinding(binding), mBufferName(0), mBufferPtr(NULL), mBufferSize(0), mBufferFreePos(0), mCurrectUsedRangeStart(0)
145   { 
146      init();
147   }
148
149   ~GLCircularVolatileBuffer()
150   {
151      glDeleteBuffers(1, &mBufferName);
152   }
153
154   void init()
155   {
156      glGenBuffers(1, &mBufferName);
157
158      PRESERVE_BUFFER( mBinding );
159      glBindBuffer(mBinding, mBufferName);
160     
161      const U32 cSizeInMB = 10;
162      mBufferSize = (cSizeInMB << 20);
163
164      if( GFXGL->mCapabilities.bufferStorage )
165      {      
166         const GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | GL_MAP_COHERENT_BIT;
167         glBufferStorage(mBinding, mBufferSize, NULL, flags);
168         mBufferPtr = glMapBufferRange(mBinding, 0, mBufferSize, flags);
169      }
170      else
171      {
172         glBufferData(mBinding, mBufferSize, NULL, GL_DYNAMIC_DRAW);
173      }
174   }
175
176   struct 
177   {
178      U32 mOffset = 0;
179      U32 mSize = 0;
180   }_getBufferData;
181
182   void lock(const U32 size, U32 offsetAlign, U32 &outOffset, void* &outPtr)
183   {
184      if( !size )
185      {
186         AssertFatal(0, "");
187         outOffset = 0;
188         outPtr = NULL;
189      }
190
191      mLockManager.waitFirstRange( mBufferFreePos, (mBufferFreePos + size)-1 );
192
193      if( mBufferFreePos + size > mBufferSize )
194      {         
195         mUsedRanges.push_back( UsedRange( mBufferFreePos, mBufferSize-1 ) );
196         mBufferFreePos = 0;
197      }
198
199      // force offset buffer align
200      if( offsetAlign )
201         mBufferFreePos = ( (mBufferFreePos/offsetAlign) + 1 ) * offsetAlign;
202
203      outOffset = mBufferFreePos;
204
205      if( GFXGL->mCapabilities.bufferStorage )
206      {         
207         outPtr = (U8*)(mBufferPtr) + mBufferFreePos; 
208      }
209      else if( GFXGL->glUseMap() )
210      {
211         PRESERVE_BUFFER( mBinding );
212         glBindBuffer(mBinding, mBufferName);
213
214         const GLbitfield access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
215         outPtr = glMapBufferRange(mBinding, outOffset, size, access);
216      }
217      else
218      {
219         _getBufferData.mOffset = outOffset;
220         _getBufferData.mSize = size;
221
222         outPtr = mFrameAllocator.lock( size );
223      }      
224
225      //set new buffer pos
226      mBufferFreePos = mBufferFreePos + size;
227
228      //align 4bytes
229      mBufferFreePos = ( (mBufferFreePos/4) + 1 ) * 4;
230   }
231
232   void unlock()
233   {
234      if( GFXGL->mCapabilities.bufferStorage )
235      {
236         return;
237      }
238      else if( GFXGL->glUseMap() )
239      {
240         PRESERVE_BUFFER( mBinding );
241         glBindBuffer(mBinding, mBufferName);
242
243         glUnmapBuffer(mBinding);
244      }
245      else
246      {
247         PRESERVE_BUFFER( mBinding );
248         glBindBuffer(mBinding, mBufferName);
249
250         glBufferSubData( mBinding, _getBufferData.mOffset, _getBufferData.mSize, mFrameAllocator.getlockedPtr() );
251
252         _getBufferData.mOffset = 0;
253         _getBufferData.mSize = 0;
254
255         mFrameAllocator.unlock();
256      }
257      
258   }
259
260   U32 getHandle() const { return mBufferName; }
261
262   void protectUsedRange()
263   {
264      for( int i = 0; i < mUsedRanges.size(); ++i )
265      {
266         mLockManager.protectOrderedRange( mUsedRanges[i].start, mUsedRanges[i].end );
267      }
268      mUsedRanges.clear();
269
270      if( mCurrectUsedRangeStart < mBufferFreePos )
271      {
272         mLockManager.protectOrderedRange( mCurrectUsedRangeStart, mBufferFreePos-1 );      
273         mCurrectUsedRangeStart = mBufferFreePos;
274      }
275   }
276
277protected:   
278
279   GLuint mBinding;
280   GLuint mBufferName;
281   void *mBufferPtr;
282   U32 mBufferSize;
283   U32 mBufferFreePos;
284   U32 mCurrectUsedRangeStart;
285
286   GLOrderedFenceRangeManager mLockManager;
287   FrameAllocatorLockableHelper mFrameAllocator;
288
289   struct UsedRange
290   {
291      UsedRange(U32 _start = 0, U32 _end = 0)
292         : start(_start), end(_end)
293      {
294
295      }
296      U32 start, end;
297   };
298   Vector<UsedRange> mUsedRanges;
299};
300
301
302#endif
303