Large vertex buffer (by CPU) or texture with less info in vertexshader for vertexdata

Started by
7 comments, last by Vertex333 15 years, 5 months ago
D3D10: Imagine I want to create an object that consists of many different positions for triangles. I use the positions to build a triangle fan (triangle strips are used). There is a very large overhead (about three times) and my main "must have goal" is to use the CPU as less as possible. My idea: Creating a static (IMMUTABLE) VB (size is known) and send it (not initialised) to the GPU. In addition, save the Position data into one or three (not sure) textures. Use the VS with vertexID and the texture to create the object. When object changes (up to every frame) only the texture needs to be updated (smaller ammount of data). I don't know which texture does that for me and if this is really faster than the normal way. The other solution would be the normal way: Using a dynamic VB and change it every frame/object change. What seems to be better (I know that this has to be tested, but implementing both would cost much time)? edit: small note: vertex count doesn't change, so textures do not need to be recreated. edit2: maybe an additional vertex buffer instead of the texture would be better? Thx, Vertex [Edited by - Vertex333 on October 21, 2008 4:21:46 AM]
Advertisement
I would try doing it with a secondary vertex buffer, like you'd do for hardware instancing. Make a smaller secondary buffer with only position data, and lock/update that buffer whenever the mesh changes.

Either way make sure you profile in PIX to see whether your lock is stalling the pipeline. Stalls will show up as red in the frame graph.
Quote:Original post by MJP
I would try doing it with a secondary vertex buffer, like you'd do for hardware instancing. Make a smaller secondary buffer with only position data, and lock/update that buffer whenever the mesh changes.

Either way make sure you profile in PIX to see whether your lock is stalling the pipeline. Stalls will show up as red in the frame graph.
Thx!
I already looked up some instancing samples and stuff for constant buffers. Nevertheless I do not understand how I can "map/bring" a second vertex buffer into the shader in a way (as described in my last post) that not the vertices get processed, but I can access this buffer while processing the vertices of another vertex buffer.

Besides, should it be a constant or vertex buffer (when creating the ressource in D3D10)?

In the FX file there is only the option to create fixed size arrays (size may be limited) in constant buffers (which are size limited anyway I think), or to use a texture. Both ways (that I acutally know) are not what we are searching for.

Thx,
Vertex
Quote:Original post by Vertex333
Nevertheless I do not understand how I can "map/bring" a second vertex buffer into the shader in a way (as described in my last post) that not the vertices get processed, but I can access this buffer while processing the vertices of another vertex buffer.


I'm not sure what you're after exactly and I'd imagine things changed a lot in DX10 which I don't use, so I guess I probably shouldn't even be replying [smile]

Anyway, in DX9 you can mix in data from another vertex buffer by setting it up on an additiontal stream. By specifiying that stream for certain elements in the vertex declaration and by using the appropriate stream source frequency, this will make the Runtime/Driver/Card interleave the data from the 2nd buffer with the original vertex data. This way you can just access the data from the 2nd buffer in the vertex shader through the semantics you defined in the declaration.

...

I got a feeling I'm not really making this any clearer, but I hope it helps and/or makes sense for DX10.
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!
Quote:Original post by remigius
Quote:Original post by Vertex333
Nevertheless I do not understand how I can "map/bring" a second vertex buffer into the shader in a way (as described in my last post) that not the vertices get processed, but I can access this buffer while processing the vertices of another vertex buffer.


I'm not sure what you're after exactly and I'd imagine things changed a lot in DX10 which I don't use, so I guess I probably shouldn't even be replying [smile]

Anyway, in DX9 you can mix in data from another vertex buffer by setting it up on an additiontal stream. By specifiying that stream for certain elements in the vertex declaration and by using the appropriate stream source frequency, this will make the Runtime/Driver/Card interleave the data from the 2nd buffer with the original vertex data. This way you can just access the data from the 2nd buffer in the vertex shader through the semantics you defined in the declaration.

...

I got a feeling I'm not really making this any clearer, but I hope it helps and/or makes sense for DX10.
Thx! This was the hint I was looking for!

But thinking twice this forces me to use a vertex buffer (although it might be smaller and has a different frequency). Is there no way to access it like other normal global FX variables?

Vertex

Quote:Original post by Vertex333
But thinking twice this forces me to use a vertex buffer (although it might be smaller and has a different frequency). Is there no way to access it like other normal global FX variables?

Vertex


Well, you could stick the positional data in a shader constants array, much like you'd do with skinning or shader instancing. In DX9 this requires you to add some index to your vertices to fetch the correct data element from the array, but from what I've read this index is generated automatically for you in DX10 (by way of the SV_VertexID semantic).

With this approach you'll be bound by the maximum number of constants supported by your graphics card though. Again from what I've read, the D3D10/SM4 spec requires cards to support 4096 constant registers, so with a few constants needed for various matrices and other stuff, you'd be limited to about 4000 vertices using a single float4 each for data. In addition to this limitation, I doubt it's really going to be much faster than using a vertex buffer, so as MJP pointed out profiling is key.
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!
Quote:Original post by remigius

Quote:Original post by Vertex333
But thinking twice this forces me to use a vertex buffer (although it might be smaller and has a different frequency). Is there no way to access it like other normal global FX variables?

Vertex


Well, you could stick the positional data in a shader constants array, much like you'd do with skinning or shader instancing. In DX9 this requires you to add some index to your vertices to fetch the correct data element from the array, but from what I've read this index is generated automatically for you in DX10 (by way of the SV_VertexID semantic).

With this approach you'll be bound by the maximum number of constants supported by your graphics card though. Again from what I've read, the D3D10/SM4 spec requires cards to support 4096 constant registers, so with a few constants needed for various matrices and other stuff, you'd be limited to about 4000 vertices using a single float4 each for data. In addition to this limitation, I doubt it's really going to be much faster than using a vertex buffer, so as MJP pointed out profiling is key.
This solution (arrays) has two problems: First, the limitation (I think 4000 is not enough, or let's say I can't limit it, although it may never be reached). Second, I have to "precompile" this in my FX file. So, there is no way to define a pointer or something like an array with an undefined size. If I would use let's say 4000 as the fixed size for the array, then I would always have to update the 4000 through the Updatesubresource or however the Effect framework does this.

I thought that a texture (better limitations, 1D or even using the 1Ds of a 2D texture for the data). But there are also two problems: I think that I can't access the texture so, that I do not get sampled or interpolated values (in other words I want the raw and correct data). The second problem is that the texture reads may be very expensive (in contrast to constant buffers).

Yes, I use the VertexID and it does what you said.

The concept to not use a vertex buffer and create the vertices with the VS works quite well (a simple rectangle) "for me", since my vertex data may change very often. For drawing an "unlimited" amount of vertices this should work too. "for me" means I want to produce as less CPU load as possible. Locking VB costs more than setting the some constant shader variables (both for every object).

Any suggestions?

edit: I think that the "buffer" data type of HLSL is not setable in C++ code, only read/setable in HLSL/FX File. Am I right? (keyword: stream-output stage)

Thx,
Vertex
Quote:Original post by Vertex333
This solution (arrays) has two problems: First, the limitation (I think 4000 is not enough, or let's say I can't limit it, although it may never be reached). Second, I have to "precompile" this in my FX file. So, there is no way to define a pointer or something like an array with an undefined size. If I would use let's say 4000 as the fixed size for the array, then I would always have to update the 4000 through the Updatesubresource or however the Effect framework does this.


Well, if the constants limitation is already a show-stopper, then there's little point in discussing the possibilities of setting specific smaller ranges of the array, even moreso since I don't know how this works out in DX10 anyway [smile] In DX9 though, it was possible to use a fixed size array and set individual array elements and/or ranges through the effect framework.

Quote:I thought that a texture (better limitations, 1D or even using the 1Ds of a 2D texture for the data). But there are also two problems: I think that I can't access the texture so, that I do not get sampled or interpolated values (in other words I want the raw and correct data). The second problem is that the texture reads may be very expensive (in contrast to constant buffers).


Yeah, I figured texture reads would be more expensive than either constant buffers or vertex buffers. I think you could get non-interpolated data from the texture using appropriate point filtering, not using mipmaps and fixing up just the right texcoords. You might want to check the Sparse Morph Sample in the DX SDK. As I recall that uses a texture to store morph targets as vertex positions, but I'm not sure.

Anyway, I think if you're worried about vertex buffer locking, then texture locking might prove just as bad. I'm not going to reiterate the importance of profiling [wink]

Quote:
The concept to not use a vertex buffer and create the vertices with the VS works quite well (a simple rectangle) "for me", since my vertex data may change very often. For drawing an "unlimited" amount of vertices this should work too. "for me" means I want to produce as less CPU load as possible. Locking VB costs more than setting the some constant shader variables (both for every object).

Any suggestions?


Do you mean your first idea in the topic start by creating vertices with the VS? I'm not quite sure I follow, since to my mind you'd have to create and set your data *somehwere*, be it in a texture, additional VB, constants or dynamic buffer. You can try and find the optimal vehicle to get the data to the card, but in the end you'll still get some CPU overhead to generate and send it.

Unless of course you can generate the data procedurally, in which case you could calculate it all using vertex and/or geometry shaders without the need to set it explicitly using the CPU.
Rim van Wersch [ MDXInfo ] [ XNAInfo ] [ YouTube ] - Do yourself a favor and bookmark this excellent free online D3D/shader book!
Quote:Original post by remigius
Quote:Original post by Vertex333
This solution (arrays) has two problems: First, the limitation (I think 4000 is not enough, or let's say I can't limit it, although it may never be reached). Second, I have to "precompile" this in my FX file. So, there is no way to define a pointer or something like an array with an undefined size. If I would use let's say 4000 as the fixed size for the array, then I would always have to update the 4000 through the Updatesubresource or however the Effect framework does this.


Well, if the constants limitation is already a show-stopper, then there's little point in discussing the possibilities of setting specific smaller ranges of the array, even moreso since I don't know how this works out in DX10 anyway [smile] In DX9 though, it was possible to use a fixed size array and set individual array elements and/or ranges through the effect framework.

Quote:I thought that a texture (better limitations, 1D or even using the 1Ds of a 2D texture for the data). But there are also two problems: I think that I can't access the texture so, that I do not get sampled or interpolated values (in other words I want the raw and correct data). The second problem is that the texture reads may be very expensive (in contrast to constant buffers).


Yeah, I figured texture reads would be more expensive than either constant buffers or vertex buffers. I think you could get non-interpolated data from the texture using appropriate point filtering, not using mipmaps and fixing up just the right texcoords. You might want to check the Sparse Morph Sample in the DX SDK. As I recall that uses a texture to store morph targets as vertex positions, but I'm not sure.

Anyway, I think if you're worried about vertex buffer locking, then texture locking might prove just as bad. I'm not going to reiterate the importance of profiling [wink]

Quote:
The concept to not use a vertex buffer and create the vertices with the VS works quite well (a simple rectangle) "for me", since my vertex data may change very often. For drawing an "unlimited" amount of vertices this should work too. "for me" means I want to produce as less CPU load as possible. Locking VB costs more than setting the some constant shader variables (both for every object).

Any suggestions?


Do you mean your first idea in the topic start by creating vertices with the VS? I'm not quite sure I follow, since to my mind you'd have to create and set your data *somehwere*, be it in a texture, additional VB, constants or dynamic buffer. You can try and find the optimal vehicle to get the data to the card, but in the end you'll still get some CPU overhead to generate and send it.

Unless of course you can generate the data procedurally, in which case you could calculate it all using vertex and/or geometry shaders without the need to set it explicitly using the CPU.
I only need some little information in contrast to the information that will be output by VS. And... it works quite well (vertex data creation with VS). I disabled the normal vertex buffer by setting the appropriate Vertex layout (so I do not use any vertex buffer). In VS I can use the Vertex ID to generate the vertex data. In addition I use shader variables to generate the vertex data (e.g. topleft and widthheight for rectangle).

I think I got the thing with the buffer working without using a texture. The use of a buffer/shader resource seems to work (not finished, but PIX shader debugging already shows correct vertex data). The pipegs dx sample demonstrate a bit of it.

Thx,
Vertex

This topic is closed to new replies.

Advertisement