From 9f67845661a0c56ea1ab21429800e710075ae00c Mon Sep 17 00:00:00 2001 From: John Stiles Date: Thu, 3 Mar 2022 22:25:55 -0500 Subject: [PATCH] Use SkTHashMap/Set in the SPIRVCodeGenerator. Change-Id: Iffc3b1febeae0c29d4c24a483f6c05a01ef363d7 Reviewed-on: https://skia-review.googlesource.com/c/skia/+/515716 Auto-Submit: John Stiles Reviewed-by: Ethan Nicholas Commit-Queue: Ethan Nicholas --- src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp | 141 ++++++++++---------- src/sksl/codegen/SkSLSPIRVCodeGenerator.h | 53 +++----- 2 files changed, 91 insertions(+), 103 deletions(-) diff --git a/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp b/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp index 80dfee3b17..72dd5dbad3 100644 --- a/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp +++ b/src/sksl/codegen/SkSLSPIRVCodeGenerator.cpp @@ -569,11 +569,11 @@ SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layou ? MemoryLayout::Standard::k430_Standard : MemoryLayout::Standard::k140_Standard; std::string otherKey = type->displayName() + std::to_string(otherStd); - SkASSERT(fTypeMap.find(otherKey) == fTypeMap.end()); + SkASSERT(!fTypeMap.find(otherKey)); #endif } - auto entry = fTypeMap.find(key); - if (entry == fTypeMap.end()) { + SpvId* entry = fTypeMap.find(key); + if (!entry) { SpvId result = this->nextId(nullptr); switch (type->typeKind()) { case Type::TypeKind::kScalar: @@ -669,7 +669,7 @@ SpvId SPIRVCodeGenerator::getType(const Type& rawType, const MemoryLayout& layou fTypeMap[key] = result; return result; } - return entry->second; + return *entry; } SpvId SPIRVCodeGenerator::getFunctionType(const FunctionDeclaration& function) { @@ -682,8 +682,8 @@ SpvId SPIRVCodeGenerator::getFunctionType(const FunctionDeclaration& function) { key += std::to_string(this->getType(parameters[i]->type())); } key += ")"; - auto entry = fTypeMap.find(key); - if (entry == fTypeMap.end()) { + SpvId* entry = fTypeMap.find(key); + if (!entry) { SpvId result = this->nextId(nullptr); int32_t length = 3 + (int32_t) parameters.size(); SpvId returnType = this->getType(function.returnType()); @@ -720,10 +720,10 @@ SpvId SPIRVCodeGenerator::getFunctionType(const FunctionDeclaration& function) { for (SpvId id : parameterTypes) { this->writeWord(id, fConstantBuffer); } - fTypeMap[key] = result; + fTypeMap.set(key, result); return result; } - return entry->second; + return *entry; } SpvId SPIRVCodeGenerator::getPointerType(const Type& type, SpvStorageClass_ storageClass) { @@ -735,15 +735,15 @@ SpvId SPIRVCodeGenerator::getPointerType(const Type& rawType, const MemoryLayout const Type& type = this->getActualType(rawType); std::string key = type.displayName() + "*" + std::to_string(layout.fStd) + std::to_string(storageClass); - auto entry = fTypeMap.find(key); - if (entry == fTypeMap.end()) { + SpvId* entry = fTypeMap.find(key); + if (!entry) { SpvId result = this->nextId(nullptr); this->writeInstruction(SpvOpTypePointer, result, storageClass, this->getType(type), fConstantBuffer); - fTypeMap[key] = result; + fTypeMap.set(key, result); return result; } - return entry->second; + return *entry; } SpvId SPIRVCodeGenerator::writeExpression(const Expression& expr, OutputStream& out) { @@ -794,27 +794,26 @@ SpvId SPIRVCodeGenerator::writeExpression(const Expression& expr, OutputStream& SpvId SPIRVCodeGenerator::writeIntrinsicCall(const FunctionCall& c, OutputStream& out) { const FunctionDeclaration& function = c.function(); - auto iter = fIntrinsicMap.find(function.intrinsicKind()); - if (iter == fIntrinsicMap.end()) { + Intrinsic* intrinsic = fIntrinsicMap.find(function.intrinsicKind()); + if (!intrinsic) { fContext.fErrors->error(c.fLine, "unsupported intrinsic '" + function.description() + "'"); return -1; } const ExpressionArray& arguments = c.arguments(); - const Intrinsic& intrinsic = iter->second; - int32_t intrinsicId = intrinsic.floatOp; + int32_t intrinsicId = intrinsic->floatOp; if (arguments.size() > 0) { const Type& type = arguments[0]->type(); - if (intrinsic.opKind == kSpecial_IntrinsicOpcodeKind || is_float(fContext, type)) { + if (intrinsic->opKind == kSpecial_IntrinsicOpcodeKind || is_float(fContext, type)) { // Keep the default float op. } else if (is_signed(fContext, type)) { - intrinsicId = intrinsic.signedOp; + intrinsicId = intrinsic->signedOp; } else if (is_unsigned(fContext, type)) { - intrinsicId = intrinsic.unsignedOp; + intrinsicId = intrinsic->unsignedOp; } else if (is_bool(fContext, type)) { - intrinsicId = intrinsic.boolOp; + intrinsicId = intrinsic->boolOp; } } - switch (intrinsic.opKind) { + switch (intrinsic->opKind) { case kGLSL_STD_450_IntrinsicOpcodeKind: { SpvId result = this->nextId(&c.type()); std::vector argumentIds; @@ -1219,8 +1218,8 @@ SpvId SPIRVCodeGenerator::writeFunctionCall(const FunctionCall& c, OutputStream& return this->writeIntrinsicCall(c, out); } const ExpressionArray& arguments = c.arguments(); - const auto& entry = fFunctionMap.find(&function); - if (entry == fFunctionMap.end()) { + SpvId* entry = fFunctionMap.find(&function); + if (!entry) { fContext.fErrors->error(c.fLine, "function '" + function.description() + "' is not defined"); return -1; @@ -1236,7 +1235,7 @@ SpvId SPIRVCodeGenerator::writeFunctionCall(const FunctionCall& c, OutputStream& this->writeOpCode(SpvOpFunctionCall, 4 + (int32_t) arguments.size(), out); this->writeWord(this->getType(c.type()), out); this->writeWord(result, out); - this->writeWord(entry->second, out); + this->writeWord(*entry, out); for (SpvId id : argumentIds) { this->writeWord(id, out); } @@ -1264,19 +1263,20 @@ SpvId SPIRVCodeGenerator::writeConstantVector(const AnyConstructor& c) { } // Check to see if we've already synthesized this vector constant. - auto [iter, newlyCreated] = fVectorConstants.insert({key, (SpvId)-1}); - if (newlyCreated) { - // Emit an OpConstantComposite instruction for this constant. - SpvId result = this->nextId(&type); - this->writeOpCode(SpvOpConstantComposite, 3 + type.columns(), fConstantBuffer); - this->writeWord(key.fTypeId, fConstantBuffer); - this->writeWord(result, fConstantBuffer); - for (int i = 0; i < type.columns(); i++) { - this->writeWord(key.fValueId[i], fConstantBuffer); - } - iter->second = result; + if (SpvId* entry = fVectorConstants.find(key)) { + return *entry; } - return iter->second; + + // Emit an OpConstantComposite instruction for this constant. + SpvId result = this->nextId(&type); + this->writeOpCode(SpvOpConstantComposite, 3 + type.columns(), fConstantBuffer); + this->writeWord(key.fTypeId, fConstantBuffer); + this->writeWord(result, fConstantBuffer); + for (int i = 0; i < type.columns(); i++) { + this->writeWord(key.fValueId[i], fConstantBuffer); + } + fVectorConstants.set(key, result); + return result; } SpvId SPIRVCodeGenerator::castScalarToType(SpvId inputExprId, @@ -1974,8 +1974,8 @@ private: }; int SPIRVCodeGenerator::findUniformFieldIndex(const Variable& var) const { - auto iter = fTopLevelUniformMap.find(&var); - return (iter != fTopLevelUniformMap.end()) ? iter->second : -1; + int* fieldIndex = fTopLevelUniformMap.find(&var); + return fieldIndex ? *fieldIndex : -1; } std::unique_ptr SPIRVCodeGenerator::getLValue(const Expression& expr, @@ -1997,9 +1997,9 @@ std::unique_ptr SPIRVCodeGenerator::getLValue(const this->getType(type), precision); } SpvId typeId = this->getType(type, this->memoryLayoutForVariable(var)); - auto entry = fVariableMap.find(&var); - SkASSERTF(entry != fVariableMap.end(), "%s", expr.description().c_str()); - return std::make_unique(*this, entry->second, + SpvId* entry = fVariableMap.find(&var); + SkASSERTF(entry, "%s", expr.description().c_str()); + return std::make_unique(*this, *entry, /*isMemoryObjectPointer=*/true, typeId, precision); } @@ -2096,7 +2096,7 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O fContext.fTypes.fFloat4.get(), /*builtin=*/true, Variable::Storage::kGlobal); - fSPIRVBonusVariables.insert(coordsVar.get()); + fSPIRVBonusVariables.add(coordsVar.get()); symbols.add(std::move(coordsVar)); } DSLGlobalVar deviceCoord(DEVICE_COORDS_NAME); @@ -2131,7 +2131,7 @@ SpvId SPIRVCodeGenerator::writeVariableReference(const VariableReference& ref, O fContext.fTypes.fBool.get(), /*builtin=*/true, Variable::Storage::kGlobal); - fSPIRVBonusVariables.insert(clockwiseVar.get()); + fSPIRVBonusVariables.add(clockwiseVar.get()); symbols.add(std::move(clockwiseVar)); } DSLGlobalVar deviceClockwise(DEVICE_CLOCKWISE_NAME); @@ -2884,21 +2884,22 @@ SpvId SPIRVCodeGenerator::writeLiteral(double value, const Type& type) { } SPIRVNumberConstant key{valueBits, type.numberKind()}; - auto [iter, newlyCreated] = fNumberConstants.insert({key, (SpvId)-1}); - if (newlyCreated) { - SpvId result = this->nextId(nullptr); - iter->second = result; - - if (type.isBoolean()) { - this->writeInstruction(valueBits ? SpvOpConstantTrue : SpvOpConstantFalse, - this->getType(type), result, fConstantBuffer); - } else { - this->writeInstruction(SpvOpConstant, this->getType(type), result, - (SpvId)valueBits, fConstantBuffer); - } + if (SpvId* entry = fNumberConstants.find(key)) { + return *entry; } - return iter->second; + SpvId result = this->nextId(nullptr); + fNumberConstants.set(key, result); + + if (type.isBoolean()) { + this->writeInstruction(valueBits ? SpvOpConstantTrue : SpvOpConstantFalse, + this->getType(type), result, fConstantBuffer); + } else { + this->writeInstruction(SpvOpConstant, this->getType(type), result, + (SpvId)valueBits, fConstantBuffer); + } + + return result; } SpvId SPIRVCodeGenerator::writeFunctionStart(const FunctionDeclaration& f, OutputStream& out) { @@ -2914,7 +2915,7 @@ SpvId SPIRVCodeGenerator::writeFunctionStart(const FunctionDeclaration& f, Outpu fNameBuffer); for (const Variable* parameter : f.parameters()) { SpvId id = this->nextId(nullptr); - fVariableMap[parameter] = id; + fVariableMap.set(parameter, id); SpvId type = this->getPointerType(parameter->type(), SpvStorageClassFunction); this->writeInstruction(SpvOpFunctionParameter, type, id, out); } @@ -3048,7 +3049,7 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool a rtFlipStructType, intfVar.isBuiltin(), intfVar.storage())); - fSPIRVBonusVariables.insert(modifiedVar); + fSPIRVBonusVariables.add(modifiedVar); InterfaceBlock modifiedCopy(intf.fLine, *modifiedVar, intf.typeName(), @@ -3059,7 +3060,7 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool a fProgram.fSymbols->add(std::make_unique( /*line=*/-1, modifiedVar, rtFlipStructType->fields().size() - 1)); } - fVariableMap[&intfVar] = result; + fVariableMap.set(&intfVar, result); fWroteRTFlip = true; return result; } @@ -3076,14 +3077,14 @@ SpvId SPIRVCodeGenerator::writeInterfaceBlock(const InterfaceBlock& intf, bool a layout.fSet = fProgram.fConfig->fSettings.fDefaultUniformSet; } this->writeLayout(layout, result, intfVar.fLine); - fVariableMap[&intfVar] = result; + fVariableMap.set(&intfVar, result); return result; } bool SPIRVCodeGenerator::isDead(const Variable& var) const { // During SPIR-V code generation, we synthesize some extra bonus variables that don't actually // exist in the Program at all and aren't tracked by the ProgramUsage. They aren't dead, though. - if (fSPIRVBonusVariables.count(&var)) { + if (fSPIRVBonusVariables.contains(&var)) { return false; } ProgramUsage::VariableCounts counts = fProgram.usage()->get(var); @@ -3115,7 +3116,7 @@ void SPIRVCodeGenerator::writeGlobalVar(ProgramKind kind, const VarDeclaration& // Add this global to the variable map. const Type& type = var.type(); SpvId id = this->nextId(&type); - fVariableMap[&var] = id; + fVariableMap.set(&var, id); if (var.modifiers().fLayout.fBuiltin == SK_SECONDARYFRAGCOLOR_BUILTIN) { // sk_SecondaryFragColor corresponds to gl_SecondaryFragColorEXT, which isn't supposed to // appear in a SPIR-V program (it's only valid in ES2). Report an error. @@ -3149,7 +3150,7 @@ void SPIRVCodeGenerator::writeGlobalVar(ProgramKind kind, const VarDeclaration& void SPIRVCodeGenerator::writeVarDeclaration(const VarDeclaration& varDecl, OutputStream& out) { const Variable& var = varDecl.var(); SpvId id = this->nextId(&var.type()); - fVariableMap[&var] = id; + fVariableMap.set(&var, id); SpvId type = this->getPointerType(var.type(), SpvStorageClassFunction); this->writeInstruction(SpvOpVariable, type, id, SpvStorageClassFunction, fVariableBuffer); this->writeInstruction(SpvOpName, id, var.name(), fNameBuffer); @@ -3437,10 +3438,9 @@ void SPIRVCodeGenerator::writeUniformBuffer(std::shared_ptr topLeve // a lookup table of variables to UniformBuffer field indices. std::vector fields; fields.reserve(fTopLevelUniforms.size()); - fTopLevelUniformMap.reserve(fTopLevelUniforms.size()); for (const VarDeclaration* topLevelUniform : fTopLevelUniforms) { const Variable* var = &topLevelUniform->var(); - fTopLevelUniformMap[var] = (int)fields.size(); + fTopLevelUniformMap.set(var, (int)fields.size()); fields.emplace_back(var->modifiers(), var->name(), &var->type()); } fUniformBuffer.fStruct = Type::MakeStructType( @@ -3524,7 +3524,7 @@ void SPIRVCodeGenerator::addRTFlipUniform(int line) { intfStruct, /*builtin=*/false, Variable::Storage::kGlobal)); - fSPIRVBonusVariables.insert(intfVar); + fSPIRVBonusVariables.add(intfVar); { AutoAttachPoolToThread attach(fProgram.fPool.get()); fProgram.fSymbols->add(std::make_unique(/*line=*/-1, intfVar, /*field=*/0)); @@ -3548,7 +3548,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream& if (e->is()) { const FunctionDefinition& funcDef = e->as(); const FunctionDeclaration& funcDecl = funcDef.declaration(); - fFunctionMap[&funcDecl] = this->nextId(nullptr); + fFunctionMap.set(&funcDecl, this->nextId(nullptr)); if (funcDecl.isMain()) { main = &funcDecl; } @@ -3590,7 +3590,7 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream& if (main->returnType().matches(*fContext.fTypes.fHalf4)) { adapter = this->writeEntrypointAdapter(*main); if (adapter.entrypointDecl) { - fFunctionMap[adapter.entrypointDecl.get()] = this->nextId(nullptr); + fFunctionMap.set(adapter.entrypointDecl.get(), this->nextId(nullptr)); this->writeFunction(*adapter.entrypointDef, body); main = adapter.entrypointDecl.get(); } @@ -3602,12 +3602,11 @@ void SPIRVCodeGenerator::writeInstructions(const Program& program, OutputStream& } } // Add global in/out variables to the list of interface variables. - for (auto entry : fVariableMap) { - const Variable* var = entry.first; + for (const auto& [var, spvId] : fVariableMap) { if (var->storage() == Variable::Storage::kGlobal && (var->modifiers().fFlags & (Modifiers::kIn_Flag | Modifiers::kOut_Flag)) && !this->isDead(*var)) { - interfaceVars.insert(entry.second); + interfaceVars.insert(spvId); } } this->writeCapabilities(out); diff --git a/src/sksl/codegen/SkSLSPIRVCodeGenerator.h b/src/sksl/codegen/SkSLSPIRVCodeGenerator.h index dc27feae3d..a44a3b1e1e 100644 --- a/src/sksl/codegen/SkSLSPIRVCodeGenerator.h +++ b/src/sksl/codegen/SkSLSPIRVCodeGenerator.h @@ -9,9 +9,8 @@ #define SKSL_SPIRVCODEGENERATOR #include -#include -#include +#include "include/private/SkTHash.h" #include "src/core/SkOpts.h" #include "src/sksl/SkSLMemoryLayout.h" #include "src/sksl/SkSLStringStream.h" @@ -58,6 +57,12 @@ struct SPIRVNumberConstant { } int32_t fValueBits; SkSL::Type::NumberKind fKind; + + struct Hash { + uint32_t operator()(const SPIRVNumberConstant& key) const { + return key.fValueBits ^ (int)key.fKind; + } + }; }; struct SPIRVVectorConstant { @@ -70,30 +75,14 @@ struct SPIRVVectorConstant { } SpvId fTypeId; SpvId fValueId[4]; + + struct Hash { + uint32_t operator()(const SPIRVVectorConstant& key) const { + return SkOpts::hash(&key, sizeof(key)); + } + }; }; -} // namespace SkSL - -namespace std { - -template <> -struct hash { - size_t operator()(const SkSL::SPIRVNumberConstant& key) const { - return key.fValueBits ^ (int)key.fKind; - } -}; - -template <> -struct hash { - size_t operator()(const SkSL::SPIRVVectorConstant& key) const { - return SkOpts::hash(&key, sizeof(key)); - } -}; - -} // namespace std - -namespace SkSL { - /** * Converts a Program into a SPIR-V binary. */ @@ -483,18 +472,18 @@ private: int32_t unsignedOp; int32_t boolOp; }; - std::unordered_map fIntrinsicMap; - std::unordered_map fFunctionMap; - std::unordered_map fVariableMap; - std::unordered_map fTypeMap; + SkTHashMap fIntrinsicMap; + SkTHashMap fFunctionMap; + SkTHashMap fVariableMap; + SkTHashMap fTypeMap; StringStream fGlobalInitializersBuffer; StringStream fConstantBuffer; StringStream fVariableBuffer; StringStream fNameBuffer; StringStream fDecorationBuffer; - std::unordered_map fNumberConstants; - std::unordered_map fVectorConstants; + SkTHashMap fNumberConstants; + SkTHashMap fVectorConstants; // label of the current block, or 0 if we are not in a block SpvId fCurrentBlock; std::stack fBreakTarget; @@ -506,8 +495,8 @@ private: // interface block. UniformBuffer fUniformBuffer; std::vector fTopLevelUniforms; - std::unordered_map fTopLevelUniformMap; // - std::unordered_set fSPIRVBonusVariables; + SkTHashMap fTopLevelUniformMap; // + SkTHashSet fSPIRVBonusVariables; SpvId fUniformBufferId = -1; friend class PointerLValue;