顶点着色器创建

时间:2015-12-17 17:42:26

标签: shader directx-11 direct3d vertex

我正在学习D3D,目前我正在使用着色器。我编写了代码并构建了它 - 成功但是在调试时我得到了这个错误:

ERROR

以下是调试器崩溃的行:

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

以下是整个功能:

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);
}

1 个答案:

答案 0 :(得分:0)

(1)您没有检查任何HRESULT值是否失败。对于任何COM API用法,包括Direct3D,这是一个必不可少的编码步骤。很可能你在编译语句中遇到了失败,因此VS将返回null。

您可以直接使用FAILEDSUCCEEDED宏来执行错误处理,也可以使用现代C ++示例中使用的DX::ThrowIfFailed帮助程序。

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
  

在传递NULL指针参数时,您还应该使用VS {2010或更高版本的nullptr而不是0,以帮助使用您使用0的各种DWORD参数保持它们。

(2)对于COM API,您还应该考虑使用类似Microsoft::WRL::ComPtr的智能指针而不是原始指针,这些指针会在变量时自动处理调用Release超出范围。

#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));

在上面的代码中,您永远不会在ReleaseVS上调用PS,因此最终会泄露该内存。

(3)不推荐使用D3DX的所有版本(包括D3DX11),DirectX SDK本身也是如此(请参阅MSDN)。使用VS 2012或更高版本,您已经拥有具有Direct3D 11标头和HLSL编译器的Windows 8.x SDK。不要使用仅仅是包装函数的D3DX11CompileFromFile,而是直接调用D3DCompileFromFile(参见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));

更新:如果您需要更详细地了解从D3DCompileFromFile返回的错误,则应为错误提供ID3DBlob

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() ) );
}