mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-02-25 13:11:00 +00:00
[qfcc] Do basic error checking on layout qualifiers
I'm not sure I got all the checks right, but bsp_gbuf.geom passes the validity (but failes due to not having implemented the application of the qualifiers).
This commit is contained in:
parent
5d7a8127c2
commit
7742450e03
5 changed files with 841 additions and 125 deletions
|
@ -31,6 +31,7 @@
|
||||||
typedef struct specifier_s specifier_t;
|
typedef struct specifier_s specifier_t;
|
||||||
typedef struct attribute_s attribute_t;
|
typedef struct attribute_s attribute_t;
|
||||||
typedef struct expr_s expr_t;
|
typedef struct expr_s expr_t;
|
||||||
|
typedef struct ex_list_s ex_list_t;
|
||||||
typedef struct type_s type_t;
|
typedef struct type_s type_t;
|
||||||
typedef struct symbol_s symbol_t;
|
typedef struct symbol_s symbol_t;
|
||||||
typedef struct symtab_s symtab_t;
|
typedef struct symtab_s symtab_t;
|
||||||
|
@ -91,11 +92,13 @@ void glsl_declare_block (specifier_t spec, symbol_t *block_sym,
|
||||||
symbol_t *instance_name);
|
symbol_t *instance_name);
|
||||||
glsl_block_t *glsl_get_block (const char *name, glsl_interface_t interface);
|
glsl_block_t *glsl_get_block (const char *name, glsl_interface_t interface);
|
||||||
symtab_t *glsl_optimize_attributes (attribute_t *attributes);
|
symtab_t *glsl_optimize_attributes (attribute_t *attributes);
|
||||||
|
void glsl_apply_attributes (symtab_t *attributes, specifier_t spec);
|
||||||
|
|
||||||
void glsl_parse_declaration (specifier_t spec,
|
void glsl_parse_declaration (specifier_t spec,
|
||||||
symbol_t *sym, const type_t *array,
|
symbol_t *sym, const type_t *array,
|
||||||
const expr_t *init, symtab_t *symtab);
|
const expr_t *init, symtab_t *symtab);
|
||||||
void glsl_declare_field (specifier_t spec, symtab_t *symtab);
|
void glsl_declare_field (specifier_t spec, symtab_t *symtab);
|
||||||
|
void glsl_layout (const ex_list_t *qualifiers, specifier_t spec);
|
||||||
|
|
||||||
bool glsl_on_include (const char *name);
|
bool glsl_on_include (const char *name);
|
||||||
void glsl_include (int behavior, void *scanner);
|
void glsl_include (int behavior, void *scanner);
|
||||||
|
|
|
@ -46,6 +46,7 @@ qfcc_SOURCES = \
|
||||||
tools/qfcc/source/glsl-block.c \
|
tools/qfcc/source/glsl-block.c \
|
||||||
tools/qfcc/source/glsl-builtins.c \
|
tools/qfcc/source/glsl-builtins.c \
|
||||||
tools/qfcc/source/glsl-declaration.c \
|
tools/qfcc/source/glsl-declaration.c \
|
||||||
|
tools/qfcc/source/glsl-layout.c \
|
||||||
tools/qfcc/source/glsl-parse.y \
|
tools/qfcc/source/glsl-parse.y \
|
||||||
tools/qfcc/source/glsl-sub_comp.c \
|
tools/qfcc/source/glsl-sub_comp.c \
|
||||||
tools/qfcc/source/glsl-sub_frag.c \
|
tools/qfcc/source/glsl-sub_frag.c \
|
||||||
|
|
|
@ -42,126 +42,6 @@
|
||||||
#include "tools/qfcc/include/type.h"
|
#include "tools/qfcc/include/type.h"
|
||||||
#include "tools/qfcc/include/value.h"
|
#include "tools/qfcc/include/value.h"
|
||||||
|
|
||||||
#if 0
|
|
||||||
typedef struct layout_qual_s {
|
|
||||||
const char *name;
|
|
||||||
bool (*valid) (symbol_t *sym, glsl_interface_t interface);
|
|
||||||
bool (*apply) ();
|
|
||||||
bool (*apply_expr) ();
|
|
||||||
} layout_qual_t;
|
|
||||||
|
|
||||||
// qual var block member iface
|
|
||||||
static layout_qual_t layout_qualifiers[] = {
|
|
||||||
{"shared", /* q _ b _ uniform/buffer */, ___, nullptr},
|
|
||||||
{"packed", /* q _ b _ uniform/buffer */, ___, nullptr},
|
|
||||||
{"std140", /* q _ b _ uniform/buffer */, ___, nullptr},
|
|
||||||
{"std430", /* q _ b _ uniform/buffer */, ___, nullptr},
|
|
||||||
{"row_major", /* q _ b m uniform/buffer */, ___, nullptr},
|
|
||||||
{"column_major", /* q _ b m uniform/buffer */, ___, nullptr},
|
|
||||||
|
|
||||||
{"binding", /* _ o b _ uniform/buffer */, nullptr, ___},
|
|
||||||
{"offset", /* _ a _ m uniform/buffer */, nullptr, ___},
|
|
||||||
{"align", /* _ o b _ uniform/buffer */, nullptr, ___},
|
|
||||||
{"set", /* _ o b _ uniform/buffer */, nullptr, ___},
|
|
||||||
{"push_constant", /* _ _ b _ uniform(vulkan) */, ___, nullptr},
|
|
||||||
{"input_attachment_index", /* _ s _ _ uniform(vulkan) */, nullptr, ___},
|
|
||||||
{"location", /* _ v _ _ uniform/buffer/subroutine */, nullptr, ___},
|
|
||||||
|
|
||||||
{"location", /* _ v b m all in/out except compute */, nullptr, ___},
|
|
||||||
{"component", /* _ v _ m all in/out except compute */, nullptr, ___},
|
|
||||||
|
|
||||||
{"index", /* _ v _ _ fragment out/subroutine */, nullptr, ___},
|
|
||||||
|
|
||||||
{"triangles", /* q _ _ _ tese in */, ___, nullptr},
|
|
||||||
{"quads", /* q _ _ _ tese in */, ___, nullptr},
|
|
||||||
{"isolines", /* q _ _ _ tese in */, ___, nullptr},
|
|
||||||
{"equal_spacing", /* q _ _ _ tese in */, ___, nullptr},
|
|
||||||
{"fractional_even_spacing", /* q _ _ _ tese in */, ___, nullptr},
|
|
||||||
{"fractional_odd_spacing", /* q _ _ _ tese in */, ___, nullptr},
|
|
||||||
{"cw", /* q _ _ _ tese in */, ___, nullptr},
|
|
||||||
{"ccw", /* q _ _ _ tese in */, ___, nullptr},
|
|
||||||
{"point_mode", /* q _ _ _ tese in */, ___, nullptr},
|
|
||||||
|
|
||||||
{"points", /* q _ _ _ geom in/out */, ___, nullptr},
|
|
||||||
//? [ points ] // q _ _ _ geom in
|
|
||||||
{"lines", /* q _ _ _ geom in */, ___, nullptr},
|
|
||||||
{"lines_adjacency", /* q _ _ _ geom in */, ___, nullptr},
|
|
||||||
{"triangles", /* q _ _ _ geom in */, ___, nullptr},
|
|
||||||
{"triangles_adjacency", /* q _ _ _ geom in */, ___, nullptr},
|
|
||||||
{"invocations", /* q _ _ _ geom in */, nullptr, ___},
|
|
||||||
|
|
||||||
{"origin_upper_left", /* _ f _ _ frag in */, ___, nullptr},
|
|
||||||
{"pixel_center_integer", /* _ f _ _ frag in */, ___, nullptr},
|
|
||||||
{"early_fragment_tests", /* q _ _ _ frag in */, ___, nullptr},
|
|
||||||
|
|
||||||
{"local_size_x", /* q _ _ _ comp in */, nullptr, ___},
|
|
||||||
{"local_size_y", /* q _ _ _ comp in */, nullptr, ___},
|
|
||||||
{"local_size_z", /* q _ _ _ comp in */, nullptr, ___},
|
|
||||||
{"local_size_x_id", /* q _ _ _ comp in */, nullptr, ___},
|
|
||||||
{"local_size_y_id", /* q _ _ _ comp in */, nullptr, ___},
|
|
||||||
{"local_size_z_id", /* q _ _ _ comp in */, nullptr, ___},
|
|
||||||
|
|
||||||
{"xfb_buffer", /* q v b m vert/tess/geom out */, nullptr, ___},
|
|
||||||
{"xfb_stride", /* q v b m vert/tess/geom out */, nullptr, ___},
|
|
||||||
{"xfb_offset", /* _ v b m vert/tess/geom out */, nullptr, ___},
|
|
||||||
|
|
||||||
{"vertices", /* q _ _ _ tesc out */, nullptr, ___},
|
|
||||||
|
|
||||||
//? [ points ] // q _ _ _ geom out
|
|
||||||
{"line_strip", /* q _ _ _ geom out */, ___, nullptr},
|
|
||||||
{"triangle_strip", /* q _ _ _ geom out */, ___, nullptr},
|
|
||||||
{"max_vertices", /* q _ _ _ geom out */, nullptr, ___},
|
|
||||||
{"stream", /* q v b m geom out */, nullptr, ___},
|
|
||||||
|
|
||||||
{"depth_any", /* _ v _ _ frag out */, ___, nullptr},
|
|
||||||
{"depth_greater", /* _ v _ _ frag out */, ___, nullptr},
|
|
||||||
{"depth_less", /* _ v _ _ frag out */, ___, nullptr},
|
|
||||||
{"depth_unchanged", /* _ v _ _ frag out */, ___, nullptr},
|
|
||||||
|
|
||||||
{"constant_id", /* _ s _ _ const */, nullptr, ___},
|
|
||||||
|
|
||||||
{"rgba32f", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rgba16f", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rg32f", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rg16f", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"r11f_g11f_b10f", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"r32f", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"r16f", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rgba16", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rgb10_a2", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rgba8", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rg16", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rg8", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"r16", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"r8", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rgba16_snorm", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rgba8_snorm", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rg16_snorm", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rg8_snorm", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"r16_snorm", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"r8_snorm", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rgba32i", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rgba16i", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rgba8i", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rg32i", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rg16i", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rg8i", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"r32i", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"r16i", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"r8i", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rgba32ui", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rgba16ui", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rgb10_a2ui", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rgba8ui", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rg32ui", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rg16ui", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"rg8ui", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"r32ui", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"r16ui", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
{"r8ui", /* _ i _ _ uniform */, ___, nullptr},
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
const char *glsl_interface_names[glsl_num_interfaces] = {
|
const char *glsl_interface_names[glsl_num_interfaces] = {
|
||||||
"in",
|
"in",
|
||||||
"out",
|
"out",
|
||||||
|
@ -197,6 +77,7 @@ glsl_optimize_attributes (attribute_t *attributes)
|
||||||
}
|
}
|
||||||
symtab_addsymbol (attrtab, attrsym);
|
symtab_addsymbol (attrtab, attrsym);
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
notice (0, "%s", attr->name);
|
notice (0, "%s", attr->name);
|
||||||
if (!attr->params) continue;
|
if (!attr->params) continue;
|
||||||
for (auto p = attr->params->list.head; p; p = p->next) {
|
for (auto p = attr->params->list.head; p; p = p->next) {
|
||||||
|
@ -208,6 +89,20 @@ glsl_optimize_attributes (attribute_t *attributes)
|
||||||
notice (0, " %s", get_value_string (p->expr->value));
|
notice (0, " %s", get_value_string (p->expr->value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
return attrtab;
|
return attrtab;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glsl_apply_attributes (symtab_t *attributes, specifier_t spec)
|
||||||
|
{
|
||||||
|
for (auto attr = attributes->symbols; attr; attr = attr->next) {
|
||||||
|
if (strcmp (attr->name, "layout") == 0) {
|
||||||
|
if (attr->sy_type != sy_list) {
|
||||||
|
internal_error (0, "bogus layout qualifier");
|
||||||
|
}
|
||||||
|
glsl_layout (&attr->list, spec);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -49,7 +49,7 @@ glsl_parse_declaration (specifier_t spec, symbol_t *sym, const type_t *array,
|
||||||
spec.type = append_type (array, spec.type);
|
spec.type = append_type (array, spec.type);
|
||||||
spec.type = find_type (spec.type);
|
spec.type = find_type (spec.type);
|
||||||
}
|
}
|
||||||
/*auto attributes =*/ glsl_optimize_attributes (spec.attributes);
|
auto attributes = glsl_optimize_attributes (spec.attributes);
|
||||||
if (sym && sym->sy_type == sy_expr) {
|
if (sym && sym->sy_type == sy_expr) {
|
||||||
auto id_list = sym->expr;
|
auto id_list = sym->expr;
|
||||||
if (id_list->type != ex_list) {
|
if (id_list->type != ex_list) {
|
||||||
|
@ -60,19 +60,22 @@ glsl_parse_declaration (specifier_t spec, symbol_t *sym, const type_t *array,
|
||||||
internal_error (id_list, "not a symbol");
|
internal_error (id_list, "not a symbol");
|
||||||
}
|
}
|
||||||
spec.sym = id->expr->symbol;
|
spec.sym = id->expr->symbol;
|
||||||
declare_symbol (spec, init, symtab);
|
spec.sym = declare_symbol (spec, init, symtab);
|
||||||
|
glsl_apply_attributes (attributes, spec);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
spec.sym = sym;
|
spec.sym = sym;
|
||||||
if (spec.sym) {
|
if (spec.sym) {
|
||||||
declare_symbol (spec, init, symtab);
|
spec.sym = declare_symbol (spec, init, symtab);
|
||||||
}
|
}
|
||||||
|
glsl_apply_attributes (attributes, spec);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
glsl_declare_field (specifier_t spec, symtab_t *symtab)
|
glsl_declare_field (specifier_t spec, symtab_t *symtab)
|
||||||
{
|
{
|
||||||
/*auto attributes =*/ glsl_optimize_attributes (spec.attributes);
|
auto attributes = glsl_optimize_attributes (spec.attributes);
|
||||||
declare_field (spec, symtab);
|
spec.sym = declare_field (spec, symtab);
|
||||||
|
glsl_apply_attributes (attributes, spec);
|
||||||
}
|
}
|
||||||
|
|
814
tools/qfcc/source/glsl-layout.c
Normal file
814
tools/qfcc/source/glsl-layout.c
Normal file
|
@ -0,0 +1,814 @@
|
||||||
|
/*
|
||||||
|
glsl-layout.c
|
||||||
|
|
||||||
|
GLSL layout attribute handling
|
||||||
|
|
||||||
|
Copyright (C) 2024 Bill Currie <bill@taniwha.org>
|
||||||
|
|
||||||
|
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 2
|
||||||
|
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:
|
||||||
|
|
||||||
|
Free Software Foundation, Inc.
|
||||||
|
59 Temple Place - Suite 330
|
||||||
|
Boston, MA 02111-1307, USA
|
||||||
|
|
||||||
|
*/
|
||||||
|
#ifdef HAVE_CONFIG_H
|
||||||
|
# include "config.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include <strings.h>
|
||||||
|
|
||||||
|
#include "QF/alloc.h"
|
||||||
|
#include "QF/hash.h"
|
||||||
|
#include "QF/heapsort.h"
|
||||||
|
#include "QF/va.h"
|
||||||
|
|
||||||
|
#include "tools/qfcc/include/attribute.h"
|
||||||
|
#include "tools/qfcc/include/def.h"
|
||||||
|
#include "tools/qfcc/include/diagnostic.h"
|
||||||
|
#include "tools/qfcc/include/glsl-lang.h"
|
||||||
|
#include "tools/qfcc/include/shared.h"
|
||||||
|
#include "tools/qfcc/include/strpool.h"
|
||||||
|
#include "tools/qfcc/include/symtab.h"
|
||||||
|
#include "tools/qfcc/include/type.h"
|
||||||
|
#include "tools/qfcc/include/value.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
decl_var = 1 << 0,
|
||||||
|
decl_qual = 1 << 1,
|
||||||
|
decl_block = 1 << 2,
|
||||||
|
decl_member = 1 << 3,
|
||||||
|
} glsl_obj_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
var_any,
|
||||||
|
var_opaque,
|
||||||
|
var_atomic,
|
||||||
|
var_subpass,
|
||||||
|
var_scalar,
|
||||||
|
var_image,
|
||||||
|
var_gl_FragCoord,
|
||||||
|
var_gl_FragDepth,
|
||||||
|
} glsl_var_t;
|
||||||
|
|
||||||
|
typedef struct layout_qual_s {
|
||||||
|
const char *name;
|
||||||
|
bool (*apply) ();
|
||||||
|
bool (*apply_expr) ();
|
||||||
|
unsigned obj_mask;
|
||||||
|
glsl_var_t var_type;
|
||||||
|
unsigned if_mask;
|
||||||
|
const char **stage_filter;
|
||||||
|
} layout_qual_t;
|
||||||
|
|
||||||
|
#define A(a) a, nullptr
|
||||||
|
#define E(e) nullptr, e
|
||||||
|
#define D(d) (decl_##d)
|
||||||
|
#define D_all D(qual)|D(var)|D(block)|D(member)
|
||||||
|
#define V(v) (var_##v)
|
||||||
|
#define I(i) (1 << (glsl_##i))
|
||||||
|
#define C (const char *[])
|
||||||
|
|
||||||
|
static bool sorted_layout_qualifiers;
|
||||||
|
static layout_qual_t layout_qualifiers[] = {
|
||||||
|
{ .name = "shared",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual)|D(block),
|
||||||
|
.if_mask = I(uniform)|I(buffer),
|
||||||
|
},
|
||||||
|
{ .name = "packed",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual)|D(block),
|
||||||
|
.if_mask = I(uniform)|I(buffer),
|
||||||
|
},
|
||||||
|
{ .name = "std140",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual)|D(block),
|
||||||
|
.if_mask = I(uniform)|I(buffer),
|
||||||
|
},
|
||||||
|
{ .name = "std430",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual)|D(block),
|
||||||
|
.if_mask = I(uniform)|I(buffer),
|
||||||
|
},
|
||||||
|
{ .name = "row_major",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual)|D(block)|D(member),
|
||||||
|
.if_mask = I(uniform)|I(buffer),
|
||||||
|
},
|
||||||
|
{ .name = "column_major",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual)|D(block)|D(member),
|
||||||
|
.if_mask = I(uniform)|I(buffer),
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "binding",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(var)|D(block),
|
||||||
|
.var_type = V(opaque),
|
||||||
|
.if_mask = I(uniform)|I(buffer),
|
||||||
|
},
|
||||||
|
{ .name = "offset",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(var)|D(member),
|
||||||
|
.var_type = V(opaque),
|
||||||
|
.if_mask = I(uniform)|I(buffer),
|
||||||
|
},
|
||||||
|
{ .name = "align",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(var)|D(block),
|
||||||
|
.var_type = V(opaque),
|
||||||
|
.if_mask = I(uniform)|I(buffer),
|
||||||
|
},
|
||||||
|
{ .name = "set",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(var)|D(block),
|
||||||
|
.var_type = V(opaque),
|
||||||
|
.if_mask = I(uniform)|I(buffer),
|
||||||
|
},
|
||||||
|
{ .name = "push_constant",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(block),
|
||||||
|
.var_type = V(any),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "input_attachment_index",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(subpass),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "location",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(any),
|
||||||
|
.if_mask = I(uniform)|I(buffer),
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "location",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(var)|D(block)|D(member),
|
||||||
|
.var_type = V(any),
|
||||||
|
.if_mask = I(in)|I(out),
|
||||||
|
.stage_filter = C { "!compute", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "component",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(var)|D(member),
|
||||||
|
.var_type = V(any),
|
||||||
|
.if_mask = I(in)|I(out),
|
||||||
|
.stage_filter = C { "!compute", nullptr },
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "index",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(any),
|
||||||
|
.if_mask = I(out),
|
||||||
|
.stage_filter = C { "fragment", nullptr },
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "triangles",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "quads",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "isolines",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "equal_spacing",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "fractional_even_spacing",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "fractional_odd_spacing",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "cw",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "ccw",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "point_mode",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "tessellation evaluation", nullptr },
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "points",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in)|I(out),
|
||||||
|
.stage_filter = C { "geometry", nullptr },
|
||||||
|
},
|
||||||
|
//? [ points ] // q _ _ _ geom in
|
||||||
|
{ .name = "lines",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "geometry", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "lines_adjacency",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "geometry", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "triangles",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "geometry", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "triangles_adjacency",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "geometry", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "invocations",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "geometry", nullptr },
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "origin_upper_left",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "fragment", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "pixel_center_integer",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "fragment", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "early_fragment_tests",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "fragment", nullptr },
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "local_size_x",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "comp", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "local_size_y",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "comp", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "local_size_z",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "comp", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "local_size_x_id",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "comp", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "local_size_y_id",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "comp", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "local_size_z_id",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(in),
|
||||||
|
.stage_filter = C { "comp", nullptr },
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "xfb_buffer",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D_all,
|
||||||
|
.var_type = V(any),
|
||||||
|
.if_mask = I(out),
|
||||||
|
.stage_filter = C {
|
||||||
|
"vertex",
|
||||||
|
"tessellation control",
|
||||||
|
"tessellation evaluation",
|
||||||
|
"geometry",
|
||||||
|
nullptr
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ .name = "xfb_stride",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D_all,
|
||||||
|
.var_type = V(any),
|
||||||
|
.if_mask = I(out),
|
||||||
|
.stage_filter = C {
|
||||||
|
"vertex",
|
||||||
|
"tessellation control",
|
||||||
|
"tessellation evaluation",
|
||||||
|
"geometry",
|
||||||
|
nullptr
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ .name = "xfb_offset",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D_all,
|
||||||
|
.var_type = V(any),
|
||||||
|
.if_mask = I(out),
|
||||||
|
.stage_filter = C {
|
||||||
|
"vertex",
|
||||||
|
"tessellation control",
|
||||||
|
"tessellation evaluation",
|
||||||
|
"geometry",
|
||||||
|
nullptr
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "vertices",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(out),
|
||||||
|
.stage_filter = C { "tessellation control", nullptr },
|
||||||
|
},
|
||||||
|
|
||||||
|
//? [ points ] // q _ _ _ geom out
|
||||||
|
{ .name = "line_strip",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(out),
|
||||||
|
.stage_filter = C { "geometry", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "triangle_strip",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(out),
|
||||||
|
.stage_filter = C { "geometry", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "max_vertices",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(qual),
|
||||||
|
.if_mask = I(out),
|
||||||
|
.stage_filter = C { "geometry", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "stream",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D_all,
|
||||||
|
.var_type = V(any),
|
||||||
|
.if_mask = I(out),
|
||||||
|
.stage_filter = C { "geometry", nullptr },
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "depth_any",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(any),
|
||||||
|
.if_mask = I(out),
|
||||||
|
.stage_filter = C { "fragment", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "depth_greater",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(any),
|
||||||
|
.if_mask = I(out),
|
||||||
|
.stage_filter = C { "fragment", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "depth_less",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(any),
|
||||||
|
.if_mask = I(out),
|
||||||
|
.stage_filter = C { "fragment", nullptr },
|
||||||
|
},
|
||||||
|
{ .name = "depth_unchanged",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(any),
|
||||||
|
.if_mask = I(out),
|
||||||
|
.stage_filter = C { "fragment", nullptr },
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "constant_id",
|
||||||
|
.apply = E(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(scalar),
|
||||||
|
},
|
||||||
|
|
||||||
|
{ .name = "rgba32f",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rgba16f",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rg32f",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rg16f",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "r11f_g11f_b10f",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "r32f",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "r16f",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rgba16",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rgb10_a2",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rgba8",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rg16",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rg8",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "r16",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "r8",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rgba16_snorm",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rgba8_snorm",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rg16_snorm",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rg8_snorm",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "r16_snorm",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "r8_snorm",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rgba32i",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rgba16i",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rgba8i",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rg32i",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rg16i",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rg8i",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "r32i",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "r16i",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "r8i",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rgba32ui",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rgba16ui",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rgb10_a2ui",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rgba8ui",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rg32ui",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rg16ui",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "rg8ui",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "r32ui",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "r16ui",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
{ .name = "r8ui",
|
||||||
|
.apply = A(nullptr),
|
||||||
|
.obj_mask = D(var),
|
||||||
|
.var_type = V(image),
|
||||||
|
.if_mask = I(uniform),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
#undef A
|
||||||
|
#undef E
|
||||||
|
#undef D
|
||||||
|
#undef D_all
|
||||||
|
#undef V
|
||||||
|
#undef I
|
||||||
|
#undef C
|
||||||
|
#define num_quals (sizeof (layout_qualifiers) / sizeof (layout_qualifiers[0]))
|
||||||
|
#define layout_qual_sz num_quals, sizeof (layout_qual_t)
|
||||||
|
|
||||||
|
static int
|
||||||
|
layout_qual_cmp (const void *_a, const void *_b)
|
||||||
|
{
|
||||||
|
auto a = (const layout_qual_t *) _a;
|
||||||
|
auto b = (const layout_qual_t *) _b;
|
||||||
|
return strcasecmp (a->name, b->name);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
layout_check_qualifier (const layout_qual_t *qual, specifier_t spec)
|
||||||
|
{
|
||||||
|
unsigned obj_mask = 0;
|
||||||
|
glsl_var_t var_type = var_any;
|
||||||
|
unsigned if_mask = 0;
|
||||||
|
|
||||||
|
auto interface = glsl_iftype_from_sc (spec.storage);
|
||||||
|
if (interface < glsl_num_interfaces) {
|
||||||
|
if_mask = 1 << interface;
|
||||||
|
}
|
||||||
|
if (spec.sym) {
|
||||||
|
auto sym = spec.sym;
|
||||||
|
if (is_handle (sym->type)) {
|
||||||
|
var_type = var_opaque;
|
||||||
|
} else if (is_scalar (sym->type)) {
|
||||||
|
var_type = var_scalar;
|
||||||
|
} else if (strcmp (sym->name, "gl_FragCoord") == 0) {
|
||||||
|
var_type = var_gl_FragCoord;
|
||||||
|
} else if (strcmp (sym->name, "gl_FragDepth") == 0) {
|
||||||
|
var_type = var_gl_FragDepth;
|
||||||
|
}
|
||||||
|
obj_mask = decl_var;
|
||||||
|
if (sym->table->parent && sym->table->parent->type == stab_struct) {
|
||||||
|
obj_mask = decl_member;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
obj_mask = decl_qual;
|
||||||
|
}
|
||||||
|
if (!(qual->obj_mask & obj_mask)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (qual->var_type != var_type) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!(qual->if_mask & if_mask)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (qual->stage_filter) {
|
||||||
|
bool ok = false;
|
||||||
|
for (auto sf = qual->stage_filter; *sf; sf++) {
|
||||||
|
if (**sf == '!') {
|
||||||
|
if (strcmp (*sf + 1, glsl_sublang.name) == 0) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ok = true;
|
||||||
|
} else {
|
||||||
|
if (strcmp (*sf, glsl_sublang.name) == 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
layout_apply_qualifier (const expr_t *qualifier, specifier_t spec)
|
||||||
|
{
|
||||||
|
layout_qual_t key = {
|
||||||
|
.name = qualifier->type == ex_expr
|
||||||
|
? expr_string (qualifier->expr.e1)
|
||||||
|
: expr_string (qualifier)
|
||||||
|
};
|
||||||
|
auto val = qualifier->type == ex_expr
|
||||||
|
? qualifier->expr.e2
|
||||||
|
: nullptr;
|
||||||
|
|
||||||
|
notice (qualifier, "%s %p", key.name, spec.sym);
|
||||||
|
const layout_qual_t *qual;
|
||||||
|
qual = bsearch (&key, layout_qualifiers, layout_qual_sz, layout_qual_cmp);
|
||||||
|
if (!qual) {
|
||||||
|
error (0, "invalid layout qualifier: %s", key.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// there may be multiple entries with the same qualifier name, so find
|
||||||
|
// the first one
|
||||||
|
while (qual > layout_qualifiers && layout_qual_cmp (&key, qual - 1) == 0) {
|
||||||
|
qual--;
|
||||||
|
}
|
||||||
|
// check all matching entries
|
||||||
|
while (qual - layout_qualifiers < (ptrdiff_t) num_quals
|
||||||
|
&& layout_qual_cmp (&key, qual) == 0) {
|
||||||
|
if (layout_check_qualifier (qual, spec)) {
|
||||||
|
if (qual->apply_expr) {
|
||||||
|
if (!val) {
|
||||||
|
error (qualifier, "%s requires a value", key.name);
|
||||||
|
} else {
|
||||||
|
qual->apply_expr ();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else if (qual->apply) {
|
||||||
|
if (!val) {
|
||||||
|
error (qualifier, "%s does not take a value", key.name);
|
||||||
|
} else {
|
||||||
|
qual->apply ();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
error (0, "unsupported layout qualifier: %s", key.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
qual++;
|
||||||
|
}
|
||||||
|
error (0, "invalid layout qualifier: %s", key.name);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
glsl_layout (const ex_list_t *qualifiers, specifier_t spec)
|
||||||
|
{
|
||||||
|
if (!sorted_layout_qualifiers) {
|
||||||
|
heapsort (layout_qualifiers, layout_qual_sz, layout_qual_cmp);
|
||||||
|
}
|
||||||
|
for (auto q = qualifiers->head; q; q = q->next) {
|
||||||
|
layout_apply_qualifier (q->expr, spec);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue