// fully_specified_type // : type_specifier // | type_qualifier type_specifier // bool HlslGrammar::acceptFullySpecifiedType(TType& type) { // type_qualifier TQualifier qualifier; qualifier.clear(); acceptQualifier(qualifier); // type_specifier if (! acceptType(type)) return false; type.getQualifier() = qualifier; return true; }
// Accumulate locations used for inputs, outputs, and uniforms, and check for collisions // as the accumulation is done. // // Returns < 0 if no collision, >= 0 if collision and the value returned is a colliding value. // // typeCollision is set to true if there is no direct collision, but the types in the same location // are different. // int TIntermediate::addUsedLocation(const TQualifier& qualifier, const TType& type, bool& typeCollision) { typeCollision = false; int set; if (qualifier.isPipeInput()) set = 0; else if (qualifier.isPipeOutput()) set = 1; else if (qualifier.storage == EvqUniform) set = 2; else if (qualifier.storage == EvqBuffer) set = 3; else return -1; int size; if (qualifier.isUniformOrBuffer()) { if (type.isArray()) size = type.getCumulativeArraySize(); else size = 1; } else { // Strip off the outer array dimension for those having an extra one. if (type.isArray() && qualifier.isArrayedIo(language)) { TType elementType(type, 0); size = computeTypeLocationSize(elementType); } else size = computeTypeLocationSize(type); } TRange locationRange(qualifier.layoutLocation, qualifier.layoutLocation + size - 1); TRange componentRange(0, 3); if (qualifier.hasComponent()) { componentRange.start = qualifier.layoutComponent; componentRange.last = componentRange.start + type.getVectorSize() - 1; } TIoRange range(locationRange, componentRange, type.getBasicType(), qualifier.hasIndex() ? qualifier.layoutIndex : 0); // check for collisions, except for vertex inputs on desktop if (! (profile != EEsProfile && language == EShLangVertex && qualifier.isPipeInput())) { for (size_t r = 0; r < usedIo[set].size(); ++r) { if (range.overlap(usedIo[set][r])) { // there is a collision; pick one return std::max(locationRange.start, usedIo[set][r].location.start); } else if (locationRange.overlap(usedIo[set][r].location) && type.getBasicType() != usedIo[set][r].basicType) { // aliased-type mismatch typeCollision = true; return std::max(locationRange.start, usedIo[set][r].location.start); } } } usedIo[set].push_back(range); return -1; // no collision }
// // Make the passed-in variable information become a member of the // global uniform block. If this doesn't exist yet, make it. // void TParseContextBase::growGlobalUniformBlock(TSourceLoc& loc, TType& memberType, TString& memberName) { // make the global block, if not yet made if (globalUniformBlock == nullptr) { TString& blockName = *NewPoolTString(getGlobalUniformBlockName()); TQualifier blockQualifier; blockQualifier.clear(); blockQualifier.storage = EvqUniform; TType blockType(new TTypeList, blockName, blockQualifier); TString* instanceName = NewPoolTString(""); globalUniformBlock = new TVariable(instanceName, blockType, true); firstNewMember = 0; } // add the requested member as a member to the block TType* type = new TType; type->shallowCopy(memberType); type->setFieldName(memberName); TTypeLoc typeLoc = {type, loc}; globalUniformBlock->getType().getWritableStruct()->push_back(typeLoc); }
// // Make the passed-in variable information become a member of the // global uniform block. If this doesn't exist yet, make it. // void TParseContextBase::growGlobalUniformBlock(const TSourceLoc& loc, TType& memberType, const TString& memberName, TTypeList* typeList) { // Make the global block, if not yet made. if (globalUniformBlock == nullptr) { TQualifier blockQualifier; blockQualifier.clear(); blockQualifier.storage = EvqUniform; TType blockType(new TTypeList, *NewPoolTString(getGlobalUniformBlockName()), blockQualifier); setUniformBlockDefaults(blockType); globalUniformBlock = new TVariable(NewPoolTString(""), blockType, true); firstNewMember = 0; } // Update with binding and set globalUniformBlock->getWritableType().getQualifier().layoutBinding = globalUniformBinding; globalUniformBlock->getWritableType().getQualifier().layoutSet = globalUniformSet; // Add the requested member as a member to the global block. TType* type = new TType; type->shallowCopy(memberType); type->setFieldName(memberName); if (typeList) type->setStruct(typeList); TTypeLoc typeLoc = {type, loc}; globalUniformBlock->getType().getWritableStruct()->push_back(typeLoc); // Insert into the symbol table. if (firstNewMember == 0) { // This is the first request; we need a normal symbol table insert if (symbolTable.insert(*globalUniformBlock)) trackLinkage(*globalUniformBlock); else error(loc, "failed to insert the global constant buffer", "uniform", ""); } else { // This is a follow-on request; we need to amend the first insert symbolTable.amend(*globalUniformBlock, firstNewMember); } ++firstNewMember; }