1
\$\begingroup\$

I have a shader that is not loading correctly and causing my Vertex Shader object to be a nullptr and Visual Studio is throwing an exception. The specific issue that is occurring is at the following lines below:

 D3DX11CompileFromFile(L"shaders.shader", 0, 0, "VShader", "vs_5_0", 0, 0, 0, &VS, 0, 0);

and because of that not compiling correctly, the corresponding call create the shader is throwing the nullptr exception.

dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);

I am guessing that it is due to a syntax error within the shader. I have a cbuffer that holds the view and projection matrices and would like to multiply those with the vertices as they are passed. What is the correct syntax to use the variables in the cbuffer in another functino within the shader file?

windowSource.cpp

void ParseGraphics() {
    // Build constant buffer for matrix data
    D3D11_BUFFER_DESC matrixBufferDesc;
    ZeroMemory(&matrixBufferDesc, sizeof(matrixBufferDesc));
    matrixBufferDesc.ByteWidth = sizeof(VS_CONSTANT_BUFFER);
    matrixBufferDesc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
    matrixBufferDesc.Usage = D3D11_USAGE_DEFAULT;
    matrixBufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
    matrixBufferDesc.MiscFlags = 0;
    matrixBufferDesc.StructureByteStride = 0;

    D3D11_SUBRESOURCE_DATA matrixSubResourceData;
    matrixSubResourceData.pSysMem = &shaderMatrixBuffer;
    matrixSubResourceData.SysMemPitch = 0;
    matrixSubResourceData.SysMemSlicePitch = 0;
    hr = dev->CreateBuffer(&matrixBufferDesc, &matrixSubResourceData, &pShaderMatrixConstantBuffer);
    if (FAILED(hr)) {
        OutputDebugString(L"Matrix Buffer Creation Failed");
    }

    devContext->VSSetConstantBuffers(0, 1, &pShaderMatrixConstantBuffer);

    // Create Vertex Buffer
    D3D11_BUFFER_DESC v_bd;
    ZeroMemory(&v_bd, sizeof(v_bd));
    v_bd.Usage = D3D11_USAGE_DYNAMIC;
    v_bd.ByteWidth = sizeof(Vertex) * 6;
    v_bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
    v_bd.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;

    dev->CreateBuffer(&v_bd, NULL, &pVBuffer);

    // copy vertices into buffer
    D3D11_MAPPED_SUBRESOURCE msr;
    devContext->Map(pVBuffer, NULL, D3D11_MAP_WRITE_DISCARD, NULL, &msr);
    memcpy(msr.pData, square, sizeof(square));
    devContext->Unmap(pVBuffer, NULL);

}

void BuildPipeline() {
    // Load and Compile Shaders
    ID3D10Blob *VS, *PS;
    D3DX11CompileFromFile(L"shaders.shader", 0, 0, "VShader", "vs_5_0", 0, 0, 0, &VS, 0, 0);
    D3DX11CompileFromFile(L"shaders.shader", 0, 0, "PShader", "ps_5_0", 0, 0, 0, &PS, 0, 0);

    // Create shaders from the data in the Blobs Buffer
    dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
    dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);

    // Apply Shaders to the device context
    devContext->VSSetShader(pVS, 0, 0);
    devContext->PSSetShader(pPS, 0, 0);

    // Define the layout of the input given to the shaders
    D3D11_INPUT_ELEMENT_DESC ied[] =
    {
        {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
        {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 3 * sizeof(float), D3D11_INPUT_PER_VERTEX_DATA, 0},

    };

    dev->CreateInputLayout(ied, 2, VS->GetBufferPointer(), VS->GetBufferSize(), &pLayout);
    devContext->IASetInputLayout(pLayout);

}

shaders.shader

struct VOut
{
    float4 position : SV_POSITION;
    float4 color : COLOR;
};

cbuffer VS_CONSTANT_BUFFER : register(b0) {
    matrix viewMatrix;
    matrix projMatrix
}

VOut VShader(float4 position : POSITION, float4 color : COLOR)
{
    VOut output;

    output.position = mul(position, viewMatrix);
    output.position = mul(output.position, projMatrix);
    output.color = color;

    return output;
}


float4 PShader(float4 position : SV_POSITION, float4 color : COLOR) : SV_TARGET
{
    return color;
}

UPDATED CODE

New shaders.shader file

struct Vin {
    float3 position : POSITION;
    float4 color : COLOR0;
};

struct VOut{

    float4 position : SV_POSITION;
    float4 color : COLOR1;
};

cbuffer VS_CONSTANT_BUFFER : register(b0) {
    matrix viewMatrix;
    matrix projMatrix;
};

VOut VShader(Vin input)
{
    VOut output;
    output.position = mul(float4(input.position, 1), viewMatrix);
    output.position = mul(output.position, projMatrix);
    output.color = input.color;

    return output;
}


float4 PShader(VOut output) : SV_TARGET
{
    return color;
}
\$\endgroup\$
  • \$\begingroup\$ If the shader is failing to compile, can you provide the compiler error? Have you tried googling error codes? \$\endgroup\$ – Honeybunch Dec 1 '16 at 22:56
  • 1
    \$\begingroup\$ "How can I access these cbuffer variables within another function?" I don't understand this part. You say the shader is failing so if its failing how can u even use it. Make the shader compile then ask for help because right now your question doesn't make much sense. \$\endgroup\$ – Justin William Stanley Bryant Dec 1 '16 at 23:11
  • \$\begingroup\$ I just realized i left out some key information. Please see the updates above. "Failing to compile" was a misleading way to phrase that. The call to D3DX11CompileFromFile is failing probably due to a syntax error when I am attempting to use the variables at register b0 of the cbuffer. Therefore I am throwing an exception when I call dev->CreatVertexShader() on VS object which is a nullptr. \$\endgroup\$ – xec86 Dec 2 '16 at 2:55
  • \$\begingroup\$ Just wrote you an answer :) \$\endgroup\$ – Justin William Stanley Bryant Dec 2 '16 at 3:37
2
\$\begingroup\$

Ok so a few things, you missed a ; after your projmatrix and at the end of the CB struct and the rest here:

Looking at your inputlayout

D3D11_INPUT_ELEMENT_DESC ied[] =
{
    {"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
    {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 3 * sizeof(float), D3D11_INPUT_PER_VERTEX_DATA, 0},

};

You have the POSITION as a vector3 and then in your vertex shader input you have it as a vector4, should be "float3 position : POSITION0;"

VOut VShader(float3 position : POSITION0, float4 color : COLOR0)

Your pixel shader input should be the same as the vertex shader output

float4 PShader(VOut input) : SV_TARGET

The way to access a CB from a different function is just the way you are doing it, think of a CB as a holder for global variables you can use them in any shader stage that you bind the CB to.

How I would write the shader:

struct VOut
{
float4 position : SV_POSITION;
float4 color : TEXCOORD0;
};
struct Vin
{
float3 position : POSITION0;
float4 color : COLOR0;
};
cbuffer VS_CONSTANT_BUFFER : register(b0)
{
matrix viewMatrix;
matrix projMatrix;
};

VOut VShader(Vin Input)
{
VOut output;

output.position = mul(float4(Input.position,1), viewMatrix);
output.position = mul(output.position, projMatrix);
output.color = Input.color;

return output;
}


float4 PShader(VOut input) : SV_TARGET0
{
return color;
}

----------------------------------EDITS------------------------------------------

You really need to make sure you are writing your code correct.

You missed a 0 on the end of the vertex input POSITION and the vertex output should be COLOR0 and SV_TARGET should be SV_TARGET0, the COLOR semantic has funky interpolation if I recall so you should always use TEXCOORD when passing color to the pixel shader, in fact I use TEXCOORD for passing most things.

You should really go have a look at the MSDN docs and read about shader Semantics.

One more thing, looking at your CPU code again I see you are using the directX utility lib and that could be your problem have a look here you should be using the built in dx11 compiler look here.

D3DX11CompileFromFile function

Note The D3DX (D3DX 9, D3DX 10, and D3DX 11) utility library is deprecated for Windows 8 and is not supported for Windows Store apps.

Note Instead of using this function, we recommend that you compile offline by using the Fxc.exe command-line compiler or use one of the HLSL compile APIs, like the D3DCompileFromFile API.

I use sharpDX but its just a wrapper around directX so you should be able to convert this snippet over:

Dim Res As CompilationResult = ShaderBytecode.CompileFromFile("Shader.fx", "VShader", "vs_5_0", ShaderFlags.Debug Or ShaderFlags.PackMatrixRowMajor, D3DCompiler.EffectFlags.None, Nothing, ShaderInc)

I use that and get a working shader just checked it a few times.

You should have a look at one of my other answers and set visual studio up so you can compile shaders with it and get error and warnings in the output window and lots of other cool stuff.

\$\endgroup\$
  • \$\begingroup\$ After adding the semicolon to the original shader code, the exception stopped being thrown. However, see the above updated shader that is similar to the code suggested. The VS object is a nullptr again after adding that code. Thanks for your help with this. \$\endgroup\$ – xec86 Dec 2 '16 at 13:49
  • \$\begingroup\$ Made some edits, have a look after the shader code \$\endgroup\$ – Justin William Stanley Bryant Dec 3 '16 at 3:23
  • \$\begingroup\$ got it working? \$\endgroup\$ – Justin William Stanley Bryant Dec 4 '16 at 5:09
  • \$\begingroup\$ I havent had a chance to move this into production but this makes complete sense due to some of the tutorials I was reading were old (Pre windows 8) and I may have inadvertently been provided deprecated code. I will update here if this isnt the case but after reading over the answer provided, I believed in it enough to mark as answered. thanks. \$\endgroup\$ – xec86 Dec 5 '16 at 15:33

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.