Skip to content

Commit 948b935

Browse files
implement support for all interface block types
1 parent 31db1e1 commit 948b935

File tree

7 files changed

+203
-19
lines changed

7 files changed

+203
-19
lines changed

ast.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,13 @@ astStruct::astStruct()
3737
{
3838
}
3939

40+
astInterfaceBlock::astInterfaceBlock()
41+
: astType(false)
42+
, name(0)
43+
, storage(0)
44+
{
45+
}
46+
4047
astBuiltin::astBuiltin(int type)
4148
: astType(true)
4249
, type(type)

ast.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ struct astExpression;
4545
struct astLayoutQualifier;
4646
struct astStatement;
4747
struct astStruct;
48+
struct astInterfaceBlock;
4849
struct astVariable;
4950

5051
struct astTU {
@@ -62,6 +63,7 @@ struct astTU {
6263
vector<astFunction*> functions;
6364
vector<astGlobalVariable*> globals;
6465
vector<astStruct*> structures;
66+
vector<astInterfaceBlock*> interfaceBlocks;
6567

6668
int type;
6769

@@ -86,6 +88,13 @@ struct astStruct : astType {
8688
vector<astVariable*> fields;
8789
};
8890

91+
struct astInterfaceBlock : astType {
92+
astInterfaceBlock();
93+
char *name;
94+
int storage; // one of the storage qualifiers: kIn, kOut, kUniform, kBuffer
95+
vector<astVariable*> fields;
96+
};
97+
8998
typedef astExpression astConstantExpression;
9099

91100
enum {

main.cpp

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -578,9 +578,22 @@ static void printStructure(astStruct *structure) {
578578
print("};\n");
579579
}
580580

581+
static void printInterfaceBlock(astInterfaceBlock *block) {
582+
printStorage(block->storage);
583+
printf("%s ", block->name);
584+
printf("{\n");
585+
for (size_t i = 0; i < block->fields.size(); i++) {
586+
printVariable(block->fields[i]);
587+
print(";\n");
588+
}
589+
printf("};\n");
590+
}
591+
581592
static void printTU(astTU *tu) {
582593
for (size_t i = 0; i < tu->structures.size(); i++)
583594
printStructure(tu->structures[i]);
595+
for (size_t i = 0; i < tu->interfaceBlocks.size(); i++)
596+
printInterfaceBlock(tu->interfaceBlocks[i]);
584597
for (size_t i = 0; i < tu->globals.size(); i++)
585598
printGlobalVariable(tu->globals[i]);
586599
for (size_t i = 0; i < tu->functions.size(); i++)

parser.cpp

Lines changed: 131 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -592,6 +592,55 @@ CHECK_RETURN bool parser::parseLayout(topLevel &current) {
592592
return true;
593593
}
594594

595+
static bool isInterfaceBlockStorage(int storage) {
596+
return storage == kIn
597+
|| storage == kOut
598+
|| storage == kUniform
599+
|| storage == kBuffer;
600+
}
601+
602+
static bool isReservedKeyword(int keyword) {
603+
return keyword == kKeyword_common
604+
|| keyword == kKeyword_partition
605+
|| keyword == kKeyword_active
606+
|| keyword == kKeyword_asm
607+
|| keyword == kKeyword_class
608+
|| keyword == kKeyword_union
609+
|| keyword == kKeyword_enum
610+
|| keyword == kKeyword_typedef
611+
|| keyword == kKeyword_template
612+
|| keyword == kKeyword_this
613+
|| keyword == kKeyword_resource
614+
|| keyword == kKeyword_goto
615+
|| keyword == kKeyword_inline
616+
|| keyword == kKeyword_noinline
617+
|| keyword == kKeyword_public
618+
|| keyword == kKeyword_static
619+
|| keyword == kKeyword_extern
620+
|| keyword == kKeyword_external
621+
|| keyword == kKeyword_interface
622+
|| keyword == kKeyword_long
623+
|| keyword == kKeyword_short
624+
|| keyword == kKeyword_half
625+
|| keyword == kKeyword_fixed
626+
|| keyword == kKeyword_unsigned
627+
|| keyword == kKeyword_superp
628+
|| keyword == kKeyword_input
629+
|| keyword == kKeyword_output
630+
|| keyword == kKeyword_hvec2
631+
|| keyword == kKeyword_hvec3
632+
|| keyword == kKeyword_hvec4
633+
|| keyword == kKeyword_fvec2
634+
|| keyword == kKeyword_fvec3
635+
|| keyword == kKeyword_fvec4
636+
|| keyword == kKeyword_sampler3DRect
637+
|| keyword == kKeyword_filter
638+
|| keyword == kKeyword_sizeof
639+
|| keyword == kKeyword_cast
640+
|| keyword == kKeyword_namespace
641+
|| keyword == kKeyword_using;
642+
}
643+
595644
CHECK_RETURN bool parser::parseTopLevelItem(topLevel &level, topLevel *continuation) {
596645
vector<topLevel> items;
597646
while (!isBuiltin() && !isType(kType_identifier)) {
@@ -600,20 +649,38 @@ CHECK_RETURN bool parser::parseTopLevelItem(topLevel &level, topLevel *continuat
600649
if (IS_TYPE(peek, kType_eof))
601650
return false;
602651

603-
topLevel next;
652+
topLevel item;
604653
if (continuation)
605-
next = *continuation;
606-
607-
if (!parseStorage(next)) return false;
608-
if (!parseAuxiliary(next)) return false;
609-
if (!parseInterpolation(next)) return false;
610-
if (!parsePrecision(next)) return false;
611-
if (!parseInvariant(next)) return false;
612-
if (!parsePrecise(next)) return false;
613-
if (!parseMemory(next)) return false;
614-
if (!parseLayout(next)) return false;
615-
616-
if (isKeyword(kKeyword_struct)) {
654+
item = *continuation;
655+
656+
if (!parseStorage(item)) return false;
657+
if (!parseAuxiliary(item)) return false;
658+
if (!parseInterpolation(item)) return false;
659+
if (!parsePrecision(item)) return false;
660+
if (!parseInvariant(item)) return false;
661+
if (!parsePrecise(item)) return false;
662+
if (!parseMemory(item)) return false;
663+
if (!parseLayout(item)) return false;
664+
665+
if (isType(kType_keyword) && isReservedKeyword(m_token.asKeyword)) {
666+
fatal("cannot use a reserved keyword");
667+
return false;
668+
}
669+
670+
// Check for interface block.
671+
if (isType(kType_identifier) && isInterfaceBlockStorage(item.storage)) {
672+
// if (!next()) return false; // skip identifier
673+
astInterfaceBlock *unique = parseInterfaceBlock(item.storage);
674+
if (!unique)
675+
return false;
676+
m_ast->interfaceBlocks.push_back(unique);
677+
if (isType(kType_semicolon)) {
678+
return true;
679+
} else {
680+
level.type = unique;
681+
}
682+
} else if (isKeyword(kKeyword_struct)) {
683+
if (!next()) return 0; // skip struct
617684
astStruct *unique = parseStruct();
618685
if (!unique)
619686
return false;
@@ -625,7 +692,7 @@ CHECK_RETURN bool parser::parseTopLevelItem(topLevel &level, topLevel *continuat
625692
level.type = unique;
626693
}
627694
} else {
628-
items.push_back(next);
695+
items.push_back(item);
629696
}
630697
}
631698

@@ -811,18 +878,17 @@ CHECK_RETURN bool parser::parseTopLevel(vector<topLevel> &items) {
811878
return true;
812879
}
813880

814-
CHECK_RETURN astStruct *parser::parseStruct() {
815-
if (!next()) return 0; // skip struct
816-
817-
astStruct *unique = GC_NEW(astType) astStruct;
881+
template<typename T>
882+
CHECK_RETURN T *parser::parseBlock(const char* type) {
883+
T *unique = GC_NEW(astType) T;
818884

819885
if (isType(kType_identifier)) {
820886
unique->name = strnew(m_token.asIdentifier);
821887
if (!next()) return 0; // skip identifier
822888
}
823889

824890
if (!isType(kType_scope_begin)) {
825-
fatal("expected '{' for structure definition");
891+
fatal("expected '{' for %s definition", type);
826892
return 0;
827893
}
828894

@@ -852,6 +918,52 @@ CHECK_RETURN astStruct *parser::parseStruct() {
852918
return unique;
853919
}
854920

921+
CHECK_RETURN astStruct *parser::parseStruct() {
922+
return parseBlock<astStruct>("structure");
923+
}
924+
925+
CHECK_RETURN astInterfaceBlock *parser::parseInterfaceBlock(int storage) {
926+
astInterfaceBlock* unique = 0;
927+
switch (storage) {
928+
case kIn:
929+
unique = parseBlock<astInterfaceBlock>("input block");
930+
break;
931+
case kOut:
932+
unique = parseBlock<astInterfaceBlock>("outout block");
933+
break;
934+
case kUniform:
935+
unique = parseBlock<astInterfaceBlock>("uniform block");
936+
break;
937+
case kBuffer:
938+
unique = parseBlock<astInterfaceBlock>("buffer block");
939+
break;
940+
}
941+
942+
if (!unique) {
943+
return 0;
944+
}
945+
946+
// When there's no identifier then implicitly declare these as globals
947+
// in their respective places.
948+
if (!isType(kType_identifier)) {
949+
const size_t n_fields = unique->fields.size();
950+
for (size_t i = 0; i < n_fields; i++) {
951+
// Check if the variable already exists
952+
astVariable *variable = unique->fields[i];
953+
if (findVariable(variable->name)) {
954+
fatal("'%s` is already declared in this scope", variable->name);
955+
return 0;
956+
}
957+
m_scopes.back().push_back(unique->fields[i]);
958+
}
959+
}
960+
961+
unique->storage = storage;
962+
return unique;
963+
964+
return 0;
965+
}
966+
855967
CHECK_RETURN astExpression *parser::parseBinary(int lhsPrecedence, astExpression *lhs, endCondition end) {
856968
// Precedence climbing
857969
while (!isEndCondition(end)) {

parser.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ struct parser {
9696
// Type parsers
9797
astBuiltin *parseBuiltin();
9898
astStruct *parseStruct();
99+
astInterfaceBlock *parseInterfaceBlock(int storage);
99100

100101
CHECK_RETURN astFunction *parseFunction(const topLevel &parse);
101102

@@ -135,6 +136,10 @@ struct parser {
135136
private:
136137
typedef vector<astVariable *> scope;
137138

139+
// Specialized in .cpp
140+
template<typename T>
141+
CHECK_RETURN T *parseBlock(const char* type);
142+
138143
astTU *m_ast;
139144
lexer m_lexer;
140145
token m_token;

tests/interface_blocks.glsl

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
uniform uniform_block { float x; };
2+
in input_block { float y; };
3+
out output_block { float z; };
4+
buffer buffer_block { float w; };
5+
6+
// same thing with instance names
7+
uniform uniform_block { float x; } uniform_data;
8+
in input_block { float y; } input_data;
9+
out output_block { float z; } output_data;
10+
buffer buffer_block { float w; } buffer_data;

tests/interface_blocks.test

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
uniform uniform_block {
2+
float x;
3+
};
4+
in input_block {
5+
float y;
6+
};
7+
out output_block {
8+
float z;
9+
};
10+
buffer buffer_block {
11+
float w;
12+
};
13+
uniform uniform_block {
14+
float x;
15+
};
16+
in input_block {
17+
float y;
18+
};
19+
out output_block {
20+
float z;
21+
};
22+
buffer buffer_block {
23+
float w;
24+
};
25+
uniform_block uniform_data;
26+
input_block input_data;
27+
output_block output_data;
28+
buffer_block buffer_data;

0 commit comments

Comments
 (0)