mirror of
https://github.com/KhronosGroup/SPIRV-Tools
synced 2024-10-18 11:10:05 +00:00
Refactored compression debugger
Markv codec now receives two optional callbacks: LogConsumer for internal codec logging DebugConsumer for testing if encoding->decoding produces the original results.
This commit is contained in:
parent
8d6e4dbc72
commit
cfd95f3d5a
@ -29,35 +29,51 @@
|
|||||||
|
|
||||||
namespace spvtools {
|
namespace spvtools {
|
||||||
|
|
||||||
struct MarkvEncoderOptions {
|
struct MarkvCodecOptions {
|
||||||
bool validate_spirv_binary = false;
|
bool validate_spirv_binary = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MarkvDecoderOptions {
|
// Debug callback. Called once per instruction.
|
||||||
bool validate_spirv_binary = false;
|
// |words| is instruction SPIR-V words.
|
||||||
};
|
// |bits| is a textual representation of the MARK-V bit sequence used to encode
|
||||||
|
// the instruction (char '0' for 0, char '1' for 1).
|
||||||
|
// |comment| contains all logs generated while processing the instruction.
|
||||||
|
using MarkvDebugConsumer = std::function<bool(
|
||||||
|
const std::vector<uint32_t>& words, const std::string& bits,
|
||||||
|
const std::string& comment)>;
|
||||||
|
|
||||||
|
// Logging callback. Called often (if decoder reads a single bit, the log
|
||||||
|
// consumer will receive 1 character string with that bit).
|
||||||
|
// This callback is more suitable for continous output than MarkvDebugConsumer,
|
||||||
|
// for example if the codec crashes it would allow to pinpoint on which operand
|
||||||
|
// or bit the crash happened.
|
||||||
|
// |snippet| could be any atomic fragment of text logged by the codec. It can
|
||||||
|
// contain a paragraph of text with newlines, or can be just one character.
|
||||||
|
using MarkvLogConsumer = std::function<void(const std::string& snippet)>;
|
||||||
|
|
||||||
// Encodes the given SPIR-V binary to MARK-V binary.
|
// Encodes the given SPIR-V binary to MARK-V binary.
|
||||||
// If |comments| is not nullptr, it would contain a textual description of
|
// |log_consumer| is optional (pass MarkvLogConsumer() to disable).
|
||||||
// how encoding was done (with snippets of disassembly and bit sequences).
|
// |debug_consumer| is optional (pass MarkvDebugConsumer() to disable).
|
||||||
spv_result_t SpirvToMarkv(spv_const_context context,
|
spv_result_t SpirvToMarkv(spv_const_context context,
|
||||||
const std::vector<uint32_t>& spirv,
|
const std::vector<uint32_t>& spirv,
|
||||||
const MarkvEncoderOptions& options,
|
const MarkvCodecOptions& options,
|
||||||
const MarkvModel& markv_model,
|
const MarkvModel& markv_model,
|
||||||
MessageConsumer message_consumer,
|
MessageConsumer message_consumer,
|
||||||
std::vector<uint8_t>* markv,
|
MarkvLogConsumer log_consumer,
|
||||||
std::string* comments);
|
MarkvDebugConsumer debug_consumer,
|
||||||
|
std::vector<uint8_t>* markv);
|
||||||
|
|
||||||
// Decodes a SPIR-V binary from the given MARK-V binary.
|
// Decodes a SPIR-V binary from the given MARK-V binary.
|
||||||
// If |comments| is not nullptr, it would contain a textual description of
|
// |log_consumer| is optional (pass MarkvLogConsumer() to disable).
|
||||||
// how decoding was done (with snippets of disassembly and bit sequences).
|
// |debug_consumer| is optional (pass MarkvDebugConsumer() to disable).
|
||||||
spv_result_t MarkvToSpirv(spv_const_context context,
|
spv_result_t MarkvToSpirv(spv_const_context context,
|
||||||
const std::vector<uint8_t>& markv,
|
const std::vector<uint8_t>& markv,
|
||||||
const MarkvDecoderOptions& options,
|
const MarkvCodecOptions& options,
|
||||||
const MarkvModel& markv_model,
|
const MarkvModel& markv_model,
|
||||||
MessageConsumer message_consumer,
|
MessageConsumer message_consumer,
|
||||||
std::vector<uint32_t>* spirv,
|
MarkvLogConsumer log_consumer,
|
||||||
std::string* comments);
|
MarkvDebugConsumer debug_consumer,
|
||||||
|
std::vector<uint32_t>* spirv);
|
||||||
|
|
||||||
} // namespace spvtools
|
} // namespace spvtools
|
||||||
|
|
||||||
|
@ -64,7 +64,6 @@ using libspirv::IdDescriptorCollection;
|
|||||||
using libspirv::Instruction;
|
using libspirv::Instruction;
|
||||||
using libspirv::ValidationState_t;
|
using libspirv::ValidationState_t;
|
||||||
using libspirv::DiagnosticStream;
|
using libspirv::DiagnosticStream;
|
||||||
using spvtools::ValidateInstructionAndUpdateValidationState;
|
|
||||||
using spvutils::BitReaderWord64;
|
using spvutils::BitReaderWord64;
|
||||||
using spvutils::BitWriterWord64;
|
using spvutils::BitWriterWord64;
|
||||||
using spvutils::HuffmanCodec;
|
using spvutils::HuffmanCodec;
|
||||||
@ -276,8 +275,11 @@ uint32_t GetMarkvVersion() {
|
|||||||
return kVersionMinor | (kVersionMajor << 16);
|
return kVersionMinor | (kVersionMajor << 16);
|
||||||
}
|
}
|
||||||
|
|
||||||
class CommentLogger {
|
class MarkvLogger {
|
||||||
public:
|
public:
|
||||||
|
MarkvLogger(MarkvLogConsumer log_consumer, MarkvDebugConsumer debug_consumer)
|
||||||
|
: log_consumer_(log_consumer), debug_consumer_(debug_consumer) {}
|
||||||
|
|
||||||
void AppendText(const std::string& str) {
|
void AppendText(const std::string& str) {
|
||||||
Append(str);
|
Append(str);
|
||||||
use_delimiter_ = false;
|
use_delimiter_ = false;
|
||||||
@ -290,6 +292,8 @@ class CommentLogger {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void AppendBitSequence(const std::string& str) {
|
void AppendBitSequence(const std::string& str) {
|
||||||
|
if (debug_consumer_)
|
||||||
|
instruction_bits_ << str;
|
||||||
if (use_delimiter_)
|
if (use_delimiter_)
|
||||||
Append("-");
|
Append("-");
|
||||||
Append(str);
|
Append(str);
|
||||||
@ -306,17 +310,36 @@ class CommentLogger {
|
|||||||
use_delimiter_ = false;
|
use_delimiter_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetText() const {
|
bool DebugInstruction(const spv_parsed_instruction_t& inst) {
|
||||||
return ss_.str();
|
bool result = true;
|
||||||
|
if (debug_consumer_) {
|
||||||
|
result = debug_consumer_(
|
||||||
|
std::vector<uint32_t>(inst.words, inst.words + inst.num_words),
|
||||||
|
instruction_bits_.str(), instruction_comment_.str());
|
||||||
|
instruction_bits_.str(std::string());
|
||||||
|
instruction_comment_.str(std::string());
|
||||||
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
MarkvLogger(const MarkvLogger&) = delete;
|
||||||
|
MarkvLogger(MarkvLogger&&) = delete;
|
||||||
|
MarkvLogger& operator=(const MarkvLogger&) = delete;
|
||||||
|
MarkvLogger& operator=(MarkvLogger&&) = delete;
|
||||||
|
|
||||||
void Append(const std::string& str) {
|
void Append(const std::string& str) {
|
||||||
ss_ << str;
|
if (log_consumer_)
|
||||||
// std::cerr << str;
|
log_consumer_(str);
|
||||||
|
if (debug_consumer_)
|
||||||
|
instruction_comment_ << str;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::stringstream ss_;
|
MarkvLogConsumer log_consumer_;
|
||||||
|
MarkvDebugConsumer debug_consumer_;
|
||||||
|
|
||||||
|
std::stringstream instruction_bits_;
|
||||||
|
std::stringstream instruction_comment_;
|
||||||
|
|
||||||
// If true a delimiter will be appended before the next bit sequence.
|
// If true a delimiter will be appended before the next bit sequence.
|
||||||
// Used to generate outputs like: 1100-0 1110-1-1100-1-1111-0 110-0.
|
// Used to generate outputs like: 1100-0 1110-1-1100-1-1111-0 110-0.
|
||||||
@ -547,6 +570,9 @@ class MarkvCodecBase {
|
|||||||
std::map<uint64_t, std::unique_ptr<HuffmanCodec<uint32_t>>>
|
std::map<uint64_t, std::unique_ptr<HuffmanCodec<uint32_t>>>
|
||||||
mtf_huffman_codecs_;
|
mtf_huffman_codecs_;
|
||||||
|
|
||||||
|
// If not nullptr, codec will log comments on the compression process.
|
||||||
|
std::unique_ptr<MarkvLogger> logger_;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
spv_const_context context_ = nullptr;
|
spv_const_context context_ = nullptr;
|
||||||
|
|
||||||
@ -572,7 +598,7 @@ class MarkvEncoder : public MarkvCodecBase {
|
|||||||
// |model| is owned by the caller, must be not null and valid during the
|
// |model| is owned by the caller, must be not null and valid during the
|
||||||
// lifetime of MarkvEncoder.
|
// lifetime of MarkvEncoder.
|
||||||
MarkvEncoder(spv_const_context context,
|
MarkvEncoder(spv_const_context context,
|
||||||
const MarkvEncoderOptions& options,
|
const MarkvCodecOptions& options,
|
||||||
const MarkvModel* model)
|
const MarkvModel* model)
|
||||||
: MarkvCodecBase(context, GetValidatorOptions(options), model),
|
: MarkvCodecBase(context, GetValidatorOptions(options), model),
|
||||||
options_(options) {
|
options_(options) {
|
||||||
@ -590,6 +616,15 @@ class MarkvEncoder : public MarkvCodecBase {
|
|||||||
return SPV_SUCCESS;
|
return SPV_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Creates an internal logger which writes comments on the encoding process.
|
||||||
|
void CreateLogger(MarkvLogConsumer log_consumer,
|
||||||
|
MarkvDebugConsumer debug_consumer) {
|
||||||
|
logger_.reset(new 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.
|
// 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
|
// Operation can fail if the instruction fails to pass the validator or if
|
||||||
// the encoder stubmles on something unexpected.
|
// the encoder stubmles on something unexpected.
|
||||||
@ -615,15 +650,6 @@ class MarkvEncoder : public MarkvCodecBase {
|
|||||||
return markv;
|
return markv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creates an internal logger which writes comments on the encoding process.
|
|
||||||
// Output can later be accessed with GetComments().
|
|
||||||
void CreateCommentsLogger() {
|
|
||||||
logger_.reset(new CommentLogger());
|
|
||||||
writer_.SetCallback([this](const std::string& str){
|
|
||||||
logger_->AppendBitSequence(str);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Optionally adds disassembly to the comments.
|
// Optionally adds disassembly to the comments.
|
||||||
// Disassembly should contain all instructions in the module separated by
|
// Disassembly should contain all instructions in the module separated by
|
||||||
// \n, and no header.
|
// \n, and no header.
|
||||||
@ -640,17 +666,10 @@ class MarkvEncoder : public MarkvCodecBase {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Extracts the text from the comment logger.
|
|
||||||
std::string GetComments() const {
|
|
||||||
if (!logger_)
|
|
||||||
return "";
|
|
||||||
return logger_->GetText();
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// Creates and returns validator options. Returned value owned by the caller.
|
// Creates and returns validator options. Returned value owned by the caller.
|
||||||
static spv_validator_options GetValidatorOptions(
|
static spv_validator_options GetValidatorOptions(
|
||||||
const MarkvEncoderOptions& options) {
|
const MarkvCodecOptions& options) {
|
||||||
return options.validate_spirv_binary ?
|
return options.validate_spirv_binary ?
|
||||||
spvValidatorOptionsCreate() : nullptr;
|
spvValidatorOptionsCreate() : nullptr;
|
||||||
}
|
}
|
||||||
@ -692,14 +711,11 @@ class MarkvEncoder : public MarkvCodecBase {
|
|||||||
// Encodes a literal number operand and writes it to the bit stream.
|
// Encodes a literal number operand and writes it to the bit stream.
|
||||||
spv_result_t EncodeLiteralNumber(const spv_parsed_operand_t& operand);
|
spv_result_t EncodeLiteralNumber(const spv_parsed_operand_t& operand);
|
||||||
|
|
||||||
MarkvEncoderOptions options_;
|
MarkvCodecOptions options_;
|
||||||
|
|
||||||
// Bit stream where encoded instructions are written.
|
// Bit stream where encoded instructions are written.
|
||||||
BitWriterWord64 writer_;
|
BitWriterWord64 writer_;
|
||||||
|
|
||||||
// If not nullptr, encoder will write comments.
|
|
||||||
std::unique_ptr<CommentLogger> logger_;
|
|
||||||
|
|
||||||
// If not nullptr, disassembled instruction lines will be written to comments.
|
// If not nullptr, disassembled instruction lines will be written to comments.
|
||||||
// Format: \n separated instruction lines, no header.
|
// Format: \n separated instruction lines, no header.
|
||||||
std::unique_ptr<std::stringstream> disassembly_;
|
std::unique_ptr<std::stringstream> disassembly_;
|
||||||
@ -712,7 +728,7 @@ class MarkvDecoder : public MarkvCodecBase {
|
|||||||
// lifetime of MarkvEncoder.
|
// lifetime of MarkvEncoder.
|
||||||
MarkvDecoder(spv_const_context context,
|
MarkvDecoder(spv_const_context context,
|
||||||
const std::vector<uint8_t>& markv,
|
const std::vector<uint8_t>& markv,
|
||||||
const MarkvDecoderOptions& options,
|
const MarkvCodecOptions& options,
|
||||||
const MarkvModel* model)
|
const MarkvModel* model)
|
||||||
: MarkvCodecBase(context, GetValidatorOptions(options), model),
|
: MarkvCodecBase(context, GetValidatorOptions(options), model),
|
||||||
options_(options), reader_(markv) {
|
options_(options), reader_(markv) {
|
||||||
@ -722,6 +738,12 @@ class MarkvDecoder : public MarkvCodecBase {
|
|||||||
inst_words_.reserve(25);
|
inst_words_.reserve(25);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Creates an internal logger which writes comments on the decoding process.
|
||||||
|
void CreateLogger(MarkvLogConsumer log_consumer,
|
||||||
|
MarkvDebugConsumer debug_consumer) {
|
||||||
|
logger_.reset(new MarkvLogger(log_consumer, debug_consumer));
|
||||||
|
}
|
||||||
|
|
||||||
// Decodes SPIR-V from MARK-V and stores the words in |spirv_binary|.
|
// Decodes SPIR-V from MARK-V and stores the words in |spirv_binary|.
|
||||||
// Can be called only once. Fails if data of wrong format or ends prematurely,
|
// Can be called only once. Fails if data of wrong format or ends prematurely,
|
||||||
// of if validation fails.
|
// of if validation fails.
|
||||||
@ -736,7 +758,7 @@ class MarkvDecoder : public MarkvCodecBase {
|
|||||||
|
|
||||||
// Creates and returns validator options. Returned value owned by the caller.
|
// Creates and returns validator options. Returned value owned by the caller.
|
||||||
static spv_validator_options GetValidatorOptions(
|
static spv_validator_options GetValidatorOptions(
|
||||||
const MarkvDecoderOptions& options) {
|
const MarkvCodecOptions& options) {
|
||||||
return options.validate_spirv_binary ?
|
return options.validate_spirv_binary ?
|
||||||
spvValidatorOptionsCreate() : nullptr;
|
spvValidatorOptionsCreate() : nullptr;
|
||||||
}
|
}
|
||||||
@ -822,7 +844,7 @@ class MarkvDecoder : public MarkvCodecBase {
|
|||||||
// kind SPV_NUMBER_NONE.
|
// kind SPV_NUMBER_NONE.
|
||||||
void RecordNumberType();
|
void RecordNumberType();
|
||||||
|
|
||||||
MarkvDecoderOptions options_;
|
MarkvCodecOptions options_;
|
||||||
|
|
||||||
// Temporary sink where decoded SPIR-V words are written. Once it contains the
|
// Temporary sink where decoded SPIR-V words are written. Once it contains the
|
||||||
// entire module, the container is moved and returned.
|
// entire module, the container is moved and returned.
|
||||||
@ -2260,6 +2282,8 @@ spv_result_t MarkvEncoder::EncodeInstruction(
|
|||||||
if (logger_) {
|
if (logger_) {
|
||||||
logger_->NewLine();
|
logger_->NewLine();
|
||||||
logger_->NewLine();
|
logger_->NewLine();
|
||||||
|
if (!logger_->DebugInstruction(inst_))
|
||||||
|
return SPV_REQUESTED_TERMINATION;
|
||||||
}
|
}
|
||||||
|
|
||||||
ProcessCurInstruction();
|
ProcessCurInstruction();
|
||||||
@ -2310,6 +2334,12 @@ spv_result_t MarkvDecoder::DecodeModule(std::vector<uint32_t>* spirv_binary) {
|
|||||||
spirv_[1] = header_.spirv_version;
|
spirv_[1] = header_.spirv_version;
|
||||||
spirv_[2] = header_.spirv_generator;
|
spirv_[2] = header_.spirv_generator;
|
||||||
|
|
||||||
|
if (logger_) {
|
||||||
|
reader_.SetCallback([this](const std::string& str){
|
||||||
|
logger_->AppendBitSequence(str);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
while (reader_.GetNumReadBits() < header_.markv_length_in_bits) {
|
while (reader_.GetNumReadBits() < header_.markv_length_in_bits) {
|
||||||
inst_ = {};
|
inst_ = {};
|
||||||
const spv_result_t decode_result = DecodeInstruction();
|
const spv_result_t decode_result = DecodeInstruction();
|
||||||
@ -2777,6 +2807,19 @@ spv_result_t MarkvDecoder::DecodeInstruction() {
|
|||||||
return Diag(SPV_ERROR_INVALID_BINARY)
|
return Diag(SPV_ERROR_INVALID_BINARY)
|
||||||
<< "Failed to read to byte break";
|
<< "Failed to read to byte break";
|
||||||
|
|
||||||
|
if (logger_) {
|
||||||
|
logger_->NewLine();
|
||||||
|
std::stringstream ss;
|
||||||
|
ss << spvOpcodeString(opcode) << " ";
|
||||||
|
for (size_t index = 1; index < inst_words_.size(); ++index)
|
||||||
|
ss << inst_words_[index] << " ";
|
||||||
|
logger_->AppendText(ss.str());
|
||||||
|
logger_->NewLine();
|
||||||
|
logger_->NewLine();
|
||||||
|
if (!logger_->DebugInstruction(inst_))
|
||||||
|
return SPV_REQUESTED_TERMINATION;
|
||||||
|
}
|
||||||
|
|
||||||
return SPV_SUCCESS;
|
return SPV_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2839,11 +2882,12 @@ spv_result_t EncodeInstruction(
|
|||||||
|
|
||||||
spv_result_t SpirvToMarkv(spv_const_context context,
|
spv_result_t SpirvToMarkv(spv_const_context context,
|
||||||
const std::vector<uint32_t>& spirv,
|
const std::vector<uint32_t>& spirv,
|
||||||
const MarkvEncoderOptions& options,
|
const MarkvCodecOptions& options,
|
||||||
const MarkvModel& markv_model,
|
const MarkvModel& markv_model,
|
||||||
MessageConsumer message_consumer,
|
MessageConsumer message_consumer,
|
||||||
std::vector<uint8_t>* markv,
|
MarkvLogConsumer log_consumer,
|
||||||
std::string* comments) {
|
MarkvDebugConsumer debug_consumer,
|
||||||
|
std::vector<uint8_t>* markv) {
|
||||||
spv_context_t hijack_context = *context;
|
spv_context_t hijack_context = *context;
|
||||||
SetContextMessageConsumer(&hijack_context, message_consumer);
|
SetContextMessageConsumer(&hijack_context, message_consumer);
|
||||||
|
|
||||||
@ -2866,8 +2910,8 @@ spv_result_t SpirvToMarkv(spv_const_context context,
|
|||||||
|
|
||||||
MarkvEncoder encoder(&hijack_context, options, &markv_model);
|
MarkvEncoder encoder(&hijack_context, options, &markv_model);
|
||||||
|
|
||||||
if (comments) {
|
if (log_consumer || debug_consumer) {
|
||||||
encoder.CreateCommentsLogger();
|
encoder.CreateLogger(log_consumer, debug_consumer);
|
||||||
|
|
||||||
spv_text text = nullptr;
|
spv_text text = nullptr;
|
||||||
if (spvBinaryToText(&hijack_context, spirv.data(), spirv.size(),
|
if (spvBinaryToText(&hijack_context, spirv.data(), spirv.size(),
|
||||||
@ -2890,26 +2934,27 @@ spv_result_t SpirvToMarkv(spv_const_context context,
|
|||||||
<< "Unable to encode to MARK-V.";
|
<< "Unable to encode to MARK-V.";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (comments)
|
|
||||||
*comments = encoder.GetComments();
|
|
||||||
|
|
||||||
*markv = encoder.GetMarkvBinary();
|
*markv = encoder.GetMarkvBinary();
|
||||||
return SPV_SUCCESS;
|
return SPV_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
spv_result_t MarkvToSpirv(spv_const_context context,
|
spv_result_t MarkvToSpirv(spv_const_context context,
|
||||||
const std::vector<uint8_t>& markv,
|
const std::vector<uint8_t>& markv,
|
||||||
const MarkvDecoderOptions& options,
|
const MarkvCodecOptions& options,
|
||||||
const MarkvModel& markv_model,
|
const MarkvModel& markv_model,
|
||||||
MessageConsumer message_consumer,
|
MessageConsumer message_consumer,
|
||||||
std::vector<uint32_t>* spirv,
|
MarkvLogConsumer log_consumer,
|
||||||
std::string* /* comments */) {
|
MarkvDebugConsumer debug_consumer,
|
||||||
|
std::vector<uint32_t>* spirv) {
|
||||||
spv_position_t position = {};
|
spv_position_t position = {};
|
||||||
spv_context_t hijack_context = *context;
|
spv_context_t hijack_context = *context;
|
||||||
SetContextMessageConsumer(&hijack_context, message_consumer);
|
SetContextMessageConsumer(&hijack_context, message_consumer);
|
||||||
|
|
||||||
MarkvDecoder decoder(&hijack_context, markv, options, &markv_model);
|
MarkvDecoder decoder(&hijack_context, markv, options, &markv_model);
|
||||||
|
|
||||||
|
if (log_consumer || debug_consumer)
|
||||||
|
decoder.CreateLogger(log_consumer, debug_consumer);
|
||||||
|
|
||||||
if (decoder.DecodeModule(spirv) != SPV_SUCCESS) {
|
if (decoder.DecodeModule(spirv) != SPV_SUCCESS) {
|
||||||
return DiagnosticStream(position, hijack_context.consumer,
|
return DiagnosticStream(position, hijack_context.consumer,
|
||||||
SPV_ERROR_INVALID_BINARY)
|
SPV_ERROR_INVALID_BINARY)
|
||||||
|
@ -414,6 +414,7 @@ size_t BitReaderWord64::ReadBits(uint64_t* bits, size_t num_bits) {
|
|||||||
|
|
||||||
if (pos_ >= buffer_.size() * 64) {
|
if (pos_ >= buffer_.size() * 64) {
|
||||||
// Reached end of buffer_.
|
// Reached end of buffer_.
|
||||||
|
EmitSequence(*bits, num_read_from_first_word);
|
||||||
return num_read_from_first_word;
|
return num_read_from_first_word;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -426,6 +427,7 @@ size_t BitReaderWord64::ReadBits(uint64_t* bits, size_t num_bits) {
|
|||||||
|
|
||||||
// We likely have written more bits than requested. Clear excessive bits.
|
// We likely have written more bits than requested. Clear excessive bits.
|
||||||
*bits = GetLowerBits(*bits, num_bits);
|
*bits = GetLowerBits(*bits, num_bits);
|
||||||
|
EmitSequence(*bits, num_bits);
|
||||||
return num_bits;
|
return num_bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -436,9 +436,26 @@ class BitReaderWord64 : public BitReaderInterface {
|
|||||||
bool OnlyZeroesLeft() const override;
|
bool OnlyZeroesLeft() const override;
|
||||||
|
|
||||||
BitReaderWord64() = delete;
|
BitReaderWord64() = delete;
|
||||||
|
|
||||||
|
// Sets callback to emit bit sequences after every read.
|
||||||
|
void SetCallback(std::function<void(const std::string&)> callback) {
|
||||||
|
callback_ = callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
// Sends string generated from arguments to callback_ if defined.
|
||||||
|
void EmitSequence(uint64_t bits, size_t num_bits) const {
|
||||||
|
if (callback_)
|
||||||
|
callback_(BitsToStream(bits, num_bits));
|
||||||
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const std::vector<uint64_t> buffer_;
|
const std::vector<uint64_t> buffer_;
|
||||||
size_t pos_;
|
size_t pos_;
|
||||||
|
|
||||||
|
// If not null, the reader will use the callback to emit the read bit
|
||||||
|
// sequence as a string of '0' and '1'.
|
||||||
|
std::function<void(const std::string&)> callback_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace spvutils
|
} // namespace spvutils
|
||||||
|
@ -89,8 +89,7 @@ void TestEncodeDecode(const std::string& original_text) {
|
|||||||
ScopedContext ctx(SPV_ENV_UNIVERSAL_1_2);
|
ScopedContext ctx(SPV_ENV_UNIVERSAL_1_2);
|
||||||
std::unique_ptr<spvtools::MarkvModel> model =
|
std::unique_ptr<spvtools::MarkvModel> model =
|
||||||
spvtools::CreateMarkvModel(spvtools::kMarkvModelShaderDefault);
|
spvtools::CreateMarkvModel(spvtools::kMarkvModelShaderDefault);
|
||||||
spvtools::MarkvEncoderOptions encoder_options;
|
spvtools::MarkvCodecOptions options;
|
||||||
spvtools::MarkvDecoderOptions decoder_options;
|
|
||||||
|
|
||||||
std::vector<uint32_t> expected_binary;
|
std::vector<uint32_t> expected_binary;
|
||||||
Compile(original_text, &expected_binary);
|
Compile(original_text, &expected_binary);
|
||||||
@ -105,26 +104,33 @@ void TestEncodeDecode(const std::string& original_text) {
|
|||||||
SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
SPV_TEXT_TO_BINARY_OPTION_PRESERVE_NUMERIC_IDS);
|
||||||
ASSERT_FALSE(binary_to_encode.empty());
|
ASSERT_FALSE(binary_to_encode.empty());
|
||||||
|
|
||||||
|
std::stringstream encoder_comments;
|
||||||
|
const auto output_to_string_stream =
|
||||||
|
[&encoder_comments](const std::string& str) {
|
||||||
|
encoder_comments << str;
|
||||||
|
};
|
||||||
|
|
||||||
std::vector<uint8_t> markv;
|
std::vector<uint8_t> markv;
|
||||||
std::string encoder_comments;
|
|
||||||
ASSERT_EQ(SPV_SUCCESS, spvtools::SpirvToMarkv(
|
ASSERT_EQ(SPV_SUCCESS, spvtools::SpirvToMarkv(
|
||||||
ctx.context, binary_to_encode, encoder_options, *model,
|
ctx.context, binary_to_encode, options, *model,
|
||||||
DiagnosticsMessageHandler, &markv, &encoder_comments));
|
DiagnosticsMessageHandler, output_to_string_stream,
|
||||||
|
spvtools::MarkvDebugConsumer(), &markv));
|
||||||
ASSERT_FALSE(markv.empty());
|
ASSERT_FALSE(markv.empty());
|
||||||
|
|
||||||
std::vector<uint32_t> decoded_binary;
|
std::vector<uint32_t> decoded_binary;
|
||||||
ASSERT_EQ(SPV_SUCCESS, spvtools::MarkvToSpirv(
|
ASSERT_EQ(SPV_SUCCESS, spvtools::MarkvToSpirv(
|
||||||
ctx.context, markv, decoder_options, *model,
|
ctx.context, markv, options, *model,
|
||||||
DiagnosticsMessageHandler, &decoded_binary, nullptr));
|
DiagnosticsMessageHandler, spvtools::MarkvLogConsumer(),
|
||||||
|
spvtools::MarkvDebugConsumer(), &decoded_binary));
|
||||||
ASSERT_FALSE(decoded_binary.empty());
|
ASSERT_FALSE(decoded_binary.empty());
|
||||||
|
|
||||||
EXPECT_EQ(expected_binary, decoded_binary) << encoder_comments;
|
EXPECT_EQ(expected_binary, decoded_binary) << encoder_comments.str();
|
||||||
|
|
||||||
std::string decoded_text;
|
std::string decoded_text;
|
||||||
Disassemble(decoded_binary, &decoded_text);
|
Disassemble(decoded_binary, &decoded_text);
|
||||||
ASSERT_FALSE(decoded_text.empty());
|
ASSERT_FALSE(decoded_text.empty());
|
||||||
|
|
||||||
EXPECT_EQ(expected_text, decoded_text) << encoder_comments;
|
EXPECT_EQ(expected_text, decoded_text) << encoder_comments.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
void TestEncodeDecodeShaderMainBody(const std::string& body) {
|
void TestEncodeDecodeShaderMainBody(const std::string& body) {
|
||||||
|
@ -65,7 +65,7 @@ if (NOT ${SPIRV_SKIP_EXECUTABLES})
|
|||||||
SRCS comp/markv.cpp
|
SRCS comp/markv.cpp
|
||||||
comp/markv_model_factory.cpp
|
comp/markv_model_factory.cpp
|
||||||
comp/markv_model_shader_default.cpp
|
comp/markv_model_shader_default.cpp
|
||||||
LIBS SPIRV-Tools-comp ${SPIRV_TOOLS})
|
LIBS SPIRV-Tools-comp SPIRV-Tools-opt ${SPIRV_TOOLS})
|
||||||
target_include_directories(spirv-markv PRIVATE ${spirv-tools_SOURCE_DIR}
|
target_include_directories(spirv-markv PRIVATE ${spirv-tools_SOURCE_DIR}
|
||||||
${SPIRV_HEADER_INCLUDE_DIR})
|
${SPIRV_HEADER_INCLUDE_DIR})
|
||||||
set(SPIRV_INSTALL_TARGETS ${SPIRV_INSTALL_TARGETS} spirv-markv)
|
set(SPIRV_INSTALL_TARGETS ${SPIRV_INSTALL_TARGETS} spirv-markv)
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
#include <algorithm>
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
@ -24,14 +25,18 @@
|
|||||||
#include "source/comp/markv.h"
|
#include "source/comp/markv.h"
|
||||||
#include "source/spirv_target_env.h"
|
#include "source/spirv_target_env.h"
|
||||||
#include "source/table.h"
|
#include "source/table.h"
|
||||||
|
#include "spirv-tools/optimizer.hpp"
|
||||||
#include "tools/io.h"
|
#include "tools/io.h"
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
const auto kSpvEnv = SPV_ENV_UNIVERSAL_1_2;
|
||||||
|
|
||||||
enum Task {
|
enum Task {
|
||||||
kNoTask = 0,
|
kNoTask = 0,
|
||||||
kEncode,
|
kEncode,
|
||||||
kDecode,
|
kDecode,
|
||||||
|
kTest,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ScopedContext {
|
struct ScopedContext {
|
||||||
@ -44,7 +49,7 @@ void print_usage(char* argv0) {
|
|||||||
printf(
|
printf(
|
||||||
R"(%s - Encodes or decodes a SPIR-V binary to or from a MARK-V binary.
|
R"(%s - Encodes or decodes a SPIR-V binary to or from a MARK-V binary.
|
||||||
|
|
||||||
USAGE: %s [e|d] [options] [<filename>]
|
USAGE: %s [e|d|t] [options] [<filename>]
|
||||||
|
|
||||||
The input binary is read from <filename>. If no file is specified,
|
The input binary is read from <filename>. If no file is specified,
|
||||||
or if the filename is "-", then the binary is read from standard input.
|
or if the filename is "-", then the binary is read from standard input.
|
||||||
@ -59,16 +64,19 @@ software is used (is doesn't write or handle version numbers yet).
|
|||||||
Tasks:
|
Tasks:
|
||||||
e Encode SPIR-V to MARK-V.
|
e Encode SPIR-V to MARK-V.
|
||||||
d Decode MARK-V to SPIR-V.
|
d Decode MARK-V to SPIR-V.
|
||||||
|
t Test the codec by first encoding the given SPIR-V file to
|
||||||
|
MARK-V, then decoding it back to SPIR-V and comparing results.
|
||||||
|
|
||||||
Options:
|
Options:
|
||||||
-h, --help Print this help.
|
-h, --help Print this help.
|
||||||
--comments Write codec comments to stdout.
|
--comments Write codec comments to stderr.
|
||||||
--version Display MARK-V codec version.
|
--version Display MARK-V codec version.
|
||||||
--validate Validate SPIR-V while encoding or decoding.
|
--validate Validate SPIR-V while encoding or decoding.
|
||||||
|
|
||||||
-o <filename> Set the output filename.
|
-o <filename> Set the output filename.
|
||||||
Output goes to standard output if this option is
|
Output goes to standard output if this option is
|
||||||
not specified, or if the filename is "-".
|
not specified, or if the filename is "-".
|
||||||
|
Not needed for 't' task (testing).
|
||||||
)",
|
)",
|
||||||
argv0, argv0);
|
argv0, argv0);
|
||||||
}
|
}
|
||||||
@ -84,11 +92,11 @@ void DiagnosticsMessageHandler(spv_message_level_t level, const char*,
|
|||||||
<< std::endl;
|
<< std::endl;
|
||||||
break;
|
break;
|
||||||
case SPV_MSG_WARNING:
|
case SPV_MSG_WARNING:
|
||||||
std::cout << "warning: " << position.index << ": " << message
|
std::cerr << "warning: " << position.index << ": " << message
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
break;
|
break;
|
||||||
case SPV_MSG_INFO:
|
case SPV_MSG_INFO:
|
||||||
std::cout << "info: " << position.index << ": " << message << std::endl;
|
std::cerr << "info: " << position.index << ": " << message << std::endl;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -113,6 +121,8 @@ int main(int argc, char** argv) {
|
|||||||
task = kEncode;
|
task = kEncode;
|
||||||
} else if (0 == strcmp("d", task_char)) {
|
} else if (0 == strcmp("d", task_char)) {
|
||||||
task = kDecode;
|
task = kDecode;
|
||||||
|
} else if (0 == strcmp("t", task_char)) {
|
||||||
|
task = kTest;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task == kNoTask) {
|
if (task == kNoTask) {
|
||||||
@ -130,7 +140,8 @@ int main(int argc, char** argv) {
|
|||||||
print_usage(argv[0]);
|
print_usage(argv[0]);
|
||||||
return 0;
|
return 0;
|
||||||
case 'o': {
|
case 'o': {
|
||||||
if (!output_filename && argi + 1 < argc) {
|
if (!output_filename && argi + 1 < argc &&
|
||||||
|
(task == kEncode || task == kDecode)) {
|
||||||
output_filename = argv[++argi];
|
output_filename = argv[++argi];
|
||||||
} else {
|
} else {
|
||||||
print_usage(argv[0]);
|
print_usage(argv[0]);
|
||||||
@ -176,76 +187,168 @@ int main(int argc, char** argv) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task == kDecode && want_comments) {
|
const auto no_comments = spvtools::MarkvLogConsumer();
|
||||||
fprintf(stderr, "warning: Decoder comments not yet implemented\n");
|
const auto output_to_stderr = [](const std::string& str) {
|
||||||
want_comments = false;
|
std::cerr << str;
|
||||||
}
|
};
|
||||||
|
|
||||||
const bool write_to_stdout = output_filename == nullptr ||
|
ScopedContext ctx(kSpvEnv);
|
||||||
0 == strcmp(output_filename, "-");
|
|
||||||
|
|
||||||
std::string comments;
|
|
||||||
std::string* comments_ptr = want_comments ? &comments : nullptr;
|
|
||||||
|
|
||||||
ScopedContext ctx(SPV_ENV_UNIVERSAL_1_2);
|
|
||||||
|
|
||||||
std::unique_ptr<spvtools::MarkvModel> model =
|
std::unique_ptr<spvtools::MarkvModel> model =
|
||||||
spvtools::CreateMarkvModel(spvtools::kMarkvModelShaderDefault);
|
spvtools::CreateMarkvModel(spvtools::kMarkvModelShaderDefault);
|
||||||
|
|
||||||
|
std::vector<uint32_t> spirv;
|
||||||
|
std::vector<uint8_t> markv;
|
||||||
|
|
||||||
|
spvtools::MarkvCodecOptions options;
|
||||||
|
options.validate_spirv_binary = validate_spirv_binary;
|
||||||
|
|
||||||
if (task == kEncode) {
|
if (task == kEncode) {
|
||||||
std::vector<uint32_t> spirv;
|
|
||||||
if (!ReadFile<uint32_t>(input_filename, "rb", &spirv)) return 1;
|
if (!ReadFile<uint32_t>(input_filename, "rb", &spirv)) return 1;
|
||||||
|
assert(!spirv.empty());
|
||||||
spvtools::MarkvEncoderOptions options;
|
|
||||||
options.validate_spirv_binary = validate_spirv_binary;
|
|
||||||
|
|
||||||
std::vector<uint8_t> markv;
|
|
||||||
|
|
||||||
if (SPV_SUCCESS != spvtools::SpirvToMarkv(
|
if (SPV_SUCCESS != spvtools::SpirvToMarkv(
|
||||||
ctx.context, spirv, options, *model, DiagnosticsMessageHandler,
|
ctx.context, spirv, options, *model, DiagnosticsMessageHandler,
|
||||||
&markv, comments_ptr)) {
|
want_comments ? output_to_stderr : no_comments,
|
||||||
|
spvtools::MarkvDebugConsumer(), &markv)) {
|
||||||
std::cerr << "error: Failed to encode " << input_filename << " to MARK-V "
|
std::cerr << "error: Failed to encode " << input_filename << " to MARK-V "
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (want_comments) {
|
if (!WriteFile<uint8_t>(output_filename, "wb", markv.data(),
|
||||||
if (!WriteFile<char>(nullptr, "w", comments.c_str(),
|
markv.size())) return 1;
|
||||||
comments.length())) return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!want_comments || !write_to_stdout) {
|
|
||||||
if (!WriteFile<uint8_t>(output_filename, "wb", markv.data(),
|
|
||||||
markv.size())) return 1;
|
|
||||||
}
|
|
||||||
} else if (task == kDecode) {
|
} else if (task == kDecode) {
|
||||||
std::vector<uint8_t> markv;
|
|
||||||
if (!ReadFile<uint8_t>(input_filename, "rb", &markv)) return 1;
|
if (!ReadFile<uint8_t>(input_filename, "rb", &markv)) return 1;
|
||||||
|
assert(!markv.empty());
|
||||||
spvtools::MarkvDecoderOptions options;
|
|
||||||
options.validate_spirv_binary = validate_spirv_binary;
|
|
||||||
|
|
||||||
std::vector<uint32_t> spirv;
|
|
||||||
|
|
||||||
if (SPV_SUCCESS != spvtools::MarkvToSpirv(
|
if (SPV_SUCCESS != spvtools::MarkvToSpirv(
|
||||||
ctx.context, markv, options, *model, DiagnosticsMessageHandler,
|
ctx.context, markv, options, *model, DiagnosticsMessageHandler,
|
||||||
&spirv, comments_ptr)) {
|
want_comments ? output_to_stderr : no_comments,
|
||||||
|
spvtools::MarkvDebugConsumer(), &spirv)) {
|
||||||
std::cerr << "error: Failed to decode " << input_filename << " to SPIR-V "
|
std::cerr << "error: Failed to decode " << input_filename << " to SPIR-V "
|
||||||
<< std::endl;
|
<< std::endl;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (want_comments) {
|
if (!WriteFile<uint32_t>(output_filename, "wb", spirv.data(),
|
||||||
if (!WriteFile<char>(nullptr, "w", comments.c_str(),
|
spirv.size())) return 1;
|
||||||
comments.length())) return 1;
|
} else if (task == kTest) {
|
||||||
|
if (!ReadFile<uint32_t>(input_filename, "rb", &spirv)) return 1;
|
||||||
|
assert(!spirv.empty());
|
||||||
|
|
||||||
|
std::vector<uint32_t> spirv_before;
|
||||||
|
spvtools::Optimizer optimizer(kSpvEnv);
|
||||||
|
optimizer.RegisterPass(spvtools::CreateCompactIdsPass());
|
||||||
|
if (!optimizer.Run(spirv.data(), spirv.size(), &spirv_before)) {
|
||||||
|
std::cerr << "error: Optimizer failure on: "
|
||||||
|
<< input_filename << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!want_comments || !write_to_stdout) {
|
std::vector<std::string> encoder_instruction_bits;
|
||||||
if (!WriteFile<uint32_t>(output_filename, "wb", spirv.data(),
|
std::vector<std::string> encoder_instruction_comments;
|
||||||
spirv.size())) return 1;
|
std::vector<std::vector<uint32_t>> encoder_instruction_words;
|
||||||
|
std::vector<std::string> decoder_instruction_bits;
|
||||||
|
std::vector<std::string> decoder_instruction_comments;
|
||||||
|
std::vector<std::vector<uint32_t>> decoder_instruction_words;
|
||||||
|
|
||||||
|
const auto encoder_debug_consumer = [&](
|
||||||
|
const std::vector<uint32_t>& words, const std::string& bits,
|
||||||
|
const std::string& comment) {
|
||||||
|
encoder_instruction_words.push_back(words);
|
||||||
|
encoder_instruction_bits.push_back(bits);
|
||||||
|
encoder_instruction_comments.push_back(comment);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (SPV_SUCCESS != spvtools::SpirvToMarkv(
|
||||||
|
ctx.context, spirv_before, options, *model, DiagnosticsMessageHandler,
|
||||||
|
want_comments ? output_to_stderr : no_comments,
|
||||||
|
encoder_debug_consumer, &markv)) {
|
||||||
|
std::cerr << "error: Failed to encode " << input_filename << " to MARK-V "
|
||||||
|
<< std::endl;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
assert(false && "Unknown task");
|
const auto write_bug_report = [&]() {
|
||||||
|
for (size_t inst_index = 0; inst_index < decoder_instruction_words.size();
|
||||||
|
++inst_index) {
|
||||||
|
std::cerr << "\nInstruction #" << inst_index << std::endl;
|
||||||
|
std::cerr << "\nEncoder words: ";
|
||||||
|
for (uint32_t word : encoder_instruction_words[inst_index])
|
||||||
|
std::cerr << word << " ";
|
||||||
|
std::cerr << "\nDecoder words: ";
|
||||||
|
for (uint32_t word : decoder_instruction_words[inst_index])
|
||||||
|
std::cerr << word << " ";
|
||||||
|
std::cerr << std::endl;
|
||||||
|
|
||||||
|
std::cerr << "\nEncoder bits: " << encoder_instruction_bits[inst_index];
|
||||||
|
std::cerr << "\nDecoder bits: " << decoder_instruction_bits[inst_index];
|
||||||
|
std::cerr << std::endl;
|
||||||
|
|
||||||
|
std::cerr << "\nEncoder comments:\n"
|
||||||
|
<< encoder_instruction_comments[inst_index];
|
||||||
|
std::cerr << "Decoder comments:\n"
|
||||||
|
<< decoder_instruction_comments[inst_index];
|
||||||
|
std::cerr << std::endl;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const auto decoder_debug_consumer = [&](
|
||||||
|
const std::vector<uint32_t>& words, const std::string& bits,
|
||||||
|
const std::string& comment) {
|
||||||
|
const size_t inst_index = decoder_instruction_words.size();
|
||||||
|
if (inst_index >= encoder_instruction_words.size()) {
|
||||||
|
write_bug_report();
|
||||||
|
std::cerr << "error: Decoder has more instructions than encoder: "
|
||||||
|
<< input_filename << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
decoder_instruction_words.push_back(words);
|
||||||
|
decoder_instruction_bits.push_back(bits);
|
||||||
|
decoder_instruction_comments.push_back(comment);
|
||||||
|
|
||||||
|
if (encoder_instruction_words[inst_index] !=
|
||||||
|
decoder_instruction_words[inst_index]) {
|
||||||
|
write_bug_report();
|
||||||
|
std::cerr << "error: Words of the last decoded instruction differ from "
|
||||||
|
"reference: " << input_filename << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (encoder_instruction_bits[inst_index] !=
|
||||||
|
decoder_instruction_bits[inst_index]) {
|
||||||
|
write_bug_report();
|
||||||
|
std::cerr << "error: Bits of the last decoded instruction differ from "
|
||||||
|
"reference: " << input_filename << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<uint32_t> spirv_after;
|
||||||
|
const spv_result_t decoding_result = spvtools::MarkvToSpirv(
|
||||||
|
ctx.context, markv, options, *model, DiagnosticsMessageHandler,
|
||||||
|
want_comments ? output_to_stderr : no_comments,
|
||||||
|
decoder_debug_consumer, &spirv_after);
|
||||||
|
|
||||||
|
if (decoding_result == SPV_REQUESTED_TERMINATION) {
|
||||||
|
std::cerr << "error: Decoding interrupted by the debugger: "
|
||||||
|
<< input_filename << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (decoding_result != SPV_SUCCESS) {
|
||||||
|
std::cerr << "error: Failed to decode encoded " << input_filename
|
||||||
|
<< " back to SPIR-V " << std::endl;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert(spirv_before.size() == spirv_after.size());
|
||||||
|
assert(std::mismatch(std::next(spirv_before.begin(), 5), spirv_before.end(),
|
||||||
|
std::next(spirv_after.begin(), 5)) ==
|
||||||
|
std::make_pair(spirv_before.end(), spirv_after.end()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
Loading…
Reference in New Issue
Block a user