DoLoop
DoLoop

Reputation: 125

Vertex Shader Creating

I am learning D3D and currently i am at shaders. I wrote the code and built it - succeed but when debug i get this error:

ERROR

Here is the line where debugger breake:

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

And here is the whole function:

void InitPipeline()
{
    // load and compile the two shaders
    ID3D10Blob *VS, *PS;
    D3DX11CompileFromFile("Shaders.shader", 0, 0, "VShader", "vs_4_0", 0, 0, 0, &VS, 0, 0);
    D3DX11CompileFromFile("Shaders.shader", 0, 0, "PShader", "ps_4_0", 0, 0, 0, &PS, 0, 0);

    // encapsulate both shaders into shader objects
    dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(), NULL, &pVS);
    dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(), NULL, &pPS);

    // set the shader objects
    devcon->VSSetShader(pVS, 0, 0);
    devcon->PSSetShader(pPS, 0, 0);

    // create the input layout object
    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, 12, D3D11_INPUT_PER_VERTEX_DATA, 0 },
    };

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

Upvotes: 0

Views: 1353

Answers (1)

Chuck Walbourn
Chuck Walbourn

Reputation: 41057

(1) You are not checking any of the HRESULT values for failure. For any COM API usage, including Direct3D, this is an essential coding step. Most likely you are getting a failure in the compile statements, so VS is coming back null.

You can use the FAILED and SUCCEEDED macros directly to do the error handling, or the DX::ThrowIfFailed helper used in modern C++ samples.

if (FAILED(D3DX11CompileFromFile("Shaders.shader", nullptr, nullptr, "VShader", "vs_4_0",
    0, 0, nullptr, &VS, nullptr, nullptr)))
    // error
if (FAILED(D3DX11CompileFromFile("Shaders.shader", nullptr, nullptr, "PShader", "ps_4_0",
    0, 0, nullptr, &PS, nullptr, nullptr)))
    // error

You should also use nullptr with VS 2010 or later instead of 0 when passing NULL pointer parameters to help keep them straight with the various DWORD parameters you are using 0 for.

(2) For the COM API, you should also consider using a smart-pointer like Microsoft::WRL::ComPtr rather than raw pointers which will automatically handle calling Release when the variable goes out of scope.

#include <wrl/client.h>

using Microsoft::WRL::ComPtr;

ComPtr<ID3D10Blob> VS, PS;
DX::ThrowIfFailed(D3DX11CompileFromFile("Shaders.shader", nullptr, nullptr, "VShader",
    "vs_4_0", 0, 0, nullptr, &VS, nullptr, nullptr));
DX::ThrowIfFailed(D3DX11CompileFromFile("Shaders.shader", nullptr, nullptr, "PShader",
    "ps_4_0", 0, 0, nullptr, &PS, nullptr, nullptr));

DX::ThrowIfFailed(dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(),
    nullptr, &pVS)(;
DX::ThrowIfFailed(dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(),
    nullptr, &pPS));

In your code above, you are never calling Release on VS or PS so would end up leaking that memory.

(3) All versions of D3DX including D3DX11 are deprecated, as is the DirectX SDK itself (See MSDN). With VS 2012 or later, you already have the Windows 8.x SDK which has Direct3D 11 headers and the HLSL compiler. Instead of using D3DX11CompileFromFile which is just a wrapper function, call D3DCompileFromFile directly (see HLSL, FXC, and D3DCompile).

#include <wrl/client.h>
#include <d3dcompiler.h>

using Microsoft::WRL::ComPtr;

ComPtr<ID3DBlob> VS, PS;
DX::ThrowIfFailed(D3DCompileFromFile("Shaders.shader", nullptr, nullptr, "VShader",
    "vs_4_0", 0, 0, &VS, nullptr));
DX::ThrowIfFailed(D3DCompileFromFile("Shaders.shader", nullptr, nullptr, "PShader",
    "ps_4_0", 0, 0, &PS, nullptr));

DX::ThrowIfFailed(dev->CreateVertexShader(VS->GetBufferPointer(), VS->GetBufferSize(),
    nullptr, &pVS)(;
DX::ThrowIfFailed(dev->CreatePixelShader(PS->GetBufferPointer(), PS->GetBufferSize(),
    nullptr, &pPS));

UPDATE: If you need more detail on the error you are getting back from D3DCompileFromFile you should provide a ID3DBlob for the errors:

ComPtr<ID3DBlob> VS, Errors;
DX::ThrowIfFailed(D3DCompileFromFile("Shaders.shader", nullptr, nullptr, "VShader",
    "vs_4_0", 0, 0, &VS, &Errors));
if ( Errors )
{
    OutputDebugStringA( reinterpret_cast<const char*>( Errors->GetBufferPointer() ) );
}

Upvotes: 1

Related Questions