Jump to content
  • Advertisement


  • Content Count

  • Joined

  • Last visited

Community Reputation

150 Neutral

About Ximsu

  • Rank
  1. Can't say for sure on you're performance drop, but I do have a few recommendations. First I would try different method of locking/creating your instance buffer, see if you can generate any sort of performance gain there, hopefully you will be able to recover most of that 300fps drop. However, with only one character present in your demo, you are not going to see the benefit of instancing, as you won't have any more draw calls than without instancing, but with instancing you will need to lock your instance buffer, so another thing you can try is using several characters, to see if the instancing method has any benefit. I'm still working out this stuff in my implementation right now (actually multiple subsets right now), so if any one else has some suggestions for Tispe, I would find them handy as well!
  2. I'm going to second the Frank D Luna (http://www.amazon.com/Introduction-Game-Programming-Direct-9-0c/dp/1598220160/ref=sr_1_1?ie=UTF8&qid=1376026640&sr=8-1&keywords=beginning+game+programming+directx9+a+shader+approach), start off with 3d math basics, covers basic DX, and most of the rest is learning HLSL through implementing various effects (particle effects, shadow mapping, normal mapping, water effects with displacement mapping, environment mapping, and terrain).
  3. You're edit is correct, the declaration has all the size information, but as one of the above posts mention, what I was using D3DXGetDeclVertexSize() for was not necessary, using either Mesh->GetNumBytesPerVertex(), or sizeof( /*you're vertex data structure*/ ) would work as well, the vertex declaration is only needed for SetDeclaration(). Also, thanks for the tips in the above posts.
  4. There's not reason in particular to use one or two streams, VBD_GEOMETRYPACKET (which contains both geometry and instance data) is needed for D3DDEV->SetDecleration() msdn had one more vertex declaration for instances that I don't.   If you look at the two calls to this function D3DXGetDeclVertexSize(VBD_GEOMETRYPACKET, 0) D3DXGetDeclVertexSize(VBD_GEOMETRYPACKET, 1) I have 0 set for the second parameter in the first call and 1 in the second call, this just refers to the stream, the function will return the vertex size of that stream, rather than the entire declaration, so in essence its functioning as two different declarations merged into one. The only reason I have the vertex declaration for the mesh is for cloning it, if you didn't need to do that, you would only technically need the one vertex declaration.   Regardless its a matter of preference, if you want another declaration for instancing like msdn it won't make any difference, though may be useful for you elsewhere in your code.
  5. Not sure mine is the ideal approach, but I'll post what I have. I'm using one dynamic vertex buffer, at a size equal to a const UINT MaxInstances.   First here are my vertex declarations //used to clone the mesh const D3DVERTEXELEMENT9 VBD_GEOMETRYDATA[] = { {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, D3DDECL_END() }; //this declaration is actually used for rendering extern LPDIRECT3DVERTEXDECLARATION9 DECL_GEOMETRYPACKET; const D3DVERTEXELEMENT9 VBD_GEOMETRYPACKET[] = { {0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0}, {0, 12, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL, 0}, {0, 24, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0}, {1, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1}, {1, 16, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 2}, {1, 32, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 3}, {1, 48, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 4}, D3DDECL_END() }; //class describing a single element of the instance buffer struct OBJECT_INSTANCE { //the four rows of the world matrix of an instance float Row1[4]; float Row2[4]; float Row3[4]; float Row4[4]; }; Here the function to create the instance buffer (should only be called once, but outside of performance wont break anything if its called multiple times) ?? void CreateInstanceBuffer() { //checks if the buffer already exists and releases it if it does ReleaseInstanceBuffer(); BufferSize = MaxInstances*sizeof(OBJECT_INSTANCE); D3DDEV->CreateVertexBuffer(BufferSize, D3DUSAGE_DYNAMIC, NULL, D3DPOOL_DEFAULT, &InstanceBuffer, NULL); D3DDEV->CreateVertexDeclaration(VBD_GEOMETRYPACKET, &DECL_GEOMETRYPACKET); } Then after loaded the mesh, clone it with your geometry declaration //when you load the tempmesh is the mesh you wish to instance D3DXMESH newmesh; tempmesh->CloneMesh(D3DXMESH_MANAGED, VBD_GEOMETRYDATA, D3DDEV, &_newmesh) //store the vertex and index buffers once newmesh->GetVertexBuffer(&MeshVB); newmesh->GetIndexBuffer(&MeshIB); //if you no longer need the old mesh release it and replace it with the new once tempmesh->Release(); tempmesh = newmesh; Here is the code I use to lock the instance buffer, note that AddIndex keeps track of where to add the next instance (and hence will also keep track of how many instance you have currently added to the buffer) when I'm done rendering one mesh I just set AddIndex to 0, and it overwrites whatever data is already there the next time I start adding instances (also note that the instance buffer should be locked and the data stored in OBJECT_INSTANCE *LockedBuffer) bool AddInstanceToLockedBuffer(D3DXMATRIX World) { //the buffer is not locked or you have reached the max instances if (!BufferLocked) return false; if (AddIndex >= MaxInstances) return false; D3DXMATRIX InverseWorld; D3DXMatrixInverse(&InverseWorld, 0, World); /*---------------------------------------------- fill LockedBuffer[AddIndex] with World ----------------------------------------------*/ //increment the instance buffers current index AddIndex++; return true; } UINT GetNumInstances() { return AddIndex; } void ResetInstanceBuffer() { AddIndex = 0; } Lastly is rendering //set the instancing parameters D3DDEV->SetVertexDeclaration(DECL_GEOMETRYPACKET); D3DDEV->SetIndices(MeshIB); D3DDEV->SetStreamSourceFreq( 0, D3DSTREAMSOURCE_INDEXEDDATA | GetNumInstances()); D3DDEV->SetStreamSource(0, _vb, 0, D3DXGetDeclVertexSize(VBD_GEOMETRYPACKET, 0)); D3DDEV->SetStreamSourceFreq( 1, D3DSTREAMSOURCE_INSTANCEDATA | 1 ); D3DDEV->SetStreamSource(1, InstanceBuffer, 0, D3DXGetDeclVertexSize (VBD_GEOMETRYPACKET, 1)); //set all the properties of your effect //render the mesh UINT numpasses; Effect->Begin(&numpasses, 0); for (int i=0; i<numpasses; i++) { Effect->BeginPass(i); D3DDEV->DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, _Mesh->GetNumVertices(), 0, Mesh->GetNumFaces()); Effect->EndPass(); } Effect->End(); //reset instancing parameters D3DDEV->SetStreamSourceFreq(0, 1); D3DDEV->SetStreamSourceFreq(1, 1); Pretty long, but hope that helps someone out. Also if anyone has any suggestions that would be cool too!   Edit: Probably noticed I haven't gotten around to rendering multiple subsets of the mesh yet, I will be doing that next. One of the links posted in one of the above replies has some stuff on that though.
  6. Thanks for the replies! Taking the responses into use, and some meddling with my own, one of the biggest things I was missing was making sure the format of my Mesh matched what I needed to pass to, so the big things I needed was just a call to CloneMesh after loaded it. Also, for anyone running into this topic with a similar issue, the first reply to this topic http://www.gamedev.net/topic/591634-directx-9-hardware-instancing/ has most of the things I needed.
  7. First things first, hello GameDev.net! Long time browser here, love the site, finally registered when I had a question that I couldn't find the answer to while browsing the rest of the internet, so here goes! I've been working on instancing with DirectX 9 using the following article http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter03.html (3.3.4 Batching with the Geometry Instancing API), however up to this point I've been using ID3DXMESH to load and render my meshes from a .x file. Because of that I never actually will call SetStreamSource() with the stream number at 0. I tried setting all the others like so   D3DDEV->SetStreamSourceFreq( 0, D3DSTREAMSOURCE_INDEXEDDATA | GetNumInstances() ); D3DDEV->SetStreamSourceFreq( 1, D3DSTREAMSOURCE_INSTANCEDATA | 1 ); D3DDEV->SetStreamSource( 1, InstanceBuffer, 0, sizeof(OBJECT_INSTANCE) ); and then calling DrawSubset on my mesh, to see if it would work, but so far I haven't been too succesfull.   So, does anyone have any ideas on what I should try, do I need to use the get functions of my mesh to render it manually? I still need to debug other parts of the code to see if they're at fault, but any tips in the right direction would be appreciated!      
  • Advertisement

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

GameDev.net is your game development community. Create an account for your GameDev Portfolio and participate in the largest developer community in the games industry.

Sign me up!