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

DirectX 11更新常量缓冲区后设置触发STATE_SETTING ERROR #246错误

错误原因排查与解决方法

核心原因分析

错误提示明确指出绑定的缓冲区未设置D3D11_BIND_CONSTANT_BUFFER标志,但你的代码里明明配置了该标志,这大概率是缓冲区创建时的字节宽度计算错误引发的连锁问题:

你当前的ByteWidth计算逻辑size + (16 - (size % 16)),在size本身是16的倍数时(比如sizeof(glm::mat4)=64),会错误生成size+16的字节数(64+16=80)。虽然80是16的倍数,但这种多余的空间会导致DirectX创建的缓冲区不符合常量缓冲区的规范,进而在绑定时被判定为无效。

另外也需要排查CheckDXError是否未正确捕获CreateBuffer的失败(比如返回E_INVALIDARG但未中断程序,导致返回无效的缓冲区指针)。

具体解决步骤

  1. 修复缓冲区字节宽度计算逻辑
    将原来的ByteWidth计算替换为正确的16字节向上取整方式,确保当size本身是16的倍数时不会额外增加长度:
cbDesc.ByteWidth = static_cast<uint32_t>((size + 15) & ~15);

或者用更易读的整数除法实现:

cbDesc.ByteWidth = ((size + 15) / 16) * 16;
  1. 验证CheckDXError的正确性
    确保它能正确检测所有失败的HRESULT并中断程序,示例实现如下:
void CheckDXError(HRESULT result)
{
    if (FAILED(result))
    {
        char errorMsg[256];
        FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
                       nullptr, result, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
                       errorMsg, sizeof(errorMsg), nullptr);
        printf("DirectX Error: %s\n", errorMsg);
        DebugBreak();
    }
}
  1. 移除冗余的缓冲区绑定操作
    在UpdateConstantBuffer中不需要再次调用VSSetConstantBuffers——缓冲区已经在创建时绑定到了槽位0,更新内容不会改变绑定状态,去掉这一行可避免不必要的状态设置。

  2. 确认设备与上下文指针有效性
    在调用CreateBuffer和绑定操作前,确保device和devContext指针不为空,避免因无效指针导致的隐式错误。

内容的提问来源于stack exchange,提问作者bquack-l

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 15:37:15