mirror of https://github.com/snes9xgit/snes9x.git
Shaders: Scan source code in as few passes as possible.
Improves loading time of crt-royale significantly.
This commit is contained in:
parent
f825f14a06
commit
fc31f47fc2
138
shaders/glsl.cpp
138
shaders/glsl.cpp
|
@ -7,6 +7,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
#include "glsl.h"
|
#include "glsl.h"
|
||||||
#include "../../conffile.h"
|
#include "../../conffile.h"
|
||||||
#include "shader_helpers.h"
|
#include "shader_helpers.h"
|
||||||
|
@ -250,18 +251,99 @@ bool GLSLShader::load_shader_preset_file(char *filename)
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLSLShader::strip_parameter_pragmas(std::vector<std::string> &lines)
|
static std::string folder_from_path(std::string filename)
|
||||||
{
|
{
|
||||||
// #pragma parameter lines tend to have " characters in them,
|
for (int i = filename.length() - 1; i >= 0; i--)
|
||||||
// which is not legal GLSL.
|
if (filename[i] == '\\' || filename[i] == '/')
|
||||||
auto it = lines.begin();
|
return filename.substr(0, i);
|
||||||
while (it != lines.end())
|
|
||||||
{
|
return std::string(".");
|
||||||
if (it->find("#pragma parameter") != std::string::npos)
|
}
|
||||||
|
|
||||||
|
static std::string canonicalize(const std::string &noncanonical)
|
||||||
|
{
|
||||||
|
char *temp = realpath(noncanonical.c_str(), NULL);
|
||||||
|
std::string filename_string(temp);
|
||||||
|
free(temp);
|
||||||
|
return filename_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
static GLuint string_to_format(char *format)
|
||||||
|
{
|
||||||
|
#define MATCH(s, f) \
|
||||||
|
if (!strcmp(format, s)) \
|
||||||
|
return f;
|
||||||
|
MATCH("R8_UNORM", GL_R8);
|
||||||
|
MATCH("R8_UINT", GL_R8UI);
|
||||||
|
MATCH("R8_SINT", GL_R8I);
|
||||||
|
MATCH("R8G8_UNORM", GL_RG8);
|
||||||
|
MATCH("R8G8_UINT", GL_RG8UI);
|
||||||
|
MATCH("R8G8_SINT", GL_RG8I);
|
||||||
|
MATCH("R8G8B8A8_UNORM", GL_RGBA8);
|
||||||
|
MATCH("R8G8B8A8_UINT", GL_RGBA8UI);
|
||||||
|
MATCH("R8G8B8A8_SINT", GL_RGBA8I);
|
||||||
|
MATCH("R8G8B8A8_SRGB", GL_SRGB8_ALPHA8);
|
||||||
|
|
||||||
|
MATCH("A2B10G10R10_UNORM_PACK32", GL_RGB10_A2);
|
||||||
|
MATCH("A2B10G10R10_UINT_PACK32", GL_RGB10_A2UI);
|
||||||
|
|
||||||
|
MATCH("R16_UINT", GL_R16UI);
|
||||||
|
MATCH("R16_SINT", GL_R16I);
|
||||||
|
MATCH("R16_SFLOAT", GL_R16F);
|
||||||
|
MATCH("R16G16_UINT", GL_RG16UI);
|
||||||
|
MATCH("R16G16_SINT", GL_RG16I);
|
||||||
|
MATCH("R16G16_SFLOAT", GL_RG16F);
|
||||||
|
MATCH("R16G16B16A16_UINT", GL_RGBA16UI);
|
||||||
|
MATCH("R16G16B16A16_SINT", GL_RGBA16I);
|
||||||
|
MATCH("R16G16B16A16_SFLOAT", GL_RGBA16F);
|
||||||
|
|
||||||
|
MATCH("R32_UINT", GL_R32UI);
|
||||||
|
MATCH("R32_SINT", GL_R32I);
|
||||||
|
MATCH("R32_SFLOAT", GL_R32F);
|
||||||
|
MATCH("R32G32_UINT", GL_RG32UI);
|
||||||
|
MATCH("R32G32_SINT", GL_RG32I);
|
||||||
|
MATCH("R32G32_SFLOAT", GL_RG32F);
|
||||||
|
MATCH("R32G32B32A32_UINT", GL_RGBA32UI);
|
||||||
|
MATCH("R32G32B32A32_SINT", GL_RGBA32I);
|
||||||
|
MATCH("R32G32B32A32_SFLOAT", GL_RGBA32F);
|
||||||
|
|
||||||
|
return GL_RGBA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// filename must be canonical
|
||||||
|
void GLSLShader::read_shader_file_with_includes(std::string filename,
|
||||||
|
std::vector<std::string> &lines,
|
||||||
|
int p)
|
||||||
|
{
|
||||||
|
std::ifstream ss(filename);
|
||||||
|
|
||||||
|
if (ss.fail())
|
||||||
|
{
|
||||||
|
printf ("Couldn't open file \"%s\"\n", filename.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string line;
|
||||||
|
|
||||||
|
while (std::getline(ss, line, '\n'))
|
||||||
|
{
|
||||||
|
if (line.empty())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (line.compare(0, 8, "#include") == 0)
|
||||||
|
{
|
||||||
|
char tmp[PATH_MAX];
|
||||||
|
sscanf(line.c_str(), "#include \"%[^\"]\"", tmp);
|
||||||
|
|
||||||
|
std::string fullpath = canonicalize(folder_from_path(filename) + "/" + tmp);
|
||||||
|
read_shader_file_with_includes(fullpath.c_str(), lines, p);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (line.compare(0, 17, "#pragma parameter") == 0)
|
||||||
{
|
{
|
||||||
GLSLParam par;
|
GLSLParam par;
|
||||||
|
|
||||||
sscanf(it->c_str(), "#pragma parameter %s \"%[^\"]\" %f %f %f %f",
|
sscanf(line.c_str(), "#pragma parameter %s \"%[^\"]\" %f %f %f %f",
|
||||||
par.id, par.name, &par.val, &par.min, &par.max, &par.step);
|
par.id, par.name, &par.val, &par.min, &par.max, &par.step);
|
||||||
|
|
||||||
if (par.step == 0.0f)
|
if (par.step == 0.0f)
|
||||||
|
@ -275,12 +357,30 @@ void GLSLShader::strip_parameter_pragmas(std::vector<std::string> &lines)
|
||||||
}
|
}
|
||||||
if (i >= param.size())
|
if (i >= param.size())
|
||||||
param.push_back(par);
|
param.push_back(par);
|
||||||
|
continue;
|
||||||
it = lines.erase(it);
|
|
||||||
}
|
}
|
||||||
else
|
#ifdef USE_SLANG
|
||||||
++it;
|
else if (line.compare(0, 12, "#pragma name") == 0)
|
||||||
}
|
{
|
||||||
|
sscanf(line.c_str(), "#pragma name %255s", pass[p].alias);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else if (line.compare(0, 14, "#pragma format") == 0)
|
||||||
|
{
|
||||||
|
char format[256];
|
||||||
|
sscanf(line.c_str(), "#pragma format %255s", format);
|
||||||
|
pass[p].format = string_to_format(format);
|
||||||
|
if (pass[p].format == GL_RGBA16F || pass[p].format == GL_RGBA32F)
|
||||||
|
pass[p].fp = TRUE;
|
||||||
|
else if (pass[p].format == GL_SRGB8_ALPHA8)
|
||||||
|
pass[p].srgb = TRUE;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
lines.push_back(line);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
GLuint GLSLShader::compile_shader(std::vector<std::string> &lines,
|
GLuint GLSLShader::compile_shader(std::vector<std::string> &lines,
|
||||||
|
@ -364,7 +464,7 @@ bool GLSLShader::load_shader(char *filename)
|
||||||
strcpy(p->filename, temp);
|
strcpy(p->filename, temp);
|
||||||
|
|
||||||
std::vector<std::string> lines;
|
std::vector<std::string> lines;
|
||||||
read_shader_file_with_includes(p->filename, lines);
|
read_shader_file_with_includes(p->filename, lines, i);
|
||||||
|
|
||||||
if (lines.empty())
|
if (lines.empty())
|
||||||
{
|
{
|
||||||
|
@ -372,13 +472,9 @@ bool GLSLShader::load_shader(char *filename)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
strip_parameter_pragmas(lines);
|
|
||||||
|
|
||||||
#ifdef USE_SLANG
|
#ifdef USE_SLANG
|
||||||
if (using_slang)
|
if (using_slang)
|
||||||
{
|
{
|
||||||
slang_parse_pragmas(lines, i);
|
|
||||||
|
|
||||||
GLint retval;
|
GLint retval;
|
||||||
retval = slang_compile(lines, "vertex");
|
retval = slang_compile(lines, "vertex");
|
||||||
if (retval < 0)
|
if (retval < 0)
|
||||||
|
@ -1064,9 +1160,9 @@ void GLSLShader::clear_shader_vars()
|
||||||
vaos.clear();
|
vaos.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
#define outs(s, v) fprintf (file, "%s%d = \"%s\"\n", s, i, v)
|
#define outs(s, v) fprintf(file, "%s%d = \"%s\"\n", s, i, v)
|
||||||
#define outf(s, v) fprintf (file, "%s%d = \"%f\"\n", s, i, v)
|
#define outf(s, v) fprintf(file, "%s%d = \"%f\"\n", s, i, v)
|
||||||
#define outd(s, v) fprintf (file, "%s%d = \"%d\"\n", s, i, v)
|
#define outd(s, v) fprintf(file, "%s%d = \"%d\"\n", s, i, v)
|
||||||
void GLSLShader::save(const char *filename)
|
void GLSLShader::save(const char *filename)
|
||||||
{
|
{
|
||||||
FILE *file = fopen(filename, "wb");
|
FILE *file = fopen(filename, "wb");
|
||||||
|
|
|
@ -163,7 +163,9 @@ typedef struct
|
||||||
GLSLViewportCallback vpcallback);
|
GLSLViewportCallback vpcallback);
|
||||||
void set_shader_vars(unsigned int pass, bool inverted);
|
void set_shader_vars(unsigned int pass, bool inverted);
|
||||||
void clear_shader_vars();
|
void clear_shader_vars();
|
||||||
void strip_parameter_pragmas(std::vector<std::string> &lines);
|
void read_shader_file_with_includes(std::string filename,
|
||||||
|
std::vector<std::string> &lines,
|
||||||
|
int p);
|
||||||
GLuint compile_shader(std::vector<std::string> &lines, const char *aliases,
|
GLuint compile_shader(std::vector<std::string> &lines, const char *aliases,
|
||||||
const char *defines, GLuint type, GLuint *out);
|
const char *defines, GLuint type, GLuint *out);
|
||||||
void save(const char *filename);
|
void save(const char *filename);
|
||||||
|
@ -186,7 +188,6 @@ typedef struct
|
||||||
#ifdef USE_SLANG
|
#ifdef USE_SLANG
|
||||||
std::string slang_get_stage(std::vector<std::string> &lines,
|
std::string slang_get_stage(std::vector<std::string> &lines,
|
||||||
std::string name);
|
std::string name);
|
||||||
void slang_parse_pragmas(std::vector<std::string> &lines, int p);
|
|
||||||
GLint slang_compile(std::vector<std::string> &lines, std::string stage);
|
GLint slang_compile(std::vector<std::string> &lines, std::string stage);
|
||||||
void slang_introspect();
|
void slang_introspect();
|
||||||
void slang_set_shader_vars(int p, bool inverted);
|
void slang_set_shader_vars(int p, bool inverted);
|
||||||
|
|
|
@ -242,85 +242,4 @@ void reduce_to_path(char *filename)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::string folder_from_path(std::string filename)
|
|
||||||
{
|
|
||||||
for (int i = filename.length() - 1; i >= 0; i--)
|
|
||||||
if (filename[i] == '\\' || filename[i] == '/')
|
|
||||||
return filename.substr(0, i);
|
|
||||||
|
|
||||||
return std::string(".");
|
|
||||||
}
|
|
||||||
|
|
||||||
static char *read_file(const char *filename)
|
|
||||||
{
|
|
||||||
FILE *file = NULL;
|
|
||||||
int size;
|
|
||||||
char *contents;
|
|
||||||
|
|
||||||
file = fopen(filename, "rb");
|
|
||||||
if (!file)
|
|
||||||
{
|
|
||||||
printf ("File not found: \"%s\"\n", filename);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
fseek(file, 0, SEEK_END);
|
|
||||||
size = ftell(file);
|
|
||||||
fseek(file, 0, SEEK_SET);
|
|
||||||
|
|
||||||
contents = new char[size + 1];
|
|
||||||
fread(contents, size, 1, file);
|
|
||||||
contents[size] = '\0';
|
|
||||||
fclose(file);
|
|
||||||
|
|
||||||
return contents;
|
|
||||||
}
|
|
||||||
|
|
||||||
static std::string canonicalize(const std::string &noncanonical)
|
|
||||||
{
|
|
||||||
char *temp = realpath(noncanonical.c_str(), NULL);
|
|
||||||
std::string filename_string(temp);
|
|
||||||
free(temp);
|
|
||||||
return filename_string;
|
|
||||||
}
|
|
||||||
|
|
||||||
// filename must be canonical
|
|
||||||
void read_shader_file_with_includes(std::string filename,
|
|
||||||
std::vector<std::string> &lines)
|
|
||||||
{
|
|
||||||
char *file_contents = read_file(filename.c_str());
|
|
||||||
if (!file_contents)
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::string string_contents(file_contents);
|
|
||||||
delete[] file_contents;
|
|
||||||
|
|
||||||
for (char &c : string_contents)
|
|
||||||
{
|
|
||||||
if (c == '\r')
|
|
||||||
c = '\n';
|
|
||||||
}
|
|
||||||
|
|
||||||
std::istringstream ss(string_contents);
|
|
||||||
std::string line;
|
|
||||||
|
|
||||||
while (std::getline(ss, line, '\n'))
|
|
||||||
{
|
|
||||||
if (line.empty())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (line.find("#include") == 0)
|
|
||||||
{
|
|
||||||
char tmp[PATH_MAX];
|
|
||||||
sscanf(line.c_str(), "#include \"%[^\"]\"", tmp);
|
|
||||||
|
|
||||||
std::string fullpath = canonicalize(folder_from_path(filename) + "/" + tmp);
|
|
||||||
read_shader_file_with_includes(fullpath.c_str(), lines);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
lines.push_back(line);
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
|
@ -48,6 +48,5 @@ bool gl_srgb_available();
|
||||||
int gl_version();
|
int gl_version();
|
||||||
bool gl_float_texture_available();
|
bool gl_float_texture_available();
|
||||||
void reduce_to_path(char* filename);
|
void reduce_to_path(char* filename);
|
||||||
void read_shader_file_with_includes(std::string filename, std::vector<std::string> &lines);
|
|
||||||
|
|
||||||
#endif // __SHADER_HELPERS_H
|
#endif // __SHADER_HELPERS_H
|
||||||
|
|
|
@ -25,7 +25,7 @@ std::string GLSLShader::slang_get_stage(std::vector<std::string> &lines,
|
||||||
|
|
||||||
for (auto &line : lines)
|
for (auto &line : lines)
|
||||||
{
|
{
|
||||||
if (line.find("#pragma stage") != std::string::npos)
|
if (line.compare(0, 13, "#pragma stage") == 0)
|
||||||
{
|
{
|
||||||
if (line.find(std::string("#pragma stage ") + name) !=
|
if (line.find(std::string("#pragma stage ") + name) !=
|
||||||
std::string::npos)
|
std::string::npos)
|
||||||
|
@ -33,10 +33,6 @@ std::string GLSLShader::slang_get_stage(std::vector<std::string> &lines,
|
||||||
else
|
else
|
||||||
in_stage = false;
|
in_stage = false;
|
||||||
}
|
}
|
||||||
else if (line.find("#pragma name") != std::string::npos ||
|
|
||||||
line.find("#pragma format") != std::string::npos)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if (in_stage)
|
else if (in_stage)
|
||||||
{
|
{
|
||||||
output << line << '\n';
|
output << line << '\n';
|
||||||
|
@ -85,71 +81,6 @@ static void printuniforms(std::vector<SlangUniform> &unif)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static GLuint string_to_format(char *format)
|
|
||||||
{
|
|
||||||
#define MATCH(s, f) \
|
|
||||||
if (!strcmp(format, s)) \
|
|
||||||
return f;
|
|
||||||
MATCH("R8_UNORM", GL_R8);
|
|
||||||
MATCH("R8_UINT", GL_R8UI);
|
|
||||||
MATCH("R8_SINT", GL_R8I);
|
|
||||||
MATCH("R8G8_UNORM", GL_RG8);
|
|
||||||
MATCH("R8G8_UINT", GL_RG8UI);
|
|
||||||
MATCH("R8G8_SINT", GL_RG8I);
|
|
||||||
MATCH("R8G8B8A8_UNORM", GL_RGBA8);
|
|
||||||
MATCH("R8G8B8A8_UINT", GL_RGBA8UI);
|
|
||||||
MATCH("R8G8B8A8_SINT", GL_RGBA8I);
|
|
||||||
MATCH("R8G8B8A8_SRGB", GL_SRGB8_ALPHA8);
|
|
||||||
|
|
||||||
MATCH("A2B10G10R10_UNORM_PACK32", GL_RGB10_A2);
|
|
||||||
MATCH("A2B10G10R10_UINT_PACK32", GL_RGB10_A2UI);
|
|
||||||
|
|
||||||
MATCH("R16_UINT", GL_R16UI);
|
|
||||||
MATCH("R16_SINT", GL_R16I);
|
|
||||||
MATCH("R16_SFLOAT", GL_R16F);
|
|
||||||
MATCH("R16G16_UINT", GL_RG16UI);
|
|
||||||
MATCH("R16G16_SINT", GL_RG16I);
|
|
||||||
MATCH("R16G16_SFLOAT", GL_RG16F);
|
|
||||||
MATCH("R16G16B16A16_UINT", GL_RGBA16UI);
|
|
||||||
MATCH("R16G16B16A16_SINT", GL_RGBA16I);
|
|
||||||
MATCH("R16G16B16A16_SFLOAT", GL_RGBA16F);
|
|
||||||
|
|
||||||
MATCH("R32_UINT", GL_R32UI);
|
|
||||||
MATCH("R32_SINT", GL_R32I);
|
|
||||||
MATCH("R32_SFLOAT", GL_R32F);
|
|
||||||
MATCH("R32G32_UINT", GL_RG32UI);
|
|
||||||
MATCH("R32G32_SINT", GL_RG32I);
|
|
||||||
MATCH("R32G32_SFLOAT", GL_RG32F);
|
|
||||||
MATCH("R32G32B32A32_UINT", GL_RGBA32UI);
|
|
||||||
MATCH("R32G32B32A32_SINT", GL_RGBA32I);
|
|
||||||
MATCH("R32G32B32A32_SFLOAT", GL_RGBA32F);
|
|
||||||
|
|
||||||
return GL_RGBA;
|
|
||||||
}
|
|
||||||
|
|
||||||
void GLSLShader::slang_parse_pragmas(std::vector<std::string> &lines, int p)
|
|
||||||
{
|
|
||||||
pass[p].format = GL_RGBA;
|
|
||||||
|
|
||||||
for (auto &line : lines)
|
|
||||||
{
|
|
||||||
if (line.find("#pragma name") != std::string::npos)
|
|
||||||
{
|
|
||||||
sscanf(line.c_str(), "#pragma name %255s", pass[p].alias);
|
|
||||||
}
|
|
||||||
else if (line.find("#pragma format") != std::string::npos)
|
|
||||||
{
|
|
||||||
char format[256];
|
|
||||||
sscanf(line.c_str(), "#pragma format %255s", format);
|
|
||||||
pass[p].format = string_to_format(format);
|
|
||||||
if (pass[p].format == GL_RGBA16F || pass[p].format == GL_RGBA32F)
|
|
||||||
pass[p].fp = TRUE;
|
|
||||||
else if (pass[p].format == GL_SRGB8_ALPHA8)
|
|
||||||
pass[p].srgb = TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static const TBuiltInResource DefaultTBuiltInResource = {
|
static const TBuiltInResource DefaultTBuiltInResource = {
|
||||||
/* .MaxLights = */ 32,
|
/* .MaxLights = */ 32,
|
||||||
/* .MaxClipPlanes = */ 6,
|
/* .MaxClipPlanes = */ 6,
|
||||||
|
|
Loading…
Reference in New Issue