You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

DirectX 11添加着色器后窗口崩溃问题排查求助

DirectX 11 程序创建着色器与输入布局后崩溃排查

我在学习Win32 DirectX 11绘制三角形的教程,原本程序能正常渲染蓝色背景,但添加着色器创建、设置及输入布局配置的代码后,窗口会在创建约1秒后崩溃。注释掉这段代码后程序恢复正常。

相关代码

InitPipeline 函数

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

//-------------------------------------------STARTS FROM HERE--------------------- 
    // 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);

//-------------------------------------------ENDS HERE------------------------
}

着色器文件(shaders.shader)

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

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

    output.position = position;
    output.color = color;

    return output;
}


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

崩溃原因排查与解决

  • 未检查着色器编译结果:当前代码没有验证D3DX11CompileFromFile的返回值,也未获取编译错误信息。如果着色器编译失败,VS或PS会是NULL,后续调用VS->GetBufferPointer()会直接触发访问违规崩溃。
    解决:添加编译错误检查,获取错误Blob并输出:

    ID3D10Blob* errorBlob = nullptr;
    HRESULT hr = D3DX11CompileFromFile("shaders.shader", 0, 0, "VShader", "vs_4_0", 0, 0, 0, &VS, &errorBlob, 0);
    if (FAILED(hr)) {
        if (errorBlob) {
            MessageBoxA(nullptr, (char*)errorBlob->GetBufferPointer(), "顶点着色器编译错误", MB_OK);
            errorBlob->Release();
        }
        // 终止流程或处理错误
        return;
    }
    // 像素着色器编译同理添加检查
    
  • 输入布局与着色器输入不匹配:输入布局中POSITION的格式是DXGI_FORMAT_R32G32B32_FLOAT(3个浮点分量),但顶点着色器的POSITION参数是float4(4个分量),两者不匹配会导致CreateInputLayout失败,pLayout为NULL,后续渲染时触发崩溃。
    解决:二选一修改:

    1. 修改输入布局的POSITION格式为DXGI_FORMAT_R32G32B32A32_FLOAT,并调整COLOR的偏移量为16:
      D3D11_INPUT_ELEMENT_DESC ied[] =
      {
          {"POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
          {"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 16, D3D11_INPUT_PER_VERTEX_DATA, 0},
      };
      
    2. 修改顶点着色器的输入为float3,并补充w分量为1.0:
      VOut VShader(float3 position : POSITION, float4 color : COLOR)
      {
          VOut output;
          output.position = float4(position, 1.0f);
          output.color = color;
          return output;
      }
      
  • COM对象未正确初始化与释放:pVS、pPS、pLayout这些COM指针如果未初始化为nullptr,或者创建失败后仍被使用,会导致访问违规。另外程序退出时需调用Release()释放这些对象,避免内存泄漏或后续错误。
    解决:声明指针时初始化为nullptr,创建失败时终止后续流程,程序退出时依次释放:

    // 声明时初始化
    ID3D11VertexShader* pVS = nullptr;
    ID3D11PixelShader* pPS = nullptr;
    ID3D11InputLayout* pLayout = nullptr;
    
    // 退出时释放
    if (pVS) pVS->Release();
    if (pPS) pPS->Release();
    if (pLayout) pLayout->Release();
    
  • 着色器文件路径错误:如果shaders.shader不在程序运行目录下,编译函数会找不到文件,导致VS/PS为NULL,后续访问崩溃。
    解决:使用绝对路径测试,或确保编译后的可执行文件与着色器文件在同一目录。

内容的提问来源于stack exchange,提问作者bugger

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 15:15:57