Put interface blocks into the intrinsic maps, too
We now support cloning global variables that are "declared" by an InterfaceBlock, or a GlocalVarDeclaration. At this point, there are no "inherited" elements - any mutable data that starts out owned by the pre-includes is cloned. Follow-up will remove the inherited element list entirely - splitting this out to make the changes clearer. Bug: skia:10589 Change-Id: I2a95c73bf53db313e9f3467c681a05dffffeaa3a Reviewed-on: https://skia-review.googlesource.com/c/skia/+/323976 Reviewed-by: Ethan Nicholas <ethannicholas@google.com> Commit-Queue: Brian Osman <brianosman@google.com>
This commit is contained in:
parent
99aa05339d
commit
afa18eeb9a
@ -73,27 +73,30 @@ namespace SkSL {
|
||||
|
||||
static void grab_intrinsics(std::vector<std::unique_ptr<ProgramElement>>* src,
|
||||
IRIntrinsicMap* target) {
|
||||
for (auto iter = src->begin(); iter != src->end(); ) {
|
||||
std::unique_ptr<ProgramElement>& element = *iter;
|
||||
for (std::unique_ptr<ProgramElement>& element : *src) {
|
||||
switch (element->kind()) {
|
||||
case ProgramElement::Kind::kFunction: {
|
||||
FunctionDefinition& f = element->as<FunctionDefinition>();
|
||||
const FunctionDefinition& f = element->as<FunctionDefinition>();
|
||||
SkASSERT(f.fDeclaration.fBuiltin);
|
||||
target->insertOrDie(f.fDeclaration.description(), std::move(element));
|
||||
iter = src->erase(iter);
|
||||
break;
|
||||
}
|
||||
case ProgramElement::Kind::kEnum: {
|
||||
Enum& e = element->as<Enum>();
|
||||
const Enum& e = element->as<Enum>();
|
||||
SkASSERT(e.isBuiltin());
|
||||
target->insertOrDie(e.typeName(), std::move(element));
|
||||
iter = src->erase(iter);
|
||||
break;
|
||||
}
|
||||
case ProgramElement::Kind::kGlobalVar: {
|
||||
const GlobalVarDeclaration& vd = element->as<GlobalVarDeclaration>();
|
||||
const Variable* var = vd.fDecl->fVar;
|
||||
const Variable* var = element->as<GlobalVarDeclaration>().fDecl->fVar;
|
||||
SkASSERT(var->isBuiltin());
|
||||
target->insertOrDie(var->name(), std::move(element));
|
||||
break;
|
||||
}
|
||||
case ProgramElement::Kind::kInterfaceBlock: {
|
||||
const Variable* var = element->as<InterfaceBlock>().fVariable;
|
||||
SkASSERT(var->isBuiltin());
|
||||
target->insertOrDie(var->name(), std::move(element));
|
||||
iter = src->erase(iter);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@ -255,12 +258,13 @@ Compiler::Compiler(Flags flags)
|
||||
|
||||
fIRGenerator->fIntrinsics = nullptr;
|
||||
std::vector<std::unique_ptr<ProgramElement>> gpuElements;
|
||||
std::vector<std::unique_ptr<ProgramElement>> vertElements;
|
||||
std::vector<std::unique_ptr<ProgramElement>> fragElements;
|
||||
#if SKSL_STANDALONE
|
||||
this->processIncludeFile(Program::kFragment_Kind, SKSL_GPU_INCLUDE, fRootSymbolTable,
|
||||
&gpuElements, &fGpuSymbolTable);
|
||||
this->processIncludeFile(Program::kVertex_Kind, SKSL_VERT_INCLUDE, fGpuSymbolTable,
|
||||
&fVertexInclude, &fVertexSymbolTable);
|
||||
&vertElements, &fVertexSymbolTable);
|
||||
this->processIncludeFile(Program::kFragment_Kind, SKSL_FRAG_INCLUDE, fGpuSymbolTable,
|
||||
&fragElements, &fFragmentSymbolTable);
|
||||
#else
|
||||
@ -277,7 +281,7 @@ Compiler::Compiler(Flags flags)
|
||||
fGpuSymbolTable, this, SKSL_INCLUDE_sksl_vert,
|
||||
SKSL_INCLUDE_sksl_vert_LENGTH);
|
||||
fVertexSymbolTable = rehydrator.symbolTable();
|
||||
fVertexInclude = rehydrator.elements();
|
||||
vertElements = rehydrator.elements();
|
||||
fModifiers.push_back(fIRGenerator->releaseModifiers());
|
||||
}
|
||||
{
|
||||
@ -295,12 +299,15 @@ Compiler::Compiler(Flags flags)
|
||||
// actually use calls from inside the intrinsics, we will clone them into the program and they
|
||||
// will get new call counts.)
|
||||
reset_call_counts(&gpuElements);
|
||||
reset_call_counts(&fVertexInclude);
|
||||
reset_call_counts(&vertElements);
|
||||
reset_call_counts(&fragElements);
|
||||
|
||||
fGPUIntrinsics = std::make_unique<IRIntrinsicMap>(/*parent=*/nullptr);
|
||||
grab_intrinsics(&gpuElements, fGPUIntrinsics.get());
|
||||
|
||||
fVertexIntrinsics = std::make_unique<IRIntrinsicMap>(fGPUIntrinsics.get());
|
||||
grab_intrinsics(&vertElements, fVertexIntrinsics.get());
|
||||
|
||||
fFragmentIntrinsics = std::make_unique<IRIntrinsicMap>(fGPUIntrinsics.get());
|
||||
grab_intrinsics(&fragElements, fFragmentIntrinsics.get());
|
||||
}
|
||||
@ -311,19 +318,22 @@ void Compiler::loadGeometryIntrinsics() {
|
||||
if (fGeometrySymbolTable) {
|
||||
return;
|
||||
}
|
||||
fGeometryIntrinsics = std::make_unique<IRIntrinsicMap>(fGPUIntrinsics.get());
|
||||
std::vector<std::unique_ptr<ProgramElement>> geomElements;
|
||||
#if !SKSL_STANDALONE
|
||||
{
|
||||
Rehydrator rehydrator(&fIRGenerator->fContext, fIRGenerator->fModifiers.get(),
|
||||
fGpuSymbolTable, this, SKSL_INCLUDE_sksl_geom,
|
||||
SKSL_INCLUDE_sksl_geom_LENGTH);
|
||||
fGeometrySymbolTable = rehydrator.symbolTable();
|
||||
fGeometryInclude = rehydrator.elements();
|
||||
geomElements = rehydrator.elements();
|
||||
fModifiers.push_back(fIRGenerator->releaseModifiers());
|
||||
}
|
||||
#else
|
||||
this->processIncludeFile(Program::kGeometry_Kind, SKSL_GEOM_INCLUDE, fGpuSymbolTable,
|
||||
&fGeometryInclude, &fGeometrySymbolTable);
|
||||
&geomElements, &fGeometrySymbolTable);
|
||||
#endif
|
||||
grab_intrinsics(&geomElements, fGeometryIntrinsics.get());
|
||||
}
|
||||
|
||||
void Compiler::loadFPIntrinsics() {
|
||||
@ -1586,9 +1596,9 @@ std::unique_ptr<Program> Compiler::convertProgram(
|
||||
std::vector<std::unique_ptr<ProgramElement>> elements;
|
||||
switch (kind) {
|
||||
case Program::kVertex_Kind:
|
||||
inherited = &fVertexInclude;
|
||||
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
|
||||
fIRGenerator->start(&settings, fVertexSymbolTable, inherited);
|
||||
inherited = nullptr;
|
||||
fIRGenerator->fIntrinsics = fVertexIntrinsics.get();
|
||||
fIRGenerator->start(&settings, fVertexSymbolTable, /*inherited=*/nullptr);
|
||||
break;
|
||||
case Program::kFragment_Kind:
|
||||
inherited = nullptr;
|
||||
@ -1597,9 +1607,9 @@ std::unique_ptr<Program> Compiler::convertProgram(
|
||||
break;
|
||||
case Program::kGeometry_Kind:
|
||||
this->loadGeometryIntrinsics();
|
||||
inherited = &fGeometryInclude;
|
||||
fIRGenerator->fIntrinsics = fGPUIntrinsics.get();
|
||||
fIRGenerator->start(&settings, fGeometrySymbolTable, inherited);
|
||||
inherited = nullptr;
|
||||
fIRGenerator->fIntrinsics = fGeometryIntrinsics.get();
|
||||
fIRGenerator->start(&settings, fGeometrySymbolTable, /*inherited=*/nullptr);
|
||||
break;
|
||||
case Program::kFragmentProcessor_Kind:
|
||||
this->loadFPIntrinsics();
|
||||
|
@ -234,17 +234,18 @@ private:
|
||||
|
||||
std::shared_ptr<SymbolTable> fGpuSymbolTable;
|
||||
std::unique_ptr<IRIntrinsicMap> fGPUIntrinsics;
|
||||
|
||||
std::shared_ptr<SymbolTable> fInterpreterSymbolTable;
|
||||
std::unique_ptr<IRIntrinsicMap> fInterpreterIntrinsics;
|
||||
|
||||
std::vector<std::unique_ptr<ProgramElement>> fVertexInclude;
|
||||
std::shared_ptr<SymbolTable> fVertexSymbolTable;
|
||||
std::unique_ptr<IRIntrinsicMap> fVertexIntrinsics;
|
||||
|
||||
std::shared_ptr<SymbolTable> fFragmentSymbolTable;
|
||||
std::unique_ptr<IRIntrinsicMap> fFragmentIntrinsics;
|
||||
|
||||
std::vector<std::unique_ptr<ProgramElement>> fGeometryInclude;
|
||||
std::shared_ptr<SymbolTable> fGeometrySymbolTable;
|
||||
std::unique_ptr<IRIntrinsicMap> fGeometryIntrinsics;
|
||||
|
||||
std::shared_ptr<SymbolTable> fPipelineSymbolTable;
|
||||
std::unique_ptr<IRIntrinsicMap> fPipelineIntrinsics;
|
||||
|
@ -195,6 +195,12 @@ void IRGenerator::start(const Program::Settings* settings,
|
||||
}
|
||||
if (fIntrinsics) {
|
||||
fIntrinsics->resetAlreadyIncluded();
|
||||
if (!fSkPerVertex) {
|
||||
if (const ProgramElement* perVertexDecl = fIntrinsics->find(Compiler::PERVERTEX_NAME)) {
|
||||
SkASSERT(perVertexDecl->is<InterfaceBlock>());
|
||||
fSkPerVertex = perVertexDecl->as<InterfaceBlock>().fVariable;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -842,7 +848,7 @@ std::unique_ptr<Statement> IRGenerator::getNormalizeSkPositionCode() {
|
||||
#define FIELD(var, idx) std::unique_ptr<Expression>(\
|
||||
new FieldAccess(REF(var), idx, FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
|
||||
#define POS std::unique_ptr<Expression>(new FieldAccess(WREF(fSkPerVertex), 0, \
|
||||
FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
|
||||
FieldAccess::kAnonymousInterfaceBlock_OwnerKind))
|
||||
#define ADJUST (fRTAdjustInterfaceBlock ? \
|
||||
FIELD(fRTAdjustInterfaceBlock, fRTAdjustFieldIndex) : \
|
||||
REF(fRTAdjust))
|
||||
@ -2854,14 +2860,22 @@ void IRGenerator::cloneBuiltinVariables() {
|
||||
void cloneVariable(const String& name) {
|
||||
// If this is the *first* time we've seen this builtin, findAndInclude will return
|
||||
// the corresponding ProgramElement.
|
||||
if (const ProgramElement* sharedDecls =
|
||||
fGenerator->fIntrinsics->findAndInclude(name)) {
|
||||
SkASSERT(sharedDecls->is<GlobalVarDeclaration>());
|
||||
if (const ProgramElement* sharedDecl = fGenerator->fIntrinsics->findAndInclude(name)) {
|
||||
SkASSERT(sharedDecl->is<GlobalVarDeclaration>() ||
|
||||
sharedDecl->is<InterfaceBlock>());
|
||||
|
||||
// Clone the GlobalVarDeclaration ProgramElement that declares this variable
|
||||
std::unique_ptr<ProgramElement> clonedDecls = sharedDecls->clone();
|
||||
VarDeclaration& varDecl = *clonedDecls->as<GlobalVarDeclaration>().fDecl;
|
||||
const Variable* sharedVar = varDecl.fVar;
|
||||
// Clone the ProgramElement that declares this variable
|
||||
std::unique_ptr<ProgramElement> clonedDecl = sharedDecl->clone();
|
||||
const Variable* sharedVar = nullptr;
|
||||
const Expression* initialValue = nullptr;
|
||||
|
||||
if (clonedDecl->is<GlobalVarDeclaration>()) {
|
||||
sharedVar = clonedDecl->as<GlobalVarDeclaration>().fDecl->fVar;
|
||||
initialValue = clonedDecl->as<GlobalVarDeclaration>().fDecl->fValue.get();
|
||||
} else {
|
||||
SkASSERT(clonedDecl->is<InterfaceBlock>());
|
||||
sharedVar = clonedDecl->as<InterfaceBlock>().fVariable;
|
||||
}
|
||||
|
||||
// Now clone the Variable, and add the clone to the Program's symbol table.
|
||||
// Any initial value expression was cloned as part of the GlobalVarDeclaration,
|
||||
@ -2870,16 +2884,20 @@ void IRGenerator::cloneBuiltinVariables() {
|
||||
fGenerator->fSymbolTable->takeOwnershipOfSymbol(std::make_unique<Variable>(
|
||||
sharedVar->fOffset, sharedVar->modifiersHandle(), sharedVar->name(),
|
||||
&sharedVar->type(), /*builtin=*/false, sharedVar->storage(),
|
||||
varDecl.fValue.get()));
|
||||
initialValue));
|
||||
|
||||
// Go back and update the VarDeclaration to point at the cloned Variable.
|
||||
varDecl.fVar = clonedVar;
|
||||
// Go back and update the declaring element to point at the cloned Variable.
|
||||
if (clonedDecl->is<GlobalVarDeclaration>()) {
|
||||
clonedDecl->as<GlobalVarDeclaration>().fDecl->fVar = clonedVar;
|
||||
} else {
|
||||
clonedDecl->as<InterfaceBlock>().fVariable = clonedVar;
|
||||
}
|
||||
|
||||
// Remember this new re-mapping...
|
||||
fRemap.insert({sharedVar, clonedVar});
|
||||
|
||||
// Add the GlobalVarDeclaration to this Program
|
||||
fNewElements.push_back(std::move(clonedDecls));
|
||||
// Add the declaring element to this Program
|
||||
fNewElements.push_back(std::move(clonedDecl));
|
||||
}
|
||||
}
|
||||
|
||||
@ -2925,8 +2943,8 @@ void IRGenerator::cloneBuiltinVariables() {
|
||||
}
|
||||
|
||||
fProgramElements->insert(fProgramElements->begin(),
|
||||
std::make_move_iterator(remapper.fNewElements.begin()),
|
||||
std::make_move_iterator(remapper.fNewElements.end()));
|
||||
std::make_move_iterator(remapper.fNewElements.begin()),
|
||||
std::make_move_iterator(remapper.fNewElements.end()));
|
||||
}
|
||||
|
||||
void IRGenerator::convertProgram(Program::Kind kind,
|
||||
|
@ -48,6 +48,14 @@ public:
|
||||
fIntrinsics[key] = Intrinsic{std::move(element), false};
|
||||
}
|
||||
|
||||
const ProgramElement* find(const String& key) {
|
||||
auto iter = fIntrinsics.find(key);
|
||||
if (iter == fIntrinsics.end()) {
|
||||
return fParent ? fParent->find(key) : nullptr;
|
||||
}
|
||||
return iter->second.fIntrinsic.get();
|
||||
}
|
||||
|
||||
// Only returns an intrinsic that isn't already marked as included, and then marks it.
|
||||
const ProgramElement* findAndInclude(const String& key) {
|
||||
auto iter = fIntrinsics.find(key);
|
||||
|
@ -35,7 +35,7 @@ public:
|
||||
};
|
||||
|
||||
Variable(int offset, ModifiersPool::Handle modifiers, StringFragment name, const Type* type,
|
||||
bool builtin, Storage storage, Expression* initialValue = nullptr)
|
||||
bool builtin, Storage storage, const Expression* initialValue = nullptr)
|
||||
: INHERITED(offset, VariableData{name, type, initialValue, modifiers, /*readCount=*/0,
|
||||
/*writeCount=*/(int16_t) (initialValue ? 1 : 0),
|
||||
(int8_t) storage, builtin}) {}
|
||||
|
Loading…
Reference in New Issue
Block a user