mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 13:11:00 +00:00
[qfcc] Handle glsl version and extension directives
The version directive really does only some error checking, and only GL_EXT_multiview and GL_GOOGLE_include_directive are supported for extensions, but enable/disable work (but not yet warn for multiview).
This commit is contained in:
parent
cba28e9421
commit
f335540e99
8 changed files with 206 additions and 9 deletions
|
@ -58,4 +58,8 @@ void glsl_block_clear (void);
|
||||||
void glsl_declare_block (struct specifier_s spec, struct symbol_s *block_sym,
|
void glsl_declare_block (struct specifier_s spec, struct symbol_s *block_sym,
|
||||||
struct symbol_s *instance_name);
|
struct symbol_s *instance_name);
|
||||||
|
|
||||||
|
bool glsl_on_include (const char *name);
|
||||||
|
void glsl_include (int behavior, void *scanner);
|
||||||
|
void glsl_multiview (int behavior, void *scanner);
|
||||||
|
|
||||||
#endif//__glsl_lang_h
|
#endif//__glsl_lang_h
|
||||||
|
|
|
@ -28,6 +28,8 @@
|
||||||
#ifndef __rua_lang_h
|
#ifndef __rua_lang_h
|
||||||
#define __rua_lang_h
|
#define __rua_lang_h
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "QF/dstring.h"
|
#include "QF/dstring.h"
|
||||||
|
|
||||||
#include "specifier.h"
|
#include "specifier.h"
|
||||||
|
@ -189,11 +191,17 @@ const char *rua_directive_get_key (const void *dir, void *unused) __attribute__(
|
||||||
const char *rua_keyword_get_key (const void *dir, void *unused) __attribute__((pure));
|
const char *rua_keyword_get_key (const void *dir, void *unused) __attribute__((pure));
|
||||||
|
|
||||||
typedef struct language_s {
|
typedef struct language_s {
|
||||||
|
bool initialized;
|
||||||
void (*init) (void);
|
void (*init) (void);
|
||||||
int (*parse) (FILE *in);
|
int (*parse) (FILE *in);
|
||||||
int (*finish) (const char *file);
|
int (*finish) (const char *file);
|
||||||
|
void (*extension) (const char *name, const char *value, void *scanner);
|
||||||
|
void (*version) (int version, const char *profile);
|
||||||
|
bool (*on_include) (const char *name);
|
||||||
} language_t;
|
} language_t;
|
||||||
|
|
||||||
|
extern language_t current_language;
|
||||||
|
|
||||||
extern language_t lang_ruamoko;
|
extern language_t lang_ruamoko;
|
||||||
extern language_t lang_pascal;
|
extern language_t lang_pascal;
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,9 @@
|
||||||
# include "config.h"
|
# include "config.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include "tools/qfcc/include/diagnostic.h"
|
||||||
#include "tools/qfcc/include/glsl-lang.h"
|
#include "tools/qfcc/include/glsl-lang.h"
|
||||||
|
#include "tools/qfcc/include/rua-lang.h"
|
||||||
|
|
||||||
#define SRC_LINE_EXP2(l,f) "#line " #l " " #f "\n"
|
#define SRC_LINE_EXP2(l,f) "#line " #l " " #f "\n"
|
||||||
#define SRC_LINE_EXP(l,f) SRC_LINE_EXP2(l,f)
|
#define SRC_LINE_EXP(l,f) SRC_LINE_EXP2(l,f)
|
||||||
|
@ -41,6 +43,9 @@ SRC_LINE
|
||||||
"in int gl_DrawID;" "\n"
|
"in int gl_DrawID;" "\n"
|
||||||
"in int gl_BaseVertex;" "\n"
|
"in int gl_BaseVertex;" "\n"
|
||||||
"in int gl_BaseInstance;" "\n"
|
"in int gl_BaseInstance;" "\n"
|
||||||
|
"#ifdef GL_EXT_multiview" "\n"
|
||||||
|
"highp int gl_ViewIndex;" "\n"
|
||||||
|
"#endif" "\n"
|
||||||
"out gl_PerVertex {" "\n"
|
"out gl_PerVertex {" "\n"
|
||||||
" vec4 gl_Position;" "\n"
|
" vec4 gl_Position;" "\n"
|
||||||
" float gl_PointSize;" "\n"
|
" float gl_PointSize;" "\n"
|
||||||
|
@ -60,6 +65,9 @@ SRC_LINE
|
||||||
"in int gl_PatchVerticesIn;" "\n"
|
"in int gl_PatchVerticesIn;" "\n"
|
||||||
"in int gl_PrimitiveID;" "\n"
|
"in int gl_PrimitiveID;" "\n"
|
||||||
"in int gl_InvocationID;" "\n"
|
"in int gl_InvocationID;" "\n"
|
||||||
|
"#ifdef GL_EXT_multiview" "\n"
|
||||||
|
"highp int gl_ViewIndex;" "\n"
|
||||||
|
"#endif" "\n"
|
||||||
"out gl_PerVertex {" "\n"
|
"out gl_PerVertex {" "\n"
|
||||||
" vec4 gl_Position;" "\n"
|
" vec4 gl_Position;" "\n"
|
||||||
" float gl_PointSize;" "\n"
|
" float gl_PointSize;" "\n"
|
||||||
|
@ -82,6 +90,9 @@ SRC_LINE
|
||||||
"in vec3 gl_TessCoord;" "\n"
|
"in vec3 gl_TessCoord;" "\n"
|
||||||
"patch in float gl_TessLevelOuter[4];" "\n"
|
"patch in float gl_TessLevelOuter[4];" "\n"
|
||||||
"patch in float gl_TessLevelInner[2];" "\n"
|
"patch in float gl_TessLevelInner[2];" "\n"
|
||||||
|
"#ifdef GL_EXT_multiview" "\n"
|
||||||
|
"highp int gl_ViewIndex;" "\n"
|
||||||
|
"#endif" "\n"
|
||||||
"out gl_PerVertex {" "\n"
|
"out gl_PerVertex {" "\n"
|
||||||
" vec4 gl_Position;" "\n"
|
" vec4 gl_Position;" "\n"
|
||||||
" float gl_PointSize;" "\n"
|
" float gl_PointSize;" "\n"
|
||||||
|
@ -99,6 +110,9 @@ SRC_LINE
|
||||||
"} gl_in[];" "\n"
|
"} gl_in[];" "\n"
|
||||||
"in int gl_PrimitiveIDIn;" "\n"
|
"in int gl_PrimitiveIDIn;" "\n"
|
||||||
"in int gl_InvocationID;" "\n"
|
"in int gl_InvocationID;" "\n"
|
||||||
|
"#ifdef GL_EXT_multiview" "\n"
|
||||||
|
"highp int gl_ViewIndex;" "\n"
|
||||||
|
"#endif" "\n"
|
||||||
"out gl_PerVertex {" "\n"
|
"out gl_PerVertex {" "\n"
|
||||||
" vec4 gl_Position;" "\n"
|
" vec4 gl_Position;" "\n"
|
||||||
" float gl_PointSize;" "\n"
|
" float gl_PointSize;" "\n"
|
||||||
|
@ -123,6 +137,9 @@ SRC_LINE
|
||||||
"in int gl_Layer;" "\n"
|
"in int gl_Layer;" "\n"
|
||||||
"in int gl_ViewportIndex;" "\n"
|
"in int gl_ViewportIndex;" "\n"
|
||||||
"in bool gl_HelperInvocation;" "\n"
|
"in bool gl_HelperInvocation;" "\n"
|
||||||
|
"#ifdef GL_EXT_multiview" "\n"
|
||||||
|
"highp int gl_ViewIndex;" "\n"
|
||||||
|
"#endif" "\n"
|
||||||
"out float gl_FragDepth;" "\n"
|
"out float gl_FragDepth;" "\n"
|
||||||
"out int gl_SampleMask[];" "\n";
|
"out int gl_SampleMask[];" "\n";
|
||||||
|
|
||||||
|
@ -817,6 +834,37 @@ bool allInvocations(bool value)
|
||||||
bool allInvocationsEqual(bool value)
|
bool allInvocationsEqual(bool value)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
void
|
||||||
|
glsl_multiview (int behavior, void *scanner)
|
||||||
|
{
|
||||||
|
if (behavior) {
|
||||||
|
rua_parse_define ("GL_EXT_multiview 1\n");
|
||||||
|
} else {
|
||||||
|
rua_undefine ("GL_EXT_multiview", scanner);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int glsl_include_state = 0;
|
||||||
|
|
||||||
|
bool
|
||||||
|
glsl_on_include (const char *name)
|
||||||
|
{
|
||||||
|
if (!glsl_include_state) {
|
||||||
|
error (0, "'#include' : required extension not requested");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (glsl_include_state > 1) {
|
||||||
|
warning (0, "'#include' : required extension not requested");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glsl_include (int behavior, void *scanner)
|
||||||
|
{
|
||||||
|
glsl_include_state = behavior;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
glsl_parse_vars (const char *var_src)
|
glsl_parse_vars (const char *var_src)
|
||||||
{
|
{
|
||||||
|
@ -826,6 +874,7 @@ glsl_parse_vars (const char *var_src)
|
||||||
static void
|
static void
|
||||||
glsl_init_common (void)
|
glsl_init_common (void)
|
||||||
{
|
{
|
||||||
|
current_language.initialized = true;
|
||||||
glsl_block_clear ();
|
glsl_block_clear ();
|
||||||
glsl_parse_vars (glsl_system_constants);
|
glsl_parse_vars (glsl_system_constants);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1492,32 +1492,143 @@ glsl_parse_string (const char *str)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const char *glsl_behaviors[] = {
|
||||||
|
"disable",
|
||||||
|
"enable",
|
||||||
|
"require",
|
||||||
|
"warn",
|
||||||
|
};
|
||||||
|
#define num_behaviors (sizeof (glsl_behaviors) / sizeof (glsl_behaviors[0]))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
const char *name;
|
||||||
|
void (*set_behavior) (int behavior, void *scanner);
|
||||||
|
} glsl_ext_t;
|
||||||
|
|
||||||
|
static glsl_ext_t glsl_extensions[] = {
|
||||||
|
{"GL_EXT_multiview", glsl_multiview },
|
||||||
|
{"GL_GOOGLE_include_directive", glsl_include },
|
||||||
|
};
|
||||||
|
#define num_extensions (sizeof (glsl_extensions) / sizeof (glsl_extensions[0]))
|
||||||
|
|
||||||
|
static int
|
||||||
|
extension_cmp (const void *_a, const void *_b)
|
||||||
|
{
|
||||||
|
auto a = (const glsl_ext_t *) _a;
|
||||||
|
auto b = (const glsl_ext_t *) _b;
|
||||||
|
return strcmp (a->name, b->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
behavior_cmp (const void *_a, const void *_b)
|
||||||
|
{
|
||||||
|
auto a = (const char **) _a;
|
||||||
|
auto b = (const char **) _b;
|
||||||
|
return strcmp (*a, *b);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
glsl_extension (const char *name, const char *value, void *scanner)
|
||||||
|
{
|
||||||
|
if (current_language.initialized) {
|
||||||
|
error (0, "extensions directives must occur before any "
|
||||||
|
"non-preprocessor tokens");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const char **res;
|
||||||
|
res = bsearch (&value, glsl_behaviors, num_behaviors, sizeof (char *),
|
||||||
|
behavior_cmp);
|
||||||
|
if (!res) {
|
||||||
|
error (0, "invalid behavior: %s", value);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
int behavior = res - glsl_behaviors;
|
||||||
|
if (strcmp (name, "all") == 0) {
|
||||||
|
if (behavior != 0 && behavior != 3) {
|
||||||
|
error (0, "behavior must be 'warn' or 'disable' for 'all'");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (size_t i = 0; i < num_extensions; i++) {
|
||||||
|
glsl_extensions[i].set_behavior (behavior, scanner);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
glsl_ext_t key = { .name = name };
|
||||||
|
glsl_ext_t *ext;
|
||||||
|
ext = bsearch (&key, glsl_extensions, num_extensions,
|
||||||
|
sizeof (glsl_ext_t), extension_cmp);
|
||||||
|
if (ext) {
|
||||||
|
ext->set_behavior (behavior, scanner);
|
||||||
|
} else {
|
||||||
|
if (behavior == 2) {
|
||||||
|
error (0, "unknown extension '%s'", name);
|
||||||
|
} else {
|
||||||
|
warning (0, "unknown extension '%s'", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
glsl_version (int version, const char *profile)
|
||||||
|
{
|
||||||
|
if (!profile || strcmp (profile, "core") == 0) {
|
||||||
|
// ok
|
||||||
|
} else if (strcmp (profile, "es") == 0
|
||||||
|
|| strcmp (profile, "compatibility") == 0) {
|
||||||
|
error (0, "profile '%s' not supported", profile);
|
||||||
|
} else {
|
||||||
|
error (0, "bad profile name '%s': use es, core or compatibility",
|
||||||
|
profile);
|
||||||
|
}
|
||||||
|
if (version != 450 && version != 460) {
|
||||||
|
error (0, "version not supported");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
language_t lang_glsl_comp = {
|
language_t lang_glsl_comp = {
|
||||||
.init = glsl_init_comp,
|
.init = glsl_init_comp,
|
||||||
.parse = glsl_yyparse,
|
.parse = glsl_yyparse,
|
||||||
|
.extension = glsl_extension,
|
||||||
|
.version = glsl_version,
|
||||||
|
.on_include = glsl_on_include,
|
||||||
};
|
};
|
||||||
|
|
||||||
language_t lang_glsl_vert = {
|
language_t lang_glsl_vert = {
|
||||||
.init = glsl_init_vert,
|
.init = glsl_init_vert,
|
||||||
.parse = glsl_yyparse,
|
.parse = glsl_yyparse,
|
||||||
|
.extension = glsl_extension,
|
||||||
|
.version = glsl_version,
|
||||||
|
.on_include = glsl_on_include,
|
||||||
};
|
};
|
||||||
|
|
||||||
language_t lang_glsl_tesc = {
|
language_t lang_glsl_tesc = {
|
||||||
.init = glsl_init_tesc,
|
.init = glsl_init_tesc,
|
||||||
.parse = glsl_yyparse,
|
.parse = glsl_yyparse,
|
||||||
|
.extension = glsl_extension,
|
||||||
|
.version = glsl_version,
|
||||||
|
.on_include = glsl_on_include,
|
||||||
};
|
};
|
||||||
|
|
||||||
language_t lang_glsl_tese = {
|
language_t lang_glsl_tese = {
|
||||||
.init = glsl_init_tese,
|
.init = glsl_init_tese,
|
||||||
.parse = glsl_yyparse,
|
.parse = glsl_yyparse,
|
||||||
|
.extension = glsl_extension,
|
||||||
|
.version = glsl_version,
|
||||||
|
.on_include = glsl_on_include,
|
||||||
};
|
};
|
||||||
|
|
||||||
language_t lang_glsl_geom = {
|
language_t lang_glsl_geom = {
|
||||||
.init = glsl_init_geom,
|
.init = glsl_init_geom,
|
||||||
.parse = glsl_yyparse,
|
.parse = glsl_yyparse,
|
||||||
|
.extension = glsl_extension,
|
||||||
|
.version = glsl_version,
|
||||||
|
.on_include = glsl_on_include,
|
||||||
};
|
};
|
||||||
|
|
||||||
language_t lang_glsl_frag = {
|
language_t lang_glsl_frag = {
|
||||||
.init = glsl_init_frag,
|
.init = glsl_init_frag,
|
||||||
.parse = glsl_yyparse,
|
.parse = glsl_yyparse,
|
||||||
|
.extension = glsl_extension,
|
||||||
|
.version = glsl_version,
|
||||||
|
.on_include = glsl_on_include,
|
||||||
};
|
};
|
||||||
|
|
|
@ -138,7 +138,7 @@ parse_error (void *scanner)
|
||||||
%token CONCAT ARGS
|
%token CONCAT ARGS
|
||||||
%token EXTENSION VERSION
|
%token EXTENSION VERSION
|
||||||
|
|
||||||
%type <t.text> string
|
%type <t.text> string opt_profile
|
||||||
%type <macro> params opt_params body arg arg_list arg_clist
|
%type <macro> params opt_params body arg arg_list arg_clist
|
||||||
%type <dstr> text text_text
|
%type <dstr> text text_text
|
||||||
%type <expr> unary_expr expr id defined defined_id line_expr
|
%type <expr> unary_expr expr id defined defined_id line_expr
|
||||||
|
@ -247,12 +247,29 @@ directive
|
||||||
extra_warn
|
extra_warn
|
||||||
| ENDIF { rua_endif (scanner); }
|
| ENDIF { rua_endif (scanner); }
|
||||||
extra_warn
|
extra_warn
|
||||||
| EXTENSION ID ':' ID eod
|
| EXTENSION ID ':' ID
|
||||||
| VERSION VALUE opt_profile eod
|
{
|
||||||
|
if (current_language.extension) {
|
||||||
|
current_language.extension ($2, $4, scanner);
|
||||||
|
} else {
|
||||||
|
internal_error (0, "invalid directive");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extra_warn
|
||||||
|
| VERSION VALUE opt_profile
|
||||||
|
{
|
||||||
|
if (current_language.version) {
|
||||||
|
auto version = get_long ($2, $<t.text>2, 460);
|
||||||
|
current_language.version (expr_long (version), $3);
|
||||||
|
} else {
|
||||||
|
internal_error (0, "invalid directive");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
extra_warn
|
||||||
;
|
;
|
||||||
|
|
||||||
opt_profile
|
opt_profile
|
||||||
: /* empty */
|
: /* empty */ { $$ = nullptr; }
|
||||||
| ID
|
| ID
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
|
@ -427,8 +427,6 @@ directive (const char *token, yyscan_t scanner)
|
||||||
extra->preprocessor = false;
|
extra->preprocessor = false;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
//auto lex = qc_yyget_extra (scanner);
|
|
||||||
//lex->current_lang = &lex->pre_lang;
|
|
||||||
return directive->value;
|
return directive->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1167,6 +1165,9 @@ qc_process (rua_extra_t *extra, int token, rua_tok_t *tok, yyscan_t scanner)
|
||||||
}
|
}
|
||||||
return token ? YYPUSH_MORE : 0;
|
return token ? YYPUSH_MORE : 0;
|
||||||
}
|
}
|
||||||
|
if (!current_language.initialized && current_language.init) {
|
||||||
|
current_language.init ();
|
||||||
|
}
|
||||||
QC_YYSTYPE lval = {};
|
QC_YYSTYPE lval = {};
|
||||||
token = qc_token (extra, &lval, tok, scanner);
|
token = qc_token (extra, &lval, tok, scanner);
|
||||||
if (token >= 0) {
|
if (token >= 0) {
|
||||||
|
@ -2141,6 +2142,11 @@ rua_include_file (const char *name, void *scanner)
|
||||||
if (extra->suppressed) {
|
if (extra->suppressed) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (current_language.on_include) {
|
||||||
|
if (!current_language.on_include (name)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
struct yyguts_t * yyg = (struct yyguts_t*)scanner;//FIXME
|
struct yyguts_t * yyg = (struct yyguts_t*)scanner;//FIXME
|
||||||
int quote = *name;
|
int quote = *name;
|
||||||
name = make_string (name, 0);
|
name = make_string (name, 0);
|
||||||
|
|
|
@ -385,14 +385,14 @@ compile_to_obj (const char *file, const char *obj, language_t *lang)
|
||||||
return !options.preprocess_only;
|
return !options.preprocess_only;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
current_language = *lang;
|
||||||
|
|
||||||
InitData ();
|
InitData ();
|
||||||
chain_initial_types ();
|
chain_initial_types ();
|
||||||
begin_compilation ();
|
begin_compilation ();
|
||||||
pr.comp_dir = save_cwd ();
|
pr.comp_dir = save_cwd ();
|
||||||
add_source_file (file);
|
add_source_file (file);
|
||||||
if (lang->init) {
|
lang->initialized = false;
|
||||||
lang->init ();
|
|
||||||
}
|
|
||||||
err = lang->parse (yyin) || pr.error_count;
|
err = lang->parse (yyin) || pr.error_count;
|
||||||
fclose (yyin);
|
fclose (yyin);
|
||||||
if (cpp_name && !options.save_temps) {
|
if (cpp_name && !options.save_temps) {
|
||||||
|
@ -672,6 +672,7 @@ compile_file (const char *filename)
|
||||||
FILE *yyin;
|
FILE *yyin;
|
||||||
int (*yyparse) (FILE *in) = lang_ruamoko.parse;
|
int (*yyparse) (FILE *in) = lang_ruamoko.parse;
|
||||||
|
|
||||||
|
current_language = lang_ruamoko;
|
||||||
yyin = preprocess_file (filename, 0);
|
yyin = preprocess_file (filename, 0);
|
||||||
if (options.preprocess_only || !yyin)
|
if (options.preprocess_only || !yyin)
|
||||||
return !options.preprocess_only;
|
return !options.preprocess_only;
|
||||||
|
|
|
@ -40,6 +40,7 @@
|
||||||
#include "tools/qfcc/include/symtab.h"
|
#include "tools/qfcc/include/symtab.h"
|
||||||
#include "tools/qfcc/include/type.h"
|
#include "tools/qfcc/include/type.h"
|
||||||
|
|
||||||
|
language_t current_language;
|
||||||
function_t *current_func;
|
function_t *current_func;
|
||||||
class_type_t *current_class;
|
class_type_t *current_class;
|
||||||
expr_t *local_expr;
|
expr_t *local_expr;
|
||||||
|
|
Loading…
Reference in a new issue