2018-09-14 09:37:20 +02:00
|
|
|
/*
|
2019-08-03 19:43:48 +02:00
|
|
|
* This software is licensed under the terms of the MIT License.
|
2018-09-14 09:37:20 +02:00
|
|
|
* See COPYING for further information.
|
|
|
|
* ---
|
2019-01-23 21:10:43 +01:00
|
|
|
* Copyright (c) 2011-2019, Lukas Weber <laochailan@web.de>.
|
2019-07-03 20:00:56 +02:00
|
|
|
* Copyright (c) 2012-2019, Andrei Alexeyev <akari@taisei-project.org>.
|
2018-09-14 09:37:20 +02:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include "taisei.h"
|
|
|
|
|
|
|
|
#include "shaders.h"
|
|
|
|
#include "util.h"
|
|
|
|
#include "opengl.h"
|
|
|
|
#include "rwops/rwops_autobuf.h"
|
|
|
|
|
2020-04-05 04:51:00 +02:00
|
|
|
ShaderLangInfoArray glcommon_shader_lang_table = { 0 };
|
2018-09-14 09:37:20 +02:00
|
|
|
|
|
|
|
static void add_glsl_version_parsed(GLSLVersion v) {
|
2020-04-05 04:51:00 +02:00
|
|
|
dynarray_foreach_elem(&glcommon_shader_lang_table, ShaderLangInfo *lang, {
|
2018-09-14 09:37:20 +02:00
|
|
|
if(!memcmp(&lang->glsl.version, &v, sizeof(v))) {
|
|
|
|
return;
|
|
|
|
}
|
2020-04-05 04:51:00 +02:00
|
|
|
});
|
2018-09-14 09:37:20 +02:00
|
|
|
|
2020-04-05 04:51:00 +02:00
|
|
|
ShaderLangInfo *lang = dynarray_append(&glcommon_shader_lang_table);
|
2018-09-14 09:37:20 +02:00
|
|
|
lang->lang = SHLANG_GLSL;
|
|
|
|
lang->glsl.version = v;
|
|
|
|
|
2019-09-16 21:53:43 +02:00
|
|
|
if(v.profile == GLSL_PROFILE_NONE && v.version >= 330) {
|
2018-09-14 09:37:20 +02:00
|
|
|
v.profile = GLSL_PROFILE_CORE;
|
2020-04-05 04:51:00 +02:00
|
|
|
lang = dynarray_append(&glcommon_shader_lang_table);
|
2018-09-14 09:37:20 +02:00
|
|
|
lang->lang = SHLANG_GLSL;
|
|
|
|
lang->glsl.version = v;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-10 17:53:46 +02:00
|
|
|
static void add_glsl_version_nonstandard(const char *vstr) {
|
|
|
|
// because intel wants to be fucking special again
|
|
|
|
|
|
|
|
char a, b, c;
|
|
|
|
|
|
|
|
if(sscanf(vstr, "%c.%c%c - ", &a, &b, &c) == 3) {
|
|
|
|
if(isdigit(a) && isdigit(b) && isdigit(c)) {
|
|
|
|
GLSLVersion v = { 0 };
|
|
|
|
v.version = (a - '0') * 100 + (b - '0') * 10 + (c - '0');
|
|
|
|
v.profile = GLSL_PROFILE_NONE;
|
|
|
|
add_glsl_version_parsed(v);
|
|
|
|
v.profile = GLSL_PROFILE_CORE;
|
|
|
|
add_glsl_version_parsed(v);
|
|
|
|
v.profile = GLSL_PROFILE_COMPATIBILITY;
|
|
|
|
add_glsl_version_parsed(v);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-09-14 09:37:20 +02:00
|
|
|
static void add_glsl_version(const char *vstr) {
|
|
|
|
if(!*vstr) {
|
|
|
|
// Special case: the very first GLSL version doesn't have a version string.
|
|
|
|
// We'll just ignore it, it's way too old to be useful anyway.
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
GLSLVersion v;
|
|
|
|
|
|
|
|
if(glsl_parse_version(vstr, &v) == vstr) {
|
2019-09-10 17:53:46 +02:00
|
|
|
add_glsl_version_nonstandard(vstr);
|
2018-09-14 09:37:20 +02:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
add_glsl_version_parsed(v);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void glcommon_build_shader_lang_table_fallback(void);
|
|
|
|
static void glcommon_build_shader_lang_table_finish(void);
|
|
|
|
|
|
|
|
void glcommon_build_shader_lang_table(void) {
|
2020-04-05 04:51:00 +02:00
|
|
|
dynarray_ensure_capacity(&glcommon_shader_lang_table, 8);
|
2018-09-14 09:37:20 +02:00
|
|
|
|
|
|
|
// NOTE: The ability to query supported GLSL versions was added in GL 4.3,
|
|
|
|
// but it's not exposed by any extension. This is pretty silly.
|
|
|
|
|
|
|
|
GLint num_versions = 0;
|
2019-09-09 03:32:22 +02:00
|
|
|
|
|
|
|
if(!glext.version.is_webgl) {
|
|
|
|
glGetIntegerv(GL_NUM_SHADING_LANGUAGE_VERSIONS, &num_versions);
|
|
|
|
}
|
2018-09-14 09:37:20 +02:00
|
|
|
|
|
|
|
for(int i = 0; i < num_versions; ++i) {
|
|
|
|
add_glsl_version((char*)glGetStringi(GL_SHADING_LANGUAGE_VERSION, i));
|
|
|
|
}
|
|
|
|
|
2020-04-05 04:51:00 +02:00
|
|
|
if(glcommon_shader_lang_table.num_elements < 1) {
|
2019-09-10 17:53:46 +02:00
|
|
|
glcommon_build_shader_lang_table_fallback();
|
|
|
|
}
|
|
|
|
|
2018-09-14 09:37:20 +02:00
|
|
|
// TODO: Maybe also detect compatibility profile somehow.
|
|
|
|
|
|
|
|
glcommon_build_shader_lang_table_finish();
|
|
|
|
}
|
|
|
|
|
|
|
|
static void glcommon_build_shader_lang_table_fallback(void) {
|
|
|
|
log_warn("Can not reliably determine all supported GLSL versions, resorting to guesswork.");
|
|
|
|
|
|
|
|
struct vtable {
|
|
|
|
uint gl;
|
|
|
|
GLSLVersion glsl;
|
|
|
|
};
|
|
|
|
|
|
|
|
static struct vtable version_map[] = {
|
|
|
|
// OpenGL Core
|
|
|
|
{ 45, { 450, GLSL_PROFILE_NONE } },
|
|
|
|
{ 46, { 460, GLSL_PROFILE_NONE } },
|
|
|
|
{ 44, { 440, GLSL_PROFILE_NONE } },
|
|
|
|
{ 43, { 430, GLSL_PROFILE_NONE } },
|
|
|
|
{ 42, { 420, GLSL_PROFILE_NONE } },
|
|
|
|
{ 41, { 410, GLSL_PROFILE_NONE } },
|
|
|
|
{ 40, { 400, GLSL_PROFILE_NONE } },
|
|
|
|
{ 33, { 330, GLSL_PROFILE_NONE } },
|
2019-09-16 21:53:43 +02:00
|
|
|
{ 32, { 150, GLSL_PROFILE_NONE } },
|
|
|
|
{ 31, { 140, GLSL_PROFILE_NONE } },
|
|
|
|
{ 30, { 130, GLSL_PROFILE_NONE } },
|
|
|
|
{ 21, { 120, GLSL_PROFILE_NONE } },
|
|
|
|
{ 20, { 110, GLSL_PROFILE_NONE } },
|
2018-09-14 09:37:20 +02:00
|
|
|
|
|
|
|
// OpenGL ES
|
|
|
|
{ 32, { 320, GLSL_PROFILE_ES } },
|
|
|
|
{ 31, { 310, GLSL_PROFILE_ES } },
|
|
|
|
{ 30, { 300, GLSL_PROFILE_ES } },
|
|
|
|
// { 20, { 100, GLSL_PROFILE_ES } },
|
|
|
|
};
|
|
|
|
|
|
|
|
const char *glslvstr = (char*)glGetString(GL_SHADING_LANGUAGE_VERSION);
|
|
|
|
const char *glslvstr_orig = glslvstr;
|
|
|
|
static const char gles_prefix[] = "OpenGL ES GLSL ES";
|
|
|
|
GLSLProfile profile = GLSL_PROFILE_NONE;
|
|
|
|
uint major, minor;
|
|
|
|
|
OpenGL ES 3.0 rendering backend (#148)
* First steps towards shader transpilation
Needs to be manually enabled via -Dshader_transpiler=true.
Requires shaderc. https://github.com/google/shaderc
Not yet functional due to missing SPIRV-Cross integration. SPIRV-Cross
currently does not have an official C API, and crossc is too minimal to
be useful. The current plan is to extend crossc and vendor it, while
also sending PRs upstream.
* Integrate crossc; shader transpilation for GLES now works
* fix leak
* gles30 backend now playable on Mesa with 3.2 context
Some rendering issues are present. Identified so far:
- Marisa's lasers are invisible
- Death effect looks wrong
Also, a small pixmap manipulation library has been written, and the
texture uploading API redesigned around it.
* fix marisa lasers in GLES (uniform name clashed with builtin)
* fix player death effect in GLES (another name clash)
* Dump ANGLE's translated shader code in debug log
* fix screenshots
* Drop support for triangle fans, switch to strips
Fans offer no advantage over strips, and they've been removed in D3D10+,
so ANGLE has to emulate them.
* crude workaround for an ANGLE bug
* Re-enable GL debug labels, fix an issue with them that affected ANGLE (but was always technically a bug)
* fix race condition in shaderc initialization
* New SDL_RWops interface for vertex buffers
* Optimize VBO streaming via buffering updates
Measurable performance improvement even with the main gl33 renderer,
drastic improvement with ANGLE.
* Fix the depth texture binding problem under ANGLE
Apparently it hates GL_DEPTH_COMPONENT16 for some reason. Sized internal
formats are not supported in GLES 2.0 anyway, so not using them is
probably a good idea.
* fix GLES2.0 segfault (the backend still doesn't work, though)
* dump GL extensions at info log level, not debug
* get around a Mesa bug; more correct texture format table for GLES2
* Correct GLES3 texture format table according to the spec
Not a Mesa bug after all
* require crossc>=1.5.0, fallback to subproject
* Request at least 8bit per color channel in GL backends
* Forbid lto for static windows builds with shader_transpiler=true
* fix edge case segfault
* Add basic ANGLE bundling support to the build system
Windows only, and no NSIS support yet
* Fix various windows-related build system and installer brokenness
* Disable gles backends by default
* update documentation
2018-10-02 00:36:10 +02:00
|
|
|
if(glslvstr == NULL) {
|
2019-02-14 22:11:27 +01:00
|
|
|
log_error("Failed to obtain the GLSL version string");
|
OpenGL ES 3.0 rendering backend (#148)
* First steps towards shader transpilation
Needs to be manually enabled via -Dshader_transpiler=true.
Requires shaderc. https://github.com/google/shaderc
Not yet functional due to missing SPIRV-Cross integration. SPIRV-Cross
currently does not have an official C API, and crossc is too minimal to
be useful. The current plan is to extend crossc and vendor it, while
also sending PRs upstream.
* Integrate crossc; shader transpilation for GLES now works
* fix leak
* gles30 backend now playable on Mesa with 3.2 context
Some rendering issues are present. Identified so far:
- Marisa's lasers are invisible
- Death effect looks wrong
Also, a small pixmap manipulation library has been written, and the
texture uploading API redesigned around it.
* fix marisa lasers in GLES (uniform name clashed with builtin)
* fix player death effect in GLES (another name clash)
* Dump ANGLE's translated shader code in debug log
* fix screenshots
* Drop support for triangle fans, switch to strips
Fans offer no advantage over strips, and they've been removed in D3D10+,
so ANGLE has to emulate them.
* crude workaround for an ANGLE bug
* Re-enable GL debug labels, fix an issue with them that affected ANGLE (but was always technically a bug)
* fix race condition in shaderc initialization
* New SDL_RWops interface for vertex buffers
* Optimize VBO streaming via buffering updates
Measurable performance improvement even with the main gl33 renderer,
drastic improvement with ANGLE.
* Fix the depth texture binding problem under ANGLE
Apparently it hates GL_DEPTH_COMPONENT16 for some reason. Sized internal
formats are not supported in GLES 2.0 anyway, so not using them is
probably a good idea.
* fix GLES2.0 segfault (the backend still doesn't work, though)
* dump GL extensions at info log level, not debug
* get around a Mesa bug; more correct texture format table for GLES2
* Correct GLES3 texture format table according to the spec
Not a Mesa bug after all
* require crossc>=1.5.0, fallback to subproject
* Request at least 8bit per color channel in GL backends
* Forbid lto for static windows builds with shader_transpiler=true
* fix edge case segfault
* Add basic ANGLE bundling support to the build system
Windows only, and no NSIS support yet
* Fix various windows-related build system and installer brokenness
* Disable gles backends by default
* update documentation
2018-10-02 00:36:10 +02:00
|
|
|
glcommon_free_shader_lang_table();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2018-09-14 09:37:20 +02:00
|
|
|
if(strstartswith(glslvstr, gles_prefix)) {
|
|
|
|
glslvstr += strlen(gles_prefix);
|
|
|
|
profile = GLSL_PROFILE_ES;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(sscanf(glslvstr, " %u.%u", &major, &minor) == 2) {
|
|
|
|
GLSLVersion glsl_version = { major * 100 + minor, profile };
|
|
|
|
|
|
|
|
// This one *must* work.
|
|
|
|
add_glsl_version_parsed(glsl_version);
|
|
|
|
|
|
|
|
// Let's be a bit optimistic here and just assume that all the older versions are supported (except those commented out).
|
|
|
|
// This seems to be the common behavior anyway.
|
|
|
|
|
|
|
|
for(struct vtable *v = version_map; v < version_map + sizeof(version_map)/sizeof(*version_map); ++v) {
|
|
|
|
if(v->glsl.version < glsl_version.version && v->glsl.profile == profile) {
|
|
|
|
add_glsl_version_parsed(v->glsl);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else {
|
2019-02-14 22:11:27 +01:00
|
|
|
log_error("Failed to parse GLSL version string: %s", glslvstr_orig);
|
2018-09-14 09:37:20 +02:00
|
|
|
|
|
|
|
// We could try to infer it from the context version, but whatever.
|
|
|
|
// If we got here, then we're probably fucked anyway.
|
|
|
|
glcommon_free_shader_lang_table();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void glcommon_build_shader_lang_table_finish(void) {
|
2020-04-05 04:51:00 +02:00
|
|
|
if(glcommon_shader_lang_table.num_elements > 0) {
|
2018-09-14 09:37:20 +02:00
|
|
|
char *str;
|
|
|
|
SDL_RWops *abuf = SDL_RWAutoBuffer((void**)&str, 256);
|
|
|
|
SDL_RWprintf(abuf, "Supported GLSL versions: ");
|
|
|
|
char vbuf[32];
|
|
|
|
|
2020-04-05 04:51:00 +02:00
|
|
|
dynarray_foreach(&glcommon_shader_lang_table, int i, ShaderLangInfo *lang, {
|
2018-09-14 09:37:20 +02:00
|
|
|
assert(lang->lang == SHLANG_GLSL);
|
|
|
|
|
|
|
|
glsl_format_version(vbuf, sizeof(vbuf), lang->glsl.version);
|
|
|
|
|
2020-04-05 04:51:00 +02:00
|
|
|
if(i == 0) {
|
2018-09-14 09:37:20 +02:00
|
|
|
SDL_RWprintf(abuf, "%s", vbuf);
|
|
|
|
} else {
|
|
|
|
SDL_RWprintf(abuf, ", %s", vbuf);
|
|
|
|
}
|
2020-04-05 04:51:00 +02:00
|
|
|
});
|
2018-09-14 09:37:20 +02:00
|
|
|
|
|
|
|
SDL_WriteU8(abuf, 0);
|
|
|
|
log_info("%s", str);
|
|
|
|
SDL_RWclose(abuf);
|
2020-04-05 04:51:00 +02:00
|
|
|
|
|
|
|
dynarray_compact(&glcommon_shader_lang_table);
|
2018-09-14 09:37:20 +02:00
|
|
|
} else {
|
2019-02-14 22:11:27 +01:00
|
|
|
log_error("Can not determine supported GLSL versions. Looks like the OpenGL implementation is non-conformant. Expect nothing to work.");
|
2018-09-14 09:37:20 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void glcommon_free_shader_lang_table(void) {
|
2020-04-05 04:51:00 +02:00
|
|
|
dynarray_free_data(&glcommon_shader_lang_table);
|
2018-09-14 09:37:20 +02:00
|
|
|
}
|