PDA

View Full Version : recompile the shader on runtime, like hot plug the new compiled shader



lummxx
04-10-2015, 02:46 AM
I am spending too much time running the render engine when i do a small change on mu GLSL shaders.

I have implemented a method that runs on a separate thread and checks for shader file stamps to see if they are different. If they are then i recompile the shaders. I plan to do this in future with OS calls and remove this not very efficient method.

I have e problem however that i can not create the program. I get invalid error for some reasons and i dont know how to fix it the whole day. :S

I also noted that i get 0 when i want to create a shader even if the shader doesn't have errors.
Also do i need to set uniforms again ??

Thanks guys for help :D





GLuint ShaderProgram::createProgram(){

GLuint newProgramId = glCreateProgram();
if (newProgramId == 0){
log_.error(std::string("Failed to create new program: "));

checkForError(programName_.c_str(), "createProgram");
for (auto& i : shaders_){
glDetachShader(newProgramId, i.second.getId());
}
return 0;
}

deleteProgram();
for (auto& i : shaders_){
glAttachShader(newProgramId, i.second.getId());
}

glLinkProgram(newProgramId);

GLint shaderStatus;
glGetProgramiv(newProgramId, GL_LINK_STATUS, &shaderStatus);
if (shaderStatus == GL_FALSE){

GLint infoLogLength;
glGetProgramiv(newProgramId, GL_INFO_LOG_LENGTH, &infoLogLength);

GLchar *strInfoLog = new GLchar[infoLogLength + 1];
glGetProgramInfoLog(newProgramId, infoLogLength, NULL, strInfoLog);
//fprintf(stderr, "Linker failure: %s\n", strInfoLog);
log_.error(std::string("Linker failure: ") + programName_ + ", " + strInfoLog + " program Id: " + std::to_string(newProgramId));

delete[] strInfoLog;
return -1;
}

checkForError(programName_.c_str(), "createProgram");

deleteProgram();
for (auto& i : shaders_){
glDetachShader(newProgramId, i.second.getId());
glDeleteShader(i.second.getId());
}


log_.info(std::string("New shader program created: ") + programName_ + " with ID " + std::to_string(newProgramId));
programId_ = newProgramId;

if (!isModifiedThread_)
isModifiedThread_ = new std::thread(&ShaderProgram::checkForModifyed, this, timer);
//isModifiedThread_->join();
return programId_;
}

void ShaderProgram::checkForModifyed(int timer){

while (true){ // use mutex to break the stop the loop and finish thread exceuton to release resourses on program close
std::this_thread::sleep_for(std::chrono::seconds(t imer));

for (auto& i : shaders_){
if (i.second.isModified()){
log_.debug(std::string("Shader modified: ") + i.second.getPath());
//for (auto& j : shaders_){
// createShader(j.second.getType(), j.second.getPath());
//}
createShader(i.second.getType(), i.second.getPath());
//deleteProgram();
createProgram();
//shaders_.erase(i);
}
}
}
}


void ShaderProgram::startThread() {
//mutex.lock();
//thread.start(threadMethod);
}

void ShaderProgram::stopThread() {
//mutex.unlock();
//thread.join();
}

GClements
04-10-2015, 03:24 AM
I have implemented a method that runs on a separate thread and checks for shader file stamps to see if they are different. If they are then i recompile the shaders.
Are you trying to compile the shaders in a different thread? If so, does that thread have a context bound to it? Does the context share data with the context used by the rendering thread?

lummxx
04-10-2015, 04:47 AM
I do poll in a different thread for file chances so i guess there is no data shared. I forgot about that. I will check and post what I did


As for now my whole render engine is on one thread will i decide to implement culling before sending the draw command. This will be done probablly after i fix a bug with spot light, work on shadows a bit more, and use some more C++11

This is how i create the thread



isModifiedThread_ = new std::thread(&ShaderProgram::checkForModifyed, this, timer);



UPDATE: they do share all the data and i still get that Invalid operation :S. still looking to fix it but i have no clue now what is happening.
and this should share the data. I will write some code inside that thread instead of calling methods to compile shaders and see that will happen.

I have to go at training now but here is the link to github code https://github.com/lumx/GameEngine/blob/master/GameEngine/src/Core/Render/ShaderProgram.cpp. In mean time i will think for a solution but still it does not seem very obvious to me. Like usual the problem is in front on my eyes but i just cant see it :S

UPDATE2: Ok i guess i know what it is but i dont know how to fix it. When i pass the values to the thread those are copied and things get screwed up because i dont have a context bound. While looking at values in debugger i got tricked because the values were the same and i though i am referring to the same class and im not copying it but is seems that i do.

Now my problem is how to fix this syntactically in C++. I have no idea now. I treid also this but it is not working


isModifiedThread_ = new std::thread(ShaderProgram::checkForModifyed, std::ref(*this), timer);
and this one does not even compile

isModifiedThread_ = new std::thread(std::ref(&this->checkForModifyed), std::ref(*this), timer);