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但未中断程序,导致返回无效的缓冲区指针)。
具体解决步骤
- 修复缓冲区字节宽度计算逻辑
将原来的ByteWidth计算替换为正确的16字节向上取整方式,确保当size本身是16的倍数时不会额外增加长度:
cbDesc.ByteWidth = static_cast<uint32_t>((size + 15) & ~15);
或者用更易读的整数除法实现:
cbDesc.ByteWidth = ((size + 15) / 16) * 16;
- 验证
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(); } }
移除冗余的缓冲区绑定操作
在UpdateConstantBuffer中不需要再次调用VSSetConstantBuffers——缓冲区已经在创建时绑定到了槽位0,更新内容不会改变绑定状态,去掉这一行可避免不必要的状态设置。确认设备与上下文指针有效性
在调用CreateBuffer和绑定操作前,确保device和devContext指针不为空,避免因无效指针导致的隐式错误。
内容的提问来源于stack exchange,提问作者bquack-l
相关产品推荐
相关产品推荐

