DrawIndexedPrimitiveUP

Discuss about anything related to the Irrlicht Engine, or read announcements about any significant features or usage changes.
Post Reply
RandomTiger
Posts: 1
Joined: Sat Nov 19, 2005 5:04 pm

DrawIndexedPrimitiveUP

Post by RandomTiger »

Hi there, I discovered Irrlicht a few days ago and at first it looked ideal for my purposes. However I have had to abandon my plans to use it before even writing a line of code because it looks like all DX rendering (correct me if Im wrong) is done using DrawIndexedPrimitiveUP which the DX docs and practical experience show is a lot slower than using proper buffers.
dhenton9000
Posts: 395
Joined: Fri Apr 08, 2005 8:46 pm

Post by dhenton9000 »

speed isn't everything. Hitting your design specs is. I just slogged through the Irrlicht internals and the only thing I can guess is that IndexedPrimitiveUP is used because it makes the code for running DX fit the same pipeline as OpenGL


Theres a major requirement in Irrlicht to support OPENGL and software rendering.

As they say, get it fast, get it right, or get it cheap, select 1 out of 3.
Guest

Post by Guest »

It isn't hard to add hardware vertex buffers in a rough manner, the performance boost is about +200% on my computer. But if you need speed you should choose ogre.
Guest

Post by Guest »

Thanks dhenton9000 but I have been badly burnt by DrawIndexedPrimitiveUP in the past. Asside from that the Irrlight implementation looks great. Some very useful file support there.

Im currently looking at Orge, not quite as straight forward but might also suit my purposes.
Grey Lantern
Posts: 34
Joined: Sat Jul 30, 2005 9:45 am
Contact:

Post by Grey Lantern »

Care to elaborate on "badly burnt" - do you just mean a lower performance result? (less FPS) or other issues?

thanks
Guest

Post by Guest »

Seriously low FPS.
Pr3t3nd3r
Posts: 186
Joined: Tue Feb 08, 2005 6:02 pm
Location: Romania
Contact:

Post by Pr3t3nd3r »

Anonymous wrote:It isn't hard to add hardware vertex buffers in a rough manner, the performance boost is about +200% on my computer. But if you need speed you should choose ogre.
Did you do that with directX too?
How?
Can you post some code? files?
Guest

Post by Guest »

here is some source:

u32 CD3D9Driver::getFVFSize(video::E_VERTEX_TYPE vType)
{
int leng=0;
if (vType==video::EVT_STANDARD) leng=sizeof(video::S3DVertex);
if (vType==video::EVT_2TCOORDS) leng=sizeof(video::S3DVertex2TCoords);
if (vType==video::EVT_TANGENTS) leng=sizeof(video::S3DVertexTangents);
return leng;
}

bool CD3D9Driver::createHardwareBuffer(scene::IMeshBuffer* buffer)
{
if (((bool)buffer->hwBuffer.indexB)^((bool)buffer->hwBuffer.vertexB)) return false;

HRESULT hr;

int leng=this->getFVFSize(buffer->getVertexType());

leng*=buffer->getVertexCount();

if (leng==0) return false;

if (!buffer->hwBuffer.indexB) {

u32 fv=getFVFID(buffer->getVertexType());

IDirect3DVertexBuffer9* theNewVertexBuffer;

hr=pID3DDevice->CreateVertexBuffer(leng,
D3DUSAGE_WRITEONLY,
fv,
D3DPOOL_MANAGED,
&theNewVertexBuffer,
0);


buffer->hwBuffer.vertexB=theNewVertexBuffer;


int indxcnt=buffer->getIndexCount();

IDirect3DIndexBuffer9* theNewIndexBuffer;

hr= pID3DDevice->CreateIndexBuffer(indxcnt*2,
D3DUSAGE_WRITEONLY,D3DFMT_INDEX16,D3DPOOL_MANAGED,&theNewIndexBuffer, 0);

buffer->hwBuffer.indexB=theNewIndexBuffer;
}

IDirect3DIndexBuffer9* myIndexBuffer=(IDirect3DIndexBuffer9*)buffer->hwBuffer.indexB;
IDirect3DVertexBuffer9* myVertexBuffer=(IDirect3DVertexBuffer9*)buffer->hwBuffer.vertexB;


void* myIndices;
u16* myIndicesu16;

hr=myIndexBuffer->Lock(0,0,&myIndices,0);

myIndicesu16=(u16*)myIndices;

u16* indices=buffer->getIndices();
int extL=buffer->getIndexCount();
for (int cntr=0;cntr<extL;cntr++) {
myIndicesu16[cntr]=indices[cntr];
}

hr=myIndexBuffer->Unlock();


void* bufferVertices;
hr=myVertexBuffer->Lock(0,0,&bufferVertices,0);
int cl=leng/4;
u32* bufferu32=(u32*)bufferVertices;
u32* src=(u32*)buffer->getVertices();
for (s32 count=0;count<cl;count++)
{
bufferu32[count]=src[count];
}
hr=myVertexBuffer->Unlock();



return true;
}

bool CD3D9Driver::deleteHardwareBuffer(scene::IMeshBuffer* buffer)
{

if (!buffer) return false;

if (buffer->hwBuffer.vertexB) {
rc=((IDirect3DVertexBuffer9*)buffer->hwBuffer.vertexB)->Release();
}

if (buffer->hwBuffer.indexB) {
rc=((IDirect3DIndexBuffer9*)buffer->hwBuffer.indexB)->Release();
}

return true;
}

void CD3D9Driver::drawIndexedTriangleListHw(void* indexP,void* vertexP,int indexC,int vertexC,video::E_VERTEX_TYPE vt)
{
setVertexShader(vt);

if (setRenderStates3DMode())
{
PrimitivesDrawn += indexC/3;


HRESULT hr=pID3DDevice->SetIndices((IDirect3DIndexBuffer9*)indexP);
hr=pID3DDevice->SetStreamSource(0,(IDirect3DVertexBuffer9*)vertexP,
0,getFVFSize(vt));

hr=pID3DDevice->DrawIndexedPrimitive(D3DPT_TRIANGLELIST,
0,
0,
vertexC,
0,
indexC/3);

}
}

#####IMESHBUFFER.H#####
struct hwBufferData {
void* vertexB;
void* indexB; //It does not include the type of renderer that created the hardware buffer, that must be added if you plan to use multiple renderers
};

hwBufferData hwBuffer;
#################

### IN THE CONSTRUCTOR OF SMESHBUFFER.H SMESHBUFFERLIGHTMAP.H SMESHBUFFERTANGENT.H####
hwBuffer.indexB=0;
hwBuffer.vertexB=0;

void CNullDriver::drawMeshBuffer(scene::IMeshBuffer* mb)
{
if (!mb)
return;

if ((mb->hwBuffer.indexB!=0)&(mb->hwBuffer.vertexB!=0)) {
this->drawIndexedTriangleListHw(mb->hwBuffer.indexB,mb->hwBuffer.vertexB,mb->getIndexCount(),mb->getVertexCount(),mb->getVertexType());
return;
}
.......................

Then you've got to update the includes of CD3D9Driver with the new functions. Update IVideoDriver.h with createHardwareBuffer and deleteHardwareBuffer if you like, as I did, so that if you want to extend that functions to other renderers you can do it easily. Of course the overloaded functions of other renderers will not do anything.
You must add some code to call ivideodriver::deleteHardwareBuffer when the mesh buffer is deleted, optimally this can be done in the destructors of meshbuffers or of smesh.h, but meshbuffers and smesh don't know the pointer of the videodriver that created the hardware buffers.
You can add that pointer, or call deleteHardwareBuffer from your game when you have got to destroy a mesh,but it is not very handy.
I've almost forgot to tell how to use this: call createHardwareBuffer for every NOT ANIMATED mesh buffer that you want to put in an hardware vertex buffer, and the engine will care about everything else.
If you modify the vertices data of a mesh buffer that has got the hardware buffer, the modifications will not apply until you call createMeshBuffer again, that function will not delete the buffer and create another one, but just lock the old one and upload the new vertices data.
But note that you cannot remove or add vertices in a buffer after the creation of hw vertex buffer.
I hope that this code will give you inspiration :idea:
Pr3t3nd3r
Posts: 186
Joined: Tue Feb 08, 2005 6:02 pm
Location: Romania
Contact:

Post by Pr3t3nd3r »

Hmm ...
Your code looks realy interesting.
So basicaly it is moving the verticles from ram to the video memory ? or what? what is the hwBuffer?

NOT ANIMATED means that the mesh will not have animation or that the node will not have animations (translations, rotations ... etc of scene node).

Somethink like this cand be applyed for bilboards? and more important for particle scene nodes to obtain an biger fps?

Meybe spintz will try this code because he already played with hardware mesh of opengl i think ..
Guest

Post by Guest »

with not animated i mean that the mesh cannot be animated, for example you cannot use this for md2 meshes, or X meshes with software skeletal animation. You can move,rotate and scale the node as usual.
The vertices are copied to video ram, but they remains in system memory too; I did think about using only hardware buffers but it needed too much modifications to Irrlicht.
I don't know much about billboards and particle scene nodes, but I think that it would be not useful: hardware vertex buffers show their strength when rendering big chunks of polygons, when rendering very small mesh buffers the direct3d call overhead will probably erase every speed up.
Guest

Post by Guest »

Now.. how about a DX8 version of your code? ;)

Actually I have an old D3D engine I was working on before I found irrlicht and was using hardware buffers in that (without software backup) which meant you lost them on deviceloss/reset. I didn't read the long code post - but does yours work robustly like that? I.E recovers from alt/tab ok etc?

YOu probably have it covered - like I say - just woke up and can hardly see straight at the moment let alone read masses of code ;)
Guest

Post by Guest »

I don't plan to do a DX8 version.
Since the buffers are created with D3DPOOL_MANAGED there is no need to recreate them if the device is lost, and it's not even needed to keep a copy of them in system memory, direct3d9 will care about that.
Dunno if direct3d8 can do this.
Guest

Post by Guest »

Ahh managed.. I thought you were using DYNAMIC (for ultimate speed). Having said this I am rusty with pure D3D now thanks to Irrlicht (*fume* ;) ) and can't even recall the best pool type for the job. My engine was actually D3D9 also.. suppose I should just go dig up the old source code ;)
Guest

Post by Guest »

did you mean DEFAULT?
I don't think that managed is slower (or maybe it is just a very little bit) because the buffers are stored in video memory like with default, when they are used.
And there are some extra advantages, for example you can lock the vertex/index buffer a lot of times within a frame, and direct3d will reupload the buffer to video memory just one time when it's needed for rendering.
The only drawback is that actually with Irrlicht you'll have two copies of the vertices data in system memory (the Irrlicht one and the direct3d one) and one copy in video memory, that's not optimal.
But I think that MANAGED saves quite a lot of work efficiently and easily.
Guest

Post by Guest »

Yeah - prob ;)

I am rust on it as I said. There were 3? pool types IIRC.. managed (which helps you out), pure software (safe as houses but slow) and the one that stored it only in VRAM and needed clearing when you lost the device.. which must be default then, but it was the "fastest" for vbuffers etc.

I really need to go and brush up on D3D it was over a year since I last did anything outside of irrlicht (though I have done some In-irrlicht D3D adjustments to the code).

anyway, I'll shut up now - your code obv works so well done! :)
Post Reply