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

## Recommended Posts

I've been thinking about how to go about doing this for a while now. I've got a shader parameter system that basically creates a chunk of data from a parameter list and allows them to be set using a map of names and offsets. The thing I can't figure out though, is how I should calculate padding for the parameters. Basically I allocate the data and store offsets like this:

bool IShaderParameterBuffer::init(const std::vector<SShaderParameterDesc>& paramDesc)
{
size_t offset = 0;

for ( unsigned int i=0; i<paramDesc.size(); ++i )
{
size_t paramSz = IInputLayout::getElementSize(paramDesc[i].Format);

m_offsetMap[paramDesc[i].Name] = offset;
offset += paramSz;
}

m_paramBuffer = (char*)malloc(offset);
m_bufferSz = offset;

return true;
}


And I take this information to create a constant buffer, but const buffer size has to be a multiple of 16. What would be the best way to go about making sure that the data size is a multiple of 16?

##### Share on other sites
m_bufferSz = (offset + 15) & 0xfffffff0;

m_bufferSz = ((offset + 15) / 16) * 16. //same thing without hex and bitwise-and if you don't like those


It sounded like that's all you were asking (pad for 16B boundary). If I misinterpreted, please clarify what you're looking for.

Edit: originally had 0x100, which is obviously wrong. (2nd edit: more fail)

Edited by richardurich

##### Share on other sites

I've deleted a lot of data just to make the post smaller.

My formula for a variable size is:

return (arraySize - 1) * 16 + VariableType_GetSizeByes(type);
where array size for non arrays is 1

Where array size for non-arrays is 1. VariableType_GetSizeByes returns the size in bytes for(float, int, float2, float3.. ect)

U32 GetTotalSizeBytes() const
{
const int numVariables = GetNumVariables();

U32 totalSize = 0;

for(int t = 0; t < numVariables; ++t)
{
const VariableReflection& var = GetVariable(t);
const U32 varSize = var.GetSizeBytes();

if (var.arraySize > 1 || bForceNewVectorPadding)//array or forced variable
{
totalSize += varSize;

//bForceNewVectorPadding = var.arraySize > 1; //next variable starts new vector
}
else //non forced variable
{
U32 freeSpaceUntilNextVector = 16 - totalSize % 16;

if (varSize <= freeSpaceUntilNextVector) totalSize += varSize;
else totalSize += varSize + freeSpaceUntilNextVector;
}
}

}

D3DReflect can provide you variable offset and total buffer size. http://msdn.microsoft.com/en-us/library/windows/desktop/ff476213(v=vs.85).aspx

To check things fast use install the "hello triangle" demo form the DXSDK June2010 and add that code under the vertex shader compilation:

for (UINT i = 0; i < shaderDesc.BoundResources; i++)
{
pReflection->GetResourceBindingDesc(i, &resourceDesc);

switch (resourceDesc.Type)
{
//CBuffer
case D3D_SIT_CBUFFER:
{
const char* pCBufferName = resourceDesc.Name;

pCBufferReflection->GetDesc(&desc);

for (unsigned int t = 0; t < desc.Variables; ++t)
{

pVariable->GetDesc(&varDesc);

int x = 10;//bla bla
};
}
}
};

Edited by imoogiBG

##### Share on other sites

U32 GetTotalSizeBytes() const
{
const int numVariables = GetNumVariables();

U32 totalSize = 0;

for(int t = 0; t < numVariables; ++t)
{
const VariableReflection& var = GetVariable(t);
const U32 varSize = var.GetSizeBytes();

if (var.arraySize > 1 || bForceNewVectorPadding)//array or forced variable
{
totalSize += varSize;

//bForceNewVectorPadding = var.arraySize > 1; //next variable starts new vector
}
else //non forced variable
{
U32 freeSpaceUntilNextVector = 16 - totalSize % 16;

if (varSize <= freeSpaceUntilNextVector) totalSize += varSize;
else totalSize += varSize + freeSpaceUntilNextVector;
}
}

}

I know you said you deleted a lot of your post to make it smaller, so I worry you might have deleted something important that makes it seem weird right now.

I can't figure out what the code intends to do with "totalSize += totalSize %16;". As listed, if you pass in char[2] elem1, char[2] elem2, char[2] elem3, you get elem1, 2 bytes of padding, elem2, 6 bytes of padding, elem3, 14 bytes of padding, elem4. Maybe that is the intent, but it seems really weird.

For OP, it's worth noting "- totalSize % 16" is mathematically the same as "& 0xfffffff0", ">>4)<<4", "/16) * 16". I suspect the only reason %16 isn't common in code is that it requires using 2 lines of code instead of one.

Edit: fixed f00 to f0 per L. Spiro's correction.

Edited by richardurich

##### Share on other sites

It’s 0xFFFFFFF0, not 0xFFFFFF00.

L. Spiro

##### Share on other sites

It’s 0xFFFFFFF0, not 0xFFFFFF00.

L. Spiro

Thank you for the correction.

##### Share on other sites

Yes i've deleted the wrong thing :

if (var.arraySize > 1 || bForceNewVectorPadding)//array or forced variable
{
...

totalSize += 16 - totalSize % 16; // add padding that line starts a new vector(16 byte aligned block). Imagine cbuffer like that:
float2 var;
float array[3];

var -> 8 bytes (total size of the buffer until now is 8 bytes)

array -> according to MSDN arrays are forced to start in a new 16byte aligned block

totalSize += 16 - totalSize % 16; or totalSize += 16 - 8 % 16

• ### Game Developer Survey

We are looking for qualified game developers to participate in a 10-minute online survey. Qualified participants will be offered a \$15 incentive for your time and insights. Click here to start!

• 16
• 11
• 23
• 42
• 75