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\$
11
  • \$\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, 2016 at 8:10
  • \$\begingroup\$ Suggested reading: Packing Rules for Constant Variables \$\endgroup\$ Oct 10, 2016 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\$ Oct 10, 2016 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\$ Oct 10, 2016 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\$ Oct 10, 2016 at 12:02

1 Answer 1

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\$
6
  • \$\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\$ Oct 10, 2016 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\$ Oct 10, 2016 at 13:52
  • \$\begingroup\$ So should all variables with a set value come before the variables pad, pad1, pad2 etc... ? \$\endgroup\$ Oct 10, 2016 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\$ Oct 10, 2016 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\$ Oct 10, 2016 at 14:29

You must log in to answer this question.

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