How can I fix using gl buffers and shaders in different thread?
I would like to render my scene on different thread. I have classes for buffers and shader.
enum BUFFER
{
ARRAY,
ELEMENT_ARRAY
};
enum USAGE
{
STATIC_DRAW, DYNAMIC_DRAW
};
class Buffer
{
public:
Buffer() = default;
virtual ~Buffer() = default;
Buffer* Create(BUFFER buffer, USAGE usage)
{
return new GLBuffer(buffer, usage);
}
virtual void GenBuffer() {}
virtual void BindBuffer(){}
virtual void AddData(const void* data, intptr size, intptr offset) {}
//Data type is an enum
virtual void AddAttibute(unsigned int index, int size, DataType type, bool normalize, int stride, const void* offset) {}
};
class GLBuffer : public Buffer
{
public:
GLBuffer(BUFFER buffer, USAGE usage)
{
GenBuffer();
BindBuffer();
type = BUFFERToOpenGL(buffer);
usage = USAGEToOpenGL(usage);
}
void GenBuffer() override { glGenBuffers(1, &buffer); }
void BindBuffer() override { glBindBuffer(type, buffer); }
unsigned int buffer;
unsigned int type;
unsigned int usage;
};
I have not shown GLBuffer::AddData()
and AddAttribute
, but I think you got an idea of this.
The same for VertexArray
class VertexArray
{
public:
VertexArray* Create() { return GLVertexArray(); }
virtual void BindVertexArray() {}
}
class GLVertexArray : public VertexArray
{
public:
...
}
and so on
Shader is a bit different
enum SHADERTYPE
{
VERTEX,
FRAGMENT
};
class Shader
{
public:
Shader* Create() { return GLShader; }
virtual const int ShaderFromSource(const char* path, SHADERTYPE type) {}
virtual void End(const int* shaders, int count) {}
virtual void UseProgram() {}
virtual void //add uniforms etc
};
class GLShader : public Shader
{
public:
GLShader()
{
shaderProgram = glCreateProgram();
}
const int GLShader::ShaderFromSource(const char* path, SHADERTYPE type) override
{
unsigned int shaderID = glCreateShader(SHADERTYPEToOpenGL(type));
glShaderSource(shaderID, 1, &shader, NULL);
glCompileShader(shaderID);
glAttachShader(shaderProgram, shaderID);
return shaderID;
}
void GLShader::End(const int ids, int count) override
{
glLinkProgram(shaderProgram);
for (int i = 0; i < count; ++i) {
glDetachShader(shaderProgram, ids[i]);
glDeleteShader(ids[i]);
}
}
void UseProgram() override { glUseProgram(shaderProgram); }
unsigned int shaderProgram;
};
I want to create vao, vbo and shader in the Cube class ctor in the main thread and call Cube::Render
in a render thread Cube::Render
calls Use program adds uniforms and call DrawArray.
void mainloop()
{
Cube cube;
std::thread* thread = nullptr;
std::mutex mutex;
std::lock_guard<std::mutex> guard(mutex);
thread = new std::thread([&]() {
while (!quit) {
SDL_GL_MakeCurrent(window, glContext);
glClearColor(0, 0, static_cast<float>(15) / 255, 1);
glClear(GL_COLOR_BUFFER_BIT);
cube.Render();
SDL_GL_SwapWindow(window);
}
});
}
Cube cube
- creates vao, vbo, shaders - adds vertices to vbo
class Cube
{
Cube()
{
vao = vao->Create();
vbo = vbo->Create(ARRAY, STATIC_DRAW);
vbo->AddData(...);
vbo->AddAttributes(...);
shader = shader->Create();
int shaders[2] = {
shader->ShaderFromSource(vs, VERTEX),
shader->ShaderFromSource(fs, FRAGMENT)
};
shader->End(shaders, 2);
}
VertexArray* vao = nullptr;
Buffer* vbo = nullptr;
Shader* shader = nullptr;
};
cube.Render()
- uses shader, adds uniforms, call draw arrays
Cube::Render()
{
shader->UseProgram();
shader->Uniform(mvp);
vao->DrawArrays(TRIANGELS, 0, 36);
}
when Cube gets created in a main thread I got this message
when Cube gets created in a render thread I got this message
Why does it happen? How to support rendering in a different thread?
c++ multithreading opengl rendering
|
show 5 more comments
I would like to render my scene on different thread. I have classes for buffers and shader.
enum BUFFER
{
ARRAY,
ELEMENT_ARRAY
};
enum USAGE
{
STATIC_DRAW, DYNAMIC_DRAW
};
class Buffer
{
public:
Buffer() = default;
virtual ~Buffer() = default;
Buffer* Create(BUFFER buffer, USAGE usage)
{
return new GLBuffer(buffer, usage);
}
virtual void GenBuffer() {}
virtual void BindBuffer(){}
virtual void AddData(const void* data, intptr size, intptr offset) {}
//Data type is an enum
virtual void AddAttibute(unsigned int index, int size, DataType type, bool normalize, int stride, const void* offset) {}
};
class GLBuffer : public Buffer
{
public:
GLBuffer(BUFFER buffer, USAGE usage)
{
GenBuffer();
BindBuffer();
type = BUFFERToOpenGL(buffer);
usage = USAGEToOpenGL(usage);
}
void GenBuffer() override { glGenBuffers(1, &buffer); }
void BindBuffer() override { glBindBuffer(type, buffer); }
unsigned int buffer;
unsigned int type;
unsigned int usage;
};
I have not shown GLBuffer::AddData()
and AddAttribute
, but I think you got an idea of this.
The same for VertexArray
class VertexArray
{
public:
VertexArray* Create() { return GLVertexArray(); }
virtual void BindVertexArray() {}
}
class GLVertexArray : public VertexArray
{
public:
...
}
and so on
Shader is a bit different
enum SHADERTYPE
{
VERTEX,
FRAGMENT
};
class Shader
{
public:
Shader* Create() { return GLShader; }
virtual const int ShaderFromSource(const char* path, SHADERTYPE type) {}
virtual void End(const int* shaders, int count) {}
virtual void UseProgram() {}
virtual void //add uniforms etc
};
class GLShader : public Shader
{
public:
GLShader()
{
shaderProgram = glCreateProgram();
}
const int GLShader::ShaderFromSource(const char* path, SHADERTYPE type) override
{
unsigned int shaderID = glCreateShader(SHADERTYPEToOpenGL(type));
glShaderSource(shaderID, 1, &shader, NULL);
glCompileShader(shaderID);
glAttachShader(shaderProgram, shaderID);
return shaderID;
}
void GLShader::End(const int ids, int count) override
{
glLinkProgram(shaderProgram);
for (int i = 0; i < count; ++i) {
glDetachShader(shaderProgram, ids[i]);
glDeleteShader(ids[i]);
}
}
void UseProgram() override { glUseProgram(shaderProgram); }
unsigned int shaderProgram;
};
I want to create vao, vbo and shader in the Cube class ctor in the main thread and call Cube::Render
in a render thread Cube::Render
calls Use program adds uniforms and call DrawArray.
void mainloop()
{
Cube cube;
std::thread* thread = nullptr;
std::mutex mutex;
std::lock_guard<std::mutex> guard(mutex);
thread = new std::thread([&]() {
while (!quit) {
SDL_GL_MakeCurrent(window, glContext);
glClearColor(0, 0, static_cast<float>(15) / 255, 1);
glClear(GL_COLOR_BUFFER_BIT);
cube.Render();
SDL_GL_SwapWindow(window);
}
});
}
Cube cube
- creates vao, vbo, shaders - adds vertices to vbo
class Cube
{
Cube()
{
vao = vao->Create();
vbo = vbo->Create(ARRAY, STATIC_DRAW);
vbo->AddData(...);
vbo->AddAttributes(...);
shader = shader->Create();
int shaders[2] = {
shader->ShaderFromSource(vs, VERTEX),
shader->ShaderFromSource(fs, FRAGMENT)
};
shader->End(shaders, 2);
}
VertexArray* vao = nullptr;
Buffer* vbo = nullptr;
Shader* shader = nullptr;
};
cube.Render()
- uses shader, adds uniforms, call draw arrays
Cube::Render()
{
shader->UseProgram();
shader->Uniform(mvp);
vao->DrawArrays(TRIANGELS, 0, 36);
}
when Cube gets created in a main thread I got this message
when Cube gets created in a render thread I got this message
Why does it happen? How to support rendering in a different thread?
c++ multithreading opengl rendering
Calling class member functions of null pointer instances is not a good practice. TheShader::Create
function should be declared as static and returnsnew GLSharder();
– tunglt
Jan 1 at 20:53
Ok, I will change it. Why it is not a good practice? It won't fix threads problem. I made a small test with new smallVBO
andGLVBO
struct which does almost the same - callsgenBuffers
andbindBuffers(GL_ARRAY_BUFFER)
and it does work. Any ideas?
– JarekBisnesu
Jan 1 at 21:12
It isn't a good practice because you force the code maintainer to reread your codes twice when the program crashed. He (or she) don't know if the called function has accessed to a member variable and catch an access violation. Usingsharder = Shader::Create();
is much clearer.
– tunglt
Jan 1 at 22:14
Sharing OpenGL objects with multi-thread model needs more work. Each thread should have its own context and the contexts must be shared between threads via wglShareLists orSDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
– tunglt
Jan 1 at 22:17
As stated in VAO specification VAO objects cannot be shared between contexts, so the multiple contexts solution will not work for your program. More discussion about using OpenGL with multithread in SO is here
– tunglt
Jan 1 at 22:43
|
show 5 more comments
I would like to render my scene on different thread. I have classes for buffers and shader.
enum BUFFER
{
ARRAY,
ELEMENT_ARRAY
};
enum USAGE
{
STATIC_DRAW, DYNAMIC_DRAW
};
class Buffer
{
public:
Buffer() = default;
virtual ~Buffer() = default;
Buffer* Create(BUFFER buffer, USAGE usage)
{
return new GLBuffer(buffer, usage);
}
virtual void GenBuffer() {}
virtual void BindBuffer(){}
virtual void AddData(const void* data, intptr size, intptr offset) {}
//Data type is an enum
virtual void AddAttibute(unsigned int index, int size, DataType type, bool normalize, int stride, const void* offset) {}
};
class GLBuffer : public Buffer
{
public:
GLBuffer(BUFFER buffer, USAGE usage)
{
GenBuffer();
BindBuffer();
type = BUFFERToOpenGL(buffer);
usage = USAGEToOpenGL(usage);
}
void GenBuffer() override { glGenBuffers(1, &buffer); }
void BindBuffer() override { glBindBuffer(type, buffer); }
unsigned int buffer;
unsigned int type;
unsigned int usage;
};
I have not shown GLBuffer::AddData()
and AddAttribute
, but I think you got an idea of this.
The same for VertexArray
class VertexArray
{
public:
VertexArray* Create() { return GLVertexArray(); }
virtual void BindVertexArray() {}
}
class GLVertexArray : public VertexArray
{
public:
...
}
and so on
Shader is a bit different
enum SHADERTYPE
{
VERTEX,
FRAGMENT
};
class Shader
{
public:
Shader* Create() { return GLShader; }
virtual const int ShaderFromSource(const char* path, SHADERTYPE type) {}
virtual void End(const int* shaders, int count) {}
virtual void UseProgram() {}
virtual void //add uniforms etc
};
class GLShader : public Shader
{
public:
GLShader()
{
shaderProgram = glCreateProgram();
}
const int GLShader::ShaderFromSource(const char* path, SHADERTYPE type) override
{
unsigned int shaderID = glCreateShader(SHADERTYPEToOpenGL(type));
glShaderSource(shaderID, 1, &shader, NULL);
glCompileShader(shaderID);
glAttachShader(shaderProgram, shaderID);
return shaderID;
}
void GLShader::End(const int ids, int count) override
{
glLinkProgram(shaderProgram);
for (int i = 0; i < count; ++i) {
glDetachShader(shaderProgram, ids[i]);
glDeleteShader(ids[i]);
}
}
void UseProgram() override { glUseProgram(shaderProgram); }
unsigned int shaderProgram;
};
I want to create vao, vbo and shader in the Cube class ctor in the main thread and call Cube::Render
in a render thread Cube::Render
calls Use program adds uniforms and call DrawArray.
void mainloop()
{
Cube cube;
std::thread* thread = nullptr;
std::mutex mutex;
std::lock_guard<std::mutex> guard(mutex);
thread = new std::thread([&]() {
while (!quit) {
SDL_GL_MakeCurrent(window, glContext);
glClearColor(0, 0, static_cast<float>(15) / 255, 1);
glClear(GL_COLOR_BUFFER_BIT);
cube.Render();
SDL_GL_SwapWindow(window);
}
});
}
Cube cube
- creates vao, vbo, shaders - adds vertices to vbo
class Cube
{
Cube()
{
vao = vao->Create();
vbo = vbo->Create(ARRAY, STATIC_DRAW);
vbo->AddData(...);
vbo->AddAttributes(...);
shader = shader->Create();
int shaders[2] = {
shader->ShaderFromSource(vs, VERTEX),
shader->ShaderFromSource(fs, FRAGMENT)
};
shader->End(shaders, 2);
}
VertexArray* vao = nullptr;
Buffer* vbo = nullptr;
Shader* shader = nullptr;
};
cube.Render()
- uses shader, adds uniforms, call draw arrays
Cube::Render()
{
shader->UseProgram();
shader->Uniform(mvp);
vao->DrawArrays(TRIANGELS, 0, 36);
}
when Cube gets created in a main thread I got this message
when Cube gets created in a render thread I got this message
Why does it happen? How to support rendering in a different thread?
c++ multithreading opengl rendering
I would like to render my scene on different thread. I have classes for buffers and shader.
enum BUFFER
{
ARRAY,
ELEMENT_ARRAY
};
enum USAGE
{
STATIC_DRAW, DYNAMIC_DRAW
};
class Buffer
{
public:
Buffer() = default;
virtual ~Buffer() = default;
Buffer* Create(BUFFER buffer, USAGE usage)
{
return new GLBuffer(buffer, usage);
}
virtual void GenBuffer() {}
virtual void BindBuffer(){}
virtual void AddData(const void* data, intptr size, intptr offset) {}
//Data type is an enum
virtual void AddAttibute(unsigned int index, int size, DataType type, bool normalize, int stride, const void* offset) {}
};
class GLBuffer : public Buffer
{
public:
GLBuffer(BUFFER buffer, USAGE usage)
{
GenBuffer();
BindBuffer();
type = BUFFERToOpenGL(buffer);
usage = USAGEToOpenGL(usage);
}
void GenBuffer() override { glGenBuffers(1, &buffer); }
void BindBuffer() override { glBindBuffer(type, buffer); }
unsigned int buffer;
unsigned int type;
unsigned int usage;
};
I have not shown GLBuffer::AddData()
and AddAttribute
, but I think you got an idea of this.
The same for VertexArray
class VertexArray
{
public:
VertexArray* Create() { return GLVertexArray(); }
virtual void BindVertexArray() {}
}
class GLVertexArray : public VertexArray
{
public:
...
}
and so on
Shader is a bit different
enum SHADERTYPE
{
VERTEX,
FRAGMENT
};
class Shader
{
public:
Shader* Create() { return GLShader; }
virtual const int ShaderFromSource(const char* path, SHADERTYPE type) {}
virtual void End(const int* shaders, int count) {}
virtual void UseProgram() {}
virtual void //add uniforms etc
};
class GLShader : public Shader
{
public:
GLShader()
{
shaderProgram = glCreateProgram();
}
const int GLShader::ShaderFromSource(const char* path, SHADERTYPE type) override
{
unsigned int shaderID = glCreateShader(SHADERTYPEToOpenGL(type));
glShaderSource(shaderID, 1, &shader, NULL);
glCompileShader(shaderID);
glAttachShader(shaderProgram, shaderID);
return shaderID;
}
void GLShader::End(const int ids, int count) override
{
glLinkProgram(shaderProgram);
for (int i = 0; i < count; ++i) {
glDetachShader(shaderProgram, ids[i]);
glDeleteShader(ids[i]);
}
}
void UseProgram() override { glUseProgram(shaderProgram); }
unsigned int shaderProgram;
};
I want to create vao, vbo and shader in the Cube class ctor in the main thread and call Cube::Render
in a render thread Cube::Render
calls Use program adds uniforms and call DrawArray.
void mainloop()
{
Cube cube;
std::thread* thread = nullptr;
std::mutex mutex;
std::lock_guard<std::mutex> guard(mutex);
thread = new std::thread([&]() {
while (!quit) {
SDL_GL_MakeCurrent(window, glContext);
glClearColor(0, 0, static_cast<float>(15) / 255, 1);
glClear(GL_COLOR_BUFFER_BIT);
cube.Render();
SDL_GL_SwapWindow(window);
}
});
}
Cube cube
- creates vao, vbo, shaders - adds vertices to vbo
class Cube
{
Cube()
{
vao = vao->Create();
vbo = vbo->Create(ARRAY, STATIC_DRAW);
vbo->AddData(...);
vbo->AddAttributes(...);
shader = shader->Create();
int shaders[2] = {
shader->ShaderFromSource(vs, VERTEX),
shader->ShaderFromSource(fs, FRAGMENT)
};
shader->End(shaders, 2);
}
VertexArray* vao = nullptr;
Buffer* vbo = nullptr;
Shader* shader = nullptr;
};
cube.Render()
- uses shader, adds uniforms, call draw arrays
Cube::Render()
{
shader->UseProgram();
shader->Uniform(mvp);
vao->DrawArrays(TRIANGELS, 0, 36);
}
when Cube gets created in a main thread I got this message
when Cube gets created in a render thread I got this message
Why does it happen? How to support rendering in a different thread?
c++ multithreading opengl rendering
c++ multithreading opengl rendering
edited Jan 1 at 19:21
JarekBisnesu
asked Jan 1 at 19:06
JarekBisnesuJarekBisnesu
495
495
Calling class member functions of null pointer instances is not a good practice. TheShader::Create
function should be declared as static and returnsnew GLSharder();
– tunglt
Jan 1 at 20:53
Ok, I will change it. Why it is not a good practice? It won't fix threads problem. I made a small test with new smallVBO
andGLVBO
struct which does almost the same - callsgenBuffers
andbindBuffers(GL_ARRAY_BUFFER)
and it does work. Any ideas?
– JarekBisnesu
Jan 1 at 21:12
It isn't a good practice because you force the code maintainer to reread your codes twice when the program crashed. He (or she) don't know if the called function has accessed to a member variable and catch an access violation. Usingsharder = Shader::Create();
is much clearer.
– tunglt
Jan 1 at 22:14
Sharing OpenGL objects with multi-thread model needs more work. Each thread should have its own context and the contexts must be shared between threads via wglShareLists orSDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
– tunglt
Jan 1 at 22:17
As stated in VAO specification VAO objects cannot be shared between contexts, so the multiple contexts solution will not work for your program. More discussion about using OpenGL with multithread in SO is here
– tunglt
Jan 1 at 22:43
|
show 5 more comments
Calling class member functions of null pointer instances is not a good practice. TheShader::Create
function should be declared as static and returnsnew GLSharder();
– tunglt
Jan 1 at 20:53
Ok, I will change it. Why it is not a good practice? It won't fix threads problem. I made a small test with new smallVBO
andGLVBO
struct which does almost the same - callsgenBuffers
andbindBuffers(GL_ARRAY_BUFFER)
and it does work. Any ideas?
– JarekBisnesu
Jan 1 at 21:12
It isn't a good practice because you force the code maintainer to reread your codes twice when the program crashed. He (or she) don't know if the called function has accessed to a member variable and catch an access violation. Usingsharder = Shader::Create();
is much clearer.
– tunglt
Jan 1 at 22:14
Sharing OpenGL objects with multi-thread model needs more work. Each thread should have its own context and the contexts must be shared between threads via wglShareLists orSDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
– tunglt
Jan 1 at 22:17
As stated in VAO specification VAO objects cannot be shared between contexts, so the multiple contexts solution will not work for your program. More discussion about using OpenGL with multithread in SO is here
– tunglt
Jan 1 at 22:43
Calling class member functions of null pointer instances is not a good practice. The
Shader::Create
function should be declared as static and returns new GLSharder();
– tunglt
Jan 1 at 20:53
Calling class member functions of null pointer instances is not a good practice. The
Shader::Create
function should be declared as static and returns new GLSharder();
– tunglt
Jan 1 at 20:53
Ok, I will change it. Why it is not a good practice? It won't fix threads problem. I made a small test with new small
VBO
and GLVBO
struct which does almost the same - calls genBuffers
and bindBuffers(GL_ARRAY_BUFFER)
and it does work. Any ideas?– JarekBisnesu
Jan 1 at 21:12
Ok, I will change it. Why it is not a good practice? It won't fix threads problem. I made a small test with new small
VBO
and GLVBO
struct which does almost the same - calls genBuffers
and bindBuffers(GL_ARRAY_BUFFER)
and it does work. Any ideas?– JarekBisnesu
Jan 1 at 21:12
It isn't a good practice because you force the code maintainer to reread your codes twice when the program crashed. He (or she) don't know if the called function has accessed to a member variable and catch an access violation. Using
sharder = Shader::Create();
is much clearer.– tunglt
Jan 1 at 22:14
It isn't a good practice because you force the code maintainer to reread your codes twice when the program crashed. He (or she) don't know if the called function has accessed to a member variable and catch an access violation. Using
sharder = Shader::Create();
is much clearer.– tunglt
Jan 1 at 22:14
Sharing OpenGL objects with multi-thread model needs more work. Each thread should have its own context and the contexts must be shared between threads via wglShareLists or
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
– tunglt
Jan 1 at 22:17
Sharing OpenGL objects with multi-thread model needs more work. Each thread should have its own context and the contexts must be shared between threads via wglShareLists or
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
– tunglt
Jan 1 at 22:17
As stated in VAO specification VAO objects cannot be shared between contexts, so the multiple contexts solution will not work for your program. More discussion about using OpenGL with multithread in SO is here
– tunglt
Jan 1 at 22:43
As stated in VAO specification VAO objects cannot be shared between contexts, so the multiple contexts solution will not work for your program. More discussion about using OpenGL with multithread in SO is here
– tunglt
Jan 1 at 22:43
|
show 5 more comments
1 Answer
1
active
oldest
votes
I see you're using SDL2, so, you have to create 2 SDL_GLContext
s, let's say
SDL_GLContext mainContext;
SDL_GLContext renderThreadContext;
if you already enabled SDL_GL_SHARE_WITH_CURRENT_CONTEXT
all you need to do is
after creating a window you have to create mainContext
context
mainContext = SDL_GL_CreateContext(window);
then create a thread and Create renderThreadContext in this thread!!!
void RenderThread() {
std::thread* renderThread = nullptr;
thread = new std::thread([&](){
renderThreadContext = SDL_GL_CreateContext(window);
//*** NOW CREATE CUBE OBJECT ***
Cube cube;
while(!quit) {
SDL_GL_Make_Current(window, renderThreadContext);
//Opengl Calls
SDL_GL_SwapWindow(window);
}
});
}
as tunglt said - Each thread should have its own context
, so you have to create a new context in a thread as I showed above.
Yep, that works! Thank you man! I did not understand tunglt at the first time. Thank you @tunglt too
– JarekBisnesu
Jan 2 at 17:34
Your welcome. Glad I helped you.
– Shout
Jan 2 at 17:36
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53998186%2fhow-can-i-fix-using-gl-buffers-and-shaders-in-different-thread%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
I see you're using SDL2, so, you have to create 2 SDL_GLContext
s, let's say
SDL_GLContext mainContext;
SDL_GLContext renderThreadContext;
if you already enabled SDL_GL_SHARE_WITH_CURRENT_CONTEXT
all you need to do is
after creating a window you have to create mainContext
context
mainContext = SDL_GL_CreateContext(window);
then create a thread and Create renderThreadContext in this thread!!!
void RenderThread() {
std::thread* renderThread = nullptr;
thread = new std::thread([&](){
renderThreadContext = SDL_GL_CreateContext(window);
//*** NOW CREATE CUBE OBJECT ***
Cube cube;
while(!quit) {
SDL_GL_Make_Current(window, renderThreadContext);
//Opengl Calls
SDL_GL_SwapWindow(window);
}
});
}
as tunglt said - Each thread should have its own context
, so you have to create a new context in a thread as I showed above.
Yep, that works! Thank you man! I did not understand tunglt at the first time. Thank you @tunglt too
– JarekBisnesu
Jan 2 at 17:34
Your welcome. Glad I helped you.
– Shout
Jan 2 at 17:36
add a comment |
I see you're using SDL2, so, you have to create 2 SDL_GLContext
s, let's say
SDL_GLContext mainContext;
SDL_GLContext renderThreadContext;
if you already enabled SDL_GL_SHARE_WITH_CURRENT_CONTEXT
all you need to do is
after creating a window you have to create mainContext
context
mainContext = SDL_GL_CreateContext(window);
then create a thread and Create renderThreadContext in this thread!!!
void RenderThread() {
std::thread* renderThread = nullptr;
thread = new std::thread([&](){
renderThreadContext = SDL_GL_CreateContext(window);
//*** NOW CREATE CUBE OBJECT ***
Cube cube;
while(!quit) {
SDL_GL_Make_Current(window, renderThreadContext);
//Opengl Calls
SDL_GL_SwapWindow(window);
}
});
}
as tunglt said - Each thread should have its own context
, so you have to create a new context in a thread as I showed above.
Yep, that works! Thank you man! I did not understand tunglt at the first time. Thank you @tunglt too
– JarekBisnesu
Jan 2 at 17:34
Your welcome. Glad I helped you.
– Shout
Jan 2 at 17:36
add a comment |
I see you're using SDL2, so, you have to create 2 SDL_GLContext
s, let's say
SDL_GLContext mainContext;
SDL_GLContext renderThreadContext;
if you already enabled SDL_GL_SHARE_WITH_CURRENT_CONTEXT
all you need to do is
after creating a window you have to create mainContext
context
mainContext = SDL_GL_CreateContext(window);
then create a thread and Create renderThreadContext in this thread!!!
void RenderThread() {
std::thread* renderThread = nullptr;
thread = new std::thread([&](){
renderThreadContext = SDL_GL_CreateContext(window);
//*** NOW CREATE CUBE OBJECT ***
Cube cube;
while(!quit) {
SDL_GL_Make_Current(window, renderThreadContext);
//Opengl Calls
SDL_GL_SwapWindow(window);
}
});
}
as tunglt said - Each thread should have its own context
, so you have to create a new context in a thread as I showed above.
I see you're using SDL2, so, you have to create 2 SDL_GLContext
s, let's say
SDL_GLContext mainContext;
SDL_GLContext renderThreadContext;
if you already enabled SDL_GL_SHARE_WITH_CURRENT_CONTEXT
all you need to do is
after creating a window you have to create mainContext
context
mainContext = SDL_GL_CreateContext(window);
then create a thread and Create renderThreadContext in this thread!!!
void RenderThread() {
std::thread* renderThread = nullptr;
thread = new std::thread([&](){
renderThreadContext = SDL_GL_CreateContext(window);
//*** NOW CREATE CUBE OBJECT ***
Cube cube;
while(!quit) {
SDL_GL_Make_Current(window, renderThreadContext);
//Opengl Calls
SDL_GL_SwapWindow(window);
}
});
}
as tunglt said - Each thread should have its own context
, so you have to create a new context in a thread as I showed above.
answered Jan 2 at 16:42
ShoutShout
1286
1286
Yep, that works! Thank you man! I did not understand tunglt at the first time. Thank you @tunglt too
– JarekBisnesu
Jan 2 at 17:34
Your welcome. Glad I helped you.
– Shout
Jan 2 at 17:36
add a comment |
Yep, that works! Thank you man! I did not understand tunglt at the first time. Thank you @tunglt too
– JarekBisnesu
Jan 2 at 17:34
Your welcome. Glad I helped you.
– Shout
Jan 2 at 17:36
Yep, that works! Thank you man! I did not understand tunglt at the first time. Thank you @tunglt too
– JarekBisnesu
Jan 2 at 17:34
Yep, that works! Thank you man! I did not understand tunglt at the first time. Thank you @tunglt too
– JarekBisnesu
Jan 2 at 17:34
Your welcome. Glad I helped you.
– Shout
Jan 2 at 17:36
Your welcome. Glad I helped you.
– Shout
Jan 2 at 17:36
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53998186%2fhow-can-i-fix-using-gl-buffers-and-shaders-in-different-thread%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Calling class member functions of null pointer instances is not a good practice. The
Shader::Create
function should be declared as static and returnsnew GLSharder();
– tunglt
Jan 1 at 20:53
Ok, I will change it. Why it is not a good practice? It won't fix threads problem. I made a small test with new small
VBO
andGLVBO
struct which does almost the same - callsgenBuffers
andbindBuffers(GL_ARRAY_BUFFER)
and it does work. Any ideas?– JarekBisnesu
Jan 1 at 21:12
It isn't a good practice because you force the code maintainer to reread your codes twice when the program crashed. He (or she) don't know if the called function has accessed to a member variable and catch an access violation. Using
sharder = Shader::Create();
is much clearer.– tunglt
Jan 1 at 22:14
Sharing OpenGL objects with multi-thread model needs more work. Each thread should have its own context and the contexts must be shared between threads via wglShareLists or
SDL_GL_SetAttribute(SDL_GL_SHARE_WITH_CURRENT_CONTEXT, 1);
– tunglt
Jan 1 at 22:17
As stated in VAO specification VAO objects cannot be shared between contexts, so the multiple contexts solution will not work for your program. More discussion about using OpenGL with multithread in SO is here
– tunglt
Jan 1 at 22:43