Data structure with bool field. How to set correctly?

Started by
6 comments, last by iedoc 9 years, 1 month ago

Hello,

I have following structure in cpp:


struct PixelData
{
    float r;
    float g;
    float b;
    float a;
    unsigned int texId;
    unsigned int type;
    unsigned int index;
    bool clip;
    unsigned int clippedParentIndex;
};

in pixel shader I have this data:


struct Data
{
    float4 col;
    uint texId;
    uint type;
    uint index;
    bool clip;
    uint clippedParentIndex;
};

I'm using this data with shader resource:


D3D11_BUFFER_DESC psDataBufferDesc{};
psDataBufferDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
psDataBufferDesc.ByteWidth = sizeof(PixelData) * maxQuads;
psDataBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
psDataBufferDesc.StructureByteStride = sizeof(PixelData);
psDataBufferDesc.Usage = D3D11_USAGE_DYNAMIC;
psDataBufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;

hr = device->CreateBuffer(&psDataBufferDesc, NULL, psDataBuffer.ReleaseAndGetAddressOf());
throwIfFailed(hr);

hr = device->CreateShaderResourceView(psDataBuffer.Get(), NULL, psDataView.ReleaseAndGetAddressOf());
throwIfFailed(hr);

and


vector<PixelData> pixelData;
pixelData.push_back({ 0.0f, 0.0f, 0.0f, 0.0f, 0, 0, 0, false, 0 });

D3D11_MAPPED_SUBRESOURCE mappedResource2;
hr = context->Map(psDataBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource2);
throwIfFailed(hr);

memcpy(mappedResource2.pData, static_cast<void*>(pixelData.data()), sizeof(PixelData) * pixelData.size());

context->Unmap(psDataBuffer.Get(), 0);

context->PSSetShaderResources(0, 1, psDataView.GetAddressOf());

Here pixelData have correct data, I double (actually triple) checked. But when I debug shader, bool field in Data is always true. Why? Maybe there're some rules that bool can't be set like this?

Advertisement

According to this thread:

http://www.gamedev.net/topic/633446-problem-setting-constant-buffers/

A bool is 4 bytes in HLSL. So try replacing your bool in PixelData with a BOOL.

phil_t is correct: the "bool" type in HLSL is 32bit/4 bytes. Same with "int" and "uint". I would suggest that you use types with well-defined sizes for your corresponding C++ struct, so that there's no ambiguity. stdint.h has types such as "uint32_t" and "int32_t" that work well for this purpose.

bool is 4 bytes? Hmm, that make sense. I thought about it, but couldn't find find any info in documentation.

Thank you guys. I just changed bool to int and now everything works fine.


[...] I just changed bool to int and now everything works fine.

To be as safe as possible you should

a) use types uint32_t and int32_t from stdint.h as suggested by MJP

b) do data padding manually; if possible disable automatic packing, e.g.


 #pragma pack(push, 1)
 struct PixelData { … };
 #pragma pack(pop)

c) implement a compile time check like (this one offered by c++11)


 static_assert(sizeof(PixelData)==36, "PixelData not correctly sized")

_

If you are not sure at some point, you can also apply a static assertion using the offsetof operation on particular struct fields.

Nice, thank you!

You could fit 32 bools into that int32_t... My efficiency sense is tingling...
for official documentation, first link you can see bool Is 1 byte. Second link shows BOOL is actually a typedef for int. Then looking back to the first link, you will see int is 4 bytes. Sorry, I've answered this before with a link to where BOOL size is directly provided, but cant seem to find that msdn Link now

https://msdn.microsoft.com/en-us/library/s3f49ktz.aspx

https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751%28v=vs.85%29.aspx

Speaking of efficiency, hlsl packs buffers into 16 byte chunks, in your original post you have 33 bytes. If you turn that bool into a BOOL, you'd have 36 bytes, which means when you send the buffer to the shaders, you'll be sending 48 bytes, just pointing that out in case its helpful

This topic is closed to new replies.

Advertisement