   Shader Instancing, what?
  I've search trough the forums (and googled) for this but in most threads they talk about hardware instancing, but refer to it as shader instancing. Confusing.I'm rendering a tile map where each tile mesh can exist many times in view. I'm changing the world matrix between each draw to place the tiles in individual spots  but this requires a draw call for each tile. Can shader instancing help me here?Is the idea to do one draw call, and then offset the mesh in the vertex shader for each combination? Wouldn't that still require one draw call per tile?   
  It's possible to do it all in one call.instancing work by taking 2 vertex buffers: One with the vertex data of one instance (eg all the vertex of a tile), as long as all the vertices of one instance.One with all the per-instance data (eg world matrix), with as many vertices as there are instances.They then get woven together on the GPU prior to rendering, so you receive your world matrix as a vertex input, and you also have to declare it in your vertex declaration. And then you have it, a different world matrix per instance. For textures you would have to use texture atlasses.Here is an example effect to look at:// position in buffer 0// all the rest per instance, so buffer 1struct Point_light_instanced_vs_input{float3 position  : POSITION;float4 world_1  : TEXCOORD0;float4 world_2  : TEXCOORD1;float4 world_3  : TEXCOORD2;float4 world_4  : TEXCOORD3;};Point_light_instanced_vs_output point_light_instanced_vs( const Point_light_instanced_vs_input input){Point_light_instanced_vs_output output; float4x4 world = {input.world_1,input.world_2,input.world_3,input.world_4};and so on...Just remember, you can't use const parameters, all changing parameters should be in the vertex buffers. That's the trick.   ;  There's a sample in the DirectX SDK which defines four types of instancing; Hardware, Shader, Constant and Stream. Hardware is basically what you want if you aim at sm3 or higher, from what I understand. It works as described by harveypekar. Shader instancing on the other hand is where you set an array of matrices in a constant register in the shader, and then iterate through that array. Which works on sm2, but you can only have 256 instances in the array so you would have to do it in batches of 256. The other two are variations of shader instancing, look in the SDK for more details.   ;  Thanks a lot Harveypekar and chot!I'll check out the DirectX sample and see if I can grasp it. The 256 limit is all well because the viewing area of the tiles are limited in my case.   ;  Note that instancing comes with an overhead. If you have rather simple meshes its not the right thing to do. If your tiles are not really complex meshes but only rectangles and if you just have a couple of hundreds of them on screen I would advise you not to reuse the same tile for rendering in different locations. Instead create a texture atlas and create an individual set of vertices for each tile on the screen with visually identical tiles just using the same texture but not sharing the same vertices with different world transform.Just create all unique geometry and place it in a single vertex buffer to render all tiles with a single call. This would be the fastest option if your tiles are indeed just simple quads.   ;Quote:Original post by WaterwalkerJust create all unique geometry and place it in a single vertex buffer to render all tiles with a single call. This would be the fastest option if your tiles are indeed just simple quads.Floor tiles are usually quads, but walls are not. They're not overly complex though, maybe like a dozen polygons each or so. So you're saying a volatile vertex buffer 'gatherer' is appropriate? Wouldn't that be limiting as I have to waste CPU cycles to build this big buffer? I mean, in the case of the tiles that aren't quads (but exported from a modelling package).Maybe if I don't build this vertex buffer every frame, and only when the player moves? (Top-down game, only 8x8 tiles visible at once).   ;Quote:Original post by WaterwalkerNote that instancing comes with an overhead. If you have rather simple meshes its not the right thing to do. If your tiles are not really complex meshes but only rectangles and if you just have a couple of hundreds of them on screen I would advise you not to reuse the same tile for rendering in different locations. Instead create a texture atlas and create an individual set of vertices for each tile on the screen with visually identical tiles just using the same texture but not sharing the same vertices with different world transform.Just create all unique geometry and place it in a single vertex buffer to render all tiles with a single call. This would be the fastest option if your tiles are indeed just simple quads.I am not sure I understand why you wouldn't want to reuse the geometry.There are three (or more) options here (at least in dx10):1) Use hardware instancing (probably not good unless tons copies2) Fill one vertex buffer with multiple copies of a quads and draw them at once.    2A) However, this would require some sort of logic in the shader to tell when to switch textures.   2B) This would also require all the textures be bound to the effect at once3) Create one quad in a single vertex buffer and draw using that buffer multiple times, binding a new texture to the effect each time.Personally I'd usually for 3, unless the situation had special circumstances. You are reusing the same vertex buffer, so you are 'reusing geometry', but you are still making multiple draw calls.Explain more why you would do otherwise?I can see some situations for all 3 really.I'd do 2 if less than 10 differant textures were needed and the number of quads was static every frame. I sure don't want to have to recreate vertex buffers. I'd still wonder if I could do better using the geometry shader to make copies for me.;  Well, my artist already reuses the same texture for all tiles in the same tileset. But tiles are still not quads only in our case (walls are a box, but isn't limited to that).I think I'm going to settle on merging tiles into bigger chunks (same VB) and render them as chunks instead. Might render a little bit out of the screen, but these draw calls are killing my FPS on a 8800 GTX and the geometry is remarkably simple for that to happen.Edit: Unless I get good results with shader instancing, though it isn't simple to piggyback into the engine we're using.   ;Quote:Original post by SymLinkedSo you're saying a volatile vertex buffer 'gatherer' is appropriate? Wouldn't that be limiting as I have to waste CPU cycles to build this big buffer?Yes I am saying that. If you only dealing with a couple of hundreds of polygons this will be okay and using instancing in such a case is like shooting sparrows with guns ... lots of guns. :)Quote:Original post by SymLinkedMaybe if I don't build this vertex buffer every frame, and only when the player moves? (Top-down game, only 8x8 tiles visible at once).Indeed, that's the way to go. Also, trust your graphics card and include the neighboring tiles that are just outside the screen. Your graphics card should be quite fast at culling it away. A smarter approach would include some more of the invisible rows in your vertex buffer and have a couple of different index buffers rendering different tiles from your static vertex buffer depending on what is actually visible on the screen. That means you have different index buffers but still onyl issue a single draw call using only one of those index buffers that includes all of those tiles visible at the moment. Hence different index buffers representing different overlapping subsets of your tiles.Quote:Original post by SymLinkedthese draw calls are killing my FPS on a 8800 GTX and the geometry is remarkably simple for that to happen.Well, you should not be able to kill a 8800 GTX with 8x8 draw calls. Have you done some more performance analysis?Quote:Original post by brekehanI am not sure I understand why you wouldn't want to reuse the geometry.*snip*3) Create one quad in a single vertex buffer and draw using that buffer multiple times, binding a new texture to the effect each time.Reusing the geometry with different world transforms leads to multiple draw calls. Even if 8x8 draw calls should not be worth the discussion its a matter of scale. Each draw call in DX consumes lots of CPU cycles, especially compared to OpenGL. Just issue a few hundred draw calls and you are stalled. The less triangles you render with each call the slower your application gets. Whenever you can create unique geometry and build texture atlases to reduce your draw calls to as few as you can get. Again, this won't notice for a few dozens of draw calls but the loss of performance scales exponentially with each draw call you add once you are beyond this point where the setup cost of each draw call starts to kill you.   ;  Thanks for your reply Waterwalker. The performance on my 8800 grinds when I reach around 1500 or so draw calls. That's after lighting (three point lights) affecting the tiles as well. The problem seems to be that the engine we're using is drawing each subshape in the tile with a seperate drawcall, and we got 4 subshapes in each tile (same textures though). That's how their exporter works, I guess. Sigh.   