123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794 |
- // Copyright (c) 2018 Google LLC
- //
- // Licensed under the Apache License, Version 2.0 (the "License");
- // you may not use this file except in compliance with the License.
- // You may obtain a copy of the License at
- //
- // http://www.apache.org/licenses/LICENSE-2.0
- //
- // Unless required by applicable law or agreed to in writing, software
- // distributed under the License is distributed on an "AS IS" BASIS,
- // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- // See the License for the specific language governing permissions and
- // limitations under the License.
- // MARK-V is a compression format for SPIR-V binaries. It strips away
- // non-essential information (such as result IDs which can be regenerated) and
- // uses various bit reduction techniques to reduce the size of the binary.
- #include "source/comp/markv_codec.h"
- #include "source/comp/markv_logger.h"
- #include "source/latest_version_glsl_std_450_header.h"
- #include "source/latest_version_opencl_std_header.h"
- #include "source/opcode.h"
- #include "source/util/make_unique.h"
- namespace spvtools {
- namespace comp {
- namespace {
- // Custom hash function used to produce short descriptors.
- uint32_t ShortHashU32Array(const std::vector<uint32_t>& words) {
- // The hash function is a sum of hashes of each word seeded by word index.
- // Knuth's multiplicative hash is used to hash the words.
- const uint32_t kKnuthMulHash = 2654435761;
- uint32_t val = 0;
- for (uint32_t i = 0; i < words.size(); ++i) {
- val += (words[i] + i + 123) * kKnuthMulHash;
- }
- return 1 + val % ((1 << MarkvCodec::kShortDescriptorNumBits) - 1);
- }
- // Returns a set of mtf rank codecs based on a plausible hand-coded
- // distribution.
- std::map<uint64_t, std::unique_ptr<HuffmanCodec<uint32_t>>>
- GetMtfHuffmanCodecs() {
- std::map<uint64_t, std::unique_ptr<HuffmanCodec<uint32_t>>> codecs;
- std::unique_ptr<HuffmanCodec<uint32_t>> codec;
- codec = MakeUnique<HuffmanCodec<uint32_t>>(std::map<uint32_t, uint32_t>({
- {0, 5},
- {1, 40},
- {2, 10},
- {3, 5},
- {4, 5},
- {5, 5},
- {6, 3},
- {7, 3},
- {8, 3},
- {9, 3},
- {MarkvCodec::kMtfRankEncodedByValueSignal, 10},
- }));
- codecs.emplace(kMtfAll, std::move(codec));
- codec = MakeUnique<HuffmanCodec<uint32_t>>(std::map<uint32_t, uint32_t>({
- {1, 50},
- {2, 20},
- {3, 5},
- {4, 5},
- {5, 2},
- {6, 1},
- {7, 1},
- {8, 1},
- {9, 1},
- {MarkvCodec::kMtfRankEncodedByValueSignal, 10},
- }));
- codecs.emplace(kMtfGenericNonZeroRank, std::move(codec));
- return codecs;
- }
- } // namespace
- const uint32_t MarkvCodec::kMarkvMagicNumber = 0x07230303;
- const uint32_t MarkvCodec::kMtfSmallestRankEncodedByValue = 10;
- const uint32_t MarkvCodec::kMtfRankEncodedByValueSignal =
- std::numeric_limits<uint32_t>::max();
- const uint32_t MarkvCodec::kShortDescriptorNumBits = 8;
- const size_t MarkvCodec::kByteBreakAfterInstIfLessThanUntilNextByte = 8;
- MarkvCodec::MarkvCodec(spv_const_context context,
- spv_validator_options validator_options,
- const MarkvModel* model)
- : validator_options_(validator_options),
- grammar_(context),
- model_(model),
- short_id_descriptors_(ShortHashU32Array),
- mtf_huffman_codecs_(GetMtfHuffmanCodecs()),
- context_(context) {}
- MarkvCodec::~MarkvCodec() { spvValidatorOptionsDestroy(validator_options_); }
- MarkvCodec::MarkvHeader::MarkvHeader()
- : magic_number(MarkvCodec::kMarkvMagicNumber),
- markv_version(MarkvCodec::GetMarkvVersion()) {}
- // Defines and returns current MARK-V version.
- // static
- uint32_t MarkvCodec::GetMarkvVersion() {
- const uint32_t kVersionMajor = 1;
- const uint32_t kVersionMinor = 4;
- return kVersionMinor | (kVersionMajor << 16);
- }
- size_t MarkvCodec::GetNumBitsToNextByte(size_t bit_pos) const {
- return (8 - (bit_pos % 8)) % 8;
- }
- // Returns true if the opcode has a fixed number of operands. May return a
- // false negative.
- bool MarkvCodec::OpcodeHasFixedNumberOfOperands(SpvOp opcode) const {
- switch (opcode) {
- // TODO(atgoo@github.com) This is not a complete list.
- case SpvOpNop:
- case SpvOpName:
- case SpvOpUndef:
- case SpvOpSizeOf:
- case SpvOpLine:
- case SpvOpNoLine:
- case SpvOpDecorationGroup:
- case SpvOpExtension:
- case SpvOpExtInstImport:
- case SpvOpMemoryModel:
- case SpvOpCapability:
- case SpvOpTypeVoid:
- case SpvOpTypeBool:
- case SpvOpTypeInt:
- case SpvOpTypeFloat:
- case SpvOpTypeVector:
- case SpvOpTypeMatrix:
- case SpvOpTypeSampler:
- case SpvOpTypeSampledImage:
- case SpvOpTypeArray:
- case SpvOpTypePointer:
- case SpvOpConstantTrue:
- case SpvOpConstantFalse:
- case SpvOpLabel:
- case SpvOpBranch:
- case SpvOpFunction:
- case SpvOpFunctionParameter:
- case SpvOpFunctionEnd:
- case SpvOpBitcast:
- case SpvOpCopyObject:
- case SpvOpTranspose:
- case SpvOpSNegate:
- case SpvOpFNegate:
- case SpvOpIAdd:
- case SpvOpFAdd:
- case SpvOpISub:
- case SpvOpFSub:
- case SpvOpIMul:
- case SpvOpFMul:
- case SpvOpUDiv:
- case SpvOpSDiv:
- case SpvOpFDiv:
- case SpvOpUMod:
- case SpvOpSRem:
- case SpvOpSMod:
- case SpvOpFRem:
- case SpvOpFMod:
- case SpvOpVectorTimesScalar:
- case SpvOpMatrixTimesScalar:
- case SpvOpVectorTimesMatrix:
- case SpvOpMatrixTimesVector:
- case SpvOpMatrixTimesMatrix:
- case SpvOpOuterProduct:
- case SpvOpDot:
- return true;
- default:
- break;
- }
- return false;
- }
- void MarkvCodec::ProcessCurInstruction() {
- instructions_.emplace_back(new val::Instruction(&inst_));
- const SpvOp opcode = SpvOp(inst_.opcode);
- if (inst_.result_id) {
- id_to_def_instruction_.emplace(inst_.result_id, instructions_.back().get());
- // Collect ids local to the current function.
- if (cur_function_id_) {
- ids_local_to_cur_function_.push_back(inst_.result_id);
- }
- // Starting new function.
- if (opcode == SpvOpFunction) {
- cur_function_id_ = inst_.result_id;
- cur_function_return_type_ = inst_.type_id;
- if (model_->id_fallback_strategy() ==
- MarkvModel::IdFallbackStrategy::kRuleBased) {
- multi_mtf_.Insert(GetMtfFunctionWithReturnType(inst_.type_id),
- inst_.result_id);
- }
- // Store function parameter types in a queue, so that we know which types
- // to expect in the following OpFunctionParameter instructions.
- const val::Instruction* def_inst = FindDef(inst_.words[4]);
- assert(def_inst);
- assert(def_inst->opcode() == SpvOpTypeFunction);
- for (uint32_t i = 3; i < def_inst->words().size(); ++i) {
- remaining_function_parameter_types_.push_back(def_inst->word(i));
- }
- }
- }
- // Remove local ids from MTFs if function end.
- if (opcode == SpvOpFunctionEnd) {
- cur_function_id_ = 0;
- for (uint32_t id : ids_local_to_cur_function_) multi_mtf_.RemoveFromAll(id);
- ids_local_to_cur_function_.clear();
- assert(remaining_function_parameter_types_.empty());
- }
- if (!inst_.result_id) return;
- {
- // Save the result ID to type ID mapping.
- // In the grammar, type ID always appears before result ID.
- // A regular value maps to its type. Some instructions (e.g. OpLabel)
- // have no type Id, and will map to 0. The result Id for a
- // type-generating instruction (e.g. OpTypeInt) maps to itself.
- auto insertion_result = id_to_type_id_.emplace(
- inst_.result_id, spvOpcodeGeneratesType(SpvOp(inst_.opcode))
- ? inst_.result_id
- : inst_.type_id);
- (void)insertion_result;
- assert(insertion_result.second);
- }
- // Add result_id to MTFs.
- if (model_->id_fallback_strategy() ==
- MarkvModel::IdFallbackStrategy::kRuleBased) {
- switch (opcode) {
- case SpvOpTypeFloat:
- case SpvOpTypeInt:
- case SpvOpTypeBool:
- case SpvOpTypeVector:
- case SpvOpTypePointer:
- case SpvOpExtInstImport:
- case SpvOpTypeSampledImage:
- case SpvOpTypeImage:
- case SpvOpTypeSampler:
- multi_mtf_.Insert(GetMtfIdGeneratedByOpcode(opcode), inst_.result_id);
- break;
- default:
- break;
- }
- if (spvOpcodeIsComposite(opcode)) {
- multi_mtf_.Insert(kMtfTypeComposite, inst_.result_id);
- }
- if (opcode == SpvOpLabel) {
- multi_mtf_.InsertOrPromote(kMtfLabel, inst_.result_id);
- }
- if (opcode == SpvOpTypeInt) {
- multi_mtf_.Insert(kMtfTypeScalar, inst_.result_id);
- multi_mtf_.Insert(kMtfTypeIntScalarOrVector, inst_.result_id);
- }
- if (opcode == SpvOpTypeFloat) {
- multi_mtf_.Insert(kMtfTypeScalar, inst_.result_id);
- multi_mtf_.Insert(kMtfTypeFloatScalarOrVector, inst_.result_id);
- }
- if (opcode == SpvOpTypeBool) {
- multi_mtf_.Insert(kMtfTypeScalar, inst_.result_id);
- multi_mtf_.Insert(kMtfTypeBoolScalarOrVector, inst_.result_id);
- }
- if (opcode == SpvOpTypeVector) {
- const uint32_t component_type_id = inst_.words[2];
- const uint32_t size = inst_.words[3];
- if (multi_mtf_.HasValue(GetMtfIdGeneratedByOpcode(SpvOpTypeFloat),
- component_type_id)) {
- multi_mtf_.Insert(kMtfTypeFloatScalarOrVector, inst_.result_id);
- } else if (multi_mtf_.HasValue(GetMtfIdGeneratedByOpcode(SpvOpTypeInt),
- component_type_id)) {
- multi_mtf_.Insert(kMtfTypeIntScalarOrVector, inst_.result_id);
- } else if (multi_mtf_.HasValue(GetMtfIdGeneratedByOpcode(SpvOpTypeBool),
- component_type_id)) {
- multi_mtf_.Insert(kMtfTypeBoolScalarOrVector, inst_.result_id);
- }
- multi_mtf_.Insert(GetMtfTypeVectorOfSize(size), inst_.result_id);
- }
- if (inst_.opcode == SpvOpTypeFunction) {
- const uint32_t return_type = inst_.words[2];
- multi_mtf_.Insert(kMtfTypeReturnedByFunction, return_type);
- multi_mtf_.Insert(GetMtfFunctionTypeWithReturnType(return_type),
- inst_.result_id);
- }
- if (inst_.type_id) {
- const val::Instruction* type_inst = FindDef(inst_.type_id);
- assert(type_inst);
- multi_mtf_.Insert(kMtfObject, inst_.result_id);
- multi_mtf_.Insert(GetMtfIdOfType(inst_.type_id), inst_.result_id);
- if (multi_mtf_.HasValue(kMtfTypeFloatScalarOrVector, inst_.type_id)) {
- multi_mtf_.Insert(kMtfFloatScalarOrVector, inst_.result_id);
- }
- if (multi_mtf_.HasValue(kMtfTypeIntScalarOrVector, inst_.type_id))
- multi_mtf_.Insert(kMtfIntScalarOrVector, inst_.result_id);
- if (multi_mtf_.HasValue(kMtfTypeBoolScalarOrVector, inst_.type_id))
- multi_mtf_.Insert(kMtfBoolScalarOrVector, inst_.result_id);
- if (multi_mtf_.HasValue(kMtfTypeComposite, inst_.type_id))
- multi_mtf_.Insert(kMtfComposite, inst_.result_id);
- switch (type_inst->opcode()) {
- case SpvOpTypeInt:
- case SpvOpTypeBool:
- case SpvOpTypePointer:
- case SpvOpTypeVector:
- case SpvOpTypeImage:
- case SpvOpTypeSampledImage:
- case SpvOpTypeSampler:
- multi_mtf_.Insert(
- GetMtfIdWithTypeGeneratedByOpcode(type_inst->opcode()),
- inst_.result_id);
- break;
- default:
- break;
- }
- if (type_inst->opcode() == SpvOpTypeVector) {
- const uint32_t component_type = type_inst->word(2);
- multi_mtf_.Insert(GetMtfVectorOfComponentType(component_type),
- inst_.result_id);
- }
- if (type_inst->opcode() == SpvOpTypePointer) {
- assert(type_inst->operands().size() > 2);
- assert(type_inst->words().size() > type_inst->operands()[2].offset);
- const uint32_t data_type =
- type_inst->word(type_inst->operands()[2].offset);
- multi_mtf_.Insert(GetMtfPointerToType(data_type), inst_.result_id);
- if (multi_mtf_.HasValue(kMtfTypeComposite, data_type))
- multi_mtf_.Insert(kMtfTypePointerToComposite, inst_.result_id);
- }
- }
- if (spvOpcodeGeneratesType(opcode)) {
- if (opcode != SpvOpTypeFunction) {
- multi_mtf_.Insert(kMtfTypeNonFunction, inst_.result_id);
- }
- }
- }
- if (model_->AnyDescriptorHasCodingScheme()) {
- const uint32_t long_descriptor =
- long_id_descriptors_.ProcessInstruction(inst_);
- if (model_->DescriptorHasCodingScheme(long_descriptor))
- multi_mtf_.Insert(GetMtfLongIdDescriptor(long_descriptor),
- inst_.result_id);
- }
- if (model_->id_fallback_strategy() ==
- MarkvModel::IdFallbackStrategy::kShortDescriptor) {
- const uint32_t short_descriptor =
- short_id_descriptors_.ProcessInstruction(inst_);
- multi_mtf_.Insert(GetMtfShortIdDescriptor(short_descriptor),
- inst_.result_id);
- }
- }
- uint64_t MarkvCodec::GetRuleBasedMtf() {
- // This function is only called for id operands (but not result ids).
- assert(spvIsIdType(operand_.type) ||
- operand_.type == SPV_OPERAND_TYPE_OPTIONAL_ID);
- assert(operand_.type != SPV_OPERAND_TYPE_RESULT_ID);
- const SpvOp opcode = static_cast<SpvOp>(inst_.opcode);
- // All operand slots which expect label id.
- if ((inst_.opcode == SpvOpLoopMerge && operand_index_ <= 1) ||
- (inst_.opcode == SpvOpSelectionMerge && operand_index_ == 0) ||
- (inst_.opcode == SpvOpBranch && operand_index_ == 0) ||
- (inst_.opcode == SpvOpBranchConditional &&
- (operand_index_ == 1 || operand_index_ == 2)) ||
- (inst_.opcode == SpvOpPhi && operand_index_ >= 3 &&
- operand_index_ % 2 == 1) ||
- (inst_.opcode == SpvOpSwitch && operand_index_ > 0)) {
- return kMtfLabel;
- }
- switch (opcode) {
- case SpvOpFAdd:
- case SpvOpFSub:
- case SpvOpFMul:
- case SpvOpFDiv:
- case SpvOpFRem:
- case SpvOpFMod:
- case SpvOpFNegate: {
- if (operand_index_ == 0) return kMtfTypeFloatScalarOrVector;
- return GetMtfIdOfType(inst_.type_id);
- }
- case SpvOpISub:
- case SpvOpIAdd:
- case SpvOpIMul:
- case SpvOpSDiv:
- case SpvOpUDiv:
- case SpvOpSMod:
- case SpvOpUMod:
- case SpvOpSRem:
- case SpvOpSNegate: {
- if (operand_index_ == 0) return kMtfTypeIntScalarOrVector;
- return kMtfIntScalarOrVector;
- }
- // TODO(atgoo@github.com) Add OpConvertFToU and other opcodes.
- case SpvOpFOrdEqual:
- case SpvOpFUnordEqual:
- case SpvOpFOrdNotEqual:
- case SpvOpFUnordNotEqual:
- case SpvOpFOrdLessThan:
- case SpvOpFUnordLessThan:
- case SpvOpFOrdGreaterThan:
- case SpvOpFUnordGreaterThan:
- case SpvOpFOrdLessThanEqual:
- case SpvOpFUnordLessThanEqual:
- case SpvOpFOrdGreaterThanEqual:
- case SpvOpFUnordGreaterThanEqual: {
- if (operand_index_ == 0) return kMtfTypeBoolScalarOrVector;
- if (operand_index_ == 2) return kMtfFloatScalarOrVector;
- if (operand_index_ == 3) {
- const uint32_t first_operand_id = GetInstWords()[3];
- const uint32_t first_operand_type = id_to_type_id_.at(first_operand_id);
- return GetMtfIdOfType(first_operand_type);
- }
- break;
- }
- case SpvOpVectorShuffle: {
- if (operand_index_ == 0) {
- assert(inst_.num_operands > 4);
- return GetMtfTypeVectorOfSize(inst_.num_operands - 4);
- }
- assert(inst_.type_id);
- if (operand_index_ == 2 || operand_index_ == 3)
- return GetMtfVectorOfComponentType(
- GetVectorComponentType(inst_.type_id));
- break;
- }
- case SpvOpVectorTimesScalar: {
- if (operand_index_ == 0) {
- // TODO(atgoo@github.com) Could be narrowed to vector of floats.
- return GetMtfIdGeneratedByOpcode(SpvOpTypeVector);
- }
- assert(inst_.type_id);
- if (operand_index_ == 2) return GetMtfIdOfType(inst_.type_id);
- if (operand_index_ == 3)
- return GetMtfIdOfType(GetVectorComponentType(inst_.type_id));
- break;
- }
- case SpvOpDot: {
- if (operand_index_ == 0) return GetMtfIdGeneratedByOpcode(SpvOpTypeFloat);
- assert(inst_.type_id);
- if (operand_index_ == 2)
- return GetMtfVectorOfComponentType(inst_.type_id);
- if (operand_index_ == 3) {
- const uint32_t vector_id = GetInstWords()[3];
- const uint32_t vector_type = id_to_type_id_.at(vector_id);
- return GetMtfIdOfType(vector_type);
- }
- break;
- }
- case SpvOpTypeVector: {
- if (operand_index_ == 1) {
- return kMtfTypeScalar;
- }
- break;
- }
- case SpvOpTypeMatrix: {
- if (operand_index_ == 1) {
- return GetMtfIdGeneratedByOpcode(SpvOpTypeVector);
- }
- break;
- }
- case SpvOpTypePointer: {
- if (operand_index_ == 2) {
- return kMtfTypeNonFunction;
- }
- break;
- }
- case SpvOpTypeStruct: {
- if (operand_index_ >= 1) {
- return kMtfTypeNonFunction;
- }
- break;
- }
- case SpvOpTypeFunction: {
- if (operand_index_ == 1) {
- return kMtfTypeNonFunction;
- }
- if (operand_index_ >= 2) {
- return kMtfTypeNonFunction;
- }
- break;
- }
- case SpvOpLoad: {
- if (operand_index_ == 0) return kMtfTypeNonFunction;
- if (operand_index_ == 2) {
- assert(inst_.type_id);
- return GetMtfPointerToType(inst_.type_id);
- }
- break;
- }
- case SpvOpStore: {
- if (operand_index_ == 0)
- return GetMtfIdWithTypeGeneratedByOpcode(SpvOpTypePointer);
- if (operand_index_ == 1) {
- const uint32_t pointer_id = GetInstWords()[1];
- const uint32_t pointer_type = id_to_type_id_.at(pointer_id);
- const val::Instruction* pointer_inst = FindDef(pointer_type);
- assert(pointer_inst);
- assert(pointer_inst->opcode() == SpvOpTypePointer);
- const uint32_t data_type =
- pointer_inst->word(pointer_inst->operands()[2].offset);
- return GetMtfIdOfType(data_type);
- }
- break;
- }
- case SpvOpVariable: {
- if (operand_index_ == 0)
- return GetMtfIdGeneratedByOpcode(SpvOpTypePointer);
- break;
- }
- case SpvOpAccessChain: {
- if (operand_index_ == 0)
- return GetMtfIdGeneratedByOpcode(SpvOpTypePointer);
- if (operand_index_ == 2) return kMtfTypePointerToComposite;
- if (operand_index_ >= 3)
- return GetMtfIdWithTypeGeneratedByOpcode(SpvOpTypeInt);
- break;
- }
- case SpvOpCompositeConstruct: {
- if (operand_index_ == 0) return kMtfTypeComposite;
- if (operand_index_ >= 2) {
- const uint32_t composite_type = GetInstWords()[1];
- if (multi_mtf_.HasValue(kMtfTypeFloatScalarOrVector, composite_type))
- return kMtfFloatScalarOrVector;
- if (multi_mtf_.HasValue(kMtfTypeIntScalarOrVector, composite_type))
- return kMtfIntScalarOrVector;
- if (multi_mtf_.HasValue(kMtfTypeBoolScalarOrVector, composite_type))
- return kMtfBoolScalarOrVector;
- }
- break;
- }
- case SpvOpCompositeExtract: {
- if (operand_index_ == 2) return kMtfComposite;
- break;
- }
- case SpvOpConstantComposite: {
- if (operand_index_ == 0) return kMtfTypeComposite;
- if (operand_index_ >= 2) {
- const val::Instruction* composite_type_inst = FindDef(inst_.type_id);
- assert(composite_type_inst);
- if (composite_type_inst->opcode() == SpvOpTypeVector) {
- return GetMtfIdOfType(composite_type_inst->word(2));
- }
- }
- break;
- }
- case SpvOpExtInst: {
- if (operand_index_ == 2)
- return GetMtfIdGeneratedByOpcode(SpvOpExtInstImport);
- if (operand_index_ >= 4) {
- const uint32_t return_type = GetInstWords()[1];
- const uint32_t ext_inst_type = inst_.ext_inst_type;
- const uint32_t ext_inst_index = GetInstWords()[4];
- // TODO(atgoo@github.com) The list of extended instructions is
- // incomplete. Only common instructions and low-hanging fruits listed.
- if (ext_inst_type == SPV_EXT_INST_TYPE_GLSL_STD_450) {
- switch (ext_inst_index) {
- case GLSLstd450FAbs:
- case GLSLstd450FClamp:
- case GLSLstd450FMax:
- case GLSLstd450FMin:
- case GLSLstd450FMix:
- case GLSLstd450Step:
- case GLSLstd450SmoothStep:
- case GLSLstd450Fma:
- case GLSLstd450Pow:
- case GLSLstd450Exp:
- case GLSLstd450Exp2:
- case GLSLstd450Log:
- case GLSLstd450Log2:
- case GLSLstd450Sqrt:
- case GLSLstd450InverseSqrt:
- case GLSLstd450Fract:
- case GLSLstd450Floor:
- case GLSLstd450Ceil:
- case GLSLstd450Radians:
- case GLSLstd450Degrees:
- case GLSLstd450Sin:
- case GLSLstd450Cos:
- case GLSLstd450Tan:
- case GLSLstd450Sinh:
- case GLSLstd450Cosh:
- case GLSLstd450Tanh:
- case GLSLstd450Asin:
- case GLSLstd450Acos:
- case GLSLstd450Atan:
- case GLSLstd450Atan2:
- case GLSLstd450Asinh:
- case GLSLstd450Acosh:
- case GLSLstd450Atanh:
- case GLSLstd450MatrixInverse:
- case GLSLstd450Cross:
- case GLSLstd450Normalize:
- case GLSLstd450Reflect:
- case GLSLstd450FaceForward:
- return GetMtfIdOfType(return_type);
- case GLSLstd450Length:
- case GLSLstd450Distance:
- case GLSLstd450Refract:
- return kMtfFloatScalarOrVector;
- default:
- break;
- }
- } else if (ext_inst_type == SPV_EXT_INST_TYPE_OPENCL_STD) {
- switch (ext_inst_index) {
- case OpenCLLIB::Fabs:
- case OpenCLLIB::FClamp:
- case OpenCLLIB::Fmax:
- case OpenCLLIB::Fmin:
- case OpenCLLIB::Step:
- case OpenCLLIB::Smoothstep:
- case OpenCLLIB::Fma:
- case OpenCLLIB::Pow:
- case OpenCLLIB::Exp:
- case OpenCLLIB::Exp2:
- case OpenCLLIB::Log:
- case OpenCLLIB::Log2:
- case OpenCLLIB::Sqrt:
- case OpenCLLIB::Rsqrt:
- case OpenCLLIB::Fract:
- case OpenCLLIB::Floor:
- case OpenCLLIB::Ceil:
- case OpenCLLIB::Radians:
- case OpenCLLIB::Degrees:
- case OpenCLLIB::Sin:
- case OpenCLLIB::Cos:
- case OpenCLLIB::Tan:
- case OpenCLLIB::Sinh:
- case OpenCLLIB::Cosh:
- case OpenCLLIB::Tanh:
- case OpenCLLIB::Asin:
- case OpenCLLIB::Acos:
- case OpenCLLIB::Atan:
- case OpenCLLIB::Atan2:
- case OpenCLLIB::Asinh:
- case OpenCLLIB::Acosh:
- case OpenCLLIB::Atanh:
- case OpenCLLIB::Cross:
- case OpenCLLIB::Normalize:
- return GetMtfIdOfType(return_type);
- case OpenCLLIB::Length:
- case OpenCLLIB::Distance:
- return kMtfFloatScalarOrVector;
- default:
- break;
- }
- }
- }
- break;
- }
- case SpvOpFunction: {
- if (operand_index_ == 0) return kMtfTypeReturnedByFunction;
- if (operand_index_ == 3) {
- const uint32_t return_type = GetInstWords()[1];
- return GetMtfFunctionTypeWithReturnType(return_type);
- }
- break;
- }
- case SpvOpFunctionCall: {
- if (operand_index_ == 0) return kMtfTypeReturnedByFunction;
- if (operand_index_ == 2) {
- const uint32_t return_type = GetInstWords()[1];
- return GetMtfFunctionWithReturnType(return_type);
- }
- if (operand_index_ >= 3) {
- const uint32_t function_id = GetInstWords()[3];
- const val::Instruction* function_inst = FindDef(function_id);
- if (!function_inst) return kMtfObject;
- assert(function_inst->opcode() == SpvOpFunction);
- const uint32_t function_type_id = function_inst->word(4);
- const val::Instruction* function_type_inst = FindDef(function_type_id);
- assert(function_type_inst);
- assert(function_type_inst->opcode() == SpvOpTypeFunction);
- const uint32_t argument_type = function_type_inst->word(operand_index_);
- return GetMtfIdOfType(argument_type);
- }
- break;
- }
- case SpvOpReturnValue: {
- if (operand_index_ == 0) return GetMtfIdOfType(cur_function_return_type_);
- break;
- }
- case SpvOpBranchConditional: {
- if (operand_index_ == 0)
- return GetMtfIdWithTypeGeneratedByOpcode(SpvOpTypeBool);
- break;
- }
- case SpvOpSampledImage: {
- if (operand_index_ == 0)
- return GetMtfIdGeneratedByOpcode(SpvOpTypeSampledImage);
- if (operand_index_ == 2)
- return GetMtfIdWithTypeGeneratedByOpcode(SpvOpTypeImage);
- if (operand_index_ == 3)
- return GetMtfIdWithTypeGeneratedByOpcode(SpvOpTypeSampler);
- break;
- }
- case SpvOpImageSampleImplicitLod: {
- if (operand_index_ == 0)
- return GetMtfIdGeneratedByOpcode(SpvOpTypeVector);
- if (operand_index_ == 2)
- return GetMtfIdWithTypeGeneratedByOpcode(SpvOpTypeSampledImage);
- if (operand_index_ == 3)
- return GetMtfIdWithTypeGeneratedByOpcode(SpvOpTypeVector);
- break;
- }
- default:
- break;
- }
- return kMtfNone;
- }
- } // namespace comp
- } // namespace spvtools
|