gfxGLVertexBuffer.cpp
Engine/source/gfx/gl/gfxGLVertexBuffer.cpp
Public Variables
Public Functions
Detailed Description
Public Variables
MODULE_INIT
MODULE_SHUTDOWN
Public Functions
getCircularVolatileVertexBuffer()
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "gfx/gl/gfxGLVertexBuffer.h" 26 27#include "gfx/gl/gfxGLDevice.h" 28#include "gfx/gl/gfxGLEnumTranslate.h" 29#include "gfx/gl/gfxGLUtils.h" 30#include "gfx/gl/gfxGLVertexAttribLocation.h" 31 32#include "gfx/gl/gfxGLCircularVolatileBuffer.h" 33 34GLCircularVolatileBuffer* getCircularVolatileVertexBuffer() 35{ 36 static GLCircularVolatileBuffer sCircularVolatileVertexBuffer(GL_ARRAY_BUFFER); 37 return &sCircularVolatileVertexBuffer; 38} 39 40GFXGLVertexBuffer::GFXGLVertexBuffer( GFXDevice *device, 41 U32 numVerts, 42 const GFXVertexFormat *vertexFormat, 43 U32 vertexSize, 44 GFXBufferType bufferType ) 45 : GFXVertexBuffer( device, numVerts, vertexFormat, vertexSize, bufferType ), 46 mBufferOffset(0), 47 mBufferVertexOffset(0), 48 mZombieCache(NULL) 49 50{ 51 if( mBufferType == GFXBufferTypeVolatile ) 52 { 53 mBuffer = getCircularVolatileVertexBuffer()->getHandle(); 54 return; 55 } 56 57 // Generate a buffer 58 glGenBuffers(1, &mBuffer); 59 60 //and allocate the needed memory 61 PRESERVE_VERTEX_BUFFER(); 62 glBindBuffer(GL_ARRAY_BUFFER, mBuffer); 63 glBufferData(GL_ARRAY_BUFFER, numVerts * vertexSize, NULL, GFXGLBufferType[bufferType]); 64} 65 66GFXGLVertexBuffer::~GFXGLVertexBuffer() 67{ 68 // While heavy handed, this does delete the buffer and frees the associated memory. 69 if( mBufferType != GFXBufferTypeVolatile ) 70 glDeleteBuffers(1, &mBuffer); 71 72 if( mZombieCache ) 73 delete [] mZombieCache; 74} 75 76void GFXGLVertexBuffer::lock( U32 vertexStart, U32 vertexEnd, void **vertexPtr ) 77{ 78 PROFILE_SCOPE(GFXGLVertexBuffer_lock); 79 80 if( mBufferType == GFXBufferTypeVolatile ) 81 { 82 AssertFatal(vertexStart == 0, ""); 83 if( GFXGL->mCapabilities.vertexAttributeBinding ) 84 { 85 getCircularVolatileVertexBuffer()->lock( mNumVerts * mVertexSize, 0, mBufferOffset, *vertexPtr ); 86 } 87 else 88 { 89 getCircularVolatileVertexBuffer()->lock( mNumVerts * mVertexSize, mVertexSize, mBufferOffset, *vertexPtr ); 90 mBufferVertexOffset = mBufferOffset / mVertexSize; 91 } 92 } 93 else 94 { 95 mFrameAllocator.lock( mNumVerts * mVertexSize ); 96 97 lockedVertexPtr = (void*)(mFrameAllocator.getlockedPtr() + (vertexStart * mVertexSize)); 98 *vertexPtr = lockedVertexPtr; 99 } 100 101 lockedVertexStart = vertexStart; 102 lockedVertexEnd = vertexEnd; 103} 104 105void GFXGLVertexBuffer::unlock() 106{ 107 PROFILE_SCOPE(GFXGLVertexBuffer_unlock); 108 109 if( mBufferType == GFXBufferTypeVolatile ) 110 { 111 getCircularVolatileVertexBuffer()->unlock(); 112 } 113 else 114 { 115 U32 offset = lockedVertexStart * mVertexSize; 116 U32 length = (lockedVertexEnd - lockedVertexStart) * mVertexSize; 117 118 PRESERVE_VERTEX_BUFFER(); 119 glBindBuffer(GL_ARRAY_BUFFER, mBuffer); 120 121 if( !lockedVertexStart && lockedVertexEnd == mNumVerts) 122 glBufferData(GL_ARRAY_BUFFER, mNumVerts * mVertexSize, NULL, GFXGLBufferType[mBufferType]); // orphan the buffer 123 124 glBufferSubData(GL_ARRAY_BUFFER, offset, length, mFrameAllocator.getlockedPtr() + offset ); 125 126 mFrameAllocator.unlock(); 127 } 128 129 lockedVertexStart = 0; 130 lockedVertexEnd = 0; 131 lockedVertexPtr = NULL; 132} 133 134void GFXGLVertexBuffer::prepare() 135{ 136 AssertFatal(0, "GFXGLVertexBuffer::prepare - use GFXGLVertexBuffer::prepare(U32 stream, U32 divisor)"); 137} 138 139void GFXGLVertexBuffer::prepare(U32 stream, U32 divisor) 140{ 141 if( GFXGL->mCapabilities.vertexAttributeBinding ) 142 { 143 glBindVertexBuffer( stream, mBuffer, mBufferOffset, mVertexSize ); 144 glVertexBindingDivisor( stream, divisor ); 145 return; 146 } 147} 148 149void GFXGLVertexBuffer::finish() 150{ 151 152} 153 154GLvoid* GFXGLVertexBuffer::getBuffer() 155{ 156 // NULL specifies no offset into the hardware buffer 157 return (GLvoid*)NULL; 158} 159 160void GFXGLVertexBuffer::zombify() 161{ 162 if(mZombieCache || !mBuffer) 163 return; 164 165 mZombieCache = new U8[mNumVerts * mVertexSize]; 166 glBindBuffer(GL_ARRAY_BUFFER, mBuffer); 167 glGetBufferSubData(GL_ARRAY_BUFFER, 0, mNumVerts * mVertexSize, mZombieCache); 168 glBindBuffer(GL_ARRAY_BUFFER, 0); 169 glDeleteBuffers(1, &mBuffer); 170 mBuffer = 0; 171} 172 173void GFXGLVertexBuffer::resurrect() 174{ 175 if(!mZombieCache) 176 return; 177 178 glGenBuffers(1, &mBuffer); 179 glBindBuffer(GL_ARRAY_BUFFER, mBuffer); 180 glBufferData(GL_ARRAY_BUFFER, mNumVerts * mVertexSize, mZombieCache, GFXGLBufferType[mBufferType]); 181 glBindBuffer(GL_ARRAY_BUFFER, 0); 182 183 delete[] mZombieCache; 184 mZombieCache = NULL; 185} 186 187namespace 188{ 189 bool onGFXDeviceSignal( GFXDevice::GFXDeviceEventType type ) 190 { 191 if( GFX->getAdapterType() == OpenGL && GFXDevice::deEndOfFrame == type ) 192 getCircularVolatileVertexBuffer()->protectUsedRange(); 193 194 return true; 195 } 196} 197 198MODULE_BEGIN( GFX_GL_VertexBuffer ) 199 MODULE_INIT_AFTER( gfx ) 200 MODULE_SHUTDOWN_BEFORE( gfx ) 201 202 MODULE_INIT 203 { 204 GFXDevice::getDeviceEventSignal().notify( &onGFXDeviceSignal ); 205 } 206 207 MODULE_SHUTDOWN 208 { 209 GFXDevice::getDeviceEventSignal( ).remove( &onGFXDeviceSignal ); 210 } 211MODULE_END 212