0
\$\begingroup\$

In my cbuffer in DirectX, I send 2 variables over to my HLSL shader called Light & Roughness. If I remove the Roughness variable my program compiles fine but as soon as I introduce Roughness I get the error: Exception thrown at 0x00007FFDDEFA0030 (d3d11.dll) in Eagle Engine.exe: 0xC0000005: Access violation reading location 0x00000000000000C0.

On the HLSL side the light variable contains it's defined value that was set in C++ and works fine without Roughness. If anyone could help me that would be great, I've included the necessary code below.

effects.fx

#include "Common.hlsl"

struct Light
{
    float3 dir;
    float4 ambient;
    float4 diffuse;
};

cbuffer cbPerFrame
{
    Light light;
    float Roughness;
};

cbuffer cbPerObject
{
    float4x4 WVP;
    float4x4 World;
};

Texture2D ObjTexture;
SamplerState ObjSamplerState
{
    Filter = ANISOTROPIC;
    MaxAnisotropy = 16;
    AddressU = Wrap;
    AddressV = Wrap;
};

struct VS_OUTPUT
{
    float4 Pos : SV_POSITION;
    float2 TexCoord : TEXCOORD;
    float3 normal : NORMAL;
};

float3 DirectDiffuseBRDF(float3 diffuseAlbedo, float nDotL)
{
    return (diffuseAlbedo * nDotL);
}

VS_OUTPUT VS(float4 inPos : POSITION, float2 inTexCoord : TEXCOORD, float3 normal : NORMAL)
{
    VS_OUTPUT output;

    output.Pos = mul(inPos, WVP);

    output.normal = mul(normal, World);

    output.TexCoord = inTexCoord;

    return output;
}

float4 PS(VS_OUTPUT input) : SV_TARGET
{
    input.normal = normalize(input.normal);

    float4 textureColor = ObjTexture.Sample(ObjSamplerState, input.TexCoord);

    float nDotL = saturate(dot(input.normal, light.dir));

    float3 diffuseLighting = textureColor * light.ambient * light.diffuse * Roughness;
    diffuseLighting += saturate(DirectDiffuseBRDF(textureColor, nDotL));

    return float4(diffuseLighting, textureColor.a);
}

In my Main.cpp

constbuffPerFrame.light = light;
constbuffPerFrame.Roughness = 1.0f;

devcon->UpdateSubresource(cbPerFrameBuffer, 0, NULL, &constbuffPerFrame, 0, 0);
devcon->PSSetConstantBuffers(0, 1, &cbPerFrameBuffer);

Header.h

struct Light
{
    Light()
    {
        ZeroMemory(this, sizeof(Light));
    }
    XMFLOAT3 dir;
    float pad;
    XMFLOAT4 ambient;
    XMFLOAT4 diffuse;
    XMFLOAT4 specular;
};

struct cbPerFrame
{
    Light  light;
    float Roughness;
};

Light light;
cbPerFrame constbuffPerFrame;
\$\endgroup\$
  • \$\begingroup\$ Are you using visual studio? if you are you can use the visual debugger to closer study what happens you can find it under debug->graphics->startthegraphicaldebugger \$\endgroup\$ – Hampus Oct 10 '16 at 8:10
  • \$\begingroup\$ Suggested reading: Packing Rules for Constant Variables \$\endgroup\$ – Maximus Minimus Oct 10 '16 at 8:41
  • 1
    \$\begingroup\$ You fill the constbufferperframe object in your C++ code but when calling UpdateSubresourcem you pass a _cbperframe object to the function. Or just a typo? \$\endgroup\$ – János Turánszki Oct 10 '16 at 8:43
  • \$\begingroup\$ @JánosTuránszki My entire post contained typos, didn't explain what the problem was, didn't include proper code or what the error was. I've updated my post to include those things (hopefully to make it more clear). \$\endgroup\$ – Arjan Singh Oct 10 '16 at 11:49
  • \$\begingroup\$ "Light light;" and what's the layour of this struct? I ask because it's almost certainly a packing problem and if so you should read and understand the link I posted. \$\endgroup\$ – Maximus Minimus Oct 10 '16 at 12:02
2
\$\begingroup\$

You are not padding after the roughness in the C++ side structure. You need to add 3 more floats of padding after roughness so that the buffer size is a multiple of 16 bytes.

On MSDN you can read a more complete explanation.

\$\endgroup\$
  • \$\begingroup\$ Thanks for the answer. In the MSDN documentation it mentions things like 1 x 16, 2 x 16, 3 x 16 elements. How do you determine which is which and how to 'pad' it? All the jargon in the MSDN page has me a little clueless. \$\endgroup\$ – Arjan Singh Oct 10 '16 at 13:24
  • \$\begingroup\$ When a variable would overflow the 16 byte boundary, then the previous variable is padded, and the new one will be placed on the next 16 bytes. The article just gives you a few examples for this. \$\endgroup\$ – János Turánszki Oct 10 '16 at 13:52
  • \$\begingroup\$ So should all variables with a set value come before the variables pad, pad1, pad2 etc... ? \$\endgroup\$ – Arjan Singh Oct 10 '16 at 13:55
  • 1
    \$\begingroup\$ No, for example if you would like to add an other float value, just replace a padding value with that. If you'd like to add a float3 value, replace pad,pad1,pad2 values with that. If you'd like to add a float4, then it should either go before the roughness, or after pad2. \$\endgroup\$ – János Turánszki Oct 10 '16 at 14:01
  • \$\begingroup\$ What are the byte sizes for float, float2, float3, float4? So basically all the variables within the buffer should multiply to give 16 bytes? \$\endgroup\$ – Arjan Singh Oct 10 '16 at 14:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.