Home | History | Annotate | Download | only in spirv-tools
      1 // Copyright (c) 2016 Google Inc.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 #ifndef INCLUDE_SPIRV_TOOLS_LIBSPIRV_HPP_
     16 #define INCLUDE_SPIRV_TOOLS_LIBSPIRV_HPP_
     17 
     18 #include <functional>
     19 #include <memory>
     20 #include <string>
     21 #include <vector>
     22 
     23 #include "spirv-tools/libspirv.h"
     24 
     25 namespace spvtools {
     26 
     27 // Message consumer. The C strings for source and message are only alive for the
     28 // specific invocation.
     29 using MessageConsumer = std::function<void(
     30     spv_message_level_t /* level */, const char* /* source */,
     31     const spv_position_t& /* position */, const char* /* message */
     32     )>;
     33 
     34 // C++ RAII wrapper around the C context object spv_context.
     35 class Context {
     36  public:
     37   // Constructs a context targeting the given environment |env|.
     38   //
     39   // The constructed instance will have an empty message consumer, which just
     40   // ignores all messages from the library. Use SetMessageConsumer() to supply
     41   // one if messages are of concern.
     42   explicit Context(spv_target_env env);
     43 
     44   // Enables move constructor/assignment operations.
     45   Context(Context&& other);
     46   Context& operator=(Context&& other);
     47 
     48   // Disables copy constructor/assignment operations.
     49   Context(const Context&) = delete;
     50   Context& operator=(const Context&) = delete;
     51 
     52   // Destructs this instance.
     53   ~Context();
     54 
     55   // Sets the message consumer to the given |consumer|. The |consumer| will be
     56   // invoked once for each message communicated from the library.
     57   void SetMessageConsumer(MessageConsumer consumer);
     58 
     59   // Returns the underlying spv_context.
     60   spv_context& CContext();
     61   const spv_context& CContext() const;
     62 
     63  private:
     64   spv_context context_;
     65 };
     66 
     67 // A RAII wrapper around a validator options object.
     68 class ValidatorOptions {
     69  public:
     70   ValidatorOptions() : options_(spvValidatorOptionsCreate()) {}
     71   ~ValidatorOptions() { spvValidatorOptionsDestroy(options_); }
     72   // Allow implicit conversion to the underlying object.
     73   operator spv_validator_options() const { return options_; }
     74 
     75   // Sets a limit.
     76   void SetUniversalLimit(spv_validator_limit limit_type, uint32_t limit) {
     77     spvValidatorOptionsSetUniversalLimit(options_, limit_type, limit);
     78   }
     79 
     80   void SetRelaxStructStore(bool val) {
     81     spvValidatorOptionsSetRelaxStoreStruct(options_, val);
     82   }
     83 
     84   // Enables VK_KHR_relaxed_block_layout when validating standard
     85   // uniform/storage buffer/push-constant layout.  If true, disables
     86   // scalar block layout rules.
     87   void SetRelaxBlockLayout(bool val) {
     88     spvValidatorOptionsSetRelaxBlockLayout(options_, val);
     89   }
     90 
     91   // Enables VK_EXT_scalar_block_layout when validating standard
     92   // uniform/storage buffer/push-constant layout.  If true, disables
     93   // relaxed block layout rules.
     94   void SetScalarBlockLayout(bool val) {
     95     spvValidatorOptionsSetScalarBlockLayout(options_, val);
     96   }
     97 
     98   // Skips validating standard uniform/storage buffer/push-constant layout.
     99   void SetSkipBlockLayout(bool val) {
    100     spvValidatorOptionsSetSkipBlockLayout(options_, val);
    101   }
    102 
    103   // Records whether or not the validator should relax the rules on pointer
    104   // usage in logical addressing mode.
    105   //
    106   // When relaxed, it will allow the following usage cases of pointers:
    107   // 1) OpVariable allocating an object whose type is a pointer type
    108   // 2) OpReturnValue returning a pointer value
    109   void SetRelaxLogicalPointer(bool val) {
    110     spvValidatorOptionsSetRelaxLogicalPointer(options_, val);
    111   }
    112 
    113  private:
    114   spv_validator_options options_;
    115 };
    116 
    117 // A C++ wrapper around an optimization options object.
    118 class OptimizerOptions {
    119  public:
    120   OptimizerOptions() : options_(spvOptimizerOptionsCreate()) {}
    121   ~OptimizerOptions() { spvOptimizerOptionsDestroy(options_); }
    122 
    123   // Allow implicit conversion to the underlying object.
    124   operator spv_optimizer_options() const { return options_; }
    125 
    126   // Records whether or not the optimizer should run the validator before
    127   // optimizing.  If |run| is true, the validator will be run.
    128   void set_run_validator(bool run) {
    129     spvOptimizerOptionsSetRunValidator(options_, run);
    130   }
    131 
    132   // Records the validator options that should be passed to the validator if it
    133   // is run.
    134   void set_validator_options(const ValidatorOptions& val_options) {
    135     spvOptimizerOptionsSetValidatorOptions(options_, val_options);
    136   }
    137 
    138   // Records the maximum possible value for the id bound.
    139   void set_max_id_bound(uint32_t new_bound) {
    140     spvOptimizerOptionsSetMaxIdBound(options_, new_bound);
    141   }
    142 
    143  private:
    144   spv_optimizer_options options_;
    145 };
    146 
    147 // A C++ wrapper around a reducer options object.
    148 class ReducerOptions {
    149  public:
    150   ReducerOptions() : options_(spvReducerOptionsCreate()) {}
    151   ~ReducerOptions() { spvReducerOptionsDestroy(options_); }
    152 
    153   // Allow implicit conversion to the underlying object.
    154   operator spv_reducer_options() const { return options_; }
    155 
    156   // Records the maximum number of reduction steps that should
    157   // run before the reducer gives up.
    158   void set_step_limit(uint32_t step_limit) {
    159     spvReducerOptionsSetStepLimit(options_, step_limit);
    160   }
    161 
    162   // Sets a seed to be used for random number generation.
    163   void set_seed(uint32_t seed) { spvReducerOptionsSetSeed(options_, seed); }
    164 
    165  private:
    166   spv_reducer_options options_;
    167 };
    168 
    169 // C++ interface for SPIRV-Tools functionalities. It wraps the context
    170 // (including target environment and the corresponding SPIR-V grammar) and
    171 // provides methods for assembling, disassembling, and validating.
    172 //
    173 // Instances of this class provide basic thread-safety guarantee.
    174 class SpirvTools {
    175  public:
    176   enum {
    177     // Default assembling option used by assemble():
    178     kDefaultAssembleOption = SPV_TEXT_TO_BINARY_OPTION_NONE,
    179 
    180     // Default disassembling option used by Disassemble():
    181     // * Avoid prefix comments from decoding the SPIR-V module header, and
    182     // * Use friendly names for variables.
    183     kDefaultDisassembleOption = SPV_BINARY_TO_TEXT_OPTION_NO_HEADER |
    184                                 SPV_BINARY_TO_TEXT_OPTION_FRIENDLY_NAMES
    185   };
    186 
    187   // Constructs an instance targeting the given environment |env|.
    188   //
    189   // The constructed instance will have an empty message consumer, which just
    190   // ignores all messages from the library. Use SetMessageConsumer() to supply
    191   // one if messages are of concern.
    192   explicit SpirvTools(spv_target_env env);
    193 
    194   // Disables copy/move constructor/assignment operations.
    195   SpirvTools(const SpirvTools&) = delete;
    196   SpirvTools(SpirvTools&&) = delete;
    197   SpirvTools& operator=(const SpirvTools&) = delete;
    198   SpirvTools& operator=(SpirvTools&&) = delete;
    199 
    200   // Destructs this instance.
    201   ~SpirvTools();
    202 
    203   // Sets the message consumer to the given |consumer|. The |consumer| will be
    204   // invoked once for each message communicated from the library.
    205   void SetMessageConsumer(MessageConsumer consumer);
    206 
    207   // Assembles the given assembly |text| and writes the result to |binary|.
    208   // Returns true on successful assembling. |binary| will be kept untouched if
    209   // assembling is unsuccessful.
    210   bool Assemble(const std::string& text, std::vector<uint32_t>* binary,
    211                 uint32_t options = kDefaultAssembleOption) const;
    212   // |text_size| specifies the number of bytes in |text|. A terminating null
    213   // character is not required to present in |text| as long as |text| is valid.
    214   bool Assemble(const char* text, size_t text_size,
    215                 std::vector<uint32_t>* binary,
    216                 uint32_t options = kDefaultAssembleOption) const;
    217 
    218   // Disassembles the given SPIR-V |binary| with the given |options| and writes
    219   // the assembly to |text|. Returns ture on successful disassembling. |text|
    220   // will be kept untouched if diassembling is unsuccessful.
    221   bool Disassemble(const std::vector<uint32_t>& binary, std::string* text,
    222                    uint32_t options = kDefaultDisassembleOption) const;
    223   // |binary_size| specifies the number of words in |binary|.
    224   bool Disassemble(const uint32_t* binary, size_t binary_size,
    225                    std::string* text,
    226                    uint32_t options = kDefaultDisassembleOption) const;
    227 
    228   // Validates the given SPIR-V |binary|. Returns true if no issues are found.
    229   // Otherwise, returns false and communicates issues via the message consumer
    230   // registered.
    231   bool Validate(const std::vector<uint32_t>& binary) const;
    232   // |binary_size| specifies the number of words in |binary|.
    233   bool Validate(const uint32_t* binary, size_t binary_size) const;
    234   // Like the previous overload, but takes an options object.
    235   bool Validate(const uint32_t* binary, size_t binary_size,
    236                 spv_validator_options options) const;
    237 
    238  private:
    239   struct Impl;  // Opaque struct for holding the data fields used by this class.
    240   std::unique_ptr<Impl> impl_;  // Unique pointer to implementation data.
    241 };
    242 
    243 }  // namespace spvtools
    244 
    245 #endif  // INCLUDE_SPIRV_TOOLS_LIBSPIRV_HPP_
    246