1 // Copyright 2021 The Tint Authors. 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 SRC_INSPECTOR_TEST_INSPECTOR_BUILDER_H_ 16 #define SRC_INSPECTOR_TEST_INSPECTOR_BUILDER_H_ 17 18 #include <memory> 19 #include <string> 20 #include <tuple> 21 #include <vector> 22 23 #include "src/ast/call_statement.h" 24 #include "src/ast/disable_validation_decoration.h" 25 #include "src/ast/override_decoration.h" 26 #include "src/ast/stage_decoration.h" 27 #include "src/ast/struct_block_decoration.h" 28 #include "src/ast/workgroup_decoration.h" 29 #include "src/program_builder.h" 30 #include "src/sem/depth_texture_type.h" 31 #include "src/sem/external_texture_type.h" 32 #include "src/sem/multisampled_texture_type.h" 33 #include "src/sem/sampled_texture_type.h" 34 #include "src/sem/variable.h" 35 #include "tint/tint.h" 36 37 namespace tint { 38 namespace inspector { 39 40 /// Utility class for building programs in inspector tests 41 class InspectorBuilder : public ProgramBuilder { 42 public: 43 InspectorBuilder(); 44 ~InspectorBuilder() override; 45 46 /// Generates an empty function 47 /// @param name name of the function created 48 /// @param decorations the function decorations 49 void MakeEmptyBodyFunction(std::string name, ast::DecorationList decorations); 50 51 /// Generates a function that calls other functions 52 /// @param caller name of the function created 53 /// @param callees names of the functions to be called 54 /// @param decorations the function decorations 55 void MakeCallerBodyFunction(std::string caller, 56 std::vector<std::string> callees, 57 ast::DecorationList decorations); 58 59 /// Generates a struct that contains user-defined IO members 60 /// @param name the name of the generated struct 61 /// @param inout_vars tuples of {name, loc} that will be the struct members 62 /// @returns a structure object 63 const ast::Struct* MakeInOutStruct( 64 std::string name, 65 std::vector<std::tuple<std::string, uint32_t>> inout_vars); 66 67 // TODO(crbug.com/tint/697): Remove this. 68 /// Add In/Out variables to the global variables 69 /// @param inout_vars tuples of {in, out} that will be added as entries to the 70 /// global variables 71 void AddInOutVariables( 72 std::vector<std::tuple<std::string, std::string>> inout_vars); 73 74 // TODO(crbug.com/tint/697): Remove this. 75 /// Generates a function that references in/out variables 76 /// @param name name of the function created 77 /// @param inout_vars tuples of {in, out} that will be converted into out = in 78 /// calls in the function body 79 /// @param decorations the function decorations 80 void MakeInOutVariableBodyFunction( 81 std::string name, 82 std::vector<std::tuple<std::string, std::string>> inout_vars, 83 ast::DecorationList decorations); 84 85 // TODO(crbug.com/tint/697): Remove this. 86 /// Generates a function that references in/out variables and calls another 87 /// function. 88 /// @param caller name of the function created 89 /// @param callee name of the function to be called 90 /// @param inout_vars tuples of {in, out} that will be converted into out = in 91 /// calls in the function body 92 /// @param decorations the function decorations 93 /// @returns a function object 94 const ast::Function* MakeInOutVariableCallerBodyFunction( 95 std::string caller, 96 std::string callee, 97 std::vector<std::tuple<std::string, std::string>> inout_vars, 98 ast::DecorationList decorations); 99 100 /// Add a pipeline constant to the global variables, with a specific ID. 101 /// @param name name of the variable to add 102 /// @param id id number for the constant id 103 /// @param type type of the variable 104 /// @param constructor val to initialize the constant with, if NULL no 105 /// constructor will be added. 106 /// @returns the constant that was created AddOverridableConstantWithID(std::string name,uint32_t id,const ast::Type * type,const ast::Expression * constructor)107 const ast::Variable* AddOverridableConstantWithID( 108 std::string name, 109 uint32_t id, 110 const ast::Type* type, 111 const ast::Expression* constructor) { 112 return GlobalConst(name, type, constructor, 113 ast::DecorationList{ 114 Override(id), 115 }); 116 } 117 118 /// Add a pipeline constant to the global variables, without a specific ID. 119 /// @param name name of the variable to add 120 /// @param type type of the variable 121 /// @param constructor val to initialize the constant with, if NULL no 122 /// constructor will be added. 123 /// @returns the constant that was created AddOverridableConstantWithoutID(std::string name,const ast::Type * type,const ast::Expression * constructor)124 const ast::Variable* AddOverridableConstantWithoutID( 125 std::string name, 126 const ast::Type* type, 127 const ast::Expression* constructor) { 128 return GlobalConst(name, type, constructor, 129 ast::DecorationList{ 130 Override(), 131 }); 132 } 133 134 /// Generates a function that references module-scoped, plain-typed constant 135 /// or variable. 136 /// @param func name of the function created 137 /// @param var name of the constant to be reference 138 /// @param type type of the const being referenced 139 /// @param decorations the function decorations 140 /// @returns a function object 141 const ast::Function* MakePlainGlobalReferenceBodyFunction( 142 std::string func, 143 std::string var, 144 const ast::Type* type, 145 ast::DecorationList decorations); 146 147 /// @param vec Vector of StageVariable to be searched 148 /// @param name Name to be searching for 149 /// @returns true if name is in vec, otherwise false 150 bool ContainsName(const std::vector<StageVariable>& vec, 151 const std::string& name); 152 153 /// Builds a string for accessing a member in a generated struct 154 /// @param idx index of member 155 /// @param type type of member 156 /// @returns a string for the member 157 std::string StructMemberName(size_t idx, const ast::Type* type); 158 159 /// Generates a struct type 160 /// @param name name for the type 161 /// @param member_types a vector of member types 162 /// @param is_block whether or not to decorate as a Block 163 /// @returns a struct type 164 const ast::Struct* MakeStructType(const std::string& name, 165 std::vector<const ast::Type*> member_types, 166 bool is_block); 167 168 /// Generates a struct type from a list of member nodes. 169 /// @param name name for the struct type 170 /// @param members a vector of members 171 /// @param is_block whether or not to decorate as a Block 172 /// @returns a struct type 173 const ast::Struct* MakeStructTypeFromMembers(const std::string& name, 174 ast::StructMemberList members, 175 bool is_block); 176 177 /// Generates a struct member with a specified index and type. 178 /// @param index index of the field within the struct 179 /// @param type the type of the member field 180 /// @param decorations a list of decorations to apply to the member field 181 /// @returns a struct member 182 const ast::StructMember* MakeStructMember(size_t index, 183 const ast::Type* type, 184 ast::DecorationList decorations); 185 186 /// Generates types appropriate for using in an uniform buffer 187 /// @param name name for the type 188 /// @param member_types a vector of member types 189 /// @returns a struct type that has the layout for an uniform buffer. 190 const ast::Struct* MakeUniformBufferType( 191 const std::string& name, 192 std::vector<const ast::Type*> member_types); 193 194 /// Generates types appropriate for using in a storage buffer 195 /// @param name name for the type 196 /// @param member_types a vector of member types 197 /// @returns a function that returns the created structure. 198 std::function<const ast::TypeName*()> MakeStorageBufferTypes( 199 const std::string& name, 200 std::vector<const ast::Type*> member_types); 201 202 /// Adds an uniform buffer variable to the program 203 /// @param name the name of the variable 204 /// @param type the type to use 205 /// @param group the binding/group/ to use for the uniform buffer 206 /// @param binding the binding number to use for the uniform buffer 207 void AddUniformBuffer(const std::string& name, 208 const ast::Type* type, 209 uint32_t group, 210 uint32_t binding); 211 212 /// Adds a workgroup storage variable to the program 213 /// @param name the name of the variable 214 /// @param type the type of the variable 215 void AddWorkgroupStorage(const std::string& name, const ast::Type* type); 216 217 /// Adds a storage buffer variable to the program 218 /// @param name the name of the variable 219 /// @param type the type to use 220 /// @param access the storage buffer access control 221 /// @param group the binding/group to use for the storage buffer 222 /// @param binding the binding number to use for the storage buffer 223 void AddStorageBuffer(const std::string& name, 224 const ast::Type* type, 225 ast::Access access, 226 uint32_t group, 227 uint32_t binding); 228 229 /// Generates a function that references a specific struct variable 230 /// @param func_name name of the function created 231 /// @param struct_name name of the struct variabler to be accessed 232 /// @param members list of members to access, by index and type 233 void MakeStructVariableReferenceBodyFunction( 234 std::string func_name, 235 std::string struct_name, 236 std::vector<std::tuple<size_t, const ast::Type*>> members); 237 238 /// Adds a regular sampler variable to the program 239 /// @param name the name of the variable 240 /// @param group the binding/group to use for the storage buffer 241 /// @param binding the binding number to use for the storage buffer 242 void AddSampler(const std::string& name, uint32_t group, uint32_t binding); 243 244 /// Adds a comparison sampler variable to the program 245 /// @param name the name of the variable 246 /// @param group the binding/group to use for the storage buffer 247 /// @param binding the binding number to use for the storage buffer 248 void AddComparisonSampler(const std::string& name, 249 uint32_t group, 250 uint32_t binding); 251 252 /// Adds a sampler or texture variable to the program 253 /// @param name the name of the variable 254 /// @param type the type to use 255 /// @param group the binding/group to use for the resource 256 /// @param binding the binding number to use for the resource 257 void AddResource(const std::string& name, 258 const ast::Type* type, 259 uint32_t group, 260 uint32_t binding); 261 262 /// Add a module scope private variable to the progames 263 /// @param name the name of the variable 264 /// @param type the type to use 265 void AddGlobalVariable(const std::string& name, const ast::Type* type); 266 267 /// Generates a function that references a specific sampler variable 268 /// @param func_name name of the function created 269 /// @param texture_name name of the texture to be sampled 270 /// @param sampler_name name of the sampler to use 271 /// @param coords_name name of the coords variable to use 272 /// @param base_type sampler base type 273 /// @param decorations the function decorations 274 /// @returns a function that references all of the values specified 275 const ast::Function* MakeSamplerReferenceBodyFunction( 276 const std::string& func_name, 277 const std::string& texture_name, 278 const std::string& sampler_name, 279 const std::string& coords_name, 280 const ast::Type* base_type, 281 ast::DecorationList decorations); 282 283 /// Generates a function that references a specific sampler variable 284 /// @param func_name name of the function created 285 /// @param texture_name name of the texture to be sampled 286 /// @param sampler_name name of the sampler to use 287 /// @param coords_name name of the coords variable to use 288 /// @param array_index name of the array index variable to use 289 /// @param base_type sampler base type 290 /// @param decorations the function decorations 291 /// @returns a function that references all of the values specified 292 const ast::Function* MakeSamplerReferenceBodyFunction( 293 const std::string& func_name, 294 const std::string& texture_name, 295 const std::string& sampler_name, 296 const std::string& coords_name, 297 const std::string& array_index, 298 const ast::Type* base_type, 299 ast::DecorationList decorations); 300 301 /// Generates a function that references a specific comparison sampler 302 /// variable. 303 /// @param func_name name of the function created 304 /// @param texture_name name of the depth texture to use 305 /// @param sampler_name name of the sampler to use 306 /// @param coords_name name of the coords variable to use 307 /// @param depth_name name of the depth reference to use 308 /// @param base_type sampler base type 309 /// @param decorations the function decorations 310 /// @returns a function that references all of the values specified 311 const ast::Function* MakeComparisonSamplerReferenceBodyFunction( 312 const std::string& func_name, 313 const std::string& texture_name, 314 const std::string& sampler_name, 315 const std::string& coords_name, 316 const std::string& depth_name, 317 const ast::Type* base_type, 318 ast::DecorationList decorations); 319 320 /// Gets an appropriate type for the data in a given texture type. 321 /// @param sampled_kind type of in the texture 322 /// @returns a pointer to a type appropriate for the coord param 323 const ast::Type* GetBaseType(ResourceBinding::SampledKind sampled_kind); 324 325 /// Gets an appropriate type for the coords parameter depending the the 326 /// dimensionality of the texture being sampled. 327 /// @param dim dimensionality of the texture being sampled 328 /// @param scalar the scalar type 329 /// @returns a pointer to a type appropriate for the coord param 330 const ast::Type* GetCoordsType(ast::TextureDimension dim, 331 const ast::Type* scalar); 332 333 /// Generates appropriate types for a Read-Only StorageTexture 334 /// @param dim the texture dimension of the storage texture 335 /// @param format the image format of the storage texture 336 /// @returns the storage texture type 337 const ast::Type* MakeStorageTextureTypes(ast::TextureDimension dim, 338 ast::ImageFormat format); 339 340 /// Adds a storage texture variable to the program 341 /// @param name the name of the variable 342 /// @param type the type to use 343 /// @param group the binding/group to use for the sampled texture 344 /// @param binding the binding57 number to use for the sampled texture 345 void AddStorageTexture(const std::string& name, 346 const ast::Type* type, 347 uint32_t group, 348 uint32_t binding); 349 350 /// Generates a function that references a storage texture variable. 351 /// @param func_name name of the function created 352 /// @param st_name name of the storage texture to use 353 /// @param dim_type type expected by textureDimensons to return 354 /// @param decorations the function decorations 355 /// @returns a function that references all of the values specified 356 const ast::Function* MakeStorageTextureBodyFunction( 357 const std::string& func_name, 358 const std::string& st_name, 359 const ast::Type* dim_type, 360 ast::DecorationList decorations); 361 362 /// Get a generator function that returns a type appropriate for a stage 363 /// variable with the given combination of component and composition type. 364 /// @param component component type of the stage variable 365 /// @param composition composition type of the stage variable 366 /// @returns a generator function for the stage variable's type. 367 std::function<const ast::Type*()> GetTypeFunction( 368 ComponentType component, 369 CompositionType composition); 370 371 /// Build the Program given all of the previous methods called and return an 372 /// Inspector for it. 373 /// Should only be called once per test. 374 /// @returns a reference to the Inspector for the built Program. 375 Inspector& Build(); 376 377 /// @returns the type for a SamplerKind::kSampler sampler_type()378 const ast::Sampler* sampler_type() { 379 return ty.sampler(ast::SamplerKind::kSampler); 380 } 381 382 /// @returns the type for a SamplerKind::kComparison comparison_sampler_type()383 const ast::Sampler* comparison_sampler_type() { 384 return ty.sampler(ast::SamplerKind::kComparisonSampler); 385 } 386 387 protected: 388 /// Program built by this builder. 389 std::unique_ptr<Program> program_; 390 /// Inspector for |program_| 391 std::unique_ptr<Inspector> inspector_; 392 }; 393 394 } // namespace inspector 395 } // namespace tint 396 397 #endif // SRC_INSPECTOR_TEST_INSPECTOR_BUILDER_H_ 398