Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Alright, I'm having a hard time grasping how constant buffers are bound to a pipeline stage and updated. I understand that DirectX11 can have up to 15 shader-constant buffers per stage and each buffer can hold up to 4096 constants. However, I don't understand whether the ID3D11Buffer COM used to interact with the constant buffers is just a mechanism (or handle) used for fill these buffer slots or if the object actually references a particular instance of buffer data that is pushed back and forth between the GPU and CPU.

I think my confusion on the topic is the cause of a problem I'm having using two different constant buffers.

Here is some example shader code.

cbuffer PerFrame : register(b0) {
    float4x4 view;
};

cbuffer PerObject : register(b1) {
    float4x4 scale;
    float4x4 rotation;
    float4x4 translation;
};

The way my code is organized, the camera will be handling updating the relevant per frame data and GameObjects will be updating their own per object data. Both classes have their own ID3D11Buffer that is used to do this (Using a hub architecture, so one GameObject class will handle the rendering of all the instanced GameObjects in the world).

The problem is I can only get one updated at a time, depending on the slot and I presume the update order one buffer gets filled while the other gets zero'd out.

This is essentially my code. Both classes use identical update logic.

static PerObjectShaderBuffer _updatedBuffer; // PerFrameShaderBuffer if Camera class
_updatedBuffer.scale       = _rScale;
_updatedBuffer.rotation    = _rRotation;
_updatedBuffer.translation = _rTranslation;
pDeviceContext->UpdateSubresource(pShaderBuffer, 0 , 0, &_updatedBuffer, 0, 0);

pDeviceContext->VSSetShader(pVShader->GetShaderPtr(), 0, 0);
pDeviceContext->PSSetShader(pPShader->GetShaderPtr(), 0, 0);
pDeviceContext->VSSetConstantBuffers(1, 1, &pShaderBuffer);
pDeviceContext->IASetVertexBuffers(0, 1, &pVertexBuffer, &vStride, &_offset );
pDeviceContext->IASetPrimitiveTopology(topologyType);
pDeviceContext->Draw(bufSize, 0);

My main questions are -

- Do I need to set or bind the ShaderBuffer in order to update it with the UpdateSubresource call? (Meaning manipulate it only when it is in the pipeline) Or is it a blob of data that will be sent in with the VSSetConstantBuffer call? (Meaning the order of binding and updating data doesn't matter, I can update it in the pipeline or somehow on the cpu)
- When setting or binding the buffer, do I need to reference slot 0 to update the PerFrame buffer and slot 1 to update the PerObject buffer? Could some kind of confusion with this call in my code cause all the buffers to be overwritten?
- How does D3D11 know which buffer I want to update or map? Does it know from the ID3D11Buffer COM used?

Edit -

Changed the constant buffer register tags in the example above. Using (cb#) instead of (b#) was affecting the buffers from updating correctly for some reason. Not sure where I picked up the original syntax or if it's valid at all, but it appears to of been my main problem.

share|improve this question

1 Answer 1

up vote 11 down vote accepted

The ID3D11Buffer references an actual chunk of memory that holds your data, whether it's a vertex buffer, constant buffer, or whatever.

Constant buffers work the same way as vertex buffers and other kinds of buffers. Namely, the data in them isn't accessed by the GPU until it actually renders the frame, so the buffer has to remain valid until the GPU is done with it. You should double-buffer each constant buffer, so you have one copy to update for the next frame, and one copy for the GPU to read while rendering the current frame. This is similiar to how you would do dynamic vertex buffers for a particle system or suchlike.

The register(cb0), register(cb1) settings in the HLSL correspond with the slots in VSSetConstantBuffers. When you update the per-frame constants you'd do VSSetConstantBuffers(0, 1, &pBuffer) to set CB0 and when you update the per-object ones you'd do VSSetConstantBuffers(1, 1, &pBuffer) to set CB1. Each call updates only the buffers referred to by the start/count parameters, and doesn't touch the others.

You do not need to bind the buffer to update it with UpdateSubresource. In fact, it shouldn't be bound when you update it, or this may force the driver to make extra memory copies internally (see the MSDN page for UpdateSubresource, notably the remarks on contention about a page down).

I'm not sure what you mean by "How does D3D11 know which buffer I want to update or map?" It updates or maps the one whose pointer you passed in.

share|improve this answer
    
Thanks! That makes thing a lot more clear. –  KlashnikovKid Oct 6 '11 at 0:23

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.