I am having a really strange issue with my render function. I currently created a spritebatcher that renders great until you go over the array size for the vertex buffer.
I currently have it set up where if you draw more primitives than the array can handle it will call the endBatch function. Which sets up everything for rendering, renders everything in the vertex buffer, and then resets the counts on the rendering items (number of shapes to draw, number of vertices, etc).
My issue is that if the max vertex count is met perfectly everything renders just fine. But if I go over the max vertex count, all of my drawn objects flicker or flash extremely fast. Like one only sprite is being drawn and it is warping to all of the locations.
Can someone please help me to figure out why this is happening. Currently my max on my vertex array is 4 (debug purposes) and I am attempting to draw 3 sprites. If you comment out 2 of the draw calls in the render function in the main.cpp file the sprite renders fine (no flickering). Otherwise my issue above happens
[+]----------------------------------[ Original Problem Solved! ]
Current Code -
main.cpp : http://pastebin.com/m7N7Y2e0
SpriteBatcher.h : http://pastebin.com/wGMJ8Wv0
SpriteBatcher.cpp : http://pastebin.com/SPdm1yfX
[+]----------------------------------[ Current topic making a better batcher! ]
You are kinda on the right track with the sprite batch, but there are some concepts that have been missed. Although I haven't done this in DX9, I have in DX10 and DX11 and conceptually I would imagine it is the same in DX9.
You don't want your sprite batch calling Present. It currently is doing this. This definitely will cause some flickering since you will only partially draw your sprites in each frame.
Should be more like:
- Clear back buffer.
- Draw sprites, as many as you want.
- Present (from somewhere outside the spritebatch when you know nothing else will be rendered).
In your SpriteBatch you should create dynamic vertex and index buffers. The key here is to make them dynamic. You are currently creating new buffers each time endBatch is called which I would imagine is slow if you do it a lot. I didn't see them cleaned up either, but I didn't look through all of the code.
Your sprite batch needs a buffer to track your queued up quads and also needs to keep track of the last position your wrote to in the dynamic buffers. When your local buffer is full, you need to get a lock on the dynamic buffers, write your new vertex and index data to wherever you left off, release the lock, then DrawIndex (whatever the DX9 equivalent is) giving the offset into your dynamic buffer that you just wrote new data to.
When you lock the dynamic buffers you want to use lock flags to let the api know what your intentions are. If you are still filling up the dynamic buffer use D3DLOCK_NOOVERWRITE and you are promising you are not going to overwrite any data that has already been submitted and might currently be drawing. Technically, I think you CAN overwrite if you want, but you'll mess things up and probably see it. Pretty sure if you don't lock it with this flag you wait until the gpu is done drawing the contents before you get the lock (bad/slow).
If you are towards the end of your dynamic buffer, you want to specify the DISCARD flag. This returns you a pointer that you can start filling from the top again. If the gpu is still processing data you already submitted you get a new pointer here. Point is, you don't have to care whether the gpu is done with it or not, if you say DISCARD you get a pointer that is valid to write to from the top.
Process is something like this:
- Take lock on buffers:
- Full or Almost full, use DISCARD
- Plenty of room left, use NOOVERWRITE
- Add vertex/index data to buffers.
- Release lock.
- DrawIndexed
You probably want your own list of quads in your sprite batch rather than directly writing them to the dynamic buffers. This lets you sort later on down the road if you need to. Fill up internal list of quads via your draw calls, call EndBatch, sort your list by image (or whatever causes a state change), fill dynamic buffers (possibly multiple lock/fill/unlock/DrawIndex).
You will need to consider how you sort, or if you sort, quads if you batch them up like I mentioned. If your quads are drawn in an order-dependent manner (some have to be on top of others), then sorting by image alone isn't enough. You'll have to decide what forces your sprite batch to submit new quads.