2

I have a problem with DirectX 12. I have made a small 3D renderer. Models are translated to 3D space in vertex shader with basic World View Projection matrixes that are in constant buffer.

To change data of the constant buffer i'm currently using memcpy(pMappedConstantBuffer + alignedSize * frame, newConstantBufferData, alignedSize) this command replaces constant buffer's data immediately.


So the problem comes here, drawing is recorded to a command list that will be later sent to the gpu for execution.

Example:

/* Now i want to change the constant buffer to change the next draw call's position to (0, 1, 0) */
memcpy(/*Parameters*/);

/* Now i want to record a draw call to the command list */
DrawInstanced(/*Parameters*/);

/* But now i want to draw other mesh to other position so i have to change the constant buffer. After this memcpy() the draw position will be (0, -1, 0) */
memcpy(/*Parameters*/);

/* Now i want to record new draw call to the list */
DrawInstanced(/*Parameters*/);

After this i sent the command list to gpu for execution, but quess what all the meshes will be in the same position, because all memcpys are executed before even the command list is sent to gpu. So basically the last memcpy overwrites the previous ones.


So basically the question is how do i draw meshes to different positions or how to replace constant buffer's data in the command list so the constant buffer changes between each draw call on gpu?

Thanks


No need for help anymore i solved it by myself. I created constant buffer for each mesh.

  • could you please format it a little bit? – Enamul Hassan Sep 30 '16 at 18:38
  • @manetsus My problem is that i need to have different constant buffers for each draw call and when you use memcpy it happens immediately unlike the drawing that is recorded and later sent for execution example: memcpy();(to update position to draw the mesh, this happens immediately), DrawInstanced() (this is recorded to the list);, memcpy() (now i want to change position to other, but now it overwrites the previous), DrawInstanced()(now i want to draw other mesh and this will be added to the list). (Now the list will be sent to gpu, and it's going to draw the models to the same place, because – Nopeeananasnas Sep 30 '16 at 19:06
  • @manetsu the first constant buffer update is overwritten by the second one – Nopeeananasnas Sep 30 '16 at 19:07
  • So the question is how to make different constant buffer for each draw call or is there any way to update constant buffer with ID3D12GraphicsCommandList – Nopeeananasnas Sep 30 '16 at 19:15
  • I assume you would need different constant buffers. But not sure. – Nico Schertler Sep 30 '16 at 21:58

1 Answers1

1

About execution order, you are totally right, you memcpy calls will update the buffers immediately, but the commands will not be processed until you push your command list in the queue (and you will not exactly know when this will happen).

In Direct3D11, when you use Map on a buffer, this is handled for you (some space will be allocated to avoid that if required).

So In Direct3D12 you have several choices, I'll consider that you want to draw N objects, and you want to store one matrix per object in your cbuffer.

First is to create one buffer per object and set data independently. If you have only a few, this is easy to maintain (and extra memory footprint due to resource allocations will be ok)

Other option is to create a large buffer (which can contain N matrices), and create N constant buffer views that points to the memory location of each object. (Please note that you also have to respect 256 bytes alignment in that case too, see CreateConstantBufferView).

You can also use a StructuredBuffer and copy all data into it (in that case you do not need the alignment), and use an index in the vertex shader to lookup the correct matrix. (it is possible to set a uint value in your shader and use SetGraphicsRoot32BitConstant to apply it directly).

mrvux
  • 8,523
  • 1
  • 27
  • 61