diff --git a/src/xenia/ui/spirv/spirv_validator.cc b/src/xenia/ui/spirv/spirv_validator.cc new file mode 100644 index 000000000..734688eb6 --- /dev/null +++ b/src/xenia/ui/spirv/spirv_validator.cc @@ -0,0 +1,80 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2016 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/ui/spirv/spirv_validator.h" + +#include "third_party/spirv-tools/include/spirv-tools/libspirv.h" +#include "xenia/base/logging.h" + +namespace xe { +namespace ui { +namespace spirv { + +SpirvValidator::Result::Result(spv_text text, spv_diagnostic diagnostic) + : text_(text), diagnostic_(diagnostic) {} + +SpirvValidator::Result::~Result() { + if (text_) { + spvTextDestroy(text_); + } + if (diagnostic_) { + spvDiagnosticDestroy(diagnostic_); + } +} + +bool SpirvValidator::Result::has_error() const { return !!diagnostic_; } + +size_t SpirvValidator::Result::error_word_index() const { + return diagnostic_ ? diagnostic_->position.index : 0; +} + +const char* SpirvValidator::Result::error_string() const { + return diagnostic_ ? diagnostic_->error : ""; +} + +const char* SpirvValidator::Result::text() const { + return text_ ? text_->str : ""; +} + +std::string SpirvValidator::Result::to_string() const { + return text_ ? std::string(text_->str, text_->length) : ""; +} + +void SpirvValidator::Result::AppendText(StringBuffer* target_buffer) const { + if (text_) { + target_buffer->AppendBytes(reinterpret_cast(text_->str), + text_->length); + } +} + +SpirvValidator::SpirvValidator() : spv_context_(spvContextCreate()) {} +SpirvValidator::~SpirvValidator() { spvContextDestroy(spv_context_); } + +std::unique_ptr SpirvValidator::Validate( + const uint32_t* words, size_t word_count) { + spv_text text = nullptr; + spv_diagnostic diagnostic = nullptr; + spv_const_binary_t binary = {words, word_count}; + auto result_code = + spvValidate(spv_context_, &binary, SPV_VALIDATE_ALL, &diagnostic); + std::unique_ptr result(new Result(text, diagnostic)); + if (result_code) { + XELOGE("Failed to validate spv: %d", result_code); + if (result->has_error()) { + return result; + } else { + return nullptr; + } + } + return result; +} + +} // namespace spirv +} // namespace ui +} // namespace xe \ No newline at end of file diff --git a/src/xenia/ui/spirv/spirv_validator.h b/src/xenia/ui/spirv/spirv_validator.h new file mode 100644 index 000000000..890843f27 --- /dev/null +++ b/src/xenia/ui/spirv/spirv_validator.h @@ -0,0 +1,66 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2016 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_UI_SPIRV_SPIRV_VALIDATOR_H_ +#define XENIA_UI_SPIRV_SPIRV_VALIDATOR_H_ + +#include +#include + +#include "xenia/base/string_buffer.h" +#include "xenia/ui/spirv/spirv_util.h" + +namespace xe { +namespace ui { +namespace spirv { + +class SpirvValidator { + public: + class Result { + public: + Result(spv_text text, spv_diagnostic diagnostic); + ~Result(); + + // True if the result has an error associated with it. + bool has_error() const; + // Index of the error in the provided binary word data. + size_t error_word_index() const; + // Human-readable description of the error. + const char* error_string() const; + + // Disassembled source text. + // Returned pointer lifetime is tied to this Result instance. + const char* text() const; + // Converts the disassembled source text to a string. + std::string to_string() const; + // Appends the disassembled source text to the given buffer. + void AppendText(StringBuffer* target_buffer) const; + + private: + spv_text text_ = nullptr; + spv_diagnostic diagnostic_ = nullptr; + }; + + SpirvValidator(); + ~SpirvValidator(); + + // Validates the given SPIRV binary. + // The return will be nullptr if validation fails due to a library error. + // The return may have an error set on it if the SPIRV binary is malformed. + std::unique_ptr Validate(const uint32_t* words, size_t word_count); + + private: + spv_context spv_context_ = nullptr; +}; + +} // namespace spirv +} // namespace ui +} // namespace xe + +#endif // XENIA_UI_SPIRV_SPIRV_VALIDATOR_H_