4
我的計劃是創建一個加載線程,其中我加載了一個遊戲資源;如3D模型,着色器,紋理等。在主線程中,我執行所有的遊戲邏輯和渲染。然後,在我的加載線程上,我創建了一個僅用於加載的sf :: Context(SFML共享OpenGL上下文)。使用第二個共享的OpenGL上下文加載線程
這是加載着色器的工作。但是,嘗試加載模型時,xserver有時會崩潰。我已經將崩潰縮小到了glBufferData()調用。我檢查了我發送的數據沒有問題。
是否可以使用第二個OpenGL上下文從第二個線程調用glBufferData()?如果不是,爲什麼可以在第二個上下文中加載着色器?如果可能的話,會出現什麼問題?
#include <iostream>
#include <thread>
#include <GL/glew.h>
#include <SFML/OpenGL.hpp>
#include <SFML/Graphics.hpp>
#include <X11/Xlib.h>
class ResourceLoader
{
public:
void Run()
{
sf::Context loadingContext;
loadingContext.setActive(true);
// Some test data.
float* testData = new float[3000];
for (unsigned int i = 0; i < 3000; ++i)
{
testData[i] = 0.0f;
}
// Create lots of VBOs containing our
// test data.
for (unsigned int i = 0; i < 1000; ++i)
{
// Create VBO.
GLuint testVBO = 0;
glGenBuffers(1, &testVBO);
std::cout << "Buffer ID: " << testVBO << std::endl;
// Bind VBO.
glBindBuffer(GL_ARRAY_BUFFER, testVBO);
// Crashes on this call!
glBufferData(
GL_ARRAY_BUFFER,
sizeof(float) * 3000,
&testData[0],
GL_STATIC_DRAW
);
// Unbind VBO.
glBindBuffer(GL_ARRAY_BUFFER, 0);
// Sleep for a bit.
std::this_thread::sleep_for(std::chrono::milliseconds(10));
}
delete[] testData;
}
};
int main()
{
XInitThreads();
// Create the main window.
sf::RenderWindow window(sf::VideoMode(800, 600), "SFML window", sf::Style::Default, sf::ContextSettings(32));
window.setVerticalSyncEnabled(true);
// Make it the active window for OpenGL calls.
window.setActive();
// Configure the OpenGL viewport to be the same size as the window.
glViewport(0, 0, window.getSize().x, window.getSize().y);
// Initialize GLEW.
glewExperimental = GL_TRUE; // OSX fix.
if (glewInit() != GLEW_OK)
{
window.close();
exit(1); // failure
}
// Enable Z-buffer reading and writing.
glEnable(GL_DEPTH_TEST);
glDepthMask(GL_TRUE);
// Create the resource loader.
ResourceLoader loader;
// Run the resource loader in a separate thread.
std::thread loaderThread(&ResourceLoader::Run, &loader);
// Detach the loading thread, allowing it to run
// in the background.
loaderThread.detach();
// Game loop.
while (window.isOpen())
{
// Event loop.
sf::Event event;
while (window.pollEvent(event))
{
if (event.type == sf::Event::Closed)
{
window.close();
}
}
// Clear scren.
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Switch to SFML's OpenGL state.
window.pushGLStates();
{
// Perform SFML drawing here...
sf::RectangleShape rect(sf::Vector2f(100.0f, 100.0f));
rect.setPosition(100.0f, 100.0f);
rect.setFillColor(sf::Color(255, 255, 255));
window.draw(rect);
}
// Switch back to our game rendering OpenGL state.
window.popGLStates();
// Perform OpenGL drawing here...
// Display the rendered frame.
window.display();
}
return 0;
}
在緩衝之前是否使上下文處於活動狀態?我知道這是在wGL中使用多線程OpenGL時必須要做的事情。 http://www.opengl.org/sdk/docs/man2/xhtml/glXMakeContextCurrent.xml – zero298
是的,我在加載線程入口函數中創建上下文,並立即使用sf :: Context :: setActive(http ://www.sfml-dev.org/documentation/2.0/classsf_1_1Context.php#a0806f915ea81ae1f4e8135a7a3696562) – Homar
頂點緩衝區對象在上下文之間共享,頂點數組對象(以及任何一般的容器對象)不是。另外,負責跟蹤哪個頂點緩衝區對象現在被***綁定的狀態機是按上下文存儲的。所有這些事情一起難以回答你現在寫的問題的方式;導致您調用'glBufferData(...)'的一些實際代碼將非常有用。 –