Jump to content
  • Advertisement
Sign in to follow this  
smsundar

Using multiple Vertex Buffers

This topic is 2547 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

hi,
I'm a beginner to DX programming. I'm trying to implement multiple Vertex buffer to understand how the 3D Pipeline uses them. In this context I had a bunch of questions on the IA (Input Assembler stage) of DX10 & DX11
a) Theoretically it is possible to bind 16 (/32) vertex buffers to IA stage as per DX10 (/DX11) specs. As per the examples that I've come across till now only states that multiple Vertex Buffers (VB) are used only for different elements of a Vertex data (say 1 buffer for Position, 1 buffer for Texture, 1 buffer for normals etc..)? Is that true?

b) I'm trying to render multiple objects (say for example 2 triangles) with 2 Vertex buffers - Is this a valid usage model? Are there any restrictions in this usage. When I try doing this I do see only the 1st triangle being rendered & the 2nd triangle is not rendered!

Pasting below the code snippet
[color="#008000"][color="#008000"]// Define the input layout

D3D10_INPUT_ELEMENT_DESC layout[] =
{
{ [color="#a31515"][color="#a31515"]"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
};

UINT numElements = [color="#0000ff"][color="#0000ff"]sizeof( layout ) / [color="#0000ff"][color="#0000ff"]sizeof( layout[0] );

[color="#008000"][color="#008000"]// Create the input layout

D3D10_PASS_DESC PassDesc;

g_pTechnique->GetPassByIndex( 0 )->GetDesc( &PassDesc );

hr = g_pd3dDevice->CreateInputLayout(layout, numElements, PassDesc.pIAInputSignature,

PassDesc.IAInputSignatureSize, &g_pVertexLayout );

[color="#0000ff"][color="#0000ff"]if( FAILED( hr ) )

[color="#0000ff"][color="#0000ff"]return hr;

[color="#008000"][color="#008000"]// Set the input layout

g_pd3dDevice->IASetInputLayout( g_pVertexLayout );

[color="#008000"][color="#008000"]// Create vertex buffers

SimpleVertex vertices[] =
{
D3DXVECTOR3( 0.0f, 0.5f, 0.5f ),
D3DXVECTOR3( 0.5f, -0.5f, 0.5f ),
D3DXVECTOR3( -0.5f, -0.5f, 0.5f ),
};

SimpleVertex vertices1[] =
{
D3DXVECTOR3( -0.5f, 0.5f, 0.5f ),
D3DXVECTOR3( 0.0f, 0.5f, 0.5f ),
D3DXVECTOR3( -0.5f, -0.5f, 0.5f ),
};

D3D10_BUFFER_DESC bd;bd.Usage = D3D10_USAGE_DEFAULT;
bd.ByteWidth = [color="#0000ff"][color="#0000ff"]sizeof( SimpleVertex ) * 3;
bd.BindFlags = D3D10_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
bd.MiscFlags = 0;
D3D10_SUBRESOURCE_DATA InitData, InitData1;
InitData.pSysMem = vertices;
hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer[0] );
InitData1.pSysMem = vertices1;
hr = g_pd3dDevice->CreateBuffer( &bd, &InitData1, &g_pVertexBuffer[1] );

[color="#0000ff"][color="#0000ff"]if( FAILED( hr ) )
[color="#0000ff"][color="#0000ff"]return hr;

[color="#008000"][color="#008000"]// Set vertex buffer

UINT stride[2] = {[color="#0000ff"][color="#0000ff"]sizeof( SimpleVertex ), [color="#0000ff"][color="#0000ff"]sizeof(SimpleVertex)};
UINT offset[2] = {0,0};

g_pd3dDevice->IASetVertexBuffers( 0, 2, g_pVertexBuffer, stride, offset );

[color="#008000"][color="#008000"]// Set primitive topology

g_pd3dDevice->IASetPrimitiveTopology( D3D10_PRIMITIVE_TOPOLOGY_TRIANGLELIST );

[color="#008000"][color="#008000"]// Draw the triangles for the respective pass

[color="#0000ff"][color="#0000ff"]for( UINT p = 0; p < techDesc.Passes; ++p )
{
g_pTechnique->GetPassByIndex( p )->Apply( 0 );
g_pd3dDevice->Draw( 6, 0 );
}



Am I missing anything here? Please help

Share this post


Link to post
Share on other sites
Advertisement
The way to use multiple vertexbuffers in the way you are using it is for different kinds of elements (i.e. Position, Normal, Tangent, etc.). To render multiple triangles you either have to store several triangles in the same vertexbuffer, or make several draw-calls with different vertexbuffers bound. Or if the geometry, etc. is the same (i.e. the only difference is the orientation of the object in the world) you can reuse the vertexbuffer and just change the worldmatrix (i.e. update a constantbuffer) between draw-calls.

Share this post


Link to post
Share on other sites

The way to use multiple vertexbuffers in the way you are using it is for different kinds of elements (i.e. Position, Normal, Tangent, etc.). To render multiple triangles you either have to store several triangles in the same vertexbuffer, or make several draw-calls with different vertexbuffers bound. Or if the geometry, etc. is the same (i.e. the only difference is the orientation of the object in the world) you can reuse the vertexbuffer and just change the worldmatrix (i.e. update a constantbuffer) between draw-calls.


Thanks for your reply.
a) When I make a SINGLE vertex buffer, I'm able to render the triangles (both of them). BTW, I do not want to use them
b) Geometry might or might not be the same. I'm ignoring the fact now that I do not want to change the World Matrix to place the objects in different locations or bother about instancing also

My requirement is to purely use 2 (or more) Vertex buffers & draw them on to screen (irrespective of their geometry). As per your statement "make several draw-calls with different vertexbuffers bound" . With a single call to
g_pd3dDevice->IASetVertexBuffers( 0, 2, g_pVertexBuffer, stride, offset );

both the (Vertex) buffers are bound to the pipeline isn't it? Do I need to call set vertex buffers twice (with different vertex bindings)? Ideally I'd like to have VB0 in slot 0 & VB1 in slot 1 & apparently that is what is done in the above call. Is my assumption wrong?

Share this post


Link to post
Share on other sites

Thanks for your reply.
a) When I make a SINGLE vertex buffer, I'm able to render the triangles (both of them). BTW, I do not want to use them
b) Geometry might or might not be the same. I'm ignoring the fact now that I do not want to change the World Matrix to place the objects in different locations or bother about instancing also


I'm note sure what you mean by "I do not want to use them". In b, With geometry I mean that if the contents of the vertexbuffer will be the same for several objects, its better to use the same buffer for all the objects than to create a new for each.


My requirement is to purely use 2 (or more) Vertex buffers & draw them on to screen (irrespective of their geometry). As per your statement "make several draw-calls with different vertexbuffers bound" . With a single call to
g_pd3dDevice->IASetVertexBuffers( 0, 2, g_pVertexBuffer, stride, offset );

hmm, If I understand you correctly, I don't think that it's possible, but with that said someone else might know. But if I needed to only make one call to draw (and setvertexbuffer) I probably would have merge the vertexbuffers to one (if the inputlayout was the same for the buffers) before setting it and drawing it.

both the (Vertex) buffers are bound to the pipeline isn't it? Do I need to call set vertex buffers twice (with different vertex bindings)? Ideally I'd like to have VB0 in slot 0 & VB1 in slot 1 & apparently that is what is done in the above call. Is my assumption wrong?

Yes, both are bound, however only one is used, in your [color="#1C2837"]

D3D10_INPUT_ELEMENT_DESC,http://msdn.microsof...6(v=vs.85).aspx ,

you describe semantic and which inputslot to fetch that data from, i.e. in your case get "POSITION" from inputslot 0, with datasize of float3 (R32G32B32).

Share this post


Link to post
Share on other sites
Thank you so much for the pointers
Realised that the input layout description declared tells that ONLY slot 0 is being used (though both the vertex buffers are bound. To correct this I made this change in the Layout declaration. Please see below
[color="#008000"][color="#008000"]
[color="#008000"][color="#008000"]// Define the input layout
D3D10_INPUT_ELEMENT_DESC layout[] =
{
{ [color="#a31515"][color="#a31515"]"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
{ [color="#a31515"][color="#a31515"]"POSITION", 1, DXGI_FORMAT_R32G32B32_FLOAT, 1, 0, D3D10_INPUT_PER_VERTEX_DATA, 0 },
};

This time I'm using slot 0 & slot 1 to be as position. Is this correct? (Hmm,, even now I do not see the 2nd triangle not getting rendered :( ). Do I need to issue 2 draw calls here?

To answer your other questions
YES, with merging both the Vertex buffers (and eventually issuing ONE draw call) I'm able to see both the triangles getting rendered!



Share this post


Link to post
Share on other sites

  1. As per the examples that I've come across till now only states that multiple Vertex Buffers (VB) are used only for different elements of a Vertex data (say 1 buffer for Position, 1 buffer for Texture, 1 buffer for normals etc..)? Is that true?
  2. I'm trying to render multiple objects (say for example 2 triangles) with 2 Vertex buffers - Is this a valid usage model? Are there any restrictions in this usage. When I try doing this I do see only the 1st triangle being rendered & the 2nd triangle is not rendered!


  1. It's more complicated than that. You can put multiple vertex attributes in the same VB resource (example: position to VB0, color+texcoord to VB1). Nobody mandates a specific layout. All vertices however, share the same indexing positions. That is, if you have two vbs with vertex stride being VB0[sub]S[/sub] and VB1[sub]S[/sub], index [3] in IB will access VB0+3*VB0[sub]S[/sub] and VB1+3*VB1[sub]S[/sub]. From those memory addresses, it will pull out blobs of data according to vertex format description and assemble a vertex. The offset will be the same in terms of indices.
  2. Yes, it is valid. But it's probably not what you're trying to do. If you put your first triangle in VB0 and your second in VB1 (like two different models), you're expected to issue two draw calls. No way you can somehow "cross the bounduaries" of a VB.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • 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!