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, mSize;
179   }_getBufferData;
180
181   void lock(const U32 size, U32 offsetAlign, U32 &outOffset, void* &outPtr)
182   {
183      if( !size )
184      {
185         AssertFatal(0, "");
186         outOffset = 0;
187         outPtr = NULL;
188      }
189
190      mLockManager.waitFirstRange( mBufferFreePos, (mBufferFreePos + size)-1 );
191
192      if( mBufferFreePos + size > mBufferSize )
193      {         
194         mUsedRanges.push_back( UsedRange( mBufferFreePos, mBufferSize-1 ) );
195         mBufferFreePos = 0;
196      }
197
198      // force offset buffer align
199      if( offsetAlign )
200         mBufferFreePos = ( (mBufferFreePos/offsetAlign) + 1 ) * offsetAlign;
201
202      outOffset = mBufferFreePos;
203
204      if( GFXGL->mCapabilities.bufferStorage )
205      {         
206         outPtr = (U8*)(mBufferPtr) + mBufferFreePos; 
207      }
208      else if( GFXGL->glUseMap() )
209      {
210         PRESERVE_BUFFER( mBinding );
211         glBindBuffer(mBinding, mBufferName);
212
213         const GLbitfield access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_RANGE_BIT | GL_MAP_UNSYNCHRONIZED_BIT;
214         outPtr = glMapBufferRange(mBinding, outOffset, size, access);
215      }
216      else
217      {
218         _getBufferData.mOffset = outOffset;
219         _getBufferData.mSize = size;
220
221         outPtr = mFrameAllocator.lock( size );
222      }      
223
224      //set new buffer pos
225      mBufferFreePos = mBufferFreePos + size;
226
227      //align 4bytes
228      mBufferFreePos = ( (mBufferFreePos/4) + 1 ) * 4;
229   }
230
231   void unlock()
232   {
233      if( GFXGL->mCapabilities.bufferStorage )
234      {
235         return;
236      }
237      else if( GFXGL->glUseMap() )
238      {
239         PRESERVE_BUFFER( mBinding );
240         glBindBuffer(mBinding, mBufferName);
241
242         glUnmapBuffer(mBinding);
243      }
244      else
245      {
246         PRESERVE_BUFFER( mBinding );
247         glBindBuffer(mBinding, mBufferName);
248
249         glBufferSubData( mBinding, _getBufferData.mOffset, _getBufferData.mSize, mFrameAllocator.getlockedPtr() );
250
251         _getBufferData.mOffset = 0;
252         _getBufferData.mSize = 0;
253
254         mFrameAllocator.unlock();
255      }
256      
257   }
258
259   U32 getHandle() const { return mBufferName; }
260
261   void protectUsedRange()
262   {
263      for( int i = 0; i < mUsedRanges.size(); ++i )
264      {
265         mLockManager.protectOrderedRange( mUsedRanges[i].start, mUsedRanges[i].end );
266      }
267      mUsedRanges.clear();
268
269      if( mCurrectUsedRangeStart < mBufferFreePos )
270      {
271         mLockManager.protectOrderedRange( mCurrectUsedRangeStart, mBufferFreePos-1 );      
272         mCurrectUsedRangeStart = mBufferFreePos;
273      }
274   }
275
276protected:   
277
278   GLuint mBinding;
279   GLuint mBufferName;
280   void *mBufferPtr;
281   U32 mBufferSize;
282   U32 mBufferFreePos;
283   U32 mCurrectUsedRangeStart;
284
285   GLOrderedFenceRangeManager mLockManager;
286   FrameAllocatorLockableHelper mFrameAllocator;
287
288   struct UsedRange
289   {
290      UsedRange(U32 _start = 0, U32 _end = 0)
291         : start(_start), end(_end)
292      {
293
294      }
295      U32 start, end;
296   };
297   Vector<UsedRange> mUsedRanges;
298};
299
300
301#endif
302