mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-12-01 07:20:05 +00:00
1963a2dbda
This CL replaces instances of reset(new ..) with MakeUnique.
168 lines
6.6 KiB
C++
168 lines
6.6 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.
|
|
|
|
#include "source/comp/bit_stream.h"
|
|
#include "source/comp/markv.h"
|
|
#include "source/comp/markv_codec.h"
|
|
#include "source/comp/markv_logger.h"
|
|
#include "source/util/make_unique.h"
|
|
|
|
#ifndef SOURCE_COMP_MARKV_ENCODER_H_
|
|
#define SOURCE_COMP_MARKV_ENCODER_H_
|
|
|
|
#include <cstring>
|
|
|
|
namespace spvtools {
|
|
namespace comp {
|
|
|
|
// SPIR-V to MARK-V encoder. Exposes functions EncodeHeader and
|
|
// EncodeInstruction which can be used as callback by spvBinaryParse.
|
|
// Encoded binary is written to an internally maintained bitstream.
|
|
// After the last instruction is encoded, the resulting MARK-V binary can be
|
|
// acquired by calling GetMarkvBinary().
|
|
//
|
|
// The encoder uses SPIR-V validator to keep internal state, therefore
|
|
// SPIR-V binary needs to be able to pass validator checks.
|
|
// CreateCommentsLogger() can be used to enable the encoder to write comments
|
|
// on how encoding was done, which can later be accessed with GetComments().
|
|
class MarkvEncoder : public MarkvCodec {
|
|
public:
|
|
// |model| is owned by the caller, must be not null and valid during the
|
|
// lifetime of MarkvEncoder.
|
|
MarkvEncoder(spv_const_context context, const MarkvCodecOptions& options,
|
|
const MarkvModel* model)
|
|
: MarkvCodec(context, GetValidatorOptions(options), model),
|
|
options_(options) {}
|
|
~MarkvEncoder() override = default;
|
|
|
|
// Writes data from SPIR-V header to MARK-V header.
|
|
spv_result_t EncodeHeader(spv_endianness_t /* endian */, uint32_t /* magic */,
|
|
uint32_t version, uint32_t generator,
|
|
uint32_t id_bound, uint32_t /* schema */) {
|
|
SetIdBound(id_bound);
|
|
header_.spirv_version = version;
|
|
header_.spirv_generator = generator;
|
|
return SPV_SUCCESS;
|
|
}
|
|
|
|
// Creates an internal logger which writes comments on the encoding process.
|
|
void CreateLogger(MarkvLogConsumer log_consumer,
|
|
MarkvDebugConsumer debug_consumer) {
|
|
logger_ = MakeUnique<MarkvLogger>(log_consumer, debug_consumer);
|
|
writer_.SetCallback(
|
|
[this](const std::string& str) { logger_->AppendBitSequence(str); });
|
|
}
|
|
|
|
// Encodes SPIR-V instruction to MARK-V and writes to bit stream.
|
|
// Operation can fail if the instruction fails to pass the validator or if
|
|
// the encoder stubmles on something unexpected.
|
|
spv_result_t EncodeInstruction(const spv_parsed_instruction_t& inst);
|
|
|
|
// Concatenates MARK-V header and the bit stream with encoded instructions
|
|
// into a single buffer and returns it as spv_markv_binary. The returned
|
|
// value is owned by the caller and needs to be destroyed with
|
|
// spvMarkvBinaryDestroy().
|
|
std::vector<uint8_t> GetMarkvBinary() {
|
|
header_.markv_length_in_bits =
|
|
static_cast<uint32_t>(sizeof(header_) * 8 + writer_.GetNumBits());
|
|
header_.markv_model =
|
|
(model_->model_type() << 16) | model_->model_version();
|
|
|
|
const size_t num_bytes = sizeof(header_) + writer_.GetDataSizeBytes();
|
|
std::vector<uint8_t> markv(num_bytes);
|
|
|
|
assert(writer_.GetData());
|
|
std::memcpy(markv.data(), &header_, sizeof(header_));
|
|
std::memcpy(markv.data() + sizeof(header_), writer_.GetData(),
|
|
writer_.GetDataSizeBytes());
|
|
return markv;
|
|
}
|
|
|
|
// Optionally adds disassembly to the comments.
|
|
// Disassembly should contain all instructions in the module separated by
|
|
// \n, and no header.
|
|
void SetDisassembly(std::string&& disassembly) {
|
|
disassembly_ = MakeUnique<std::stringstream>(std::move(disassembly));
|
|
}
|
|
|
|
// Extracts the next instruction line from the disassembly and logs it.
|
|
void LogDisassemblyInstruction() {
|
|
if (logger_ && disassembly_) {
|
|
std::string line;
|
|
std::getline(*disassembly_, line, '\n');
|
|
logger_->AppendTextNewLine(line);
|
|
}
|
|
}
|
|
|
|
private:
|
|
// Creates and returns validator options. Returned value owned by the caller.
|
|
static spv_validator_options GetValidatorOptions(
|
|
const MarkvCodecOptions& options) {
|
|
return options.validate_spirv_binary ? spvValidatorOptionsCreate()
|
|
: nullptr;
|
|
}
|
|
|
|
// Writes a single word to bit stream. operand_.type determines if the word is
|
|
// encoded and how.
|
|
spv_result_t EncodeNonIdWord(uint32_t word);
|
|
|
|
// Writes both opcode and num_operands as a single code.
|
|
// Returns SPV_UNSUPPORTED iff no suitable codec was found.
|
|
spv_result_t EncodeOpcodeAndNumOperands(uint32_t opcode,
|
|
uint32_t num_operands);
|
|
|
|
// Writes mtf rank to bit stream. |mtf| is used to determine the codec
|
|
// scheme. |fallback_method| is used if no codec defined for |mtf|.
|
|
spv_result_t EncodeMtfRankHuffman(uint32_t rank, uint64_t mtf,
|
|
uint64_t fallback_method);
|
|
|
|
// Writes id using coding based on mtf associated with the id descriptor.
|
|
// Returns SPV_UNSUPPORTED iff fallback method needs to be used.
|
|
spv_result_t EncodeIdWithDescriptor(uint32_t id);
|
|
|
|
// Writes id using coding based on the given |mtf|, which is expected to
|
|
// contain the given |id|.
|
|
spv_result_t EncodeExistingId(uint64_t mtf, uint32_t id);
|
|
|
|
// Writes type id of the current instruction if can't be inferred.
|
|
spv_result_t EncodeTypeId();
|
|
|
|
// Writes result id of the current instruction if can't be inferred.
|
|
spv_result_t EncodeResultId();
|
|
|
|
// Writes ids which are neither type nor result ids.
|
|
spv_result_t EncodeRefId(uint32_t id);
|
|
|
|
// Writes bits to the stream until the beginning of the next byte if the
|
|
// number of bits until the next byte is less than |byte_break_if_less_than|.
|
|
void AddByteBreak(size_t byte_break_if_less_than);
|
|
|
|
// Encodes a literal number operand and writes it to the bit stream.
|
|
spv_result_t EncodeLiteralNumber(const spv_parsed_operand_t& operand);
|
|
|
|
MarkvCodecOptions options_;
|
|
|
|
// Bit stream where encoded instructions are written.
|
|
BitWriterWord64 writer_;
|
|
|
|
// If not nullptr, disassembled instruction lines will be written to comments.
|
|
// Format: \n separated instruction lines, no header.
|
|
std::unique_ptr<std::stringstream> disassembly_;
|
|
};
|
|
|
|
} // namespace comp
|
|
} // namespace spvtools
|
|
|
|
#endif // SOURCE_COMP_MARKV_ENCODER_H_
|