Dynamic Vertex Buffers

BlitzMax Forums/BlitzMax Programming/Dynamic Vertex Buffers

HrdNutz(Posted 2008) [#1]
Hi,
Im really flaky with DirectX, but maybe someone can help me figure out major differences between dx7 and 8 in terms of vertex buffer implementation?

I'm trying to implement a vertex cache class, and looking at old DX8 code I could create a vertex buffer with DYNAMIC flag to speed up uploading that buffer to video every frame, to be used for all dynamic geometry.

This is what dx8 flags look like:

pDevice->CreateVertexBuffer(maxVerts*stride, D3DUSAGE_DYNAMIC|D3DUSAGE_WRITEONLY|PROCESSING,
FVF,D3DPOOL_DEFAULT,&vBuf);

I have this working for dx7 now in Blitz, but I cant find the dynamic flag :/

desc.dwCaps = D3DVBCAPS_WRITEONLY
D3D7GraphicsDriver().Direct3D7().CreateVertexBuffer(desc , Varptr(VB) , 0)

How do i make sure my dx7 vertex buffer is in system memory and gets best options for dynamic access?

Would using DrawPrimitiveUP and passing array be any better than updating the vertex buffer and calling DrawPrimitiveVB?

Maybe someone has a pointer in a direction of some dx7 optimized rendering sources, I would really appreciate that.

TIA


Dreamora(Posted 2008) [#2]
DX7 lacks many of this features. DX8+ got the "highly optimized vertex pipeline" features ...

Not sure if you can make DX7 vertexbuffers even non-system RAM based as they have no hardware processing at all


tonyg(Posted 2008) [#3]
Could this help?


HrdNutz(Posted 2008) [#4]
Dug up DX7 docs and found system memory flag, but nothing about dynamic, optimized flag makes app crash :*

Here is something I whipped up just now, it's not optimized or anything, but it works :D Even in this state there is some boost, drawing 12,000 sprites went to 300 fps using cache from 90 using DrawImage.

An object which accumulates quads until it runs out of vertex space, then flushes the array whole. One thing to note is there is no image being used, for simplicity right now i just insert a DrawImage somewhere before so dx uploads a texture, which gets used for all the cached vertices.

Needs work, but there is potential. If sorted by texture, one could achieve greater performance if big chunks of geometry can be sent in few calls. This object can also be extended to function as static VB. Another thing to note is transformations would have to be done manually before adding data to the buffer, as the whole vertex buffer gets rendered with same world transform.

Init code
vc:TVCache = new TVCache
vc.Init()

Render code
DrawImage someImage, 1000, 1000 ' temporary texture fix
vc.Begin()
' loop
 vc.AddQuad(x, y, width, height)
' next
vc.Flush()


And heres the vertex cache in its rudimentary form

Type TVCache	
	Field VB:IDirect3DVertexBuffer7	
	Field maxVerts:Int = 24000
	Field curVert:Int
	Field vCache:TVertex[maxVerts]
	Field pVerts : Float Ptr
	Field Flushed = True	
	Method Init()
		Local desc:D3DVERTEXBUFFERDESC = New D3DVERTEXBUFFERDESC
		desc.dwSize =SizeOf(desc)
		desc.dwNumVertices = maxVerts
		desc.dwFVF = D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_TEX1 
		desc.dwCaps = 0	
		desc.dwCaps = D3DVBCAPS_WRITEONLY | D3DVBCAPS_SYSTEMMEMORY
		D3D7GraphicsDriver().Direct3D7().CreateVertexBuffer(desc,Varptr(VB),0)
		For Local i = 0 To maxVerts - 1
			vCache[i] = New TVertex
		Next
	End Method
	Method AddQuad(x:Float , y:Float , w:Float , h:Float)
		If Flushed = True Then Begin()
		Local of = 6
		
		pVerts[curVert*of+0] = x
		pVerts[curVert*of+1] = y
		pVerts[curVert*of+2] = 0
		Int Ptr(pVerts)[curVert*of+3] = $FFFFFFFF
		pVerts[curVert*of+4] = 0.0
		pVerts[curVert*of+5] = 0.0
				
		curVert = curVert + 1

		pVerts[curVert*of+0] = x + w
		pVerts[curVert*of+1] = y
		pVerts[curVert*of+2] = 0
		Int Ptr(pVerts)[curVert*of+3] = $FFFFFFFF
		pVerts[curVert*of+4] = 1.0
		pVerts[curVert*of+5] = 0.0

		curVert = curVert + 1

		pVerts[curVert*of+0] = x + w
		pVerts[curVert*of+1] = y + h
		pVerts[curVert*of+2] = 0
		Int Ptr(pVerts)[curVert*of+3] = $FFFFFFFF
		pVerts[curVert*of+4] = 1.0
		pVerts[curVert*of+5] = 1.0
			
		curVert = curVert + 1

		pVerts[curVert*of+0] = x
		pVerts[curVert*of+1] = y
		pVerts[curVert*of+2] = 0
		Int Ptr(pVerts)[curVert*of+3] = $FFFFFFFF
		pVerts[curVert*of+4] = 0.0
		pVerts[curVert*of+5] = 0.0
			
		curVert = curVert + 1

		pVerts[curVert*of+0] = x + w
		pVerts[curVert*of+1] = y + h
		pVerts[curVert*of+2] = 0
		Int Ptr(pVerts)[curVert*of+3] = $FFFFFFFF
		pVerts[curVert*of+4] = 1.0
		pVerts[curVert*of+5] = 1.0
			
		curVert = curVert + 1

		pVerts[curVert*of+0] = x
		pVerts[curVert*of+1] = y + h
		pVerts[curVert*of+2] = 0
		Int Ptr(pVerts)[curVert*of+3] = $FFFFFFFF
		pVerts[curVert*of+4] = 0.0
		pVerts[curVert*of+5] = 1.0
		
		curVert = curVert + 1		
		If curVert >= maxVerts Then
			Flush()
		End If		
	End Method		
	Method Begin()		
		VB.lock(DDLOCK_WAIT | DDLOCK_WRITEONLY , Varptr pVerts , Null)
		Flushed = False
	End Method
	Method Flush()
		Flushed = True
		VB.Unlock()
		D3D7GraphicsDriver().Direct3DDevice7().DrawPrimitiveVB(D3DPT_TRIANGLELIST,VB,0,curVert,0)
		curVert = 0
	End Method	
End Type
Type TVertex
	Field x:Float
	Field y:Float
	Field z:Float
	Field color:Int
	Field tu:Float
	Field tv:Float
End Type