shader auto reload

This commit is contained in:
2019-02-21 20:20:43 +01:00
parent eaab9c79e5
commit 78ca0ee6ad
7 changed files with 77 additions and 15 deletions

View File

@@ -505,6 +505,7 @@ void App::update(float dt)
{ {
static std::mutex mutex; static std::mutex mutex;
static float rec_timer = 0.f; static float rec_timer = 0.f;
static float reload_timer = 0.f;
// avoid multiple threads to update the scene // avoid multiple threads to update the scene
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
@@ -524,17 +525,18 @@ void App::update(float dt)
//glClear(GL_COLOR_BUFFER_BIT); //glClear(GL_COLOR_BUFFER_BIT);
//if (!canvas->m_mouse_captured) //if (!canvas->m_mouse_captured)
#if _DEBUG && (_WIN32 || __OSX__)
reload_timer += dt;
if (reload_timer > 1.0)
{ {
#if _WIN32 || __OSX__ reload_timer = 0;
ShaderManager::reload();
layout.reload(); layout.reload();
#endif
if (auto* main = layout[main_id]) if (auto* main = layout[main_id])
{
main->update(width, height, zoom); main->update(width, height, zoom);
//stroke->update_controls();
}
} }
#endif
{ {
static glm::vec4 color_button_normal{ .1, .1, .1, 1 }; static glm::vec4 color_button_normal{ .1, .1, .1, 1 };
static glm::vec4 color_button_hlight{ 1, .0, .0, 1 }; static glm::vec4 color_button_hlight{ 1, .0, .0, 1 };

View File

@@ -220,12 +220,15 @@ glm::uint8_t* Asset::read_all()
void Asset::close() void Asset::close()
{ {
#ifdef __ANDROID__ #ifdef __ANDROID__
AAsset_close(m_asset); if (m_asset)
AAsset_close(m_asset);
m_asset = nullptr;
#else #else
if (m_fp) if (m_fp)
fclose(m_fp); fclose(m_fp);
if (m_data) if (m_data)
delete m_data; delete m_data;
m_data = nullptr; m_data = nullptr;
m_fp = nullptr;
#endif #endif
} }

View File

@@ -19,5 +19,6 @@ public:
bool open(const char* path); bool open(const char* path);
uint8_t* read_all(); uint8_t* read_all();
void close(); void close();
~Asset() { close(); }
}; };

View File

@@ -7,7 +7,7 @@
#include <stb/stb_image.h> #include <stb/stb_image.h>
#include <stb/stb_image_write.h> #include <stb/stb_image_write.h>
#ifdef DEBUG #ifdef _DEBUG
#pragma comment (lib, "libcurl_debug.lib") #pragma comment (lib, "libcurl_debug.lib")
#else #else
#pragma comment (lib, "libcurl.lib") #pragma comment (lib, "libcurl.lib")

View File

@@ -162,7 +162,7 @@ bool RTT::create(int width, int height, int tex/* = -1*/, GLint internal_format)
void RTT::bindFramebuffer() void RTT::bindFramebuffer()
{ {
#ifdef DEBUG #ifdef _DEBUG
if (bound) if (bound)
{ {
LOG("framebuffer bound twice!"); LOG("framebuffer bound twice!");

View File

@@ -13,6 +13,10 @@ std::string Shader::read(const std::string& path)
std::string ret; std::string ret;
if (a.open(path.c_str())) if (a.open(path.c_str()))
{ {
struct stat tmp_info;
if (stat(path.c_str(), &tmp_info) == 0)
m_deps[path] = tmp_info;
std::regex reg_include(R"!(#include "([^"]+)")!"); std::regex reg_include(R"!(#include "([^"]+)")!");
std::string data((char*)a.read_all(), a.m_len); std::string data((char*)a.read_all(), a.m_len);
@@ -105,18 +109,46 @@ bool Shader::load(const std::string& path)
{ {
*sections["vertex"] = SHADER_VERSION + *sections["vertex"]; *sections["vertex"] = SHADER_VERSION + *sections["vertex"];
*sections["fragment"] = SHADER_VERSION + *sections["fragment"]; *sections["fragment"] = SHADER_VERSION + *sections["fragment"];
return create(sections["vertex"]->c_str(), sections["fragment"]->c_str()); if (create(sections["vertex"]->c_str(), sections["fragment"]->c_str()))
{
m_path = path;
return true;
}
} }
else else
{ {
LOG("could not find [[vertex]] and [[fragment]] sections on %s", path.c_str()); LOG("could not find [[vertex]] and [[fragment]] sections on %s", path.c_str());
} }
m_path = path;
return false; return false;
} }
bool Shader::reload()
{
if (m_path.empty())
return false;
bool dirty = false;
struct stat tmp_info;
for (auto& d : m_deps)
{
if (stat(d.first.c_str(), &tmp_info) != 0)
continue;
if (tmp_info.st_mtime > d.second.st_mtime)
{
d.second = tmp_info;
dirty = true;
}
}
if (dirty)
{
LOG("reload shader %s", m_path.c_str());
destroy();
return load(m_path);
}
}
bool Shader::create(const char* vertex, const char* fragment) bool Shader::create(const char* vertex, const char* fragment)
{ {
GLint status; GLint status;
@@ -136,7 +168,7 @@ bool Shader::create(const char* vertex, const char* fragment)
glGetShaderInfoLog(vs, sizeof(infolog), &infolen, infolog); glGetShaderInfoLog(vs, sizeof(infolog), &infolen, infolog);
if (infolen > 0) if (infolen > 0)
{ {
LOG("\nVERTEX SHADER:"); LOG("\nVERTEX SHADER: %s", m_path.c_str());
parse_error(infolog, vertex); parse_error(infolog, vertex);
} }
if (status == 0) if (status == 0)
@@ -158,7 +190,7 @@ bool Shader::create(const char* vertex, const char* fragment)
glGetShaderInfoLog(fs, sizeof(infolog), &infolen, infolog); glGetShaderInfoLog(fs, sizeof(infolog), &infolen, infolog);
if (infolen > 0) if (infolen > 0)
{ {
LOG("\nFRAGMENT SHADER:"); LOG("\nFRAGMENT SHADER: %s", m_path.c_str());
parse_error(infolog, fragment); parse_error(infolog, fragment);
} }
if (status == 0) if (status == 0)
@@ -200,7 +232,7 @@ bool Shader::create(const char* vertex, const char* fragment)
glGetProgramiv(ps, GL_LINK_STATUS, &status); glGetProgramiv(ps, GL_LINK_STATUS, &status);
glGetProgramInfoLog(ps, sizeof(infolog), &infolen, infolog); glGetProgramInfoLog(ps, sizeof(infolog), &infolen, infolog);
if (infolen > 0) if (infolen > 0)
LOG("LINK SHADER:\n%s", infolog); LOG("LINK SHADER: %s\n%s", m_path.c_str(), infolog);
if (status == 0) if (status == 0)
{ {
glDeleteProgram(ps); glDeleteProgram(ps);
@@ -228,6 +260,18 @@ bool Shader::create(const char* vertex, const char* fragment)
return true; return true;
} }
void Shader::destroy()
{
if (prog)
{
glUseProgram(0);
glDeleteProgram(prog);
prog = 0;
}
m_umap.clear();
}
void Shader::use() void Shader::use()
{ {
glUseProgram(prog); glUseProgram(prog);
@@ -282,6 +326,14 @@ bool ShaderManager::load(kShader id, const std::string& path)
return m_shaders[id].load(path); return m_shaders[id].load(path);
} }
bool ShaderManager::reload()
{
bool success = true;
for (auto& s : m_shaders)
success &= s.second.reload();
return success;
}
bool ShaderManager::create(kShader id, const char* vertex, const char* fragment) bool ShaderManager::create(kShader id, const char* vertex, const char* fragment)
{ {
m_shaders[id].name = id; m_shaders[id].name = id;

View File

@@ -74,6 +74,7 @@ enum class kShader : uint16_t
class Shader class Shader
{ {
std::map<std::string, struct stat> m_deps;
std::string m_path; std::string m_path;
std::map<kShaderUniform, GLuint> m_umap; std::map<kShaderUniform, GLuint> m_umap;
GLuint prog; GLuint prog;
@@ -82,7 +83,9 @@ public:
kShader name; kShader name;
void parse_error(const char* msg, const char* code); void parse_error(const char* msg, const char* code);
bool load(const std::string& path); bool load(const std::string& path);
bool reload();
bool create(const char* vertex, const char* fragment); bool create(const char* vertex, const char* fragment);
void destroy();
void use(); void use();
void u_vec4(kShaderUniform id, const glm::vec4& v); void u_vec4(kShaderUniform id, const glm::vec4& v);
void u_vec3(kShaderUniform id, const glm::vec3& v); void u_vec3(kShaderUniform id, const glm::vec3& v);
@@ -100,6 +103,7 @@ class ShaderManager
public: public:
static bool ext_framebuffer_fetch; static bool ext_framebuffer_fetch;
static bool load(kShader id, const std::string& path); static bool load(kShader id, const std::string& path);
static bool reload();
static bool create(kShader id, const char* vertex, const char* fragment); static bool create(kShader id, const char* vertex, const char* fragment);
static void use(kShader id); static void use(kShader id);
static void use(const char* name); static void use(const char* name);