render implement thread, wrap GL commands into tasks
This commit is contained in:
240
src/shader.cpp
240
src/shader.cpp
@@ -2,6 +2,7 @@
|
||||
#include "log.h"
|
||||
#include "shader.h"
|
||||
#include "asset.h"
|
||||
#include "app.h"
|
||||
|
||||
std::map<kShader, Shader> ShaderManager::m_shaders;
|
||||
Shader* ShaderManager::m_current;
|
||||
@@ -153,122 +154,135 @@ bool Shader::reload()
|
||||
|
||||
bool Shader::create(const char* vertex, const char* fragment)
|
||||
{
|
||||
GLint status;
|
||||
static char infolog[4096];
|
||||
int infolen;
|
||||
const GLchar* source;
|
||||
|
||||
auto vs = glCreateShader(GL_VERTEX_SHADER);
|
||||
if (!vs)
|
||||
bool ret = true;
|
||||
App::I.render_task([&]
|
||||
{
|
||||
return false;
|
||||
}
|
||||
source = vertex;
|
||||
glShaderSource(vs, 1, &source, nullptr);
|
||||
glCompileShader(vs);
|
||||
glGetShaderiv(vs, GL_COMPILE_STATUS, &status);
|
||||
glGetShaderInfoLog(vs, sizeof(infolog), &infolen, infolog);
|
||||
if (infolen > 0)
|
||||
{
|
||||
LOG("\nVERTEX SHADER: %s", m_path.c_str());
|
||||
parse_error(infolog, vertex);
|
||||
}
|
||||
if (status == 0)
|
||||
{
|
||||
glDeleteShader(vs);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto fs = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
if (!fs)
|
||||
{
|
||||
glDeleteShader(vs);
|
||||
return false;
|
||||
}
|
||||
source = fragment;
|
||||
glShaderSource(fs, 1, &source, nullptr);
|
||||
glCompileShader(fs);
|
||||
glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
|
||||
glGetShaderInfoLog(fs, sizeof(infolog), &infolen, infolog);
|
||||
if (infolen > 0)
|
||||
{
|
||||
LOG("\nFRAGMENT SHADER: %s", m_path.c_str());
|
||||
parse_error(infolog, fragment);
|
||||
}
|
||||
if (status == 0)
|
||||
{
|
||||
glDeleteShader(vs);
|
||||
glDeleteShader(fs);
|
||||
return false;
|
||||
}
|
||||
|
||||
auto ps = glCreateProgram();
|
||||
if (!ps)
|
||||
{
|
||||
glDeleteShader(vs);
|
||||
glDeleteShader(fs);
|
||||
return false;
|
||||
}
|
||||
glAttachShader(ps, vs);
|
||||
glAttachShader(ps, fs);
|
||||
glDeleteShader(vs);
|
||||
glDeleteShader(fs);
|
||||
|
||||
glLinkProgram(ps);
|
||||
if (glGetAttribLocation(ps, "pos") != -1)
|
||||
glBindAttribLocation(ps, 0, "pos");
|
||||
|
||||
if (glGetAttribLocation(ps, "uvs") != -1)
|
||||
glBindAttribLocation(ps, 1, "uvs");
|
||||
|
||||
if (glGetAttribLocation(ps, "uvs2") != -1)
|
||||
glBindAttribLocation(ps, 2, "uvs2");
|
||||
GLint status;
|
||||
static char infolog[4096];
|
||||
int infolen;
|
||||
const GLchar* source;
|
||||
|
||||
if (glGetAttribLocation(ps, "col") != -1)
|
||||
glBindAttribLocation(ps, 3, "col");
|
||||
|
||||
if (glGetAttribLocation(ps, "nor") != -1)
|
||||
glBindAttribLocation(ps, 3, "nor");
|
||||
|
||||
glLinkProgram(ps);
|
||||
glGetProgramiv(ps, GL_LINK_STATUS, &status);
|
||||
glGetProgramInfoLog(ps, sizeof(infolog), &infolen, infolog);
|
||||
if (infolen > 0)
|
||||
LOG("LINK SHADER: %s\n%s", m_path.c_str(), infolog);
|
||||
if (status == 0)
|
||||
{
|
||||
glDeleteProgram(ps);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse shader uniforms
|
||||
{
|
||||
GLint count;
|
||||
GLint size; // size of the variable
|
||||
GLenum type; // type of the variable (float, vec3 or mat4, etc)
|
||||
const GLsizei bufSize = 16; // maximum name length
|
||||
GLchar name[bufSize]; // variable name in GLSL
|
||||
GLsizei length; // name length
|
||||
glGetProgramiv(ps, GL_ACTIVE_UNIFORMS, &count);
|
||||
for (int i = 0; i < count; i++)
|
||||
auto vs = glCreateShader(GL_VERTEX_SHADER);
|
||||
if (!vs)
|
||||
{
|
||||
glGetActiveUniform(ps, (GLuint)i, bufSize, &length, &size, &type, name);
|
||||
m_umap[(kShaderUniform)const_hash(name)] = glGetUniformLocation(ps, name);
|
||||
//printf("Uniform #%d Type: %u Name: %s Loc: %d\n", i, type, name, glGetUniformLocation(ps, name));
|
||||
ret = false;
|
||||
return;
|
||||
}
|
||||
}
|
||||
source = vertex;
|
||||
glShaderSource(vs, 1, &source, nullptr);
|
||||
glCompileShader(vs);
|
||||
glGetShaderiv(vs, GL_COMPILE_STATUS, &status);
|
||||
glGetShaderInfoLog(vs, sizeof(infolog), &infolen, infolog);
|
||||
if (infolen > 0)
|
||||
{
|
||||
LOG("\nVERTEX SHADER: %s", m_path.c_str());
|
||||
parse_error(infolog, vertex);
|
||||
}
|
||||
if (status == 0)
|
||||
{
|
||||
glDeleteShader(vs);
|
||||
ret = false;
|
||||
return;
|
||||
}
|
||||
|
||||
auto fs = glCreateShader(GL_FRAGMENT_SHADER);
|
||||
if (!fs)
|
||||
{
|
||||
glDeleteShader(vs);
|
||||
ret = false;
|
||||
return;
|
||||
}
|
||||
source = fragment;
|
||||
glShaderSource(fs, 1, &source, nullptr);
|
||||
glCompileShader(fs);
|
||||
glGetShaderiv(fs, GL_COMPILE_STATUS, &status);
|
||||
glGetShaderInfoLog(fs, sizeof(infolog), &infolen, infolog);
|
||||
if (infolen > 0)
|
||||
{
|
||||
LOG("\nFRAGMENT SHADER: %s", m_path.c_str());
|
||||
parse_error(infolog, fragment);
|
||||
}
|
||||
if (status == 0)
|
||||
{
|
||||
glDeleteShader(vs);
|
||||
glDeleteShader(fs);
|
||||
ret = false;
|
||||
return;
|
||||
}
|
||||
|
||||
auto ps = glCreateProgram();
|
||||
if (!ps)
|
||||
{
|
||||
glDeleteShader(vs);
|
||||
glDeleteShader(fs);
|
||||
ret = false;
|
||||
return;
|
||||
}
|
||||
glAttachShader(ps, vs);
|
||||
glAttachShader(ps, fs);
|
||||
glDeleteShader(vs);
|
||||
glDeleteShader(fs);
|
||||
|
||||
glLinkProgram(ps);
|
||||
if (glGetAttribLocation(ps, "pos") != -1)
|
||||
glBindAttribLocation(ps, 0, "pos");
|
||||
|
||||
if (glGetAttribLocation(ps, "uvs") != -1)
|
||||
glBindAttribLocation(ps, 1, "uvs");
|
||||
|
||||
if (glGetAttribLocation(ps, "uvs2") != -1)
|
||||
glBindAttribLocation(ps, 2, "uvs2");
|
||||
|
||||
if (glGetAttribLocation(ps, "col") != -1)
|
||||
glBindAttribLocation(ps, 3, "col");
|
||||
|
||||
if (glGetAttribLocation(ps, "nor") != -1)
|
||||
glBindAttribLocation(ps, 3, "nor");
|
||||
|
||||
glLinkProgram(ps);
|
||||
glGetProgramiv(ps, GL_LINK_STATUS, &status);
|
||||
glGetProgramInfoLog(ps, sizeof(infolog), &infolen, infolog);
|
||||
if (infolen > 0)
|
||||
LOG("LINK SHADER: %s\n%s", m_path.c_str(), infolog);
|
||||
if (status == 0)
|
||||
{
|
||||
glDeleteProgram(ps);
|
||||
ret = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Parse shader uniforms
|
||||
{
|
||||
GLint count;
|
||||
GLint size; // size of the variable
|
||||
GLenum type; // type of the variable (float, vec3 or mat4, etc)
|
||||
const GLsizei bufSize = 16; // maximum name length
|
||||
GLchar name[bufSize]; // variable name in GLSL
|
||||
GLsizei length; // name length
|
||||
glGetProgramiv(ps, GL_ACTIVE_UNIFORMS, &count);
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
glGetActiveUniform(ps, (GLuint)i, bufSize, &length, &size, &type, name);
|
||||
m_umap[(kShaderUniform)const_hash(name)] = glGetUniformLocation(ps, name);
|
||||
//printf("Uniform #%d Type: %u Name: %s Loc: %d\n", i, type, name, glGetUniformLocation(ps, name));
|
||||
}
|
||||
}
|
||||
|
||||
prog = ps;
|
||||
});
|
||||
|
||||
prog = ps;
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
void Shader::destroy()
|
||||
{
|
||||
if (prog)
|
||||
{
|
||||
glUseProgram(0);
|
||||
glDeleteProgram(prog);
|
||||
App::I.render_task_async([prog=prog]
|
||||
{
|
||||
glUseProgram(0);
|
||||
glDeleteProgram(prog);
|
||||
});
|
||||
prog = 0;
|
||||
}
|
||||
m_umap.clear();
|
||||
@@ -276,16 +290,19 @@ void Shader::destroy()
|
||||
|
||||
void Shader::use()
|
||||
{
|
||||
assert(App::I.is_render_thread());
|
||||
glUseProgram(prog);
|
||||
}
|
||||
void Shader::u_vec4(kShaderUniform id, const glm::vec4& v)
|
||||
{
|
||||
if (m_umap.count(id) == 0)
|
||||
assert(App::I.is_render_thread());
|
||||
if (m_umap.count(id) == 0)
|
||||
LOG("UNIFORM vec4 %d NOT FOUND in shader %d", (int)id, (int)name)
|
||||
else glUniform4fv(m_umap[id], 1, glm::value_ptr(v));
|
||||
}
|
||||
void Shader::u_vec3(kShaderUniform id, const glm::vec3& v)
|
||||
{
|
||||
assert(App::I.is_render_thread());
|
||||
if (m_umap.count(id) == 0)
|
||||
LOG("UNIFORM vec3 %d NOT FOUND in shader %d", (int)id, (int)name)
|
||||
else glUniform3fv(m_umap[id], 1, glm::value_ptr(v));
|
||||
@@ -293,19 +310,22 @@ void Shader::u_vec3(kShaderUniform id, const glm::vec3& v)
|
||||
|
||||
void Shader::u_vec2(kShaderUniform id, const glm::vec2& v)
|
||||
{
|
||||
if (m_umap.count(id) == 0)
|
||||
assert(App::I.is_render_thread());
|
||||
if (m_umap.count(id) == 0)
|
||||
LOG("UNIFORM vec2 %d NOT FOUND in shader %d", (int)id, (int)name)
|
||||
else glUniform2fv(m_umap[id], 1, glm::value_ptr(v));
|
||||
}
|
||||
|
||||
void Shader::u_mat4(kShaderUniform id, const glm::mat4& m)
|
||||
{
|
||||
if (m_umap.count(id) == 0)
|
||||
assert(App::I.is_render_thread());
|
||||
if (m_umap.count(id) == 0)
|
||||
LOG("UNIFORM mat4 %d NOT FOUND in shader %d", (int)id, (int)name)
|
||||
else glUniformMatrix4fv(m_umap[id], 1, GL_FALSE, glm::value_ptr(m));
|
||||
}
|
||||
void Shader::u_int(kShaderUniform id, int i)
|
||||
{
|
||||
assert(App::I.is_render_thread());
|
||||
if (m_umap.count(id) == 0)
|
||||
LOG("UNIFORM int %d NOT FOUND in shader %d", (int)id, (int)name)
|
||||
else
|
||||
@@ -313,12 +333,14 @@ void Shader::u_int(kShaderUniform id, int i)
|
||||
}
|
||||
void Shader::u_float(kShaderUniform id, float f)
|
||||
{
|
||||
if (m_umap.count(id) == 0)
|
||||
assert(App::I.is_render_thread());
|
||||
if (m_umap.count(id) == 0)
|
||||
LOG("UNIFORM float %d NOT FOUND in shader %d", (int)id, (int)name)
|
||||
else glUniform1f(m_umap[id], f);
|
||||
}
|
||||
GLint Shader::GetAttribLocation(const char* name)
|
||||
{
|
||||
assert(App::I.is_render_thread());
|
||||
return glGetAttribLocation(prog, name);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user