Commit a35d8232 by Alexis Hetu Committed by Alexis Hétu

Adding Interface Blocks to glsl parser

Added code to parse interface blocks and the corresponding layout qualifiers to the glsl parser. Change-Id: Idfcbf08f3f877ea9641ae611e6bddd2be1ffb952 Reviewed-on: https://swiftshader-review.googlesource.com/3480Tested-by: 's avatarAlexis Hétu <sugoi@google.com> Reviewed-by: 's avatarNicolas Capens <capn@google.com>
parent 0085c440
......@@ -1762,6 +1762,42 @@ TIntermAggregate *TParseContext::parseArrayInitDeclarator(const TPublicType &pub
}
}
void TParseContext::parseGlobalLayoutQualifier(const TPublicType &typeQualifier)
{
if(shaderVersion < 300)
{
error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 only", "layout");
recover();
return;
}
if(typeQualifier.qualifier != EvqUniform)
{
error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "global layout must be uniform");
recover();
return;
}
const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
ASSERT(!layoutQualifier.isEmpty());
if(layoutLocationErrorCheck(typeQualifier.line, typeQualifier.layoutQualifier))
{
recover();
return;
}
if(layoutQualifier.matrixPacking != EmpUnspecified)
{
defaultMatrixPacking = layoutQualifier.matrixPacking;
}
if(layoutQualifier.blockStorage != EbsUnspecified)
{
defaultBlockStorage = layoutQualifier.blockStorage;
}
}
// This function is used to test for the correctness of the parameters passed to various constructor functions
// and also convert them to the right datatype if it is allowed and required.
//
......@@ -1981,6 +2017,146 @@ TIntermTyped* TParseContext::addConstStruct(const TString& identifier, TIntermTy
}
//
// Interface/uniform blocks
//
TIntermAggregate* TParseContext::addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList,
const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine)
{
if(reservedErrorCheck(nameLine, blockName))
recover();
if(typeQualifier.qualifier != EvqUniform)
{
error(typeQualifier.line, "invalid qualifier:", getQualifierString(typeQualifier.qualifier), "interface blocks must be uniform");
recover();
}
TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
if(layoutLocationErrorCheck(typeQualifier.line, blockLayoutQualifier))
{
recover();
}
if(blockLayoutQualifier.matrixPacking == EmpUnspecified)
{
blockLayoutQualifier.matrixPacking = defaultMatrixPacking;
}
if(blockLayoutQualifier.blockStorage == EbsUnspecified)
{
blockLayoutQualifier.blockStorage = defaultBlockStorage;
}
TSymbol* blockNameSymbol = new TSymbol(&blockName);
if(!symbolTable.declare(*blockNameSymbol)) {
error(nameLine, "redefinition", blockName.c_str(), "interface block name");
recover();
}
// check for sampler types and apply layout qualifiers
for(size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex) {
TField* field = (*fieldList)[memberIndex];
TType* fieldType = field->type();
if(IsSampler(fieldType->getBasicType())) {
error(field->line(), "unsupported type", fieldType->getBasicString(), "sampler types are not allowed in interface blocks");
recover();
}
const TQualifier qualifier = fieldType->getQualifier();
switch(qualifier)
{
case EvqGlobal:
case EvqUniform:
break;
default:
error(field->line(), "invalid qualifier on interface block member", getQualifierString(qualifier));
recover();
break;
}
// check layout qualifiers
TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
if(layoutLocationErrorCheck(field->line(), fieldLayoutQualifier))
{
recover();
}
if(fieldLayoutQualifier.blockStorage != EbsUnspecified)
{
error(field->line(), "invalid layout qualifier:", getBlockStorageString(fieldLayoutQualifier.blockStorage), "cannot be used here");
recover();
}
if(fieldLayoutQualifier.matrixPacking == EmpUnspecified)
{
fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
}
else if(!fieldType->isMatrix())
{
error(field->line(), "invalid layout qualifier:", getMatrixPackingString(fieldLayoutQualifier.matrixPacking), "can only be used on matrix types");
recover();
}
fieldType->setLayoutQualifier(fieldLayoutQualifier);
}
// add array index
int arraySize = 0;
if(arrayIndex != NULL)
{
if(arraySizeErrorCheck(arrayIndexLine, arrayIndex, arraySize))
recover();
}
TInterfaceBlock* interfaceBlock = new TInterfaceBlock(&blockName, fieldList, instanceName, arraySize, blockLayoutQualifier);
TType interfaceBlockType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier, arraySize);
TString symbolName = "";
int symbolId = 0;
if(!instanceName)
{
// define symbols for the members of the interface block
for(size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
{
TField* field = (*fieldList)[memberIndex];
TType* fieldType = field->type();
// set parent pointer of the field variable
fieldType->setInterfaceBlock(interfaceBlock);
TVariable* fieldVariable = new TVariable(&field->name(), *fieldType);
fieldVariable->setQualifier(typeQualifier.qualifier);
if(!symbolTable.declare(*fieldVariable)) {
error(field->line(), "redefinition", field->name().c_str(), "interface block member name");
recover();
}
}
}
else
{
// add a symbol for this interface block
TVariable* instanceTypeDef = new TVariable(instanceName, interfaceBlockType, false);
instanceTypeDef->setQualifier(typeQualifier.qualifier);
if(!symbolTable.declare(*instanceTypeDef)) {
error(instanceLine, "redefinition", instanceName->c_str(), "interface block instance name");
recover();
}
symbolId = instanceTypeDef->getUniqueId();
symbolName = instanceTypeDef->getName();
}
TIntermAggregate *aggregate = intermediate.makeAggregate(intermediate.addSymbol(symbolId, symbolName, interfaceBlockType, typeQualifier.line), nameLine);
aggregate->setOp(EOpDeclaration);
exitStructDeclaration();
return aggregate;
}
//
// Parse an array index expression
//
TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression, const TSourceLoc &location, TIntermTyped *indexExpression)
......
......@@ -160,6 +160,7 @@ struct TParseContext {
const TString &identifier, const TSourceLoc &indexLocation, TIntermTyped *indexExpression,
const TSourceLoc &initLocation, TIntermTyped *initializer);
void parseGlobalLayoutQualifier(const TPublicType &typeQualifier);
TIntermTyped* addConstructor(TIntermNode*, const TType*, TOperator, TFunction*, TSourceLoc);
TIntermTyped* foldConstConstructor(TIntermAggregate* aggrNode, const TType& type);
TIntermTyped* addConstVectorNode(TVectorFields&, TIntermTyped*, TSourceLoc);
......@@ -172,6 +173,9 @@ struct TParseContext {
TFieldList *addStructDeclaratorList(const TPublicType &typeSpecifier, TFieldList *fieldList);
TPublicType addStructure(const TSourceLoc &structLine, const TSourceLoc &nameLine, const TString *structName, TFieldList *fieldList);
TIntermAggregate* addInterfaceBlock(const TPublicType& typeQualifier, const TSourceLoc& nameLine, const TString& blockName, TFieldList* fieldList,
const TString* instanceName, const TSourceLoc& instanceLine, TIntermTyped* arrayIndex, const TSourceLoc& arrayIndexLine);
TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine);
TLayoutQualifier parseLayoutQualifier(const TString &qualifierType, const TSourceLoc& qualifierTypeLine, const TString &intValueString, int intValue, const TSourceLoc& intValueLine);
TLayoutQualifier joinLayoutQualifiers(TLayoutQualifier leftQualifier, TLayoutQualifier rightQualifier);
......
......@@ -183,6 +183,8 @@ extern void yyerror(TParseContext* context, const char* reason);
%type <interm> function_call_header_with_parameters function_call_header_no_parameters function_call_generic function_prototype
%type <interm> function_call_or_method
%type <lex> enter_struct
%start translation_unit
%%
......@@ -888,6 +890,14 @@ constant_expression
}
;
enter_struct
: IDENTIFIER LEFT_BRACE {
if (context->enterStructDeclaration($1.line, *$1.string))
context->recover();
$$ = $1;
}
;
declaration
: function_prototype SEMICOLON {
TFunction &function = *($1.function);
......@@ -929,6 +939,22 @@ declaration
}
$$ = 0;
}
| type_qualifier enter_struct struct_declaration_list RIGHT_BRACE SEMICOLON {
ES3_ONLY(getQualifierString($1.qualifier), $1.line);
$$ = context->addInterfaceBlock($1, $2.line, *$2.string, $3, NULL, $1.line, NULL, $1.line);
}
| type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER SEMICOLON {
ES3_ONLY(getQualifierString($1.qualifier), $1.line);
$$ = context->addInterfaceBlock($1, $2.line, *$2.string, $3, $5.string, $5.line, NULL, $1.line);
}
| type_qualifier enter_struct struct_declaration_list RIGHT_BRACE IDENTIFIER LEFT_BRACKET constant_expression RIGHT_BRACKET SEMICOLON {
ES3_ONLY(getQualifierString($1.qualifier), $1.line);
$$ = context->addInterfaceBlock($1, $2.line, *$2.string, $3, $5.string, $5.line, $7, $6.line);
}
| type_qualifier SEMICOLON {
context->parseGlobalLayoutQualifier($1);
$$ = 0;
}
;
function_prototype
......
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment