| // Copyright (c) 2016 Google Inc. | |
| // | |
| // 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. | |
| namespace spvtools { | |
| // Message consumer. The C strings for source and message are only alive for the | |
| // specific invocation. | |
| using MessageConsumer = std::function<void( | |
| spv_message_level_t /* level */, const char* /* source */, | |
| const spv_position_t& /* position */, const char* /* message */ | |
| )>; | |
| using HeaderParser = std::function<spv_result_t( | |
| const spv_endianness_t endianess, const spv_parsed_header_t& instruction)>; | |
| using InstructionParser = | |
| std::function<spv_result_t(const spv_parsed_instruction_t& instruction)>; | |
| // C++ RAII wrapper around the C context object spv_context. | |
| class SPIRV_TOOLS_EXPORT Context { | |
| public: | |
| // Constructs a context targeting the given environment |env|. | |
| // | |
| // See specific API calls for how the target environment is interpreted | |
| // (particularly assembly and validation). | |
| // | |
| // The constructed instance will have an empty message consumer, which just | |
| // ignores all messages from the library. Use SetMessageConsumer() to supply | |
| // one if messages are of concern. | |
| explicit Context(spv_target_env env); | |
| // Enables move constructor/assignment operations. | |
| Context(Context&& other); | |
| Context& operator=(Context&& other); | |
| // Disables copy constructor/assignment operations. | |
| Context(const Context&) = delete; | |
| Context& operator=(const Context&) = delete; | |
| // Destructs this instance. | |
| ~Context(); | |
| // Sets the message consumer to the given |consumer|. The |consumer| will be | |
| // invoked once for each message communicated from the library. | |
| void SetMessageConsumer(MessageConsumer consumer); | |
| // Returns the underlying spv_context. | |
| spv_context& CContext(); | |
| const spv_context& CContext() const; | |
| private: | |
| spv_context context_; | |
| }; | |
| // A RAII wrapper around a validator options object. | |
| class SPIRV_TOOLS_EXPORT ValidatorOptions { | |
| public: | |
| ValidatorOptions() : options_(spvValidatorOptionsCreate()) {} | |
| ~ValidatorOptions() { spvValidatorOptionsDestroy(options_); } | |
| // Allow implicit conversion to the underlying object. | |
| operator spv_validator_options() const { return options_; } | |
| // Sets a limit. | |
| void SetUniversalLimit(spv_validator_limit limit_type, uint32_t limit) { | |
| spvValidatorOptionsSetUniversalLimit(options_, limit_type, limit); | |
| } | |
| void SetRelaxStructStore(bool val) { | |
| spvValidatorOptionsSetRelaxStoreStruct(options_, val); | |
| } | |
| // Enables VK_KHR_relaxed_block_layout when validating standard | |
| // uniform/storage buffer/push-constant layout. If true, disables | |
| // scalar block layout rules. | |
| void SetRelaxBlockLayout(bool val) { | |
| spvValidatorOptionsSetRelaxBlockLayout(options_, val); | |
| } | |
| // Enables VK_KHR_uniform_buffer_standard_layout when validating standard | |
| // uniform layout. If true, disables scalar block layout rules. | |
| void SetUniformBufferStandardLayout(bool val) { | |
| spvValidatorOptionsSetUniformBufferStandardLayout(options_, val); | |
| } | |
| // Enables VK_EXT_scalar_block_layout when validating standard | |
| // uniform/storage buffer/push-constant layout. If true, disables | |
| // relaxed block layout rules. | |
| void SetScalarBlockLayout(bool val) { | |
| spvValidatorOptionsSetScalarBlockLayout(options_, val); | |
| } | |
| // Enables scalar layout when validating Workgroup blocks. See | |
| // VK_KHR_workgroup_memory_explicit_layout. | |
| void SetWorkgroupScalarBlockLayout(bool val) { | |
| spvValidatorOptionsSetWorkgroupScalarBlockLayout(options_, val); | |
| } | |
| // Skips validating standard uniform/storage buffer/push-constant layout. | |
| void SetSkipBlockLayout(bool val) { | |
| spvValidatorOptionsSetSkipBlockLayout(options_, val); | |
| } | |
| // Enables LocalSizeId decorations where the environment would not otherwise | |
| // allow them. | |
| void SetAllowLocalSizeId(bool val) { | |
| spvValidatorOptionsSetAllowLocalSizeId(options_, val); | |
| } | |
| // Records whether or not the validator should relax the rules on pointer | |
| // usage in logical addressing mode. | |
| // | |
| // When relaxed, it will allow the following usage cases of pointers: | |
| // 1) OpVariable allocating an object whose type is a pointer type | |
| // 2) OpReturnValue returning a pointer value | |
| void SetRelaxLogicalPointer(bool val) { | |
| spvValidatorOptionsSetRelaxLogicalPointer(options_, val); | |
| } | |
| // Records whether or not the validator should relax the rules because it is | |
| // expected that the optimizations will make the code legal. | |
| // | |
| // When relaxed, it will allow the following: | |
| // 1) It will allow relaxed logical pointers. Setting this option will also | |
| // set that option. | |
| // 2) Pointers that are pass as parameters to function calls do not have to | |
| // match the storage class of the formal parameter. | |
| // 3) Pointers that are actual parameters on function calls do not have to | |
| // point to the same type pointed as the formal parameter. The types just | |
| // need to logically match. | |
| // 4) GLSLstd450 Interpolate* instructions can have a load of an interpolant | |
| // for a first argument. | |
| void SetBeforeHlslLegalization(bool val) { | |
| spvValidatorOptionsSetBeforeHlslLegalization(options_, val); | |
| } | |
| // Whether friendly names should be used in validation error messages. | |
| void SetFriendlyNames(bool val) { | |
| spvValidatorOptionsSetFriendlyNames(options_, val); | |
| } | |
| private: | |
| spv_validator_options options_; | |
| }; | |
| // A C++ wrapper around an optimization options object. | |
| class SPIRV_TOOLS_EXPORT OptimizerOptions { | |
| public: | |
| OptimizerOptions() : options_(spvOptimizerOptionsCreate()) {} | |
| ~OptimizerOptions() { spvOptimizerOptionsDestroy(options_); } | |
| // Allow implicit conversion to the underlying object. | |
| operator spv_optimizer_options() const { return options_; } | |
| // Records whether or not the optimizer should run the validator before | |
| // optimizing. If |run| is true, the validator will be run. | |
| void set_run_validator(bool run) { | |
| spvOptimizerOptionsSetRunValidator(options_, run); | |
| } | |
| // Records the validator options that should be passed to the validator if it | |
| // is run. | |
| void set_validator_options(const ValidatorOptions& val_options) { | |
| spvOptimizerOptionsSetValidatorOptions(options_, val_options); | |
| } | |
| // Records the maximum possible value for the id bound. | |
| void set_max_id_bound(uint32_t new_bound) { | |
| spvOptimizerOptionsSetMaxIdBound(options_, new_bound); | |
| } | |
| // Records whether all bindings within the module should be preserved. | |
| void set_preserve_bindings(bool preserve_bindings) { | |
| spvOptimizerOptionsSetPreserveBindings(options_, preserve_bindings); | |
| } | |
| // Records whether all specialization constants within the module | |
| // should be preserved. | |
| void set_preserve_spec_constants(bool preserve_spec_constants) { | |
| spvOptimizerOptionsSetPreserveSpecConstants(options_, | |
| preserve_spec_constants); | |
| } | |
| private: | |
| spv_optimizer_options options_; | |
| }; | |
| // A C++ wrapper around a reducer options object. | |
| class SPIRV_TOOLS_EXPORT ReducerOptions { | |
| public: | |
| ReducerOptions() : options_(spvReducerOptionsCreate()) {} | |
| ~ReducerOptions() { spvReducerOptionsDestroy(options_); } | |
| // Allow implicit conversion to the underlying object. | |
| operator spv_reducer_options() const { // NOLINT(google-explicit-constructor) | |
| return options_; | |
| } | |
| // See spvReducerOptionsSetStepLimit. | |
| void set_step_limit(uint32_t step_limit) { | |
| spvReducerOptionsSetStepLimit(options_, step_limit); | |
| } | |
| // See spvReducerOptionsSetFailOnValidationError. | |
| void set_fail_on_validation_error(bool fail_on_validation_error) { | |
| spvReducerOptionsSetFailOnValidationError(options_, | |
| fail_on_validation_error); | |
| } | |
| // See spvReducerOptionsSetTargetFunction. | |
| void set_target_function(uint32_t target_function) { | |
| spvReducerOptionsSetTargetFunction(options_, target_function); | |
| } | |
| private: | |
| spv_reducer_options options_; | |
| }; | |
| // A C++ wrapper around a fuzzer options object. | |
| class SPIRV_TOOLS_EXPORT FuzzerOptions { | |
| public: | |
| FuzzerOptions() : options_(spvFuzzerOptionsCreate()) {} | |
| ~FuzzerOptions() { spvFuzzerOptionsDestroy(options_); } | |
| // Allow implicit conversion to the underlying object. | |
| operator spv_fuzzer_options() const { // NOLINT(google-explicit-constructor) | |
| return options_; | |
| } | |
| // See spvFuzzerOptionsEnableReplayValidation. | |
| void enable_replay_validation() { | |
| spvFuzzerOptionsEnableReplayValidation(options_); | |
| } | |
| // See spvFuzzerOptionsSetRandomSeed. | |
| void set_random_seed(uint32_t seed) { | |
| spvFuzzerOptionsSetRandomSeed(options_, seed); | |
| } | |
| // See spvFuzzerOptionsSetReplayRange. | |
| void set_replay_range(int32_t replay_range) { | |
| spvFuzzerOptionsSetReplayRange(options_, replay_range); | |
| } | |
| // See spvFuzzerOptionsSetShrinkerStepLimit. | |
| void set_shrinker_step_limit(uint32_t shrinker_step_limit) { | |
| spvFuzzerOptionsSetShrinkerStepLimit(options_, shrinker_step_limit); | |
| } | |
| // See spvFuzzerOptionsEnableFuzzerPassValidation. | |
| void enable_fuzzer_pass_validation() { | |
| spvFuzzerOptionsEnableFuzzerPassValidation(options_); | |
| } | |
| // See spvFuzzerOptionsEnableAllPasses. | |
| void enable_all_passes() { spvFuzzerOptionsEnableAllPasses(options_); } | |
| private: | |
| spv_fuzzer_options options_; | |
| }; | |
| // C++ interface for SPIRV-Tools functionalities. It wraps the context | |
| // (including target environment and the corresponding SPIR-V grammar) and | |
| // provides methods for assembling, disassembling, and validating. | |
| // | |
| // Instances of this class provide basic thread-safety guarantee. | |
| class SPIRV_TOOLS_EXPORT SpirvTools { | |
| public: | |
| enum { | |
| // Default assembling option used by assemble(): | |
| kDefaultAssembleOption = SPV_TEXT_TO_BINARY_OPTION_NONE, | |
| // Default disassembling option used by Disassemble(): | |
| // * Avoid prefix comments from decoding the SPIR-V module header, and | |
| // * Use friendly names for variables. | |
| kDefaultDisassembleOption = SPV_BINARY_TO_TEXT_OPTION_NO_HEADER | | |
| SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES | |
| }; | |
| // Constructs an instance targeting the given environment |env|. | |
| // | |
| // The constructed instance will have an empty message consumer, which just | |
| // ignores all messages from the library. Use SetMessageConsumer() to supply | |
| // one if messages are of concern. | |
| explicit SpirvTools(spv_target_env env); | |
| // Disables copy/move constructor/assignment operations. | |
| SpirvTools(const SpirvTools&) = delete; | |
| SpirvTools(SpirvTools&&) = delete; | |
| SpirvTools& operator=(const SpirvTools&) = delete; | |
| SpirvTools& operator=(SpirvTools&&) = delete; | |
| // Destructs this instance. | |
| ~SpirvTools(); | |
| // Sets the message consumer to the given |consumer|. The |consumer| will be | |
| // invoked once for each message communicated from the library. | |
| void SetMessageConsumer(MessageConsumer consumer); | |
| // Assembles the given assembly |text| and writes the result to |binary|. | |
| // Returns true on successful assembling. |binary| will be kept untouched if | |
| // assembling is unsuccessful. | |
| // The SPIR-V binary version is set to the highest version of SPIR-V supported | |
| // by the target environment with which this SpirvTools object was created. | |
| bool Assemble(const std::string& text, std::vector<uint32_t>* binary, | |
| uint32_t options = kDefaultAssembleOption) const; | |
| // |text_size| specifies the number of bytes in |text|. A terminating null | |
| // character is not required to present in |text| as long as |text| is valid. | |
| // The SPIR-V binary version is set to the highest version of SPIR-V supported | |
| // by the target environment with which this SpirvTools object was created. | |
| bool Assemble(const char* text, size_t text_size, | |
| std::vector<uint32_t>* binary, | |
| uint32_t options = kDefaultAssembleOption) const; | |
| // Disassembles the given SPIR-V |binary| with the given |options| and writes | |
| // the assembly to |text|. Returns true on successful disassembling. |text| | |
| // will be kept untouched if diassembling is unsuccessful. | |
| bool Disassemble(const std::vector<uint32_t>& binary, std::string* text, | |
| uint32_t options = kDefaultDisassembleOption) const; | |
| // |binary_size| specifies the number of words in |binary|. | |
| bool Disassemble(const uint32_t* binary, size_t binary_size, | |
| std::string* text, | |
| uint32_t options = kDefaultDisassembleOption) const; | |
| // Parses a SPIR-V binary, specified as counted sequence of 32-bit words. | |
| // Parsing feedback is provided via two callbacks provided as std::function. | |
| // In a valid parse the parsed-header callback is called once, and | |
| // then the parsed-instruction callback is called once for each instruction | |
| // in the stream. | |
| // Returns true on successful parsing. | |
| // If diagnostic is non-null, a diagnostic is emitted on failed parsing. | |
| // If diagnostic is null the context's message consumer | |
| // will be used to emit any errors. If a callback returns anything other than | |
| // SPV_SUCCESS, then that status code is returned, no further callbacks are | |
| // issued, and no additional diagnostics are emitted. | |
| // This is a wrapper around the C API spvBinaryParse. | |
| bool Parse(const std::vector<uint32_t>& binary, | |
| const HeaderParser& header_parser, | |
| const InstructionParser& instruction_parser, | |
| spv_diagnostic* diagnostic = nullptr); | |
| // Validates the given SPIR-V |binary|. Returns true if no issues are found. | |
| // Otherwise, returns false and communicates issues via the message consumer | |
| // registered. | |
| // Validates for SPIR-V spec rules for the SPIR-V version named in the | |
| // binary's header (at word offset 1). Additionally, if the target | |
| // environment is a client API (such as Vulkan 1.1), then validate for that | |
| // client API version, to the extent that it is verifiable from data in the | |
| // binary itself. | |
| bool Validate(const std::vector<uint32_t>& binary) const; | |
| // Like the previous overload, but provides the binary as a pointer and size: | |
| // |binary_size| specifies the number of words in |binary|. | |
| // Validates for SPIR-V spec rules for the SPIR-V version named in the | |
| // binary's header (at word offset 1). Additionally, if the target | |
| // environment is a client API (such as Vulkan 1.1), then validate for that | |
| // client API version, to the extent that it is verifiable from data in the | |
| // binary itself. | |
| bool Validate(const uint32_t* binary, size_t binary_size) const; | |
| // Like the previous overload, but takes an options object. | |
| // Validates for SPIR-V spec rules for the SPIR-V version named in the | |
| // binary's header (at word offset 1). Additionally, if the target | |
| // environment is a client API (such as Vulkan 1.1), then validate for that | |
| // client API version, to the extent that it is verifiable from data in the | |
| // binary itself, or in the validator options. | |
| bool Validate(const uint32_t* binary, size_t binary_size, | |
| spv_validator_options options) const; | |
| // Was this object successfully constructed. | |
| bool IsValid() const; | |
| private: | |
| struct SPIRV_TOOLS_LOCAL | |
| Impl; // Opaque struct for holding the data fields used by this class. | |
| std::unique_ptr<Impl> impl_; // Unique pointer to implementation data. | |
| }; | |
| } // namespace spvtools | |