diff options
Diffstat (limited to 'linden/indra/llrender/llvertexbuffer.cpp')
-rw-r--r-- | linden/indra/llrender/llvertexbuffer.cpp | 538 |
1 files changed, 273 insertions, 265 deletions
diff --git a/linden/indra/llrender/llvertexbuffer.cpp b/linden/indra/llrender/llvertexbuffer.cpp index d19e885..f3c6997 100644 --- a/linden/indra/llrender/llvertexbuffer.cpp +++ b/linden/indra/llrender/llvertexbuffer.cpp | |||
@@ -31,6 +31,8 @@ | |||
31 | 31 | ||
32 | #include "linden_common.h" | 32 | #include "linden_common.h" |
33 | 33 | ||
34 | #include <boost/static_assert.hpp> | ||
35 | |||
34 | #include "llvertexbuffer.h" | 36 | #include "llvertexbuffer.h" |
35 | // #include "llrender.h" | 37 | // #include "llrender.h" |
36 | #include "llglheaders.h" | 38 | #include "llglheaders.h" |
@@ -40,8 +42,16 @@ | |||
40 | //============================================================================ | 42 | //============================================================================ |
41 | 43 | ||
42 | //static | 44 | //static |
45 | LLVBOPool LLVertexBuffer::sStreamVBOPool; | ||
46 | LLVBOPool LLVertexBuffer::sDynamicVBOPool; | ||
47 | LLVBOPool LLVertexBuffer::sStreamIBOPool; | ||
48 | LLVBOPool LLVertexBuffer::sDynamicIBOPool; | ||
49 | |||
50 | U32 LLVertexBuffer::sBindCount = 0; | ||
51 | U32 LLVertexBuffer::sSetCount = 0; | ||
43 | S32 LLVertexBuffer::sCount = 0; | 52 | S32 LLVertexBuffer::sCount = 0; |
44 | S32 LLVertexBuffer::sGLCount = 0; | 53 | S32 LLVertexBuffer::sGLCount = 0; |
54 | S32 LLVertexBuffer::sMappedCount = 0; | ||
45 | BOOL LLVertexBuffer::sEnableVBOs = TRUE; | 55 | BOOL LLVertexBuffer::sEnableVBOs = TRUE; |
46 | U32 LLVertexBuffer::sGLRenderBuffer = 0; | 56 | U32 LLVertexBuffer::sGLRenderBuffer = 0; |
47 | U32 LLVertexBuffer::sGLRenderIndices = 0; | 57 | U32 LLVertexBuffer::sGLRenderIndices = 0; |
@@ -50,9 +60,9 @@ BOOL LLVertexBuffer::sVBOActive = FALSE; | |||
50 | BOOL LLVertexBuffer::sIBOActive = FALSE; | 60 | BOOL LLVertexBuffer::sIBOActive = FALSE; |
51 | U32 LLVertexBuffer::sAllocatedBytes = 0; | 61 | U32 LLVertexBuffer::sAllocatedBytes = 0; |
52 | BOOL LLVertexBuffer::sRenderActive = FALSE; | 62 | BOOL LLVertexBuffer::sRenderActive = FALSE; |
63 | BOOL LLVertexBuffer::sMapped = FALSE; | ||
53 | 64 | ||
54 | std::vector<U32> LLVertexBuffer::sDeleteList; | 65 | std::vector<U32> LLVertexBuffer::sDeleteList; |
55 | LLVertexBuffer::buffer_list_t LLVertexBuffer::sLockedList; | ||
56 | 66 | ||
57 | S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = | 67 | S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = |
58 | { | 68 | { |
@@ -70,6 +80,10 @@ S32 LLVertexBuffer::sTypeOffsets[LLVertexBuffer::TYPE_MAX] = | |||
70 | void LLVertexBuffer::initClass(bool use_vbo) | 80 | void LLVertexBuffer::initClass(bool use_vbo) |
71 | { | 81 | { |
72 | sEnableVBOs = use_vbo; | 82 | sEnableVBOs = use_vbo; |
83 | LLGLNamePool::registerPool(&sDynamicVBOPool); | ||
84 | LLGLNamePool::registerPool(&sDynamicIBOPool); | ||
85 | LLGLNamePool::registerPool(&sStreamVBOPool); | ||
86 | LLGLNamePool::registerPool(&sStreamIBOPool); | ||
73 | } | 87 | } |
74 | 88 | ||
75 | //static | 89 | //static |
@@ -88,13 +102,13 @@ void LLVertexBuffer::unbind() | |||
88 | 102 | ||
89 | sGLRenderBuffer = 0; | 103 | sGLRenderBuffer = 0; |
90 | sGLRenderIndices = 0; | 104 | sGLRenderIndices = 0; |
105 | sLastMask = 0; | ||
91 | } | 106 | } |
92 | 107 | ||
93 | //static | 108 | //static |
94 | void LLVertexBuffer::cleanupClass() | 109 | void LLVertexBuffer::cleanupClass() |
95 | { | 110 | { |
96 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); | 111 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); |
97 | sLockedList.clear(); | ||
98 | startRender(); | 112 | startRender(); |
99 | stopRender(); | 113 | stopRender(); |
100 | clientCopy(); // deletes GL buffers | 114 | clientCopy(); // deletes GL buffers |
@@ -127,41 +141,8 @@ void LLVertexBuffer::clientCopy(F64 max_time) | |||
127 | { | 141 | { |
128 | if (!sDeleteList.empty()) | 142 | if (!sDeleteList.empty()) |
129 | { | 143 | { |
130 | size_t num = sDeleteList.size(); | ||
131 | glDeleteBuffersARB(sDeleteList.size(), (GLuint*) &(sDeleteList[0])); | 144 | glDeleteBuffersARB(sDeleteList.size(), (GLuint*) &(sDeleteList[0])); |
132 | sDeleteList.clear(); | 145 | sDeleteList.clear(); |
133 | sGLCount -= num; | ||
134 | } | ||
135 | |||
136 | if (sEnableVBOs) | ||
137 | { | ||
138 | LLTimer timer; | ||
139 | BOOL reset = TRUE; | ||
140 | buffer_list_t::iterator iter = sLockedList.begin(); | ||
141 | while(iter != sLockedList.end()) | ||
142 | { | ||
143 | LLVertexBuffer* buffer = *iter; | ||
144 | if (buffer->isLocked() && buffer->useVBOs()) | ||
145 | { | ||
146 | buffer->setBuffer(0); | ||
147 | } | ||
148 | ++iter; | ||
149 | if (reset) | ||
150 | { | ||
151 | reset = FALSE; | ||
152 | timer.reset(); //skip first copy (don't count pipeline stall) | ||
153 | } | ||
154 | else | ||
155 | { | ||
156 | if (timer.getElapsedTimeF64() > max_time) | ||
157 | { | ||
158 | break; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | } | ||
163 | |||
164 | sLockedList.erase(sLockedList.begin(), iter); | ||
165 | } | 146 | } |
166 | } | 147 | } |
167 | 148 | ||
@@ -175,27 +156,40 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : | |||
175 | mFinal(FALSE), | 156 | mFinal(FALSE), |
176 | mFilthy(FALSE), | 157 | mFilthy(FALSE), |
177 | mEmpty(TRUE), | 158 | mEmpty(TRUE), |
178 | mResized(FALSE) | 159 | mResized(FALSE), |
160 | mDynamicSize(FALSE) | ||
179 | { | 161 | { |
180 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); | 162 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); |
181 | if (!sEnableVBOs) | 163 | if (!sEnableVBOs) |
182 | { | 164 | { |
183 | mUsage = GL_STREAM_DRAW_ARB; | 165 | mUsage = 0 ; |
184 | } | 166 | } |
185 | 167 | ||
168 | S32 stride = calcStride(typemask, mOffsets); | ||
169 | |||
170 | mTypeMask = typemask; | ||
171 | mStride = stride; | ||
172 | sCount++; | ||
173 | } | ||
174 | |||
175 | //static | ||
176 | S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets) | ||
177 | { | ||
186 | S32 stride = 0; | 178 | S32 stride = 0; |
187 | for (S32 i=0; i<TYPE_MAX; i++) | 179 | for (S32 i=0; i<TYPE_MAX; i++) |
188 | { | 180 | { |
189 | U32 mask = 1<<i; | 181 | U32 mask = 1<<i; |
190 | if (typemask & mask) | 182 | if (typemask & mask) |
191 | { | 183 | { |
192 | mOffsets[i] = stride; | 184 | if (offsets) |
185 | { | ||
186 | offsets[i] = stride; | ||
187 | } | ||
193 | stride += sTypeOffsets[i]; | 188 | stride += sTypeOffsets[i]; |
194 | } | 189 | } |
195 | } | 190 | } |
196 | mTypeMask = typemask; | 191 | |
197 | mStride = stride; | 192 | return stride; |
198 | sCount++; | ||
199 | } | 193 | } |
200 | 194 | ||
201 | // protected, use unref() | 195 | // protected, use unref() |
@@ -206,23 +200,80 @@ LLVertexBuffer::~LLVertexBuffer() | |||
206 | destroyGLBuffer(); | 200 | destroyGLBuffer(); |
207 | destroyGLIndices(); | 201 | destroyGLIndices(); |
208 | sCount--; | 202 | sCount--; |
209 | |||
210 | if (mLocked) | ||
211 | { | ||
212 | //pull off of locked list | ||
213 | for (buffer_list_t::iterator i = sLockedList.begin(); i != sLockedList.end(); ++i) | ||
214 | { | ||
215 | if (*i == this) | ||
216 | { | ||
217 | sLockedList.erase(i); | ||
218 | break; | ||
219 | } | ||
220 | } | ||
221 | } | ||
222 | }; | 203 | }; |
223 | 204 | ||
224 | //---------------------------------------------------------------------------- | 205 | //---------------------------------------------------------------------------- |
225 | 206 | ||
207 | void LLVertexBuffer::genBuffer() | ||
208 | { | ||
209 | if (mUsage == GL_STREAM_DRAW_ARB) | ||
210 | { | ||
211 | mGLBuffer = sStreamVBOPool.allocate(); | ||
212 | } | ||
213 | else if (mUsage == GL_DYNAMIC_DRAW_ARB) | ||
214 | { | ||
215 | mGLBuffer = sDynamicVBOPool.allocate(); | ||
216 | } | ||
217 | else | ||
218 | { | ||
219 | BOOST_STATIC_ASSERT(sizeof(mGLBuffer) == sizeof(GLuint)); | ||
220 | glGenBuffersARB(1, (GLuint*)&mGLBuffer); | ||
221 | } | ||
222 | sGLCount++; | ||
223 | } | ||
224 | |||
225 | void LLVertexBuffer::genIndices() | ||
226 | { | ||
227 | if (mUsage == GL_STREAM_DRAW_ARB) | ||
228 | { | ||
229 | mGLIndices = sStreamIBOPool.allocate(); | ||
230 | } | ||
231 | else if (mUsage == GL_DYNAMIC_DRAW_ARB) | ||
232 | { | ||
233 | mGLIndices = sDynamicIBOPool.allocate(); | ||
234 | } | ||
235 | else | ||
236 | { | ||
237 | BOOST_STATIC_ASSERT(sizeof(mGLBuffer) == sizeof(GLuint)); | ||
238 | glGenBuffersARB(1, (GLuint*)&mGLIndices); | ||
239 | } | ||
240 | sGLCount++; | ||
241 | } | ||
242 | |||
243 | void LLVertexBuffer::releaseBuffer() | ||
244 | { | ||
245 | if (mUsage == GL_STREAM_DRAW_ARB) | ||
246 | { | ||
247 | sStreamVBOPool.release(mGLBuffer); | ||
248 | } | ||
249 | else if (mUsage == GL_DYNAMIC_DRAW_ARB) | ||
250 | { | ||
251 | sDynamicVBOPool.release(mGLBuffer); | ||
252 | } | ||
253 | else | ||
254 | { | ||
255 | sDeleteList.push_back(mGLBuffer); | ||
256 | } | ||
257 | sGLCount--; | ||
258 | } | ||
259 | |||
260 | void LLVertexBuffer::releaseIndices() | ||
261 | { | ||
262 | if (mUsage == GL_STREAM_DRAW_ARB) | ||
263 | { | ||
264 | sStreamIBOPool.release(mGLIndices); | ||
265 | } | ||
266 | else if (mUsage == GL_DYNAMIC_DRAW_ARB) | ||
267 | { | ||
268 | sDynamicIBOPool.release(mGLIndices); | ||
269 | } | ||
270 | else | ||
271 | { | ||
272 | sDeleteList.push_back(mGLIndices); | ||
273 | } | ||
274 | sGLCount--; | ||
275 | } | ||
276 | |||
226 | void LLVertexBuffer::createGLBuffer() | 277 | void LLVertexBuffer::createGLBuffer() |
227 | { | 278 | { |
228 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); | 279 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); |
@@ -238,20 +289,20 @@ void LLVertexBuffer::createGLBuffer() | |||
238 | return; | 289 | return; |
239 | } | 290 | } |
240 | 291 | ||
241 | mMappedData = new U8[size]; | ||
242 | memset(mMappedData, 0, size); | ||
243 | mEmpty = TRUE; | 292 | mEmpty = TRUE; |
244 | 293 | ||
245 | if (useVBOs()) | 294 | if (useVBOs()) |
246 | { | 295 | { |
247 | glGenBuffersARB(1, (GLuint*) &mGLBuffer); | 296 | mMappedData = NULL; |
297 | genBuffer(); | ||
248 | mResized = TRUE; | 298 | mResized = TRUE; |
249 | sGLCount++; | ||
250 | } | 299 | } |
251 | else | 300 | else |
252 | { | 301 | { |
253 | static int gl_buffer_idx = 0; | 302 | static int gl_buffer_idx = 0; |
254 | mGLBuffer = ++gl_buffer_idx; | 303 | mGLBuffer = ++gl_buffer_idx; |
304 | mMappedData = new U8[size]; | ||
305 | memset(mMappedData, 0, size); | ||
255 | } | 306 | } |
256 | } | 307 | } |
257 | 308 | ||
@@ -270,18 +321,18 @@ void LLVertexBuffer::createGLIndices() | |||
270 | return; | 321 | return; |
271 | } | 322 | } |
272 | 323 | ||
273 | mMappedIndexData = new U8[size]; | ||
274 | memset(mMappedIndexData, 0, size); | ||
275 | mEmpty = TRUE; | 324 | mEmpty = TRUE; |
276 | 325 | ||
277 | if (useVBOs()) | 326 | if (useVBOs()) |
278 | { | 327 | { |
279 | glGenBuffersARB(1, (GLuint*) &mGLIndices); | 328 | mMappedIndexData = NULL; |
329 | genIndices(); | ||
280 | mResized = TRUE; | 330 | mResized = TRUE; |
281 | sGLCount++; | ||
282 | } | 331 | } |
283 | else | 332 | else |
284 | { | 333 | { |
334 | mMappedIndexData = new U8[size]; | ||
335 | memset(mMappedIndexData, 0, size); | ||
285 | static int gl_buffer_idx = 0; | 336 | static int gl_buffer_idx = 0; |
286 | mGLIndices = ++gl_buffer_idx; | 337 | mGLIndices = ++gl_buffer_idx; |
287 | } | 338 | } |
@@ -294,12 +345,19 @@ void LLVertexBuffer::destroyGLBuffer() | |||
294 | { | 345 | { |
295 | if (useVBOs()) | 346 | if (useVBOs()) |
296 | { | 347 | { |
297 | sDeleteList.push_back(mGLBuffer); | 348 | if (mMappedData || mMappedIndexData) |
349 | { | ||
350 | llerrs << "Vertex buffer destroyed while mapped!" << llendl; | ||
351 | } | ||
352 | releaseBuffer(); | ||
353 | } | ||
354 | else | ||
355 | { | ||
356 | delete [] mMappedData; | ||
357 | mMappedData = NULL; | ||
358 | mEmpty = TRUE; | ||
298 | } | 359 | } |
299 | 360 | ||
300 | delete [] mMappedData; | ||
301 | mMappedData = NULL; | ||
302 | mEmpty = TRUE; | ||
303 | sAllocatedBytes -= getSize(); | 361 | sAllocatedBytes -= getSize(); |
304 | } | 362 | } |
305 | 363 | ||
@@ -313,12 +371,19 @@ void LLVertexBuffer::destroyGLIndices() | |||
313 | { | 371 | { |
314 | if (useVBOs()) | 372 | if (useVBOs()) |
315 | { | 373 | { |
316 | sDeleteList.push_back(mGLIndices); | 374 | if (mMappedData || mMappedIndexData) |
375 | { | ||
376 | llerrs << "Vertex buffer destroyed while mapped." << llendl; | ||
377 | } | ||
378 | releaseIndices(); | ||
379 | } | ||
380 | else | ||
381 | { | ||
382 | delete [] mMappedIndexData; | ||
383 | mMappedIndexData = NULL; | ||
384 | mEmpty = TRUE; | ||
317 | } | 385 | } |
318 | 386 | ||
319 | delete [] mMappedIndexData; | ||
320 | mMappedIndexData = NULL; | ||
321 | mEmpty = TRUE; | ||
322 | sAllocatedBytes -= getIndicesSize(); | 387 | sAllocatedBytes -= getIndicesSize(); |
323 | } | 388 | } |
324 | 389 | ||
@@ -328,6 +393,15 @@ void LLVertexBuffer::destroyGLIndices() | |||
328 | void LLVertexBuffer::updateNumVerts(S32 nverts) | 393 | void LLVertexBuffer::updateNumVerts(S32 nverts) |
329 | { | 394 | { |
330 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); | 395 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); |
396 | |||
397 | if (nverts >= 65535) | ||
398 | { | ||
399 | llwarns << "Vertex buffer overflow!" << llendl; | ||
400 | nverts = 65535; | ||
401 | } | ||
402 | |||
403 | mRequestedNumVerts = nverts; | ||
404 | |||
331 | if (!mDynamicSize) | 405 | if (!mDynamicSize) |
332 | { | 406 | { |
333 | mNumVerts = nverts; | 407 | mNumVerts = nverts; |
@@ -336,18 +410,19 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) | |||
336 | nverts > mNumVerts || | 410 | nverts > mNumVerts || |
337 | nverts < mNumVerts/2) | 411 | nverts < mNumVerts/2) |
338 | { | 412 | { |
339 | if (mUsage != GL_STATIC_DRAW_ARB) | 413 | if (mUsage != GL_STATIC_DRAW_ARB && nverts + nverts/4 <= 65535) |
340 | { | 414 | { |
341 | nverts += nverts/4; | 415 | nverts += nverts/4; |
342 | } | 416 | } |
343 | |||
344 | mNumVerts = nverts; | 417 | mNumVerts = nverts; |
345 | } | 418 | } |
419 | |||
346 | } | 420 | } |
347 | 421 | ||
348 | void LLVertexBuffer::updateNumIndices(S32 nindices) | 422 | void LLVertexBuffer::updateNumIndices(S32 nindices) |
349 | { | 423 | { |
350 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); | 424 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); |
425 | mRequestedNumIndices = nindices; | ||
351 | if (!mDynamicSize) | 426 | if (!mDynamicSize) |
352 | { | 427 | { |
353 | mNumIndices = nindices; | 428 | mNumIndices = nindices; |
@@ -365,54 +440,6 @@ void LLVertexBuffer::updateNumIndices(S32 nindices) | |||
365 | } | 440 | } |
366 | } | 441 | } |
367 | 442 | ||
368 | void LLVertexBuffer::makeStatic() | ||
369 | { | ||
370 | if (!sEnableVBOs) | ||
371 | { | ||
372 | return; | ||
373 | } | ||
374 | |||
375 | if (sRenderActive) | ||
376 | { | ||
377 | llerrs << "Make static called during render." << llendl; | ||
378 | } | ||
379 | |||
380 | if (mUsage != GL_STATIC_DRAW_ARB) | ||
381 | { | ||
382 | if (useVBOs()) | ||
383 | { | ||
384 | if (mGLBuffer) | ||
385 | { | ||
386 | sDeleteList.push_back(mGLBuffer); | ||
387 | } | ||
388 | if (mGLIndices) | ||
389 | { | ||
390 | sDeleteList.push_back(mGLIndices); | ||
391 | } | ||
392 | } | ||
393 | |||
394 | if (mGLBuffer) | ||
395 | { | ||
396 | sGLCount++; | ||
397 | glGenBuffersARB(1, (GLuint*) &mGLBuffer); | ||
398 | } | ||
399 | if (mGLIndices) | ||
400 | { | ||
401 | sGLCount++; | ||
402 | glGenBuffersARB(1, (GLuint*) &mGLIndices); | ||
403 | } | ||
404 | |||
405 | mUsage = GL_STATIC_DRAW_ARB; | ||
406 | mResized = TRUE; | ||
407 | |||
408 | if (!mLocked) | ||
409 | { | ||
410 | mLocked = TRUE; | ||
411 | sLockedList.push_back(this); | ||
412 | } | ||
413 | } | ||
414 | } | ||
415 | |||
416 | void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) | 443 | void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) |
417 | { | 444 | { |
418 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); | 445 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); |
@@ -435,6 +462,9 @@ void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) | |||
435 | 462 | ||
436 | void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) | 463 | void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) |
437 | { | 464 | { |
465 | mRequestedNumVerts = newnverts; | ||
466 | mRequestedNumIndices = newnindices; | ||
467 | |||
438 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); | 468 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); |
439 | mDynamicSize = TRUE; | 469 | mDynamicSize = TRUE; |
440 | if (mUsage == GL_STATIC_DRAW_ARB) | 470 | if (mUsage == GL_STATIC_DRAW_ARB) |
@@ -469,22 +499,25 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) | |||
469 | else | 499 | else |
470 | { | 500 | { |
471 | //delete old buffer, keep GL buffer for now | 501 | //delete old buffer, keep GL buffer for now |
472 | U8* old = mMappedData; | 502 | if (!useVBOs()) |
473 | mMappedData = new U8[newsize]; | 503 | { |
474 | if (old) | 504 | U8* old = mMappedData; |
475 | { | 505 | mMappedData = new U8[newsize]; |
476 | memcpy(mMappedData, old, llmin(newsize, oldsize)); | 506 | if (old) |
477 | if (newsize > oldsize) | 507 | { |
508 | memcpy(mMappedData, old, llmin(newsize, oldsize)); | ||
509 | if (newsize > oldsize) | ||
510 | { | ||
511 | memset(mMappedData+oldsize, 0, newsize-oldsize); | ||
512 | } | ||
513 | |||
514 | delete [] old; | ||
515 | } | ||
516 | else | ||
478 | { | 517 | { |
479 | memset(mMappedData+oldsize, 0, newsize-oldsize); | 518 | memset(mMappedData, 0, newsize); |
519 | mEmpty = TRUE; | ||
480 | } | 520 | } |
481 | |||
482 | delete [] old; | ||
483 | } | ||
484 | else | ||
485 | { | ||
486 | memset(mMappedData, 0, newsize); | ||
487 | mEmpty = TRUE; | ||
488 | } | 521 | } |
489 | mResized = TRUE; | 522 | mResized = TRUE; |
490 | } | 523 | } |
@@ -502,22 +535,26 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) | |||
502 | } | 535 | } |
503 | else | 536 | else |
504 | { | 537 | { |
505 | //delete old buffer, keep GL buffer for now | 538 | if (!useVBOs()) |
506 | U8* old = mMappedIndexData; | 539 | { |
507 | mMappedIndexData = new U8[new_index_size]; | 540 | //delete old buffer, keep GL buffer for now |
508 | if (old) | 541 | U8* old = mMappedIndexData; |
509 | { | 542 | mMappedIndexData = new U8[new_index_size]; |
510 | memcpy(mMappedIndexData, old, llmin(new_index_size, old_index_size)); | 543 | |
511 | if (new_index_size > old_index_size) | 544 | if (old) |
545 | { | ||
546 | memcpy(mMappedIndexData, old, llmin(new_index_size, old_index_size)); | ||
547 | if (new_index_size > old_index_size) | ||
548 | { | ||
549 | memset(mMappedIndexData+old_index_size, 0, new_index_size - old_index_size); | ||
550 | } | ||
551 | delete [] old; | ||
552 | } | ||
553 | else | ||
512 | { | 554 | { |
513 | memset(mMappedIndexData+old_index_size, 0, new_index_size - old_index_size); | 555 | memset(mMappedIndexData, 0, new_index_size); |
556 | mEmpty = TRUE; | ||
514 | } | 557 | } |
515 | delete [] old; | ||
516 | } | ||
517 | else | ||
518 | { | ||
519 | memset(mMappedIndexData, 0, new_index_size); | ||
520 | mEmpty = TRUE; | ||
521 | } | 558 | } |
522 | mResized = TRUE; | 559 | mResized = TRUE; |
523 | } | 560 | } |
@@ -527,18 +564,29 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) | |||
527 | destroyGLIndices(); | 564 | destroyGLIndices(); |
528 | } | 565 | } |
529 | } | 566 | } |
567 | |||
568 | if (mResized && useVBOs()) | ||
569 | { | ||
570 | setBuffer(0); | ||
571 | } | ||
530 | } | 572 | } |
531 | 573 | ||
532 | BOOL LLVertexBuffer::useVBOs() const | 574 | BOOL LLVertexBuffer::useVBOs() const |
533 | { | 575 | { |
534 | //it's generally ineffective to use VBO for things that are streaming | 576 | //it's generally ineffective to use VBO for things that are streaming on apple |
535 | //when we already have a client buffer around | 577 | |
536 | if (mUsage == GL_STREAM_DRAW_ARB) | 578 | #if LL_DARWIN |
579 | if (!mUsage || mUsage == GL_STREAM_DRAW_ARB) | ||
537 | { | 580 | { |
538 | return FALSE; | 581 | return FALSE; |
539 | } | 582 | } |
540 | 583 | #else | |
541 | return sEnableVBOs && (!sRenderActive || !mLocked); | 584 | if (!mUsage) |
585 | { | ||
586 | return FALSE; | ||
587 | } | ||
588 | #endif | ||
589 | return sEnableVBOs; // && (!sRenderActive || !mLocked); | ||
542 | } | 590 | } |
543 | 591 | ||
544 | //---------------------------------------------------------------------------- | 592 | //---------------------------------------------------------------------------- |
@@ -547,27 +595,27 @@ BOOL LLVertexBuffer::useVBOs() const | |||
547 | U8* LLVertexBuffer::mapBuffer(S32 access) | 595 | U8* LLVertexBuffer::mapBuffer(S32 access) |
548 | { | 596 | { |
549 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); | 597 | LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); |
550 | if (sRenderActive) | ||
551 | { | ||
552 | llwarns << "Buffer mapped during render frame!" << llendl; | ||
553 | } | ||
554 | if (!mGLBuffer && !mGLIndices) | ||
555 | { | ||
556 | llerrs << "LLVertexBuffer::mapBuffer() called before createGLBuffer" << llendl; | ||
557 | } | ||
558 | if (mFinal) | 598 | if (mFinal) |
559 | { | 599 | { |
560 | llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl; | 600 | llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl; |
561 | } | 601 | } |
562 | if (!mMappedData && !mMappedIndexData) | 602 | if (!useVBOs() && !mMappedData && !mMappedIndexData) |
563 | { | 603 | { |
564 | llerrs << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl; | 604 | llerrs << "LLVertexBuffer::mapBuffer() called on unallocated buffer." << llendl; |
565 | } | 605 | } |
566 | 606 | ||
567 | if (!mLocked && useVBOs()) | 607 | if (!mLocked && useVBOs()) |
568 | { | 608 | { |
609 | setBuffer(0); | ||
569 | mLocked = TRUE; | 610 | mLocked = TRUE; |
570 | sLockedList.push_back(this); | 611 | mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); |
612 | mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); | ||
613 | /*if (sMapped) | ||
614 | { | ||
615 | llerrs << "Mapped two VBOs at the same time!" << llendl; | ||
616 | } | ||
617 | sMapped = TRUE;*/ | ||
618 | sMappedCount++; | ||
571 | } | 619 | } |
572 | 620 | ||
573 | return mMappedData; | 621 | return mMappedData; |
@@ -580,64 +628,19 @@ void LLVertexBuffer::unmapBuffer() | |||
580 | { | 628 | { |
581 | if (useVBOs() && mLocked) | 629 | if (useVBOs() && mLocked) |
582 | { | 630 | { |
583 | if (mGLBuffer) | 631 | glUnmapBufferARB(GL_ARRAY_BUFFER_ARB); |
584 | { | 632 | glUnmapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB); |
585 | if (mResized) | 633 | |
586 | { | 634 | /*if (!sMapped) |
587 | glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), mMappedData, mUsage); | ||
588 | } | ||
589 | else | ||
590 | { | ||
591 | if (mEmpty || mDirtyRegions.empty()) | ||
592 | { | ||
593 | glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, getSize(), mMappedData); | ||
594 | } | ||
595 | else | ||
596 | { | ||
597 | for (std::vector<DirtyRegion>::iterator i = mDirtyRegions.begin(); i != mDirtyRegions.end(); ++i) | ||
598 | { | ||
599 | DirtyRegion& region = *i; | ||
600 | glBufferSubDataARB(GL_ARRAY_BUFFER_ARB, region.mIndex*mStride, region.mCount*mStride, mMappedData + region.mIndex*mStride); | ||
601 | } | ||
602 | } | ||
603 | } | ||
604 | } | ||
605 | |||
606 | if (mGLIndices) | ||
607 | { | 635 | { |
608 | if (mResized) | 636 | llerrs << "Redundantly unmapped VBO!" << llendl; |
609 | { | ||
610 | glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), mMappedIndexData, mUsage); | ||
611 | } | ||
612 | else | ||
613 | { | ||
614 | if (mEmpty || mDirtyRegions.empty()) | ||
615 | { | ||
616 | glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0, getIndicesSize(), mMappedIndexData); | ||
617 | } | ||
618 | else | ||
619 | { | ||
620 | for (std::vector<DirtyRegion>::iterator i = mDirtyRegions.begin(); i != mDirtyRegions.end(); ++i) | ||
621 | { | ||
622 | DirtyRegion& region = *i; | ||
623 | glBufferSubDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, region.mIndicesIndex*sizeof(U32), | ||
624 | region.mIndicesCount*sizeof(U32), mMappedIndexData + region.mIndicesIndex*sizeof(U32)); | ||
625 | } | ||
626 | } | ||
627 | } | ||
628 | } | 637 | } |
629 | 638 | sMapped = FALSE;*/ | |
630 | mDirtyRegions.clear(); | 639 | sMappedCount--; |
631 | mFilthy = FALSE; | ||
632 | mResized = FALSE; | ||
633 | 640 | ||
634 | if (mUsage == GL_STATIC_DRAW_ARB) | 641 | if (mUsage == GL_STATIC_DRAW_ARB) |
635 | { //static draw buffers can only be mapped a single time | 642 | { //static draw buffers can only be mapped a single time |
636 | //throw out client data (we won't be using it again) | 643 | //throw out client data (we won't be using it again) |
637 | delete [] mMappedData; | ||
638 | delete [] mMappedIndexData; | ||
639 | mMappedIndexData = NULL; | ||
640 | mMappedData = NULL; | ||
641 | mEmpty = TRUE; | 644 | mEmpty = TRUE; |
642 | mFinal = TRUE; | 645 | mFinal = TRUE; |
643 | } | 646 | } |
@@ -645,10 +648,11 @@ void LLVertexBuffer::unmapBuffer() | |||
645 | { | 648 | { |
646 | mEmpty = FALSE; | 649 | mEmpty = FALSE; |
647 | } | 650 | } |
651 | |||
652 | mMappedIndexData = NULL; | ||
653 | mMappedData = NULL; | ||
648 | 654 | ||
649 | mLocked = FALSE; | 655 | mLocked = FALSE; |
650 | |||
651 | glFlush(); | ||
652 | } | 656 | } |
653 | } | 657 | } |
654 | } | 658 | } |
@@ -690,9 +694,9 @@ bool LLVertexBuffer::getVertexStrider(LLStrider<LLVector3>& strider, S32 index) | |||
690 | { | 694 | { |
691 | return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index); | 695 | return VertexBufferStrider<LLVector3,TYPE_VERTEX>::get(*this, strider, index); |
692 | } | 696 | } |
693 | bool LLVertexBuffer::getIndexStrider(LLStrider<U32>& strider, S32 index) | 697 | bool LLVertexBuffer::getIndexStrider(LLStrider<U16>& strider, S32 index) |
694 | { | 698 | { |
695 | return VertexBufferStrider<U32,TYPE_INDEX>::get(*this, strider, index); | 699 | return VertexBufferStrider<U16,TYPE_INDEX>::get(*this, strider, index); |
696 | } | 700 | } |
697 | bool LLVertexBuffer::getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index) | 701 | bool LLVertexBuffer::getTexCoordStrider(LLStrider<LLVector2>& strider, S32 index) |
698 | { | 702 | { |
@@ -755,16 +759,46 @@ void LLVertexBuffer::setBuffer(U32 data_mask) | |||
755 | { | 759 | { |
756 | if (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive)) | 760 | if (mGLBuffer && (mGLBuffer != sGLRenderBuffer || !sVBOActive)) |
757 | { | 761 | { |
762 | /*if (sMapped) | ||
763 | { | ||
764 | llerrs << "VBO bound while another VBO mapped!" << llendl; | ||
765 | }*/ | ||
758 | glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer); | 766 | glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer); |
767 | sBindCount++; | ||
759 | sVBOActive = TRUE; | 768 | sVBOActive = TRUE; |
760 | setup = TRUE; // ... or the bound buffer changed | 769 | setup = TRUE; // ... or the bound buffer changed |
761 | } | 770 | } |
762 | if (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive)) | 771 | if (mGLIndices && (mGLIndices != sGLRenderIndices || !sIBOActive)) |
763 | { | 772 | { |
773 | /*if (sMapped) | ||
774 | { | ||
775 | llerrs << "VBO bound while another VBO mapped!" << llendl; | ||
776 | }*/ | ||
764 | glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices); | 777 | glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices); |
778 | sBindCount++; | ||
765 | sIBOActive = TRUE; | 779 | sIBOActive = TRUE; |
766 | } | 780 | } |
767 | 781 | ||
782 | if (mResized) | ||
783 | { | ||
784 | if (mGLBuffer) | ||
785 | { | ||
786 | glBufferDataARB(GL_ARRAY_BUFFER_ARB, getSize(), NULL, mUsage); | ||
787 | } | ||
788 | if (mGLIndices) | ||
789 | { | ||
790 | glBufferDataARB(GL_ELEMENT_ARRAY_BUFFER_ARB, getIndicesSize(), NULL, mUsage); | ||
791 | } | ||
792 | |||
793 | mEmpty = TRUE; | ||
794 | mResized = FALSE; | ||
795 | |||
796 | if (data_mask != 0) | ||
797 | { | ||
798 | llerrs << "Buffer set for rendering before being filled after resize." << llendl; | ||
799 | } | ||
800 | } | ||
801 | |||
768 | unmapBuffer(); | 802 | unmapBuffer(); |
769 | } | 803 | } |
770 | else | 804 | else |
@@ -774,6 +808,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask) | |||
774 | if (sEnableVBOs && sVBOActive) | 808 | if (sEnableVBOs && sVBOActive) |
775 | { | 809 | { |
776 | glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); | 810 | glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); |
811 | sBindCount++; | ||
777 | sVBOActive = FALSE; | 812 | sVBOActive = FALSE; |
778 | setup = TRUE; // ... or a VBO is deactivated | 813 | setup = TRUE; // ... or a VBO is deactivated |
779 | } | 814 | } |
@@ -784,7 +819,12 @@ void LLVertexBuffer::setBuffer(U32 data_mask) | |||
784 | } | 819 | } |
785 | if (sEnableVBOs && mGLIndices && sIBOActive) | 820 | if (sEnableVBOs && mGLIndices && sIBOActive) |
786 | { | 821 | { |
822 | /*if (sMapped) | ||
823 | { | ||
824 | llerrs << "VBO unbound while potentially mapped!" << llendl; | ||
825 | }*/ | ||
787 | glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); | 826 | glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); |
827 | sBindCount++; | ||
788 | sIBOActive = FALSE; | 828 | sIBOActive = FALSE; |
789 | } | 829 | } |
790 | } | 830 | } |
@@ -803,9 +843,11 @@ void LLVertexBuffer::setBuffer(U32 data_mask) | |||
803 | llwarns << "Vertex buffer set for rendering outside of render frame." << llendl; | 843 | llwarns << "Vertex buffer set for rendering outside of render frame." << llendl; |
804 | } | 844 | } |
805 | setupVertexBuffer(data_mask); // subclass specific setup (virtual function) | 845 | setupVertexBuffer(data_mask); // subclass specific setup (virtual function) |
806 | sLastMask = data_mask; | 846 | sSetCount++; |
807 | } | 847 | } |
808 | } | 848 | } |
849 | |||
850 | sLastMask = data_mask; | ||
809 | } | 851 | } |
810 | 852 | ||
811 | // virtual (default) | 853 | // virtual (default) |
@@ -821,10 +863,6 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const | |||
821 | llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; | 863 | llerrs << "LLVertexBuffer::setupVertexBuffer missing required components for supplied data mask." << llendl; |
822 | } | 864 | } |
823 | 865 | ||
824 | if (data_mask & MAP_VERTEX) | ||
825 | { | ||
826 | glVertexPointer(3,GL_FLOAT, stride, (void*)(base + 0)); | ||
827 | } | ||
828 | if (data_mask & MAP_NORMAL) | 866 | if (data_mask & MAP_NORMAL) |
829 | { | 867 | { |
830 | glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL])); | 868 | glNormalPointer(GL_FLOAT, stride, (void*)(base + mOffsets[TYPE_NORMAL])); |
@@ -855,49 +893,19 @@ void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const | |||
855 | { | 893 | { |
856 | glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, stride, (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); | 894 | glVertexAttribPointerARB(4, 4, GL_FLOAT, TRUE, stride, (void*)(base + mOffsets[TYPE_CLOTHWEIGHT])); |
857 | } | 895 | } |
896 | if (data_mask & MAP_VERTEX) | ||
897 | { | ||
898 | glVertexPointer(3,GL_FLOAT, stride, (void*)(base + 0)); | ||
899 | } | ||
858 | 900 | ||
859 | llglassertok(); | 901 | llglassertok(); |
860 | } | 902 | } |
861 | 903 | ||
862 | void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count) | 904 | void LLVertexBuffer::markDirty(U32 vert_index, U32 vert_count, U32 indices_index, U32 indices_count) |
863 | { | 905 | { |
864 | if (useVBOs() && !mFilthy) | 906 | // TODO: use GL_APPLE_flush_buffer_range here |
865 | { | 907 | /*if (useVBOs() && !mFilthy) |
866 | if (!mDirtyRegions.empty()) | ||
867 | { | ||
868 | DirtyRegion& region = *(mDirtyRegions.rbegin()); | ||
869 | |||
870 | if (region.mIndex+region.mCount > vert_index) | ||
871 | { | ||
872 | //this buffer has received multiple updates since the last copy, mark it filthy | ||
873 | mFilthy = TRUE; | ||
874 | mDirtyRegions.clear(); | ||
875 | return; | ||
876 | } | ||
877 | |||
878 | if (region.mIndex + region.mCount == vert_index && | ||
879 | region.mIndicesIndex + region.mIndicesCount == indices_index) | ||
880 | { | ||
881 | region.mCount += vert_count; | ||
882 | region.mIndicesCount += indices_count; | ||
883 | return; | ||
884 | } | ||
885 | } | ||
886 | |||
887 | mDirtyRegions.push_back(DirtyRegion(vert_index,vert_count,indices_index,indices_count)); | ||
888 | } | ||
889 | } | ||
890 | |||
891 | void LLVertexBuffer::markClean() | ||
892 | { | ||
893 | if (!mResized && !mEmpty && !mFilthy) | ||
894 | { | 908 | { |
895 | buffer_list_t::reverse_iterator iter = sLockedList.rbegin(); | 909 | |
896 | if (*iter == this) | 910 | }*/ |
897 | { | ||
898 | mLocked = FALSE; | ||
899 | sLockedList.pop_back(); | ||
900 | } | ||
901 | } | ||
902 | } | 911 | } |
903 | |||