Managing constant buffers without FX interface in Direct3D10

Started by
1 comment, last by BrechtDebruyne 11 years, 5 months ago
I am aware that there is a sample on working without FX in the samplebrowser, and I already checked that one. However, some questions arise:


In the sample:

D3DXMATRIXA16 mWorldViewProj;
D3DXMATRIXA16 mWorld;
D3DXMATRIXA16 mView;
D3DXMATRIXA16 mProj;
mWorld = g_World;
mView = g_View;
mProj = g_Projection;
mWorldViewProj = mWorld * mView * mProj;
VS_CONSTANT_BUFFER* pConstData;
g_pConstantBuffer10->Map( D3D10_MAP_WRITE_DISCARD, NULL, ( void** )&pConstData );
pConstData->mWorldViewProj = mWorldViewProj;
pConstData->fTime = fBoundedTime;
g_pConstantBuffer10->Unmap();



They are copying their D3DXMATRIX'es to D3DXMATRIXA16. Checked on msdn, these new matrices are 16 byte aligned and optimised for intel pentium 4. So as my first question:

1) Is it necessary to copy matrices to D3DXMATRIXA16 before sending them to the constant buffer? And if no, why don't we just use D3DXMATRIXA16 all the time?


I have another question about managing multiple constant buffers within one shader.
Suppose that, within your shader, you have multiple constant buffers that need to be updated at different times:


cbuffer cbNeverChanges
{
matrix View;
};
cbuffer cbChangeOnResize
{
matrix Projection;
};
cbuffer cbChangesEveryFrame
{
matrix World;
float4 vMeshColor;
};


Then how would I set these buffers all at different times?
g_pd3dDevice->VSSetConstantBuffers( 0, 1, &g_pConstantBuffer10 );
gives me the possibility to set multiple buffers, but that is within one call.


2) Is that okay even if my constant buffers are updated at different times? And do I suppose I have to make sure the constantbuffers are in the same position in the array as the order they appear in the shader?
Advertisement
The 16-byte aligned version of the matrix probably utilizes the SSE2 instruction set (which is what they mean by P4 optimised).
The matrices are converted into this SSE-friendly format before the two matrix multiplications take place -- that's the significance, not the copying into the buffer afterwards.

Many engines that I've worked with do make use of 16-byte aligned vectors, matrices, and even floats, throughout all math-heavy parts of the code, so that SSE (or equivalent) instruction sets can be used in those parts of the code-base.

The ability to set multiple buffers in a single call to *SSetConstantBuffers is just an optimisation for the times when you would call it 3 times in a row. i.e. You can call it many times to bind resources to many different slots, but if you find that you're making multiple calls in a row, then you can instead pass an array to a single call to reduce the number of API calls you have to make.

2) Yes, updating the contents of a buffer is completely separate to binding that buffer to a slot. If you bind it to a slot, then update it, then it's still bound to the slot.
Basically all your call does is store a pointer to your buffer resource into an array, e.g. conceptually--
device.VertexShaderConstantBuffers[slot] = input;//just storing a pointer
// or
for( int i=0; i != NumBuffers; ++i )
device.VertexShaderConstantBuffers[i+StartSlot] = input;


To match up the slots correctly when binding buffers, you've got 2 choices:
a) After you compile your shader, reflect on the binary to find which slots your named cbuffers have ended up in.
b) When writing your shaders, manually specify which slot a cbuffer is designated with the register keyword
cbuffer MyData : register(b7) // "MyData" buffer should be bound to slot #7
{
};
Thanks, cleared up all my questions :)

This topic is closed to new replies.

Advertisement