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,
|
||||
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
|
||||
|
|
|
@ -28,6 +28,8 @@
|
|||
#ifndef __rua_lang_h
|
||||
#define __rua_lang_h
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "QF/dstring.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));
|
||||
|
||||
typedef struct language_s {
|
||||
bool initialized;
|
||||
void (*init) (void);
|
||||
int (*parse) (FILE *in);
|
||||
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;
|
||||
|
||||
extern language_t current_language;
|
||||
|
||||
extern language_t lang_ruamoko;
|
||||
extern language_t lang_pascal;
|
||||
|
||||
|
|
|
@ -28,7 +28,9 @@
|
|||
# include "config.h"
|
||||
#endif
|
||||
|
||||
#include "tools/qfcc/include/diagnostic.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_EXP(l,f) SRC_LINE_EXP2(l,f)
|
||||
|
@ -41,6 +43,9 @@ SRC_LINE
|
|||
"in int gl_DrawID;" "\n"
|
||||
"in int gl_BaseVertex;" "\n"
|
||||
"in int gl_BaseInstance;" "\n"
|
||||
"#ifdef GL_EXT_multiview" "\n"
|
||||
"highp int gl_ViewIndex;" "\n"
|
||||
"#endif" "\n"
|
||||
"out gl_PerVertex {" "\n"
|
||||
" vec4 gl_Position;" "\n"
|
||||
" float gl_PointSize;" "\n"
|
||||
|
@ -60,6 +65,9 @@ SRC_LINE
|
|||
"in int gl_PatchVerticesIn;" "\n"
|
||||
"in int gl_PrimitiveID;" "\n"
|
||||
"in int gl_InvocationID;" "\n"
|
||||
"#ifdef GL_EXT_multiview" "\n"
|
||||
"highp int gl_ViewIndex;" "\n"
|
||||
"#endif" "\n"
|
||||
"out gl_PerVertex {" "\n"
|
||||
" vec4 gl_Position;" "\n"
|
||||
" float gl_PointSize;" "\n"
|
||||
|
@ -82,6 +90,9 @@ SRC_LINE
|
|||
"in vec3 gl_TessCoord;" "\n"
|
||||
"patch in float gl_TessLevelOuter[4];" "\n"
|
||||
"patch in float gl_TessLevelInner[2];" "\n"
|
||||
"#ifdef GL_EXT_multiview" "\n"
|
||||
"highp int gl_ViewIndex;" "\n"
|
||||
"#endif" "\n"
|
||||
"out gl_PerVertex {" "\n"
|
||||
" vec4 gl_Position;" "\n"
|
||||
" float gl_PointSize;" "\n"
|
||||
|
@ -99,6 +110,9 @@ SRC_LINE
|
|||
"} gl_in[];" "\n"
|
||||
"in int gl_PrimitiveIDIn;" "\n"
|
||||
"in int gl_InvocationID;" "\n"
|
||||
"#ifdef GL_EXT_multiview" "\n"
|
||||
"highp int gl_ViewIndex;" "\n"
|
||||
"#endif" "\n"
|
||||
"out gl_PerVertex {" "\n"
|
||||
" vec4 gl_Position;" "\n"
|
||||
" float gl_PointSize;" "\n"
|
||||
|
@ -123,6 +137,9 @@ SRC_LINE
|
|||
"in int gl_Layer;" "\n"
|
||||
"in int gl_ViewportIndex;" "\n"
|
||||
"in bool gl_HelperInvocation;" "\n"
|
||||
"#ifdef GL_EXT_multiview" "\n"
|
||||
"highp int gl_ViewIndex;" "\n"
|
||||
"#endif" "\n"
|
||||
"out float gl_FragDepth;" "\n"
|
||||
"out int gl_SampleMask[];" "\n";
|
||||
|
||||
|
@ -817,6 +834,37 @@ bool allInvocations(bool value)
|
|||
bool allInvocationsEqual(bool value)
|
||||
#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
|
||||
glsl_parse_vars (const char *var_src)
|
||||
{
|
||||
|
@ -826,6 +874,7 @@ glsl_parse_vars (const char *var_src)
|
|||
static void
|
||||
glsl_init_common (void)
|
||||
{
|
||||
current_language.initialized = true;
|
||||
glsl_block_clear ();
|
||||
glsl_parse_vars (glsl_system_constants);
|
||||
}
|
||||
|
|
|
@ -1492,32 +1492,143 @@ glsl_parse_string (const char *str)
|
|||
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 = {
|
||||
.init = glsl_init_comp,
|
||||
.parse = glsl_yyparse,
|
||||
.extension = glsl_extension,
|
||||
.version = glsl_version,
|
||||
.on_include = glsl_on_include,
|
||||
};
|
||||
|
||||
language_t lang_glsl_vert = {
|
||||
.init = glsl_init_vert,
|
||||
.parse = glsl_yyparse,
|
||||
.extension = glsl_extension,
|
||||
.version = glsl_version,
|
||||
.on_include = glsl_on_include,
|
||||
};
|
||||
|
||||
language_t lang_glsl_tesc = {
|
||||
.init = glsl_init_tesc,
|
||||
.parse = glsl_yyparse,
|
||||
.extension = glsl_extension,
|
||||
.version = glsl_version,
|
||||
.on_include = glsl_on_include,
|
||||
};
|
||||
|
||||
language_t lang_glsl_tese = {
|
||||
.init = glsl_init_tese,
|
||||
.parse = glsl_yyparse,
|
||||
.extension = glsl_extension,
|
||||
.version = glsl_version,
|
||||
.on_include = glsl_on_include,
|
||||
};
|
||||
|
||||
language_t lang_glsl_geom = {
|
||||
.init = glsl_init_geom,
|
||||
.parse = glsl_yyparse,
|
||||
.extension = glsl_extension,
|
||||
.version = glsl_version,
|
||||
.on_include = glsl_on_include,
|
||||
};
|
||||
|
||||
language_t lang_glsl_frag = {
|
||||
.init = glsl_init_frag,
|
||||
.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 EXTENSION VERSION
|
||||
|
||||
%type <t.text> string
|
||||
%type <t.text> string opt_profile
|
||||
%type <macro> params opt_params body arg arg_list arg_clist
|
||||
%type <dstr> text text_text
|
||||
%type <expr> unary_expr expr id defined defined_id line_expr
|
||||
|
@ -247,12 +247,29 @@ directive
|
|||
extra_warn
|
||||
| ENDIF { rua_endif (scanner); }
|
||||
extra_warn
|
||||
| EXTENSION ID ':' ID eod
|
||||
| VERSION VALUE opt_profile eod
|
||||
| EXTENSION ID ':' ID
|
||||
{
|
||||
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
|
||||
: /* empty */
|
||||
: /* empty */ { $$ = nullptr; }
|
||||
| ID
|
||||
;
|
||||
|
||||
|
|
|
@ -427,8 +427,6 @@ directive (const char *token, yyscan_t scanner)
|
|||
extra->preprocessor = false;
|
||||
return -1;
|
||||
}
|
||||
//auto lex = qc_yyget_extra (scanner);
|
||||
//lex->current_lang = &lex->pre_lang;
|
||||
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;
|
||||
}
|
||||
if (!current_language.initialized && current_language.init) {
|
||||
current_language.init ();
|
||||
}
|
||||
QC_YYSTYPE lval = {};
|
||||
token = qc_token (extra, &lval, tok, scanner);
|
||||
if (token >= 0) {
|
||||
|
@ -2141,6 +2142,11 @@ rua_include_file (const char *name, void *scanner)
|
|||
if (extra->suppressed) {
|
||||
return;
|
||||
}
|
||||
if (current_language.on_include) {
|
||||
if (!current_language.on_include (name)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
struct yyguts_t * yyg = (struct yyguts_t*)scanner;//FIXME
|
||||
int quote = *name;
|
||||
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;
|
||||
}
|
||||
|
||||
current_language = *lang;
|
||||
|
||||
InitData ();
|
||||
chain_initial_types ();
|
||||
begin_compilation ();
|
||||
pr.comp_dir = save_cwd ();
|
||||
add_source_file (file);
|
||||
if (lang->init) {
|
||||
lang->init ();
|
||||
}
|
||||
lang->initialized = false;
|
||||
err = lang->parse (yyin) || pr.error_count;
|
||||
fclose (yyin);
|
||||
if (cpp_name && !options.save_temps) {
|
||||
|
@ -672,6 +672,7 @@ compile_file (const char *filename)
|
|||
FILE *yyin;
|
||||
int (*yyparse) (FILE *in) = lang_ruamoko.parse;
|
||||
|
||||
current_language = lang_ruamoko;
|
||||
yyin = preprocess_file (filename, 0);
|
||||
if (options.preprocess_only || !yyin)
|
||||
return !options.preprocess_only;
|
||||
|
|
|
@ -40,6 +40,7 @@
|
|||
#include "tools/qfcc/include/symtab.h"
|
||||
#include "tools/qfcc/include/type.h"
|
||||
|
||||
language_t current_language;
|
||||
function_t *current_func;
|
||||
class_type_t *current_class;
|
||||
expr_t *local_expr;
|
||||
|
|
Loading…
Reference in a new issue