1 // Copyright 2018 The Amber 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_SCRIPT_H_ 16 #define SRC_SCRIPT_H_ 17 18 #include <algorithm> 19 #include <cstdint> 20 #include <map> 21 #include <memory> 22 #include <string> 23 #include <utility> 24 #include <vector> 25 26 #include "amber/recipe.h" 27 #include "amber/result.h" 28 #include "src/buffer.h" 29 #include "src/command.h" 30 #include "src/engine.h" 31 #include "src/format.h" 32 #include "src/pipeline.h" 33 #include "src/sampler.h" 34 #include "src/shader.h" 35 #include "src/virtual_file_store.h" 36 37 namespace amber { 38 39 /// Class representing the script to be run against an engine. 40 class Script : public RecipeImpl { 41 public: 42 Script(); 43 ~Script() override; 44 45 bool IsKnownFeature(const std::string& name) const; 46 47 /// Retrieves information on the shaders in the given script. 48 std::vector<ShaderInfo> GetShaderInfo() const override; 49 50 /// Returns required features in the given recipe. GetRequiredFeatures()51 std::vector<std::string> GetRequiredFeatures() const override { 52 return engine_info_.required_features; 53 } 54 55 /// Returns required device extensions in the given recipe. GetRequiredDeviceExtensions()56 std::vector<std::string> GetRequiredDeviceExtensions() const override { 57 return engine_info_.required_device_extensions; 58 } 59 60 /// Returns required instance extensions in the given recipe. GetRequiredInstanceExtensions()61 std::vector<std::string> GetRequiredInstanceExtensions() const override { 62 return engine_info_.required_instance_extensions; 63 } 64 65 /// Sets the fence timeout to |timeout_ms|. SetFenceTimeout(uint32_t timeout_ms)66 void SetFenceTimeout(uint32_t timeout_ms) override { 67 engine_data_.fence_timeout_ms = timeout_ms; 68 } 69 70 /// Adds |pipeline| to the list of known pipelines. The |pipeline| must have 71 /// a unique name over all pipelines in the script. AddPipeline(std::unique_ptr<Pipeline> pipeline)72 Result AddPipeline(std::unique_ptr<Pipeline> pipeline) { 73 if (name_to_pipeline_.count(pipeline->GetName()) > 0) 74 return Result("duplicate pipeline name provided"); 75 76 pipelines_.push_back(std::move(pipeline)); 77 name_to_pipeline_[pipelines_.back()->GetName()] = pipelines_.back().get(); 78 return {}; 79 } 80 81 /// Retrieves the pipeline with |name|, |nullptr| if not found. GetPipeline(const std::string & name)82 Pipeline* GetPipeline(const std::string& name) const { 83 auto it = name_to_pipeline_.find(name); 84 return it == name_to_pipeline_.end() ? nullptr : it->second; 85 } 86 87 /// Retrieves a list of all pipelines. GetPipelines()88 const std::vector<std::unique_ptr<Pipeline>>& GetPipelines() const { 89 return pipelines_; 90 } 91 92 /// Adds |shader| to the list of known shaders. The |shader| must have a 93 /// unique name over all shaders in the script. AddShader(std::unique_ptr<Shader> shader)94 Result AddShader(std::unique_ptr<Shader> shader) { 95 if (name_to_shader_.count(shader->GetName()) > 0) 96 return Result("duplicate shader name provided"); 97 98 shaders_.push_back(std::move(shader)); 99 name_to_shader_[shaders_.back()->GetName()] = shaders_.back().get(); 100 return {}; 101 } 102 103 /// Retrieves the shader with |name|, |nullptr| if not found. GetShader(const std::string & name)104 Shader* GetShader(const std::string& name) const { 105 auto it = name_to_shader_.find(name); 106 return it == name_to_shader_.end() ? nullptr : it->second; 107 } 108 109 /// Retrieves a list of all shaders. GetShaders()110 const std::vector<std::unique_ptr<Shader>>& GetShaders() const { 111 return shaders_; 112 } 113 114 /// Adds |buffer| to the list of known buffers. The |buffer| must have a 115 /// unique name over all buffers in the script. AddBuffer(std::unique_ptr<Buffer> buffer)116 Result AddBuffer(std::unique_ptr<Buffer> buffer) { 117 if (name_to_buffer_.count(buffer->GetName()) > 0) 118 return Result("duplicate buffer name provided"); 119 120 buffers_.push_back(std::move(buffer)); 121 name_to_buffer_[buffers_.back()->GetName()] = buffers_.back().get(); 122 return {}; 123 } 124 125 /// Retrieves the buffer with |name|, |nullptr| if not found. GetBuffer(const std::string & name)126 Buffer* GetBuffer(const std::string& name) const { 127 auto it = name_to_buffer_.find(name); 128 return it == name_to_buffer_.end() ? nullptr : it->second; 129 } 130 131 /// Retrieves a list of all buffers. GetBuffers()132 const std::vector<std::unique_ptr<Buffer>>& GetBuffers() const { 133 return buffers_; 134 } 135 136 /// Adds |sampler| to the list of known sampler. The |sampler| must have a 137 /// unique name over all samplers in the script. AddSampler(std::unique_ptr<Sampler> sampler)138 Result AddSampler(std::unique_ptr<Sampler> sampler) { 139 if (name_to_sampler_.count(sampler->GetName()) > 0) 140 return Result("duplicate sampler name provided"); 141 142 samplers_.push_back(std::move(sampler)); 143 name_to_sampler_[samplers_.back()->GetName()] = samplers_.back().get(); 144 return {}; 145 } 146 147 /// Retrieves the sampler with |name|, |nullptr| if not found. GetSampler(const std::string & name)148 Sampler* GetSampler(const std::string& name) const { 149 auto it = name_to_sampler_.find(name); 150 return it == name_to_sampler_.end() ? nullptr : it->second; 151 } 152 153 /// Retrieves a list of all samplers. GetSamplers()154 const std::vector<std::unique_ptr<Sampler>>& GetSamplers() const { 155 return samplers_; 156 } 157 158 /// Adds |feature| to the list of features that must be supported by the 159 /// engine. AddRequiredFeature(const std::string & feature)160 void AddRequiredFeature(const std::string& feature) { 161 engine_info_.required_features.push_back(feature); 162 } 163 164 /// Checks if |feature| is in required features IsRequiredFeature(const std::string & feature)165 bool IsRequiredFeature(const std::string& feature) const { 166 return std::find(engine_info_.required_features.begin(), 167 engine_info_.required_features.end(), 168 feature) != engine_info_.required_features.end(); 169 } 170 171 /// Adds |ext| to the list of device extensions that must be supported. AddRequiredDeviceExtension(const std::string & ext)172 void AddRequiredDeviceExtension(const std::string& ext) { 173 engine_info_.required_device_extensions.push_back(ext); 174 } 175 176 /// Adds |ext| to the list of instance extensions that must be supported. AddRequiredInstanceExtension(const std::string & ext)177 void AddRequiredInstanceExtension(const std::string& ext) { 178 engine_info_.required_instance_extensions.push_back(ext); 179 } 180 181 /// Adds |ext| to the list of extensions that must be supported by the engine. 182 /// Note, this should only be used by the VkScript engine where there is no 183 /// differentiation between the types of extensions. 184 void AddRequiredExtension(const std::string& ext); 185 186 /// Retrieves the engine configuration data for this script. GetEngineData()187 EngineData& GetEngineData() { return engine_data_; } 188 /// Retrieves the engine configuration data for this script. GetEngineData()189 const EngineData& GetEngineData() const { return engine_data_; } 190 191 /// Sets |cmds| to the list of commands to execute against the engine. SetCommands(std::vector<std::unique_ptr<Command>> cmds)192 void SetCommands(std::vector<std::unique_ptr<Command>> cmds) { 193 commands_ = std::move(cmds); 194 } 195 196 /// Retrieves the list of commands to execute against the engine. GetCommands()197 const std::vector<std::unique_ptr<Command>>& GetCommands() const { 198 return commands_; 199 } 200 201 /// Sets the SPIR-V target environment. SetSpvTargetEnv(const std::string & env)202 void SetSpvTargetEnv(const std::string& env) { spv_env_ = env; } 203 /// Retrieves the SPIR-V target environment. GetSpvTargetEnv()204 const std::string& GetSpvTargetEnv() const { return spv_env_; } 205 206 /// Assign ownership of the format to the script. RegisterFormat(std::unique_ptr<Format> fmt)207 Format* RegisterFormat(std::unique_ptr<Format> fmt) { 208 formats_.push_back(std::move(fmt)); 209 return formats_.back().get(); 210 } 211 212 /// Assigns ownership of the type to the script. RegisterType(std::unique_ptr<type::Type> type)213 type::Type* RegisterType(std::unique_ptr<type::Type> type) { 214 types_.push_back(std::move(type)); 215 return types_.back().get(); 216 } 217 218 /// Adds |type| to the list of known types. The |type| must have 219 /// a unique name over all types in the script. AddType(const std::string & name,std::unique_ptr<type::Type> type)220 Result AddType(const std::string& name, std::unique_ptr<type::Type> type) { 221 if (name_to_type_.count(name) > 0) 222 return Result("duplicate type name provided"); 223 224 name_to_type_[name] = std::move(type); 225 return {}; 226 } 227 228 /// Retrieves the type with |name|, |nullptr| if not found. GetType(const std::string & name)229 type::Type* GetType(const std::string& name) const { 230 auto it = name_to_type_.find(name); 231 return it == name_to_type_.end() ? nullptr : it->second.get(); 232 } 233 234 // Returns the virtual file store. GetVirtualFiles()235 VirtualFileStore* GetVirtualFiles() const { return virtual_files_.get(); } 236 237 /// Adds the virtual file with content |content| to the virtual file path 238 /// |path|. If there's already a virtual file with the given path, an error is 239 /// returned. AddVirtualFile(const std::string & path,const std::string & content)240 Result AddVirtualFile(const std::string& path, const std::string& content) { 241 return virtual_files_->Add(path, content); 242 } 243 244 /// Look up the virtual file by path. If the file was found, the content is 245 /// assigned to content. GetVirtualFile(const std::string & path,std::string * content)246 Result GetVirtualFile(const std::string& path, std::string* content) const { 247 return virtual_files_->Get(path, content); 248 } 249 250 type::Type* ParseType(const std::string& str); 251 252 private: 253 struct { 254 std::vector<std::string> required_features; 255 std::vector<std::string> required_device_extensions; 256 std::vector<std::string> required_instance_extensions; 257 } engine_info_; 258 259 EngineData engine_data_; 260 std::string spv_env_; 261 std::map<std::string, Shader*> name_to_shader_; 262 std::map<std::string, Buffer*> name_to_buffer_; 263 std::map<std::string, Sampler*> name_to_sampler_; 264 std::map<std::string, Pipeline*> name_to_pipeline_; 265 std::map<std::string, std::unique_ptr<type::Type>> name_to_type_; 266 std::vector<std::unique_ptr<Shader>> shaders_; 267 std::vector<std::unique_ptr<Command>> commands_; 268 std::vector<std::unique_ptr<Buffer>> buffers_; 269 std::vector<std::unique_ptr<Sampler>> samplers_; 270 std::vector<std::unique_ptr<Pipeline>> pipelines_; 271 std::vector<std::unique_ptr<type::Type>> types_; 272 std::vector<std::unique_ptr<Format>> formats_; 273 std::unique_ptr<VirtualFileStore> virtual_files_; 274 }; 275 276 } // namespace amber 277 278 #endif // SRC_SCRIPT_H_ 279