3
\$\begingroup\$

I've got a shader with the following constant buffer:

cbuffer ShaderParameters
{
    matrix inverseViewProjectionMatrix;
    float4 cameraPosition;
};

When using Visual Studio 2012's graphic debugger I see that the last column of this matrix contains only NaNs, the other values are correct. So somehow my program is passing wrong values to the GPU.

However when I debugged my C++ code I see no NaNs in the matrix that I upload to the GPU. So what is going on? Below are the relevant parts of code

Struct for the constant buffer on the CPU:

struct ShaderParameters
{
    XMMATRIX inverseViewProjectionMatrix;
    XMFLOAT4 cameraPosition;
};

Buffer creation:

D3D11_BUFFER_DESC shaderParametersDesc;
shaderParametersDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
shaderParametersDesc.ByteWidth = sizeof(ShaderParameters);
shaderParametersDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
shaderParametersDesc.MiscFlags = 0;
shaderParametersDesc.StructureByteStride = 0;
device->CreateBuffer(&shaderParametersDesc, NULL, &m_shaderParameters);

Buffer setting (every frame)

D3D11_MAPPED_SUBRESOURCE mappedResource;
ShaderParameters* shaderParameters;
deviceContext->Map(m_shaderParameters, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
shaderParameters = (ShaderParameters*)mappedResource.pData;

XMMATRIX view = camera->GetViewMatrix();
XMMATRIX proj = camera->GetProjectionMatrix();
XMMATRIX mult = XMMatrixMultiply(view, proj);
XMMATRIX invp = XMMatrixInverse(nullptr, mult);

if(XMMatrixIsNaN(invp))
    throw std::exception("invp is NAN");

shaderParameters->inverseViewProjectionMatrix = XMMatrixTranspose(invp);
shaderParameters->cameraPosition = camera->GetPosition();

deviceContext->Unmap(m_shaderParameters, 0);
deviceContext->VSSetConstantBuffers(0, 1, &m_shaderParameters);

Note that the exception is never thrown and if I inspect the matrix manually there are sane values in there (see image) values on CPU and GPU

EDIT: some asked (via twitter) to include some more shader source code as unused values might be seen by the debugger as NaN. So here is the complete vertex shader:

cbuffer ShaderParameters
{
    matrix inverseViewProjectionMatrix;
    float4 cameraPosition;
};

struct VertexInputType
{
    float4 position : POSITION;
    float4 uv       : TEXCOORD0;
};

struct PixelInputType
{
    float4 position         : SV_POSITION;      
    float4 direction        : TEXCOORD0;
    float4 cameraPosition   : TEXCOORD1;
};

PixelInputType main(VertexInputType input)
{
        PixelInputType output;

        input.position.w = 1.0f;        
        output.position = input.position;

        output.direction = mul(input.position, inverseViewProjectionMatrix) - cameraPosition;
        output.direction.xyz = normalize(output.direction.xyz);

        output.direction.w = 1.0f;  

        output.cameraPosition = cameraPosition;

        return output;
}
\$\endgroup\$

1 Answer 1

5
\$\begingroup\$

The person on Twitter was right.

Because you overwrite output.direction.w with 1.0f the shader optimizer will see that it doesn't need to use that row of the matrix to calculate it.

Try commenting out that line to see the effect - the disassembly will include an extra dp4 instruction when it's gone.

\$\endgroup\$
4
  • \$\begingroup\$ Wow, that I wasn't expecting. Especially since I set some compiler options to prevent this kind of stuff (/Od, disables optimizations, /Zi enables debug info). Man some hours wasted on this :P. \$\endgroup\$
    – Roy T.
    Commented Mar 2, 2013 at 16:48
  • \$\begingroup\$ Those are options for the C++ compiler, not the shader compiler. You can change optimization settings for the shader compiler too if you want - pass D3DCOMPILE_SKIP_OPTIMIZATION to D3DCompile(). \$\endgroup\$
    – Adam
    Commented Mar 2, 2013 at 23:46
  • \$\begingroup\$ they are in the VS2012 shader compiler property window so I'm pretty sure they are for the shader compiler :). There is no D3DCOMPILE_SKIP_OPTIMIZATION flag there but maybe I can add it manually, I'll have to consult the docs. \$\endgroup\$
    – Roy T.
    Commented Mar 3, 2013 at 9:52
  • \$\begingroup\$ Ahh yeah, sorry, those are the command line options for fxc too. I was assuming you were compiling shaders at runtime. \$\endgroup\$
    – Adam
    Commented Mar 3, 2013 at 11:15

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .