Reputation: 125
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:
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
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