0

I'm working on a Directx C++/CX (Universal Windows) project.

I'm not all that familiar with Directx11 by the way.

My code is mostly based on the sample projects on MSDN related to rendering directx in UWP using swapchainpanels.

Now I wanted to add a float variable to the shader. I believe this has to be done using the constantbuffer. Currently this is as follows (and works):

//c++:
struct ModelViewProjectionConstantBuffer
{
    DirectX::XMFLOAT4X4 model;
    DirectX::XMFLOAT4X4 view;
    DirectX::XMFLOAT4X4 projection;
    //float distance;
};

//hlsl:
cbuffer ModelViewProjectionConstantBuffer : register(b0)
{
    matrix model;
    matrix view;
    matrix projection;
    //float distance;
};

Now when I add a float, it stops working. It throws an exception when I update the constant buffer (which happens before each rendered frame):

_d3dContext->UpdateSubresource(
    _constantBuffer.Get(),
    0,
    NULL,
    &_constantBufferData,
    0,
    0
);

The exception is a SEHException (so as far as I can find, this doesn't tell me anything).

I'm basing all this on the following page: https://msdn.microsoft.com/en-us/library/ff476896(v=vs.85).aspx

Can anyone tell me what I'm doing wrong?

Stef
  • 315
  • 3
  • 14

1 Answers1

2

Constant buffers have size aligned on 16 bytes, when you had a single float at the end, you in fact inflate the constant buffer size by 16, but on the code side, your struct only inflate by 4. What is happening is that UpdateSubResource try to read these 12 extra bytes and produce a memory access violation.

You should be able to fix things by adding the padding like that

struct ModelViewProjectionConstantBuffer
{
   DirectX::XMFLOAT4X4 model;
   DirectX::XMFLOAT4X4 view;
   DirectX::XMFLOAT4X4 projection;
   float distance;
   float pad[3]
};

You can read about the padding rules here for more details : https://msdn.microsoft.com/en-us/library/windows/desktop/bb509632(v=vs.85).aspx

galop1n
  • 8,573
  • 22
  • 36
  • If your reasoning is correct, and this is the core issue, then it would be easier and safer to use an `XMFLOAT4X4A` in place of the `XMFLOAT4X4`s. The padding is thus no longer necessary. – IInspectable Nov 08 '16 at 02:10
  • @IInspectable Not really, some rules are more subtile and cannot reproduce with the C++ language, even if in the OP case, it would do the trick. Another solution would be to provide the proper size of the code object to `UpdateSubResource` but then the debug layer would flood the log with a warning that you upload less than the cbuffer size ( that is 100% safe in our case ). – galop1n Nov 08 '16 at 06:59
  • Thanks, yeah that fixes it. I realise now that's what they were trying to say on those msdn pages (but I feel they could have been a lot more clear). It would also have been usefull if the exception contained any usefull info. :| – Stef Nov 08 '16 at 10:50
  • @Stef: Every SEH exception comes with an exception code. You decided to ignore it, and now complain, that there is no useful information. That doesn't make sense. Add the exception code to your question. – IInspectable Nov 08 '16 at 14:31
  • @IInspectable: I didn't ignore it, I looked up what that code could mean but found absolutely nothing. Don't assume I ignored it. If you can point me to where I can go to with these exception codes it would be much appreciated. – Stef Nov 08 '16 at 16:05
  • @Stef: You certainly never posted the value in your question (and that's where it belongs). If you need to look up the error code, you'd best go looking for the value in hexadecimal representation (instead of the decimal representation, of a (probably) negative value). – IInspectable Nov 08 '16 at 16:13
  • A good way to ensure this is to use ``static_assert( (sizeof(ModelViewProjectionConstantBuffer) % 16) == 0, "Constant buffers should be 16-byte aligned);`` – Chuck Walbourn Nov 08 '16 at 17:18