Re-using transformed vertices

Started by
3 comments, last by d000hg 21 years, 1 month ago
I have the situation with my terrain engine where I want to use the same vertex data with multiple calls to DrawIndexedPrimitive, with different index data e.g pseudo:

do
{
Load vertex data to VB
do
{
load some indices to IB
DrawIndexedPrimitive()
} some no. of times
}for each chunk of vertex data
  
Now since after the draw call the vertex data is transformed I have to re-copy it (typically I have ~2000 vertices with blocks of a few 100 indexed triangles at a time) which is very inefficient especially since I have to keep locking to copy it. I want to copy the vertices across once then somehow keep them untransformed afterwards. Is this possible? I guess an alternative would be to use them as post-transformed with rhw after but this would involve re-formating the vertices and switching FVF lots which is ugly! Read about my game, project #1 NEW (18th December)2 new screenshots, one from the engine and one from the level editor John 3:16 [edited by - d000hg on March 7, 2003 6:58:21 AM]
Advertisement
The T&L in PC graphics hardware is write/push only I''m afraid - AFAIK there is often never even a complete list of transformed vertices available to the hardware - i.e. it does them after primitive assembly.

About all you can do is use any spare CPU cycles you have and do something like ProcessVertices() to transform once (PV is always done in software) and then copy the result into your buffer multiple times as necessary.

Since the vertices aren''t changing for your multiple passes, there''s no reason there should be multiple copies of the vertex data though!

--
Simon O''Connor
Creative Asylum Ltd
www.creative-asylum.com

Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site

I should explain my algo better:
As the triangle count isn''t known, I store vertices used in rendering in blocks of ~2000 using stl::vector. Because I use different textures for different ground types (sand,grass etc) I have different triangles using these vertices for multiple textures, so I also store blocks of indexing data for each texture for each block of vertices. However if I made the blocks for indexing large, this means that just one extra triangle uses a whole new block. So I make indexing blocks small to reduce wastage. This means that a block of indices may use many index blocks for each texture. I render by texture so this means for one vertex block I want to render many index blocks without reloading vertex data. I CAN just copy all the index data across from multiple blocks into a larger IB, but then I''m rendering like 4K polys in one call.

I don''t want the vertices to be transformed after calling DrawPrimitive - is there not some way of forcing the data in the VB to be unchanged after the call?

Failing that, would using processvertices once and using transformed vrtices be quicker than having to potentially recalculate each vertex 4-6 times. In SW vertex processing I''m guessing yes, but what about Vs HW?
quote:Original post by d000hg
I don''t want the vertices to be transformed after calling DrawPrimitive - is there not some way of forcing the data in the VB to be unchanged after the call?


Every time you pass untransformed vertices to Draw*Primitive, then they''ll be transformed (& lit) before rendering. That''s just the way T&L (& vshader) 3D hardware works.

The contents of the source VB you pass to Draw*Primitive aren''t ever changed by the Draw*Primitive call - that''s the point it''s one way, the vertices in the source VB are input only, the chip or even the SW T&L pipe doesn''t transform the vertices and overwrite the source buffer.



quote:Failing that, would using processvertices once and using transformed vrtices be quicker than having to potentially recalculate each vertex 4-6 times. In SW vertex processing I''m guessing yes, but what about Vs HW?


That''s one of those cases where ideally your code should be performing runtime profiling of itself during the first few frames to decide which is the best strategy. Failing that you''ll have to test with your specific app. Complexity of shader, how many lights, whether things like NORMALIZENORMALS are enabled, CPU load, efficiency of your dynamic locking etc all affect whether a single PV() followed by multiple Draw*Primitive()s from the transformed result is faster than multiple Draw*Primitive() calls with untransformed data.

What I will say though is most of the time the T&L on modern chips is very starved of data by most apps, there''s a lot of underused power there - so the multiple DrawPrimitive()s from the same buffer won''t be anywhere near as bad as you''re assuming.



--
Simon O''Connor
Creative Asylum Ltd
www.creative-asylum.com

Simon O'Connor | Technical Director (Newcastle) Lockwood Publishing | LinkedIn | Personal site

quote:The contents of the source VB you pass to Draw*Primitive aren''t ever changed by the Draw*Primitive call - that''s the point it''s one way, the vertices in the source VB are input only, the chip or even the SW T&L pipe doesn''t transform the vertices and overwrite the source buffer.
Really? I assumed that''s why it didn''t work properly?
So I can say load 10 vertices, then call DrawIndexedPrim for indices 1,2,3. Then in a second call to drawindexedprimitive, without touching the VB, I can say draw with indices 3,4,5 without vertex #3 being changed by the previous call?
quote:What I will say though is most of the time the T&L on modern chips is very starved of data by most apps, there''s a lot of underused power there - so the multiple DrawPrimitive()s from the same buffer won''t be anywhere near as bad as you''re assuming.
I''m not actually bothered about the data being transformed often, I jsut don''t want to reload the VB many times as that IS slow. I''ll check out why it screwed up I guess. Though I am aiming for this to run on SW T&L cards...

This topic is closed to new replies.

Advertisement