mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-01 07:20:05 +00:00
5fc011b453
bit_stream, move_to_front and huffman_codec are only used by source/tools. Move into that directory to make the usage clearer.
233 lines
9.4 KiB
C++
233 lines
9.4 KiB
C++
// 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.
|
|
|
|
#ifndef SOURCE_COMP_MARKV_MODEL_H_
|
|
#define SOURCE_COMP_MARKV_MODEL_H_
|
|
|
|
#include <unordered_set>
|
|
|
|
#include "source/comp/huffman_codec.h"
|
|
#include "source/latest_version_spirv_header.h"
|
|
#include "spirv-tools/libspirv.hpp"
|
|
|
|
namespace spvtools {
|
|
namespace comp {
|
|
|
|
// Base class for MARK-V models.
|
|
// The class contains encoding/decoding model with various constants and
|
|
// codecs used by the compression algorithm.
|
|
class MarkvModel {
|
|
public:
|
|
MarkvModel()
|
|
: operand_chunk_lengths_(
|
|
static_cast<size_t>(SPV_OPERAND_TYPE_NUM_OPERAND_TYPES), 0) {
|
|
// Set default values.
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_TYPE_ID] = 4;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_RESULT_ID] = 8;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_ID] = 8;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_SCOPE_ID] = 8;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_MEMORY_SEMANTICS_ID] = 8;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_LITERAL_INTEGER] = 6;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_OPTIONAL_LITERAL_INTEGER] = 6;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_CAPABILITY] = 6;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_SOURCE_LANGUAGE] = 3;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_EXECUTION_MODEL] = 3;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_ADDRESSING_MODEL] = 2;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_MEMORY_MODEL] = 2;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_EXECUTION_MODE] = 6;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_STORAGE_CLASS] = 4;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_DIMENSIONALITY] = 3;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_SAMPLER_ADDRESSING_MODE] = 3;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_SAMPLER_FILTER_MODE] = 2;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_SAMPLER_IMAGE_FORMAT] = 6;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_FP_ROUNDING_MODE] = 2;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_LINKAGE_TYPE] = 2;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_ACCESS_QUALIFIER] = 2;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_OPTIONAL_ACCESS_QUALIFIER] = 2;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_FUNCTION_PARAMETER_ATTRIBUTE] = 3;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_DECORATION] = 6;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_BUILT_IN] = 6;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_GROUP_OPERATION] = 2;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_KERNEL_ENQ_FLAGS] = 2;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_KERNEL_PROFILING_INFO] = 2;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_FP_FAST_MATH_MODE] = 4;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_FUNCTION_CONTROL] = 4;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_LOOP_CONTROL] = 4;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_IMAGE] = 4;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_OPTIONAL_IMAGE] = 4;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_OPTIONAL_MEMORY_ACCESS] = 4;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_SELECTION_CONTROL] = 4;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_EXTENSION_INSTRUCTION_NUMBER] = 6;
|
|
operand_chunk_lengths_[SPV_OPERAND_TYPE_TYPED_LITERAL_NUMBER] = 6;
|
|
}
|
|
|
|
uint32_t model_type() const { return model_type_; }
|
|
uint32_t model_version() const { return model_version_; }
|
|
|
|
uint32_t opcode_chunk_length() const { return opcode_chunk_length_; }
|
|
uint32_t num_operands_chunk_length() const {
|
|
return num_operands_chunk_length_;
|
|
}
|
|
uint32_t mtf_rank_chunk_length() const { return mtf_rank_chunk_length_; }
|
|
|
|
uint32_t u64_chunk_length() const { return u64_chunk_length_; }
|
|
uint32_t s64_chunk_length() const { return s64_chunk_length_; }
|
|
uint32_t s64_block_exponent() const { return s64_block_exponent_; }
|
|
|
|
enum class IdFallbackStrategy {
|
|
kRuleBased = 0,
|
|
kShortDescriptor,
|
|
};
|
|
|
|
IdFallbackStrategy id_fallback_strategy() const {
|
|
return id_fallback_strategy_;
|
|
}
|
|
|
|
// Returns a codec for common opcode_and_num_operands words for the given
|
|
// previous opcode. May return nullptr if the codec doesn't exist.
|
|
const HuffmanCodec<uint64_t>* GetOpcodeAndNumOperandsMarkovHuffmanCodec(
|
|
uint32_t prev_opcode) const {
|
|
if (prev_opcode == SpvOpNop)
|
|
return opcode_and_num_operands_huffman_codec_.get();
|
|
|
|
const auto it =
|
|
opcode_and_num_operands_markov_huffman_codecs_.find(prev_opcode);
|
|
if (it == opcode_and_num_operands_markov_huffman_codecs_.end())
|
|
return nullptr;
|
|
return it->second.get();
|
|
}
|
|
|
|
// Returns a codec for common non-id words used for given operand slot.
|
|
// Operand slot is defined by the opcode and the operand index.
|
|
// May return nullptr if the codec doesn't exist.
|
|
const HuffmanCodec<uint64_t>* GetNonIdWordHuffmanCodec(
|
|
uint32_t opcode, uint32_t operand_index) const {
|
|
const auto it = non_id_word_huffman_codecs_.find(
|
|
std::pair<uint32_t, uint32_t>(opcode, operand_index));
|
|
if (it == non_id_word_huffman_codecs_.end()) return nullptr;
|
|
return it->second.get();
|
|
}
|
|
|
|
// Returns a codec for common id descriptos used for given operand slot.
|
|
// Operand slot is defined by the opcode and the operand index.
|
|
// May return nullptr if the codec doesn't exist.
|
|
const HuffmanCodec<uint64_t>* GetIdDescriptorHuffmanCodec(
|
|
uint32_t opcode, uint32_t operand_index) const {
|
|
const auto it = id_descriptor_huffman_codecs_.find(
|
|
std::pair<uint32_t, uint32_t>(opcode, operand_index));
|
|
if (it == id_descriptor_huffman_codecs_.end()) return nullptr;
|
|
return it->second.get();
|
|
}
|
|
|
|
// Returns a codec for common strings used by the given opcode.
|
|
// Operand slot is defined by the opcode and the operand index.
|
|
// May return nullptr if the codec doesn't exist.
|
|
const HuffmanCodec<std::string>* GetLiteralStringHuffmanCodec(
|
|
uint32_t opcode) const {
|
|
const auto it = literal_string_huffman_codecs_.find(opcode);
|
|
if (it == literal_string_huffman_codecs_.end()) return nullptr;
|
|
return it->second.get();
|
|
}
|
|
|
|
// Checks if |descriptor| has a coding scheme in any of
|
|
// id_descriptor_huffman_codecs_.
|
|
bool DescriptorHasCodingScheme(uint32_t descriptor) const {
|
|
return descriptors_with_coding_scheme_.count(descriptor);
|
|
}
|
|
|
|
// Checks if any descriptor has a coding scheme.
|
|
bool AnyDescriptorHasCodingScheme() const {
|
|
return !descriptors_with_coding_scheme_.empty();
|
|
}
|
|
|
|
// Returns chunk length used for variable length encoding of spirv operand
|
|
// words.
|
|
uint32_t GetOperandVariableWidthChunkLength(spv_operand_type_t type) const {
|
|
return operand_chunk_lengths_.at(static_cast<size_t>(type));
|
|
}
|
|
|
|
// Sets model type.
|
|
void SetModelType(uint32_t in_model_type) { model_type_ = in_model_type; }
|
|
|
|
// Sets model version.
|
|
void SetModelVersion(uint32_t in_model_version) {
|
|
model_version_ = in_model_version;
|
|
}
|
|
|
|
// Returns value used by Huffman codecs as a signal that a value is not in the
|
|
// coding table.
|
|
static uint64_t GetMarkvNoneOfTheAbove() {
|
|
// Magic number.
|
|
return 1111111111111111111;
|
|
}
|
|
|
|
MarkvModel(const MarkvModel&) = delete;
|
|
const MarkvModel& operator=(const MarkvModel&) = delete;
|
|
|
|
protected:
|
|
// Huffman codec for base-rate of opcode_and_num_operands.
|
|
std::unique_ptr<HuffmanCodec<uint64_t>>
|
|
opcode_and_num_operands_huffman_codec_;
|
|
|
|
// Huffman codecs for opcode_and_num_operands. The map key is previous opcode.
|
|
std::map<uint32_t, std::unique_ptr<HuffmanCodec<uint64_t>>>
|
|
opcode_and_num_operands_markov_huffman_codecs_;
|
|
|
|
// Huffman codecs for non-id single-word operand values.
|
|
// The map key is pair <opcode, operand_index>.
|
|
std::map<std::pair<uint32_t, uint32_t>,
|
|
std::unique_ptr<HuffmanCodec<uint64_t>>>
|
|
non_id_word_huffman_codecs_;
|
|
|
|
// Huffman codecs for id descriptors. The map key is pair
|
|
// <opcode, operand_index>.
|
|
std::map<std::pair<uint32_t, uint32_t>,
|
|
std::unique_ptr<HuffmanCodec<uint64_t>>>
|
|
id_descriptor_huffman_codecs_;
|
|
|
|
// Set of all descriptors which have a coding scheme in any of
|
|
// id_descriptor_huffman_codecs_.
|
|
std::unordered_set<uint32_t> descriptors_with_coding_scheme_;
|
|
|
|
// Huffman codecs for literal strings. The map key is the opcode of the
|
|
// current instruction. This assumes, that there is no more than one literal
|
|
// string operand per instruction, but would still work even if this is not
|
|
// the case. Names and debug information strings are not collected.
|
|
std::map<uint32_t, std::unique_ptr<HuffmanCodec<std::string>>>
|
|
literal_string_huffman_codecs_;
|
|
|
|
// Chunk lengths used for variable width encoding of operands (index is
|
|
// spv_operand_type of the operand).
|
|
std::vector<uint32_t> operand_chunk_lengths_;
|
|
|
|
uint32_t opcode_chunk_length_ = 7;
|
|
uint32_t num_operands_chunk_length_ = 3;
|
|
uint32_t mtf_rank_chunk_length_ = 5;
|
|
|
|
uint32_t u64_chunk_length_ = 8;
|
|
uint32_t s64_chunk_length_ = 8;
|
|
uint32_t s64_block_exponent_ = 10;
|
|
|
|
IdFallbackStrategy id_fallback_strategy_ =
|
|
IdFallbackStrategy::kShortDescriptor;
|
|
|
|
uint32_t model_type_ = 0;
|
|
uint32_t model_version_ = 0;
|
|
};
|
|
|
|
} // namespace comp
|
|
} // namespace spvtools
|
|
|
|
#endif // SOURCE_COMP_MARKV_MODEL_H_
|