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 /// Sets or clears runtime layer bit to |enabled|. SetPipelineRuntimeLayerEnabled(bool enabled)71 void SetPipelineRuntimeLayerEnabled(bool enabled) override { 72 engine_data_.pipeline_runtime_layer_enabled = enabled; 73 } 74 75 /// Adds |pipeline| to the list of known pipelines. The |pipeline| must have 76 /// a unique name over all pipelines in the script. AddPipeline(std::unique_ptr<Pipeline> pipeline)77 Result AddPipeline(std::unique_ptr<Pipeline> pipeline) { 78 if (name_to_pipeline_.count(pipeline->GetName()) > 0) 79 return Result("duplicate pipeline name provided"); 80 81 pipelines_.push_back(std::move(pipeline)); 82 name_to_pipeline_[pipelines_.back()->GetName()] = pipelines_.back().get(); 83 return {}; 84 } 85 86 /// Retrieves the pipeline with |name|, |nullptr| if not found. GetPipeline(const std::string & name)87 Pipeline* GetPipeline(const std::string& name) const { 88 auto it = name_to_pipeline_.find(name); 89 return it == name_to_pipeline_.end() ? nullptr : it->second; 90 } 91 92 /// Retrieves a list of all pipelines. GetPipelines()93 const std::vector<std::unique_ptr<Pipeline>>& GetPipelines() const { 94 return pipelines_; 95 } 96 97 /// Adds |shader| to the list of known shaders. The |shader| must have a 98 /// unique name over all shaders in the script. AddShader(std::unique_ptr<Shader> shader)99 Result AddShader(std::unique_ptr<Shader> shader) { 100 if (name_to_shader_.count(shader->GetName()) > 0) 101 return Result("duplicate shader name provided"); 102 103 shaders_.push_back(std::move(shader)); 104 name_to_shader_[shaders_.back()->GetName()] = shaders_.back().get(); 105 return {}; 106 } 107 108 /// Retrieves the shader with |name|, |nullptr| if not found. GetShader(const std::string & name)109 Shader* GetShader(const std::string& name) const { 110 auto it = name_to_shader_.find(name); 111 return it == name_to_shader_.end() ? nullptr : it->second; 112 } 113 114 /// Retrieves a list of all shaders. GetShaders()115 const std::vector<std::unique_ptr<Shader>>& GetShaders() const { 116 return shaders_; 117 } 118 119 /// Adds |buffer| to the list of known buffers. The |buffer| must have a 120 /// unique name over all buffers in the script. AddBuffer(std::unique_ptr<Buffer> buffer)121 Result AddBuffer(std::unique_ptr<Buffer> buffer) { 122 if (name_to_buffer_.count(buffer->GetName()) > 0) 123 return Result("duplicate buffer name provided"); 124 125 buffers_.push_back(std::move(buffer)); 126 name_to_buffer_[buffers_.back()->GetName()] = buffers_.back().get(); 127 return {}; 128 } 129 130 /// Retrieves the buffer with |name|, |nullptr| if not found. GetBuffer(const std::string & name)131 Buffer* GetBuffer(const std::string& name) const { 132 auto it = name_to_buffer_.find(name); 133 return it == name_to_buffer_.end() ? nullptr : it->second; 134 } 135 136 /// Retrieves a list of all buffers. GetBuffers()137 const std::vector<std::unique_ptr<Buffer>>& GetBuffers() const { 138 return buffers_; 139 } 140 141 /// Adds |sampler| to the list of known sampler. The |sampler| must have a 142 /// unique name over all samplers in the script. AddSampler(std::unique_ptr<Sampler> sampler)143 Result AddSampler(std::unique_ptr<Sampler> sampler) { 144 if (name_to_sampler_.count(sampler->GetName()) > 0) 145 return Result("duplicate sampler name provided"); 146 147 samplers_.push_back(std::move(sampler)); 148 name_to_sampler_[samplers_.back()->GetName()] = samplers_.back().get(); 149 return {}; 150 } 151 152 /// Retrieves the sampler with |name|, |nullptr| if not found. GetSampler(const std::string & name)153 Sampler* GetSampler(const std::string& name) const { 154 auto it = name_to_sampler_.find(name); 155 return it == name_to_sampler_.end() ? nullptr : it->second; 156 } 157 158 /// Retrieves a list of all samplers. GetSamplers()159 const std::vector<std::unique_ptr<Sampler>>& GetSamplers() const { 160 return samplers_; 161 } 162 163 /// Adds |feature| to the list of features that must be supported by the 164 /// engine. AddRequiredFeature(const std::string & feature)165 void AddRequiredFeature(const std::string& feature) { 166 engine_info_.required_features.push_back(feature); 167 } 168 169 /// Checks if |feature| is in required features IsRequiredFeature(const std::string & feature)170 bool IsRequiredFeature(const std::string& feature) const { 171 return std::find(engine_info_.required_features.begin(), 172 engine_info_.required_features.end(), 173 feature) != engine_info_.required_features.end(); 174 } 175 176 /// Adds |ext| to the list of device extensions that must be supported. AddRequiredDeviceExtension(const std::string & ext)177 void AddRequiredDeviceExtension(const std::string& ext) { 178 engine_info_.required_device_extensions.push_back(ext); 179 } 180 181 /// Adds |ext| to the list of instance extensions that must be supported. AddRequiredInstanceExtension(const std::string & ext)182 void AddRequiredInstanceExtension(const std::string& ext) { 183 engine_info_.required_instance_extensions.push_back(ext); 184 } 185 186 /// Adds |ext| to the list of extensions that must be supported by the engine. 187 /// Note, this should only be used by the VkScript engine where there is no 188 /// differentiation between the types of extensions. 189 void AddRequiredExtension(const std::string& ext); 190 191 /// Retrieves the engine configuration data for this script. GetEngineData()192 EngineData& GetEngineData() { return engine_data_; } 193 /// Retrieves the engine configuration data for this script. GetEngineData()194 const EngineData& GetEngineData() const { return engine_data_; } 195 196 /// Sets |cmds| to the list of commands to execute against the engine. SetCommands(std::vector<std::unique_ptr<Command>> cmds)197 void SetCommands(std::vector<std::unique_ptr<Command>> cmds) { 198 commands_ = std::move(cmds); 199 } 200 201 /// Retrieves the list of commands to execute against the engine. GetCommands()202 const std::vector<std::unique_ptr<Command>>& GetCommands() const { 203 return commands_; 204 } 205 206 /// Sets the SPIR-V target environment. SetSpvTargetEnv(const std::string & env)207 void SetSpvTargetEnv(const std::string& env) { spv_env_ = env; } 208 /// Retrieves the SPIR-V target environment. GetSpvTargetEnv()209 const std::string& GetSpvTargetEnv() const { return spv_env_; } 210 211 /// Assign ownership of the format to the script. RegisterFormat(std::unique_ptr<Format> fmt)212 Format* RegisterFormat(std::unique_ptr<Format> fmt) { 213 formats_.push_back(std::move(fmt)); 214 return formats_.back().get(); 215 } 216 217 /// Assigns ownership of the type to the script. RegisterType(std::unique_ptr<type::Type> type)218 type::Type* RegisterType(std::unique_ptr<type::Type> type) { 219 types_.push_back(std::move(type)); 220 return types_.back().get(); 221 } 222 223 /// Adds |type| to the list of known types. The |type| must have 224 /// a unique name over all types in the script. AddType(const std::string & name,std::unique_ptr<type::Type> type)225 Result AddType(const std::string& name, std::unique_ptr<type::Type> type) { 226 if (name_to_type_.count(name) > 0) 227 return Result("duplicate type name provided"); 228 229 name_to_type_[name] = std::move(type); 230 return {}; 231 } 232 233 /// Retrieves the type with |name|, |nullptr| if not found. GetType(const std::string & name)234 type::Type* GetType(const std::string& name) const { 235 auto it = name_to_type_.find(name); 236 return it == name_to_type_.end() ? nullptr : it->second.get(); 237 } 238 239 // Returns the virtual file store. GetVirtualFiles()240 VirtualFileStore* GetVirtualFiles() const { return virtual_files_.get(); } 241 242 /// Adds the virtual file with content |content| to the virtual file path 243 /// |path|. If there's already a virtual file with the given path, an error is 244 /// returned. AddVirtualFile(const std::string & path,const std::string & content)245 Result AddVirtualFile(const std::string& path, const std::string& content) { 246 return virtual_files_->Add(path, content); 247 } 248 249 /// Look up the virtual file by path. If the file was found, the content is 250 /// assigned to content. GetVirtualFile(const std::string & path,std::string * content)251 Result GetVirtualFile(const std::string& path, std::string* content) const { 252 return virtual_files_->Get(path, content); 253 } 254 255 type::Type* ParseType(const std::string& str); 256 257 private: 258 struct { 259 std::vector<std::string> required_features; 260 std::vector<std::string> required_device_extensions; 261 std::vector<std::string> required_instance_extensions; 262 } engine_info_; 263 264 EngineData engine_data_; 265 std::string spv_env_; 266 std::map<std::string, Shader*> name_to_shader_; 267 std::map<std::string, Buffer*> name_to_buffer_; 268 std::map<std::string, Sampler*> name_to_sampler_; 269 std::map<std::string, Pipeline*> name_to_pipeline_; 270 std::map<std::string, std::unique_ptr<type::Type>> name_to_type_; 271 std::vector<std::unique_ptr<Shader>> shaders_; 272 std::vector<std::unique_ptr<Command>> commands_; 273 std::vector<std::unique_ptr<Buffer>> buffers_; 274 std::vector<std::unique_ptr<Sampler>> samplers_; 275 std::vector<std::unique_ptr<Pipeline>> pipelines_; 276 std::vector<std::unique_ptr<type::Type>> types_; 277 std::vector<std::unique_ptr<Format>> formats_; 278 std::unique_ptr<VirtualFileStore> virtual_files_; 279 }; 280 281 } // namespace amber 282 283 #endif // SRC_SCRIPT_H_ 284