Correct Vertex Buffer Usage

Started by
3 comments, last by Namethatnobodyelsetook 16 years, 3 months ago
My questions are targeted at Direct3D 9, although notes an any differences with D3D 10/OpenGL VBOs are appreciated. I am trying to implement a vertex buffer memory allocation scheme based around Heap Layers, if that changes things somehow. Also, I haven't thought about instancing/index buffers so insights on integrating those features would be helpful as well. I'm planning to make I/O asynchronous and multithreaded and all that, so this is how I think vertex buffers will be used: 1) Lock a vertex buffer 2) Pass the mapped memory region to whoever needs it 3) After some amount of time, the memory is written to 4) The vertex buffer is unlocked (probably after the render thread dequeues the request) Now, the questions (correctness and performance info is appreciated): 1) Can I lock multiple vertex buffers at once? (Both static and dynamic VBs) 2) It's possible to lock only part of the VB. Can I lock the same VB multiple times? What if I limit the locks to non-overlapping regions?
Advertisement
1) Sure. Lock as many as you'd like.

2) You can sort of lock part of the VB. If you specify an offset and length to lock, the pointer you receive back will point to that offset instead of the start of the buffer. But...
2a) If the buffer is a static buffer, it doesn't matter where you lock, the whole buffer is considered locked. This may stall the CPU to wait for the GPU even though the GPU and CPU are looking at different parts of the buffer.
2b) If the buffer is dynamic, locking with NOOVERWRITE will lock without stalling, regardless of the offset passed in. It's up to you to correctly offset your write to not interfere with the GPU, either by passing in an offset, or by writing to an address higher than the one returned. Locking with DISCARD will usually lock without stalling, and shouldn't be offset.
2c) Because of reasons I cannot share publically, I'd not recommend locking a subset, and just locking the entire buffer.
2d) I don't think you can lock the same buffer multiple times, as Unlock doesn't take a lock in as an argument... perhaps it does keep a lock count though.

Note your architecture doesn't handle dynamic VBs at all. Passing messages to the renderer with pointers to the data to render can fix that, as long as you can keep everything atomic (so a third thread doesn't interfere). Either by having a single message perform lock, write, unlock, setup, draw, or by having a way to pass multiple messages at once that will be executed in order, and added to your queue atomically.
All the data caching is done at once, and then the shader setup/draw calls are done sequentially so I'm not too worried about race conditions.

If it doesn't impact performance to have lots of vertex buffers locked, I'll try to keep multiple buffers locked for as long as I can during the caching step. (Aside from not being able to render, will it have any other impact on performance?)

Rather than having the standard pointers to data for memcpy(), I have callbacks that will fill a given memory region with vertex data in a specified format.

I'm not sure about handling dynamic data, since the draw calls need to occur before they can be locked with DISCARD (if I'm using the buffers multiple times per frame).
Quote:Original post by Namethatnobodyelsetook
2c) Because of reasons I cannot share publically, I'd not recommend locking a subset, and just locking the entire buffer.

Though I think you're completely right, it's difficult for me to imagine any reason that lets you think that AND isn't suitable for being shared publicly.

I have attended a conference in Montreal where a guy DirectX/Microsoft guy explained that whether you locked partially or totally a dynamic vertex buffer wouldn't matter since internally the whole buffer is locked anyway. this is why in Direct3d 10, the new Lock function (renamed to Map()) does not have th offset/size parameters any more.

JA
Quote:Original post by janta
Quote:Original post by Namethatnobodyelsetook
2c) Because of reasons I cannot share publically, I'd not recommend locking a subset, and just locking the entire buffer.

Though I think you're completely right, it's difficult for me to imagine any reason that lets you think that AND isn't suitable for being shared publicly.
Because it's not up to me to decide what my NDAs cover and don't cover. My particular reason is based upon something NDA. D3D10 compatability may be another good reason. Perhaps OpenGL doesn't support locking a subset, so that's potentially a third reason. I'd guess that my reason won't really affect 99.9% of the users here, but if I can drop a subtle hint to help out the 0.1% of people may help one day, then why not. It's not a big thing to work around anyway. Your engine can take an offset, lock the whole buffer, then offset the pointer D3D gives you before handing back to the app. The rest of your app can think it's still locking at an offset.

This topic is closed to new replies.

Advertisement