Allow all shader files to be loaded only once
Todo: preload
This commit is contained in:
parent
7894e5c864
commit
2a9656bfdc
@ -919,7 +919,6 @@ void IrrDriver::applyResolutionSettings()
|
|||||||
// FIXME: this load sequence is (mostly) duplicated from main.cpp!!
|
// FIXME: this load sequence is (mostly) duplicated from main.cpp!!
|
||||||
// That's just error prone
|
// That's just error prone
|
||||||
// (we're sure to update main.cpp at some point and forget this one...)
|
// (we're sure to update main.cpp at some point and forget this one...)
|
||||||
ShaderBase::updateShaders();
|
|
||||||
VAOManager::getInstance()->kill();
|
VAOManager::getInstance()->kill();
|
||||||
resetTextureTable();
|
resetTextureTable();
|
||||||
cleanUnicolorTextures();
|
cleanUnicolorTextures();
|
||||||
@ -930,6 +929,7 @@ void IrrDriver::applyResolutionSettings()
|
|||||||
}
|
}
|
||||||
delete m_renderer;
|
delete m_renderer;
|
||||||
initDevice();
|
initDevice();
|
||||||
|
ShaderBase::updateShaders();
|
||||||
|
|
||||||
font_manager = new FontManager();
|
font_manager = new FontManager();
|
||||||
font_manager->loadFonts();
|
font_manager->loadFonts();
|
||||||
|
@ -19,198 +19,16 @@
|
|||||||
#ifndef SERVER_ONLY
|
#ifndef SERVER_ONLY
|
||||||
|
|
||||||
#include "graphics/shader.hpp"
|
#include "graphics/shader.hpp"
|
||||||
|
|
||||||
#include "graphics/central_settings.hpp"
|
|
||||||
#include "graphics/gl_headers.hpp"
|
|
||||||
#include "graphics/irr_driver.hpp"
|
#include "graphics/irr_driver.hpp"
|
||||||
#include "graphics/shared_gpu_objects.hpp"
|
|
||||||
#include "graphics/spherical_harmonics.hpp"
|
#include "graphics/spherical_harmonics.hpp"
|
||||||
#include "io/file_manager.hpp"
|
|
||||||
#include "utils/log.hpp"
|
#include "utils/log.hpp"
|
||||||
|
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
std::string ShaderBase::m_shader_header = "";
|
|
||||||
std::vector<void(*)()> ShaderBase::m_all_kill_functions;
|
std::vector<void(*)()> ShaderBase::m_all_kill_functions;
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
/** Returns a string with the content of header.txt (which contains basic
|
|
||||||
* shader defines).
|
|
||||||
*/
|
|
||||||
const std::string& ShaderBase::getHeader()
|
|
||||||
{
|
|
||||||
// Only read file first time
|
|
||||||
if (m_shader_header.empty())
|
|
||||||
{
|
|
||||||
std::ifstream stream(file_manager->getShader("header.txt"), std::ios::in);
|
|
||||||
if (stream.is_open())
|
|
||||||
{
|
|
||||||
std::string line = "";
|
|
||||||
while (getline(stream, line))
|
|
||||||
m_shader_header += "\n" + line;
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
} // if m_shader_header.empty()
|
|
||||||
|
|
||||||
return m_shader_header;
|
|
||||||
} // getHeader
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
/** Loads a single shader.
|
|
||||||
* \param file Filename of the shader to load.
|
|
||||||
* \param type Type of the shader.
|
|
||||||
*/
|
|
||||||
GLuint ShaderBase::loadShader(const std::string &file, unsigned type)
|
|
||||||
{
|
|
||||||
GLuint id = glCreateShader(type);
|
|
||||||
|
|
||||||
std::ostringstream code;
|
|
||||||
#if !defined(USE_GLES2)
|
|
||||||
code << "#version " << CVS->getGLSLVersion()<<"\n";
|
|
||||||
#else
|
|
||||||
if (CVS->isGLSL())
|
|
||||||
code << "#version 300 es\n";
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !defined(USE_GLES2)
|
|
||||||
// Some drivers report that the compute shaders extension is available,
|
|
||||||
// but they report only OpenGL 3.x version, and thus these extensions
|
|
||||||
// must be enabled manually. Otherwise the shaders compilation will fail
|
|
||||||
// because STK tries to use extensions which are available, but disabled
|
|
||||||
// by default.
|
|
||||||
if (type == GL_COMPUTE_SHADER)
|
|
||||||
{
|
|
||||||
if (CVS->isARBComputeShaderUsable())
|
|
||||||
code << "#extension GL_ARB_compute_shader : enable\n";
|
|
||||||
if (CVS->isARBImageLoadStoreUsable())
|
|
||||||
code << "#extension GL_ARB_shader_image_load_store : enable\n";
|
|
||||||
if (CVS->isARBArraysOfArraysUsable())
|
|
||||||
code << "#extension GL_ARB_arrays_of_arrays : enable\n";
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (CVS->isAMDVertexShaderLayerUsable())
|
|
||||||
code << "#extension GL_AMD_vertex_shader_layer : enable\n";
|
|
||||||
|
|
||||||
if (CVS->isARBExplicitAttribLocationUsable())
|
|
||||||
code << "#extension GL_ARB_explicit_attrib_location : enable\n";
|
|
||||||
|
|
||||||
if (CVS->isAZDOEnabled())
|
|
||||||
{
|
|
||||||
code << "#extension GL_ARB_bindless_texture : enable\n";
|
|
||||||
code << "#define Use_Bindless_Texture\n";
|
|
||||||
}
|
|
||||||
code << "//" << file << "\n";
|
|
||||||
if (!CVS->isARBUniformBufferObjectUsable())
|
|
||||||
code << "#define UBO_DISABLED\n";
|
|
||||||
if (CVS->isAMDVertexShaderLayerUsable())
|
|
||||||
code << "#define VSLayer\n";
|
|
||||||
if (CVS->needsRGBBindlessWorkaround())
|
|
||||||
code << "#define SRGBBindlessFix\n";
|
|
||||||
|
|
||||||
#if !defined(USE_GLES2)
|
|
||||||
//shader compilation fails with some drivers if there is no precision qualifier
|
|
||||||
if (type == GL_FRAGMENT_SHADER)
|
|
||||||
code << "precision mediump float;\n";
|
|
||||||
#else
|
|
||||||
int range[2], precision;
|
|
||||||
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range, &precision);
|
|
||||||
|
|
||||||
if (precision > 0)
|
|
||||||
code << "precision highp float;\n";
|
|
||||||
else
|
|
||||||
code << "precision mediump float;\n";
|
|
||||||
#endif
|
|
||||||
code << "#define MAX_BONES " << SharedGPUObjects::getMaxMat4Size() << "\n";
|
|
||||||
|
|
||||||
code << getHeader();
|
|
||||||
|
|
||||||
std::ifstream stream(file_manager->getShader(file), std::ios::in);
|
|
||||||
if (stream.is_open())
|
|
||||||
{
|
|
||||||
std::string Line = "";
|
|
||||||
while (getline(stream, Line))
|
|
||||||
{
|
|
||||||
const std::string stk_include = "#stk_include";
|
|
||||||
std::size_t pos = Line.find(stk_include);
|
|
||||||
if (pos != std::string::npos)
|
|
||||||
{
|
|
||||||
std::size_t pos = Line.find("\"");
|
|
||||||
if (pos == std::string::npos)
|
|
||||||
{
|
|
||||||
Log::error("shader", "Invalid #stk_include line: '%s'.", Line.c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string filename = Line.substr(pos+1);
|
|
||||||
|
|
||||||
pos = filename.find("\"");
|
|
||||||
if (pos == std::string::npos)
|
|
||||||
{
|
|
||||||
Log::error("shader", "Invalid #stk_include line: '%s'.", Line.c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
filename = filename.substr(0, pos);
|
|
||||||
|
|
||||||
std::ifstream include_stream(file_manager->getShader(filename), std::ios::in);
|
|
||||||
if (!include_stream.is_open())
|
|
||||||
{
|
|
||||||
Log::error("shader", "Couldn't open included shader: '%s'.", filename.c_str());
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string include_line = "";
|
|
||||||
while (getline(include_stream, include_line))
|
|
||||||
{
|
|
||||||
code << "\n" << include_line;
|
|
||||||
}
|
|
||||||
|
|
||||||
include_stream.close();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
code << "\n" << Line;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stream.close();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log::error("shader", "Can not open '%s'.", file.c_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
Log::info("shader", "Compiling shader : %s", file.c_str());
|
|
||||||
const std::string &source = code.str();
|
|
||||||
char const *source_pointer = source.c_str();
|
|
||||||
int len = source.size();
|
|
||||||
glShaderSource(id, 1, &source_pointer, &len);
|
|
||||||
glCompileShader(id);
|
|
||||||
|
|
||||||
GLint result = GL_FALSE;
|
|
||||||
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
|
|
||||||
if (result == GL_FALSE)
|
|
||||||
{
|
|
||||||
int info_length;
|
|
||||||
Log::error("GLWrap", "Error in shader %s", file.c_str());
|
|
||||||
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &info_length);
|
|
||||||
if (info_length<0)
|
|
||||||
info_length = 1024;
|
|
||||||
char *error_message = new char[info_length];
|
|
||||||
error_message[0] = 0;
|
|
||||||
glGetShaderInfoLog(id, info_length, NULL, error_message);
|
|
||||||
Log::error("GLWrap", error_message);
|
|
||||||
delete[] error_message;
|
|
||||||
}
|
|
||||||
|
|
||||||
glGetError();
|
|
||||||
|
|
||||||
return id;
|
|
||||||
} // loadShader
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
/** Loads a transform feedback buffer shader with a given number of varying
|
/** Loads a transform feedback buffer shader with a given number of varying
|
||||||
* parameters.
|
* parameters.
|
||||||
@ -239,7 +57,7 @@ int ShaderBase::loadTFBProgram(const std::string &shader_name,
|
|||||||
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &info_log_length);
|
glGetProgramiv(m_program, GL_INFO_LOG_LENGTH, &info_log_length);
|
||||||
char *error_message = new char[info_log_length];
|
char *error_message = new char[info_log_length];
|
||||||
glGetProgramInfoLog(m_program, info_log_length, NULL, error_message);
|
glGetProgramInfoLog(m_program, info_log_length, NULL, error_message);
|
||||||
Log::error("GLWrap", error_message);
|
Log::error("ShaderBase", error_message);
|
||||||
delete[] error_message;
|
delete[] error_message;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "graphics/central_settings.hpp"
|
#include "graphics/central_settings.hpp"
|
||||||
#include "graphics/gl_headers.hpp"
|
#include "graphics/gl_headers.hpp"
|
||||||
|
#include "graphics/shader_files_manager.hpp"
|
||||||
#include "graphics/shared_gpu_objects.hpp"
|
#include "graphics/shared_gpu_objects.hpp"
|
||||||
#include "utils/singleton.hpp"
|
#include "utils/singleton.hpp"
|
||||||
|
|
||||||
@ -40,13 +41,6 @@
|
|||||||
*/
|
*/
|
||||||
class ShaderBase
|
class ShaderBase
|
||||||
{
|
{
|
||||||
private:
|
|
||||||
// Static members
|
|
||||||
/** Stores the context of header.txt, to avoid reading
|
|
||||||
* this file repeatedly. */
|
|
||||||
static std::string m_shader_header;
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
/** Maintains a list of all shaders. */
|
/** Maintains a list of all shaders. */
|
||||||
static std::vector<void (*)()> m_all_kill_functions;
|
static std::vector<void (*)()> m_all_kill_functions;
|
||||||
@ -75,8 +69,12 @@ protected:
|
|||||||
void loadAndAttachShader(GLint shader_type, const std::string &name,
|
void loadAndAttachShader(GLint shader_type, const std::string &name,
|
||||||
Types ... args)
|
Types ... args)
|
||||||
{
|
{
|
||||||
GLint shader_id = loadShader(name, shader_type);
|
GLint shader_id = ShaderFilesManager::getInstance()
|
||||||
|
->getShaderFile(name, shader_type);
|
||||||
glAttachShader(m_program, shader_id);
|
glAttachShader(m_program, shader_id);
|
||||||
|
GLint is_deleted = GL_TRUE;
|
||||||
|
glGetShaderiv(shader_id, GL_DELETE_STATUS, &is_deleted);
|
||||||
|
if (is_deleted == GL_FALSE)
|
||||||
glDeleteShader(shader_id);
|
glDeleteShader(shader_id);
|
||||||
loadAndAttachShader(args...);
|
loadAndAttachShader(args...);
|
||||||
} // loadAndAttachShader
|
} // loadAndAttachShader
|
||||||
@ -89,9 +87,6 @@ protected:
|
|||||||
loadAndAttachShader(shader_type, std::string(name), args...);
|
loadAndAttachShader(shader_type, std::string(name), args...);
|
||||||
} // loadAndAttachShader
|
} // loadAndAttachShader
|
||||||
// ------------------------------------------------------------------------
|
// ------------------------------------------------------------------------
|
||||||
|
|
||||||
const std::string& getHeader();
|
|
||||||
GLuint loadShader(const std::string &file, unsigned type);
|
|
||||||
void setAttribute(AttributeType type);
|
void setAttribute(AttributeType type);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -681,6 +681,7 @@ ShaderBasedRenderer::~ShaderBasedRenderer()
|
|||||||
delete m_spherical_harmonics;
|
delete m_spherical_harmonics;
|
||||||
delete m_skybox;
|
delete m_skybox;
|
||||||
delete m_rtts;
|
delete m_rtts;
|
||||||
|
ShaderFilesManager::kill();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
|
228
src/graphics/shader_files_manager.cpp
Normal file
228
src/graphics/shader_files_manager.cpp
Normal file
@ -0,0 +1,228 @@
|
|||||||
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
|
// Copyright (C) 2016 SuperTuxKart-Team
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 3
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#ifndef SERVER_ONLY
|
||||||
|
|
||||||
|
#include "graphics/shader_files_manager.hpp"
|
||||||
|
#include "graphics/central_settings.hpp"
|
||||||
|
#include "graphics/shared_gpu_objects.hpp"
|
||||||
|
#include "io/file_manager.hpp"
|
||||||
|
#include "utils/log.hpp"
|
||||||
|
|
||||||
|
#include <fstream>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
std::string ShaderFilesManager::m_shader_header = "";
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Returns a string with the content of header.txt (which contains basic
|
||||||
|
* shader defines).
|
||||||
|
*/
|
||||||
|
const std::string& ShaderFilesManager::getHeader()
|
||||||
|
{
|
||||||
|
// Only read file first time
|
||||||
|
if (m_shader_header.empty())
|
||||||
|
{
|
||||||
|
std::ifstream stream(file_manager->getShader("header.txt"),
|
||||||
|
std::ios::in);
|
||||||
|
if (stream.is_open())
|
||||||
|
{
|
||||||
|
std::string line = "";
|
||||||
|
while (getline(stream, line))
|
||||||
|
m_shader_header += "\n" + line;
|
||||||
|
stream.close();
|
||||||
|
}
|
||||||
|
} // if m_shader_header.empty()
|
||||||
|
|
||||||
|
return m_shader_header;
|
||||||
|
} // getHeader
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
/** Loads a single shader file, and add it to the loaded list
|
||||||
|
* \param file Filename of the shader to load.
|
||||||
|
* \param type Type of the shader.
|
||||||
|
*/
|
||||||
|
GLuint ShaderFilesManager::addShaderFile(const std::string &file,
|
||||||
|
unsigned type)
|
||||||
|
{
|
||||||
|
GLuint id = glCreateShader(type);
|
||||||
|
|
||||||
|
std::ostringstream code;
|
||||||
|
#if !defined(USE_GLES2)
|
||||||
|
code << "#version " << CVS->getGLSLVersion()<<"\n";
|
||||||
|
#else
|
||||||
|
if (CVS->isGLSL())
|
||||||
|
code << "#version 300 es\n";
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#if !defined(USE_GLES2)
|
||||||
|
// Some drivers report that the compute shaders extension is available,
|
||||||
|
// but they report only OpenGL 3.x version, and thus these extensions
|
||||||
|
// must be enabled manually. Otherwise the shaders compilation will fail
|
||||||
|
// because STK tries to use extensions which are available, but disabled
|
||||||
|
// by default.
|
||||||
|
if (type == GL_COMPUTE_SHADER)
|
||||||
|
{
|
||||||
|
if (CVS->isARBComputeShaderUsable())
|
||||||
|
code << "#extension GL_ARB_compute_shader : enable\n";
|
||||||
|
if (CVS->isARBImageLoadStoreUsable())
|
||||||
|
code << "#extension GL_ARB_shader_image_load_store : enable\n";
|
||||||
|
if (CVS->isARBArraysOfArraysUsable())
|
||||||
|
code << "#extension GL_ARB_arrays_of_arrays : enable\n";
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (CVS->isAMDVertexShaderLayerUsable())
|
||||||
|
code << "#extension GL_AMD_vertex_shader_layer : enable\n";
|
||||||
|
|
||||||
|
if (CVS->isARBExplicitAttribLocationUsable())
|
||||||
|
code << "#extension GL_ARB_explicit_attrib_location : enable\n";
|
||||||
|
|
||||||
|
if (CVS->isAZDOEnabled())
|
||||||
|
{
|
||||||
|
code << "#extension GL_ARB_bindless_texture : enable\n";
|
||||||
|
code << "#define Use_Bindless_Texture\n";
|
||||||
|
}
|
||||||
|
code << "//" << file << "\n";
|
||||||
|
if (!CVS->isARBUniformBufferObjectUsable())
|
||||||
|
code << "#define UBO_DISABLED\n";
|
||||||
|
if (CVS->isAMDVertexShaderLayerUsable())
|
||||||
|
code << "#define VSLayer\n";
|
||||||
|
if (CVS->needsRGBBindlessWorkaround())
|
||||||
|
code << "#define SRGBBindlessFix\n";
|
||||||
|
|
||||||
|
#if !defined(USE_GLES2)
|
||||||
|
// shader compilation fails with some drivers if there is no precision
|
||||||
|
// qualifier
|
||||||
|
if (type == GL_FRAGMENT_SHADER)
|
||||||
|
code << "precision mediump float;\n";
|
||||||
|
#else
|
||||||
|
int range[2], precision;
|
||||||
|
glGetShaderPrecisionFormat(GL_FRAGMENT_SHADER, GL_HIGH_FLOAT, range,
|
||||||
|
&precision);
|
||||||
|
|
||||||
|
if (precision > 0)
|
||||||
|
code << "precision highp float;\n";
|
||||||
|
else
|
||||||
|
code << "precision mediump float;\n";
|
||||||
|
#endif
|
||||||
|
code << "#define MAX_BONES " << SharedGPUObjects::getMaxMat4Size() << "\n";
|
||||||
|
|
||||||
|
code << getHeader();
|
||||||
|
|
||||||
|
std::ifstream stream(file_manager->getShader(file), std::ios::in);
|
||||||
|
if (stream.is_open())
|
||||||
|
{
|
||||||
|
std::string line = "";
|
||||||
|
while (getline(stream, line))
|
||||||
|
{
|
||||||
|
const std::string stk_include = "#stk_include";
|
||||||
|
std::size_t pos = line.find(stk_include);
|
||||||
|
if (pos != std::string::npos)
|
||||||
|
{
|
||||||
|
std::size_t pos = line.find("\"");
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
{
|
||||||
|
Log::error("ShaderFilesManager", "Invalid #stk_include"
|
||||||
|
" line: '%s'.", line.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string filename = line.substr(pos + 1);
|
||||||
|
|
||||||
|
pos = filename.find("\"");
|
||||||
|
if (pos == std::string::npos)
|
||||||
|
{
|
||||||
|
Log::error("ShaderFilesManager", "Invalid #stk_include"
|
||||||
|
" line: '%s'.", line.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
filename = filename.substr(0, pos);
|
||||||
|
|
||||||
|
std::ifstream include_stream(file_manager->getShader(filename),
|
||||||
|
std::ios::in);
|
||||||
|
if (!include_stream.is_open())
|
||||||
|
{
|
||||||
|
Log::error("ShaderFilesManager", "Couldn't open included"
|
||||||
|
" shader: '%s'.", filename.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string include_line = "";
|
||||||
|
while (getline(include_stream, include_line))
|
||||||
|
{
|
||||||
|
code << "\n" << include_line;
|
||||||
|
}
|
||||||
|
include_stream.close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
code << "\n" << line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.close();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log::error("ShaderFilesManager", "Can not open '%s'.", file.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
Log::info("ShaderFilesManager", "Compiling shader : %s", file.c_str());
|
||||||
|
const std::string &source = code.str();
|
||||||
|
char const *source_pointer = source.c_str();
|
||||||
|
int len = source.size();
|
||||||
|
glShaderSource(id, 1, &source_pointer, &len);
|
||||||
|
glCompileShader(id);
|
||||||
|
|
||||||
|
GLint result = GL_FALSE;
|
||||||
|
glGetShaderiv(id, GL_COMPILE_STATUS, &result);
|
||||||
|
if (result == GL_FALSE)
|
||||||
|
{
|
||||||
|
int info_length;
|
||||||
|
Log::error("ShaderFilesManager", "Error in shader %s", file.c_str());
|
||||||
|
glGetShaderiv(id, GL_INFO_LOG_LENGTH, &info_length);
|
||||||
|
if (info_length < 0)
|
||||||
|
info_length = 1024;
|
||||||
|
char *error_message = new char[info_length];
|
||||||
|
error_message[0] = 0;
|
||||||
|
glGetShaderInfoLog(id, info_length, NULL, error_message);
|
||||||
|
Log::error("ShaderFilesManager", error_message);
|
||||||
|
delete[] error_message;
|
||||||
|
}
|
||||||
|
|
||||||
|
glGetError();
|
||||||
|
m_shader_files_loaded[file] = id;
|
||||||
|
return id;
|
||||||
|
|
||||||
|
} // addShaderFile
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------------
|
||||||
|
GLuint ShaderFilesManager::getShaderFile(const std::string &file,
|
||||||
|
unsigned type)
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, GLuint>::const_iterator i =
|
||||||
|
m_shader_files_loaded.find(file);
|
||||||
|
if (i != m_shader_files_loaded.end())
|
||||||
|
return i->second;
|
||||||
|
else
|
||||||
|
return addShaderFile(file, type);
|
||||||
|
|
||||||
|
} // getShaderFile
|
||||||
|
|
||||||
|
#endif // !SERVER_ONLY
|
59
src/graphics/shader_files_manager.hpp
Normal file
59
src/graphics/shader_files_manager.hpp
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
// SuperTuxKart - a fun racing game with go-kart
|
||||||
|
// Copyright (C) 2016 SuperTuxKart-Team
|
||||||
|
//
|
||||||
|
// This program is free software; you can redistribute it and/or
|
||||||
|
// modify it under the terms of the GNU General Public License
|
||||||
|
// as published by the Free Software Foundation; either version 3
|
||||||
|
// of the License, or (at your option) any later version.
|
||||||
|
//
|
||||||
|
// This program is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with this program; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||||
|
|
||||||
|
#ifndef SERVER_ONLY
|
||||||
|
|
||||||
|
#ifndef HEADER_SHADER_FILES_MANAGER_HPP
|
||||||
|
#define HEADER_SHADER_FILES_MANAGER_HPP
|
||||||
|
|
||||||
|
#include "graphics/gl_headers.hpp"
|
||||||
|
#include "utils/no_copy.hpp"
|
||||||
|
#include "utils/singleton.hpp"
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
|
#include <string>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class ShaderFilesManager : public Singleton<ShaderFilesManager>, NoCopy
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
/** Stores the context of header.txt, to avoid reading
|
||||||
|
* this file repeatedly. */
|
||||||
|
static std::string m_shader_header;
|
||||||
|
|
||||||
|
std::unordered_map<std::string, GLuint> m_shader_files_loaded;
|
||||||
|
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
const std::string& getHeader();
|
||||||
|
|
||||||
|
public:
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
ShaderFilesManager() {}
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
~ShaderFilesManager() { clean(); }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
void clean() { m_shader_files_loaded.clear(); }
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
GLuint addShaderFile(const std::string &file, unsigned type);
|
||||||
|
// ------------------------------------------------------------------------
|
||||||
|
GLuint getShaderFile(const std::string &file, unsigned type);
|
||||||
|
|
||||||
|
}; // ShaderFilesManager
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif // !SERVER_ONLY
|
@ -174,69 +174,6 @@ static std::string loadHeader()
|
|||||||
return result;
|
return result;
|
||||||
} // loadHeader
|
} // loadHeader
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
|
||||||
// Mostly from shader tutorial
|
|
||||||
GLuint loadShader(const char * file, unsigned type)
|
|
||||||
{
|
|
||||||
GLuint Id = glCreateShader(type);
|
|
||||||
char versionString[20];
|
|
||||||
#if !defined(USE_GLES2)
|
|
||||||
sprintf(versionString, "#version %d\n", CVS->getGLSLVersion());
|
|
||||||
#else
|
|
||||||
if (CVS->isGLSL())
|
|
||||||
sprintf(versionString, "#version 300 es\n");
|
|
||||||
#endif
|
|
||||||
std::string Code = versionString;
|
|
||||||
if (CVS->isAMDVertexShaderLayerUsable())
|
|
||||||
Code += "#extension GL_AMD_vertex_shader_layer : enable\n";
|
|
||||||
if (CVS->isAZDOEnabled())
|
|
||||||
{
|
|
||||||
Code += "#extension GL_ARB_bindless_texture : enable\n";
|
|
||||||
Code += "#define Use_Bindless_Texture\n";
|
|
||||||
}
|
|
||||||
std::ifstream Stream(file, std::ios::in);
|
|
||||||
Code += "//" + std::string(file) + "\n";
|
|
||||||
if (!CVS->isARBUniformBufferObjectUsable())
|
|
||||||
Code += "#define UBO_DISABLED\n";
|
|
||||||
if (CVS->isAMDVertexShaderLayerUsable())
|
|
||||||
Code += "#define VSLayer\n";
|
|
||||||
if (CVS->needsRGBBindlessWorkaround())
|
|
||||||
Code += "#define SRGBBindlessFix\n";
|
|
||||||
Code += loadHeader();
|
|
||||||
if (Stream.is_open())
|
|
||||||
{
|
|
||||||
std::string Line = "";
|
|
||||||
while (getline(Stream, Line))
|
|
||||||
Code += "\n" + Line;
|
|
||||||
Stream.close();
|
|
||||||
}
|
|
||||||
GLint Result = GL_FALSE;
|
|
||||||
int InfoLogLength;
|
|
||||||
Log::info("GLWrap", "Compiling shader : %s", file);
|
|
||||||
char const * SourcePointer = Code.c_str();
|
|
||||||
int length = (int)strlen(SourcePointer);
|
|
||||||
glShaderSource(Id, 1, &SourcePointer, &length);
|
|
||||||
glCompileShader(Id);
|
|
||||||
|
|
||||||
glGetShaderiv(Id, GL_COMPILE_STATUS, &Result);
|
|
||||||
if (Result == GL_FALSE)
|
|
||||||
{
|
|
||||||
Log::error("GLWrap", "Error in shader %s", file);
|
|
||||||
glGetShaderiv(Id, GL_INFO_LOG_LENGTH, &InfoLogLength);
|
|
||||||
if (InfoLogLength<0)
|
|
||||||
InfoLogLength = 1024;
|
|
||||||
char *ErrorMessage = new char[InfoLogLength];
|
|
||||||
ErrorMessage[0] = 0;
|
|
||||||
glGetShaderInfoLog(Id, InfoLogLength, NULL, ErrorMessage);
|
|
||||||
Log::error("GLWrap", ErrorMessage);
|
|
||||||
delete[] ErrorMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
glGetError();
|
|
||||||
|
|
||||||
return Id;
|
|
||||||
} // loadShader
|
|
||||||
|
|
||||||
// ----------------------------------------------------------------------------
|
// ----------------------------------------------------------------------------
|
||||||
void Shaders::loadShaders()
|
void Shaders::loadShaders()
|
||||||
{
|
{
|
||||||
|
@ -236,6 +236,7 @@ bool handleContextMenuAction(s32 cmd_id)
|
|||||||
case DEBUG_GRAPHICS_RELOAD_SHADERS:
|
case DEBUG_GRAPHICS_RELOAD_SHADERS:
|
||||||
#ifndef SERVER_ONLY
|
#ifndef SERVER_ONLY
|
||||||
Log::info("Debug", "Reloading shaders...");
|
Log::info("Debug", "Reloading shaders...");
|
||||||
|
ShaderFilesManager::getInstance()->clean();
|
||||||
ShaderBase::updateShaders();
|
ShaderBase::updateShaders();
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
|
Loading…
Reference in New Issue
Block a user