2015-09-08 46 views
0

我正在使用Assimp的模型加載器中實現動畫;用於渲染的C++/OpenGL。我一直在關注這個教程:http://ogldev.atspace.co.uk/www/tutorial38/tutorial38.html廣泛。只需說我沒有完全按照教程進行操作,因爲有些代碼我不同意,所以我對它進行了修改。請注意,我不使用作者在其中使用的數學組件,所以我使用了glm。無論如何,問題在於有時我的程序運行,而在其他時間則不會。當我運行我的程序時,它會運行,然後立即崩潰,而在其他時候,它會正常運行。產生intel_drm錯誤的動畫

有幾件事情要考慮到:

  1. 加入之前的動畫/加載的骨頭,模型加載器的工作完全沒品裝載模式沒有任何未造成死機;

  2. 沒有骨骼的模型仍然加載一樣好;只有裝有骨骼的模型纔會成爲問題。

  3. 請注意,骨頭上沒有東西正在呈現。我甚至沒有開始將骨骼分配給頂點屬性;甚至沒有爲此修改着色器。

  4. 一切正在單線程上運行;沒有多線程......但是。

所以,自然我採取了這一點的代碼實際上加載骨頭。我調試的應用程序,發現問題在哪裏大多是在這裏:

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因爲它使用哪個我認爲有缺陷的原始陣列:

結構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實例化一個賽格故障;

有時...我的程序運行時沒有崩潰!

公平地說,實現動畫對我的筆記本電腦來說可能會非常苛刻,所以可能是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錯誤?

+0

當我寫這篇教程中,我使用的NVIDIA GPU。我們需要了解問題是否與MESA驅動程序有關(無論是驅動程序錯誤還是應用程序方面的問題,這些錯誤都可能沒有被正確實現,但在某種程度上通過了NVIDIA)。任何機會,你可以採取這些代碼,並在NVIDIA上運行它?另外,你是否嘗試使用GDB運行它? –

+0

不幸的是我沒有一臺擁有NVIDIA GPU的機器(我曾經用過)。但這是有趣的;我將骨骼加載代碼封裝到它自己的函數loadBones(..)中,然後把它放在'if(pAnimate)'條件中的一個線程中。有趣的是,我得到的崩潰數量大大減少了。但是,它仍然會崩潰;所以可以肯定的說它可能是CPU/GPU問題,或者僅僅是缺乏多線程。 – Poriferous

回答

0

我轉載此問題,並發現,當談到加載骨頭可能已經與缺乏多線程的問題。我決定將加載的骨骼勘誤移入前面教程中規定的自己的函數中。我後來所做的是:

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>。對線程優化的建議值得歡迎!