• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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:
ValidatorOptions()70   ValidatorOptions() : options_(spvValidatorOptionsCreate()) {}
~ValidatorOptions()71   ~ValidatorOptions() { spvValidatorOptionsDestroy(options_); }
72   // Allow implicit conversion to the underlying object.
operator spv_validator_options() const73   operator spv_validator_options() const { return options_; }
74 
75   // Sets a limit.
SetUniversalLimit(spv_validator_limit limit_type,uint32_t limit)76   void SetUniversalLimit(spv_validator_limit limit_type, uint32_t limit) {
77     spvValidatorOptionsSetUniversalLimit(options_, limit_type, limit);
78   }
79 
SetRelaxStructStore(bool val)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.
SetRelaxBlockLayout(bool val)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.
SetScalarBlockLayout(bool val)94   void SetScalarBlockLayout(bool val) {
95     spvValidatorOptionsSetScalarBlockLayout(options_, val);
96   }
97 
98   // Skips validating standard uniform/storage buffer/push-constant layout.
SetSkipBlockLayout(bool val)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
SetRelaxLogicalPointer(bool val)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:
OptimizerOptions()120   OptimizerOptions() : options_(spvOptimizerOptionsCreate()) {}
~OptimizerOptions()121   ~OptimizerOptions() { spvOptimizerOptionsDestroy(options_); }
122 
123   // Allow implicit conversion to the underlying object.
operator spv_optimizer_options() const124   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.
set_run_validator(bool 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.
set_validator_options(const ValidatorOptions & val_options)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.
set_max_id_bound(uint32_t new_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:
ReducerOptions()150   ReducerOptions() : options_(spvReducerOptionsCreate()) {}
~ReducerOptions()151   ~ReducerOptions() { spvReducerOptionsDestroy(options_); }
152 
153   // Allow implicit conversion to the underlying object.
operator spv_reducer_options() const154   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.
set_step_limit(uint32_t step_limit)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.
set_seed(uint32_t seed)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