动画产生intel_drm错误
Animations producing intel_drm errors
我正在使用Assimp的模型加载器中实现动画;c++/OpenGL渲染。我一直在关注这个教程:http://ogldev.atspace.co.uk/www/tutorial38/tutorial38.html。可以这么说,我并没有完全遵循教程,因为在代码方面有一些我不同意的地方,所以我改编了它。请注意,我没有使用作者使用的任何数学成分,所以我使用了glm。无论如何,问题是我的程序有时运行,有时不运行。当我运行我的程序时,它会运行,然后立即崩溃,而在其他时候,它只是正常运行。
要考虑的几件事:
-
在添加动画/加载骨骼之前,模型加载器工作得很好,模型加载不会造成任何崩溃;
-
没有骨骼的模型仍然加载得很好;
-
请注意,没有骨头被渲染。我甚至还没有开始分配骨头到顶点属性;
-
所有东西都在一个线程上运行;没有多线程…然而。
所以,我很自然地使用了这段代码,它实际加载了骨骼。我调试了应用程序,发现问题主要在这里:
Mesh* processMesh(uint meshIndex, aiMesh *mesh)
{
vector<VertexBoneData> bones;
bones.resize(mesh->mNumVertices);
// .. getting other mesh data
if (pAnimate)
{
for (uint i = 0; i < mesh->mNumBones; i++)
{
uint boneIndex = 0;
string boneName(mesh->mBones[i]->mName.data);
auto it = pBoneMap.find(boneName);
if (it == pBoneMap.end())
{
boneIndex = pNumBones;
++pNumBones;
BoneInfo bi;
pBoneInfo.push_back(bi);
auto tempMat = mesh->mBones[i]->mOffsetMatrix;
pBoneInfo[boneIndex].boneOffset = to_glm_mat4(tempMat);
pBoneMap[boneName] = boneIndex;
}
else boneIndex = pBoneMap[boneName];
for (uint j = 0; j < mesh->mBones[i]->mNumWeights; j++)
{
uint vertexID = mesh->mBones[i]->mWeights[j].mVertexId;
float weit = mesh->mBones[i]->mWeights[j].mWeight;
bones.at(vertexID).addBoneData(boneIndex, weit);
}
}
}
}
在最后一行中,作者使用[]
操作符访问元素,但我决定使用' .at
进行范围检查。函数to_glm_mat4
定义如下:
glm::mat4 to_glm_mat4(const aiMatrix4x4 &m)
{
glm::mat4 to;
to[0][0] = m.a1; to[1][0] = m.a2;
to[2][0] = m.a3; to[3][0] = m.a4;
to[0][1] = m.b1; to[1][1] = m.b2;
to[2][1] = m.b3; to[3][1] = m.b4;
to[0][2] = m.c1; to[1][2] = m.c2;
to[2][2] = m.c3; to[3][2] = m.c4;
to[0][3] = m.d1; to[1][3] = m.d2;
to[2][3] = m.d3; to[3][3] = m.d4;
return to;
}
我也不得不改变VertexBoneData,因为它使用了我认为有缺陷的原始数组:
struct VertexBoneData{向量boneIDs;向量权重;
VertexBoneData()
{
reset();
boneIDs.resize(NUM_BONES_PER_VERTEX);
weights.resize(NUM_BONES_PER_VERTEX);
}
void reset()
{
boneIDs.clear();
weights.clear();
}
void addBoneData(unsigned int boneID, float weight)
{
for (uint i = 0; i < boneIDs.size(); i++)
{
if (weights.at(i) == 0.0) // SEG FAULT HERE
{
boneIDs.at(i) = boneID;
weights.at(i) = weight;
return;
}
}
assert(0);
}
};
现在,我不完全确定是什么导致了崩溃,但最让我困惑的是,有时程序会运行(这意味着代码不一定是罪魁祸首)。所以我决定进行一次调试,包括检查每个骨头(我跳过了一些;有大量的骨头!),并发现在所有的骨头都被加载后,我会得到这个非常奇怪的错误:
No source available for "drm_intel_bo_unreference() at 0x7fffec369ed9"
,有时我会得到这个错误:
Error in '/home/.../: corrupted double-linked list (not small): 0x00000 etc ***
,有时我会从glm中获得关于vec4实例化的segfault;
,有时……我的程序从来没有崩溃过!
公平地说,在我的笔记本电脑上实现动画可能会很苛刻,所以可能是CPU/GPU问题,因为它无法一次处理这么多数据,这导致了这次崩溃。我的理论是,由于它无法处理那么多数据,这些数据永远不会分配给向量。
我没有使用任何多线程,但它已经闪过我的脑海。我认为这可能是CPU无法处理如此多的数据,因此机会运行。如果我实现线程,这样骨加载是在另一个线程上完成的;或者更好的是,使用互斥锁,因为我发现,通过缓慢调试应用程序,程序可以运行,这是有意义的,因为每个任务都被分解成块;这就是互斥锁在技术上的作用。
为了讨论的方便,我的技术规格:
Ubuntu 15.04 64-bit
Intel i5 dual-core
Intel HD 5500
Mesa 10.5.9 (OpenGL 3.3)
Programming on Eclipse Mars
因此,我问,到底是什么导致了这些intel_drm错误? 我已经复制了这个问题,发现它可能是在加载骨骼时缺乏多线程的问题。我决定将加载骨勘误表移动到前面教程中规定的自己的功能中。我后来做的是:
if (pAnimate)
{
std::thread t1[&] {
loadBones(meshIndex, mesh, bones);
});
t1.join();
}
上面的lambda函数有[&]
表示我们将所有内容作为引用传递,以确保没有创建副本。为了防止任何外力"接触"loadBones(..)
函数中的数据,我在函数中安装了一个互斥锁,如下所示:
void ModelLoader::loadBones(uint meshIndex, const aiMesh *mesh, std::vector<VertexBoneData> &bones)
{
std::mutex mut;
std::lock_guard<std::mutex> lock(mut);
// load bones
}
这只是一个快速和肮脏的修复。它可能并不适用于所有人,也不能保证程序不会崩溃。
以下是一些测试结果:
Sans threading & mutex: program runs 0 out of 3 times in a row
With threading; sans mutex: program runs 2 out of 3 times in a row
With threading & mutex: program runs 3 out of 3 times in a row
如果您使用的是Linux,请记住链接pthread
以及包括<thread>
和<mutex>
。欢迎对线程优化提出建议!
- 警告处理为错误这里有什么问题
- "error: no matching function for call to"构造函数错误
- boost::进程间消息队列引发错误
- C++,OpenCV,尝试显示图像时"OpenCV(4.3.0) Error: Assertion failed (size.width>0 && size.height>0)"此错误
- 有关插入适配器的错误。[错误]请求从 'back_insert_iterator<vector<>>' 类型转换为非标量类型
- QT在错误的班级中寻找空位
- vector.resize()中的分配错误
- 代码在main()中运行,但在函数中出现错误
- 释放错误后堆使用
- (C++)分析树以计算返回错误值的简单算术表达式
- Project Euler问题4的错误解决方案
- 我的字符计数代码计算错误.为什么
- 从"int*"强制转换为"unsigned int"会丢失精度错误
- 尝试导入pybind-opencv模块时出现libgtk错误
- CMake项目Boost库错误:Boost/config/compiler/gcc.hpp:165:10:致命错误:cs
- 在某些循环内使用vector.push_back时出现分段错误
- MSVC多行宏编译器错误
- 静态数据成员的问题-修复链接错误会导致编译器错误
- 为什么在运行时没有向我们提供有关分段错误的更多信息?
- 错误:未在此范围内声明'reverse'