C++ OpenGL-在ubuntu中的线程上创建vbo?

C++ OpenGL-在ubuntu中的线程上创建vbo?,c++,multithreading,opengl,thread-safety,x11,C++,Multithreading,Opengl,Thread Safety,X11,我有一个在服务器上有远程网格数据的应用程序。其中一些网格有400k个顶点,因此在下载过程中需要线程。当我在一个线程上运行所有东西时,我没有任何问题,所有代码都工作正常,除了在线程版本中将下载的缓冲区上传到openGL land中。我最终在尝试使用opengl调用创建vbo时遇到崩溃。应用程序通常在glGenBuffers上设置故障。我在尝试让OpenGL调用线程安全时读到的一些例子涉及特定的windows API和特定于平台的东西,这些东西在x11 ubuntu环境中没有多大帮助 所以我希望以前

我有一个在服务器上有远程网格数据的应用程序。其中一些网格有400k个顶点,因此在下载过程中需要线程。当我在一个线程上运行所有东西时,我没有任何问题,所有代码都工作正常,除了在线程版本中将下载的缓冲区上传到openGL land中。我最终在尝试使用opengl调用创建vbo时遇到崩溃。应用程序通常在glGenBuffers上设置故障。我在尝试让OpenGL调用线程安全时读到的一些例子涉及特定的windows API和特定于平台的东西,这些东西在x11 ubuntu环境中没有多大帮助

所以我希望以前做过这件事的人能给我打几个电话,这样在重新设计一个工件之前这可能是可行的

我的加载代码非常简单和轻量级,vbo上载是glGenBuffer、glBind、glBufferData调用的典型步骤:

///
/// \brief The LoadMeshThread class
///     Thread to load a mesh (geometry data) from database
///
class LoadMeshThread : public vtrus::core::Thread
{
    CLASSEXTENDS(LoadMeshThread, vtrus::core::Thread)
    ADD_TO_CLASS_MAP
public:
    VTRUS_HOST
    LoadMeshThread( Chunk* chunk, uint32_t mapID, ChunkGrid* chunkVolume ) :
      super(),
      ChunkToLoadMesh(chunk),
      CpuVertices(NULL),
      CpuNormals(NULL),
      VertexCount(0),
      ChunkVolume(chunkVolume)
    {
        printf("Loading [%s]\n", chunk->GridLocation.ToString().str());
        MapID = mapID;

        ChunkToLoadMesh->AddRef();
        ChunkGrid::LiveLoadThreads++;
    }

    ///
    /// \brief ~LoadHashThread
    /// Destroyed after pthread has ended
    virtual ~LoadMeshThread()
    {
        vprintf(vtrus::debug::Threading, "[%d]\n", this->ThreadID);
        ChunkToLoadMesh->Release();
        ChunkGrid::LiveLoadThreads--;
        delete [] CpuVertices;
        delete [] CpuNormals;
    }

    ///
    /// \brief Run
    ///  Called by base class when the pthread is created
    virtual void Run();

    ///
    /// \brief ReadFromDataBase
    ///
    void ReadFromDataBase();

private:
    ChunkGrid* ChunkVolume; //Access to world data
    uint32_t MapID;
    vtrus::slam::Chunk* ChunkToLoadMesh;
    GLfloat* CpuVertices;
    GLfloat* CpuNormals;
    int VertexCount;
};

///
/// \brief LoadMeshThread::ReadFromDataBase
/// Calls into mysql and grabs the blobs containing the data
void LoadMeshThread::ReadFromDataBase()
{
    Eigen::Vector3i chunkR3 = ChunkToLoadMesh->GridLocation.ToEigen();
    uint32_t chunkID = R3ToChunkID( chunkR3 );
    vtrus::database::DataBase* vtrusDB = vtrus::database::DataBase::GetInstance();

    {
        vtrusDB->Driver->threadInit();
        {
            try
            {
                vtrus::core::String connectionString = vtrusDB->GetConnectionString();
                sql::Connection* connection = vtrusDB->Driver->connect(connectionString.str(), "gobble", "gobblegobble" );
                connection->setSchema( "gobble" );

                sql::ResultSet* result = vtrusDB->GetMeshData( connection, chunkID, MapID, 1 );

                if( result != NULL && result->next() )
                {
                    std::istream* verticesBlob = result->getBlob("VertexBuffer");
                    std::istream* normalsBlob = result->getBlob("NormalsBuffer");
                    VertexCount = result->getInt("VertexCount");

                    uint bufferSize = VertexCount*sizeof(vtrus::geometry::Vec3f);
                    CpuVertices = new GLfloat[bufferSize];
                    CpuNormals = new GLfloat[bufferSize];
                    //printf("Loading %d entries \n", entryCount );
                    verticesBlob->read( reinterpret_cast<char*>(&CpuVertices[0]), (std::streamsize)bufferSize );
                    normalsBlob->read( reinterpret_cast<char*>(&CpuNormals[0]), (std::streamsize)bufferSize );

                    delete verticesBlob;
                    delete normalsBlob;
                }

                delete result;
                delete connection;
            }
            catch ( sql::SQLException * exception )
            {
                //do nothing
                printf("WARNING: SqlException on Loading\n");
            }
        }
        vtrusDB->Driver->threadEnd();
    }
}

void LoadMeshThread::Run()
{
    vtrus::core::ScopedTimer timer("**** LoadHashThread::Run ****");

    vprintf(vtrus::debug::Threading, "[%d]\n", this->ThreadID);
    int numAttempts = 0;
    const int maxAttenpts = 10;
    uint countRemaining = 0;
    uint maxCount = 0;

    ReadFromDataBase();

    if( VertexCount > 0 )
    {
        printf("Creating [%d] vertices\n", VertexCount);
        //CRASH here when the mesh constructor calls glGenBuffer          
        vtrus::resources::Mesh* newMesh = new vtrus::resources::Mesh(VertexCount);
        //upload cpu vertices / normals to GPU

        glBindBuffer( GL_ARRAY_BUFFER, newMesh->GetVertexBuffer()->bo );
        glBufferData(GL_ARRAY_BUFFER, VertexCount * sizeof(vtrus::geometry::Vec3f), &CpuVertices[0], GL_STATIC_DRAW);

        glBindBuffer( GL_ARRAY_BUFFER, newMesh->GetNormalsBuffer()->bo);
        glBufferData(GL_ARRAY_BUFFER, VertexCount * sizeof(vtrus::geometry::Vec3f), &CpuNormals[0], GL_STATIC_DRAW);

        glBindBuffer( GL_ARRAY_BUFFER, 0 );

        ChunkVolume->AddMesh(newMesh, ChunkToLoadMesh);
        newMesh->Release();

        ChunkToLoadMesh->IsLoaded = true;
        ChunkToLoadMesh->IsSaved = true;
        ChunkToLoadMesh->SavedBlockCount = maxCount;
    }

    //Access mutex
    ChunkToLoadMesh->IsLoading = false;
}
///
///\简要介绍LoadMeshThread类
///线程从数据库加载网格(几何体数据)
///
类LoadMeshThread:public vtrus::core::Thread
{
CLASSEXTENDS(LoadMeshThread,vtrus::core::Thread)
将\添加到\类\映射
公众:
VTRU_主机
LoadMeshThread(Chunk*Chunk,uint32\t mapID,ChunkGrid*chunkVolume):
超级(),
ChunkToLoadMesh(块),
CpuVertices(空),
CpuNormals(NULL),
垂直计数(0),
ChunkVolume(ChunkVolume)
{
printf(“加载[%s]\n”,chunk->GridLocation.ToString().str());
MapID=MapID;
ChunkToLoadMesh->AddRef();
ChunkGrid::LiveLoadThreads++;
}
///
///\brief~LoadHashThread
///pthread结束后销毁
虚拟~LoadMeshThread()
{
vprintf(vtrus::debug::Threading,[%d]\n],this->ThreadID);
ChunkToLoadMesh->Release();
ChunkGrid::LiveLoadThreads--;
删除[]个证书;
删除[]个非正常值;
}
///
///\短时间运行
///创建pthread时由基类调用
虚空运行();
///
///\BRIENT ReadFromDataBase
///
void ReadFromDataBase();
私人:
ChunkGrid*ChunkVolume;//访问世界数据
uint32_t MapID;
vtru::slam::Chunk*ChunkToLoadMesh;
GLfloat*cpuverties;
GLfloat*CpuNormals;
int VertexCount;
};
///
///\brief LoadMeshThread::ReadFromDataBase
///调用mysql并获取包含数据的blob
void LoadMeshThread::ReadFromDataBase()
{
Eigen::Vector3i chunkR3=ChunkToLoadMesh->GridLocation.ToEigen();
uint32\u t chunkID=R3ToChunkID(chunkR3);
vtrus::database::database*vtrusDB=vtrus::database::database::GetInstance();
{
vtrusDB->Driver->threadInit();
{
尝试
{
vtrus::core::String connectionString=vtrusDB->GetConnectionString();
sql::Connection*Connection=vtrusDB->Driver->connect(connectionString.str(),“gobble”,“gobblegobble”);
连接->设置模式(“gobble”);
sql::ResultSet*result=vtrusDB->GetMeshData(连接,chunkID,MapID,1);
if(result!=NULL&&result->next())
{
std::istream*verticesBlob=result->getBlob(“VertexBuffer”);
std::istream*normalsBlob=result->getBlob(“NormalsBuffer”);
VertexCount=结果->获取整数(“VertexCount”);
uint bufferSize=VertexCount*sizeof(vtrus::geometry::Vec3f);
CpuVertices=新的GLfloat[bufferSize];
CpuNormals=newglfloat[bufferSize];
//printf(“正在加载%d个条目”,entryCount);
verticesBlob->read(重新解释强制转换(&CpuVertices[0]),(std::streamsize)bufferSize);
normalsBlob->read(reinterpret_cast(&CpuNormals[0]),(std::streamsize)bufferSize);
删除verticesBlob;
删除normalsBlob;
}
删除结果;
删除连接;
}
捕获(sql::SQLException*异常)
{
//无所事事
printf(“警告:加载时发生SqlException\n”);
}
}
vtrusDB->Driver->threadEnd();
}
}
void LoadMeshThread::Run()
{
vtrus::core::ScopedTimer计时器(“*****LoadHashThread::Run****”;
vprintf(vtrus::debug::Threading,[%d]\n],this->ThreadID);
int numatempts=0;
常数int MAXANTPTS=10;
uint count剩余=0;
uint最大计数=0;
ReadFromDataBase();
如果(顶点计数>0)
{
printf(“创建[%d]个顶点\n”,顶点计数);
//当网格构造函数调用glGenBuffer时在此崩溃
vtrus::resources::Mesh*newMesh=newvtrus::resources::Mesh(VertexCount);
//将cpu顶点/法线上载到GPU
glBindBuffer(GL_数组_BUFFER,newMesh->GetVertexBuffer()->bo);
glBufferData(GL_数组_缓冲区、VertexCount*sizeof(vtrus::geometry::Vec3f)和CpuVertices[0],GL_静态_绘图);
glBindBuffer(GL_数组_BUFFER,newMesh->GetNormalsBuffer()->bo);
glBufferData(GL_数组_缓冲区、VertexCount*sizeof(vtrus::geometry::Vec3f)和CpuNormals[0],GL_静态_绘图);
glBindBuffer(GL_数组_BUFFER,0);
ChunkVolume->AddMesh(新建网格、ChunkToLoadMesh);
newMesh->Release();
ChunkToLoadMesh->IsLoaded=true;
ChunkToLoadMesh->IsSaved=true;
ChunkToLoadMesh->SavedBlockCount=maxCount;
}
//访问互斥
ChunkToLoadMesh->IsLoading=false;
}

在使用任何
glXXX
命令之前,必须将gl上下文设置为将使用这些命令的线程的当前上下文。 在X11世界中,要使用的命令是
glXMakeContextCurrent
或更老的命令,但仍然有效
glXMakeCurrent
。看见如果您使用的库为您处理gl上下文,则