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_PIPELINE_H_ 16 #define SRC_PIPELINE_H_ 17 18 #include <map> 19 #include <memory> 20 #include <string> 21 #include <unordered_map> 22 #include <utility> 23 #include <vector> 24 25 #include "amber/result.h" 26 #include "src/buffer.h" 27 #include "src/command_data.h" 28 #include "src/pipeline_data.h" 29 #include "src/sampler.h" 30 #include "src/shader.h" 31 32 namespace amber { 33 34 enum class PipelineType { kCompute = 0, kGraphics }; 35 36 /// Stores all information related to a pipeline. 37 class Pipeline { 38 public: 39 /// Information on a shader attached to this pipeline. 40 class ShaderInfo { 41 public: 42 ShaderInfo(Shader*, ShaderType type); 43 ShaderInfo(const ShaderInfo&); 44 ~ShaderInfo(); 45 46 ShaderInfo& operator=(const ShaderInfo&) = default; 47 48 // Set the optimization options for this shader. Optimizations are 49 // specified like command-line arguments to spirv-opt (see its --help). 50 // Parsing is done by spvtools::Optimizer::RegisterPassesFromFlags (see 51 // SPIRV-Tools include/spirv-tools/optimizer.hpp). SetShaderOptimizations(const std::vector<std::string> & opts)52 void SetShaderOptimizations(const std::vector<std::string>& opts) { 53 shader_optimizations_ = opts; 54 } GetShaderOptimizations()55 const std::vector<std::string>& GetShaderOptimizations() const { 56 return shader_optimizations_; 57 } 58 SetCompileOptions(const std::vector<std::string> & options)59 void SetCompileOptions(const std::vector<std::string>& options) { 60 compile_options_ = options; 61 } GetCompileOptions()62 const std::vector<std::string>& GetCompileOptions() const { 63 return compile_options_; 64 } 65 66 enum class RequiredSubgroupSizeSetting : uint32_t { 67 kNotSet = 0, 68 kSetToSpecificSize, 69 kSetToMinimumSize, 70 kSetToMaximumSize 71 }; 72 SetRequiredSubgroupSizeSetting(RequiredSubgroupSizeSetting setting,uint32_t size)73 void SetRequiredSubgroupSizeSetting(RequiredSubgroupSizeSetting setting, 74 uint32_t size) { 75 required_subgroup_size_setting_ = setting; 76 required_subgroup_size_ = size; 77 } GetRequiredSubgroupSizeSetting()78 RequiredSubgroupSizeSetting GetRequiredSubgroupSizeSetting() const { 79 return required_subgroup_size_setting_; 80 } GetRequiredSubgroupSize()81 uint32_t GetRequiredSubgroupSize() const { return required_subgroup_size_; } 82 SetVaryingSubgroupSize(const bool isSet)83 void SetVaryingSubgroupSize(const bool isSet) { 84 varying_subgroup_size_ = isSet; 85 } GetVaryingSubgroupSize()86 bool GetVaryingSubgroupSize() const { return varying_subgroup_size_; } 87 SetRequireFullSubgroups(const bool isSet)88 void SetRequireFullSubgroups(const bool isSet) { 89 require_full_subgroups_ = isSet; 90 } GetRequireFullSubgroups()91 bool GetRequireFullSubgroups() const { return require_full_subgroups_; } 92 SetEmitDebugInfo(const bool isSet)93 void SetEmitDebugInfo(const bool isSet) { emit_debug_info_ = isSet; } GetEmitDebugInfo()94 bool GetEmitDebugInfo() const { return emit_debug_info_; } 95 SetShader(Shader * shader)96 void SetShader(Shader* shader) { shader_ = shader; } GetShader()97 const Shader* GetShader() const { return shader_; } 98 SetEntryPoint(const std::string & ep)99 void SetEntryPoint(const std::string& ep) { entry_point_ = ep; } GetEntryPoint()100 const std::string& GetEntryPoint() const { return entry_point_; } 101 SetShaderType(ShaderType type)102 void SetShaderType(ShaderType type) { shader_type_ = type; } GetShaderType()103 ShaderType GetShaderType() const { return shader_type_; } 104 GetData()105 const std::vector<uint32_t> GetData() const { return data_; } SetData(std::vector<uint32_t> && data)106 void SetData(std::vector<uint32_t>&& data) { data_ = std::move(data); } 107 GetSpecialization()108 const std::map<uint32_t, uint32_t>& GetSpecialization() const { 109 return specialization_; 110 } AddSpecialization(uint32_t spec_id,uint32_t value)111 void AddSpecialization(uint32_t spec_id, uint32_t value) { 112 specialization_[spec_id] = value; 113 } 114 115 /// Descriptor information for an OpenCL-C shader. 116 struct DescriptorMapEntry { 117 std::string arg_name = ""; 118 119 enum class Kind : int { 120 UNKNOWN, 121 SSBO, 122 UBO, 123 POD, 124 POD_UBO, 125 POD_PUSHCONSTANT, 126 RO_IMAGE, 127 WO_IMAGE, 128 SAMPLER, 129 } kind; 130 131 uint32_t descriptor_set = 0; 132 uint32_t binding = 0; 133 uint32_t arg_ordinal = 0; 134 uint32_t pod_offset = 0; 135 uint32_t pod_arg_size = 0; 136 }; 137 AddDescriptorEntry(const std::string & kernel,DescriptorMapEntry && entry)138 void AddDescriptorEntry(const std::string& kernel, 139 DescriptorMapEntry&& entry) { 140 descriptor_map_[kernel].emplace_back(std::move(entry)); 141 } 142 const std::unordered_map<std::string, std::vector<DescriptorMapEntry>>& GetDescriptorMap()143 GetDescriptorMap() const { 144 return descriptor_map_; 145 } 146 147 /// Push constant information for an OpenCL-C shader. 148 struct PushConstant { 149 enum class PushConstantType { 150 kDimensions = 0, 151 kGlobalOffset, 152 kRegionOffset, 153 }; 154 PushConstantType type; 155 uint32_t offset = 0; 156 uint32_t size = 0; 157 }; 158 AddPushConstant(PushConstant && pc)159 void AddPushConstant(PushConstant&& pc) { 160 push_constants_.emplace_back(std::move(pc)); 161 } GetPushConstants()162 const std::vector<PushConstant>& GetPushConstants() const { 163 return push_constants_; 164 } 165 166 private: 167 Shader* shader_ = nullptr; 168 ShaderType shader_type_; 169 std::vector<std::string> shader_optimizations_; 170 std::string entry_point_; 171 std::vector<uint32_t> data_; 172 std::map<uint32_t, uint32_t> specialization_; 173 std::unordered_map<std::string, std::vector<DescriptorMapEntry>> 174 descriptor_map_; 175 std::vector<PushConstant> push_constants_; 176 std::vector<std::string> compile_options_; 177 RequiredSubgroupSizeSetting required_subgroup_size_setting_; 178 uint32_t required_subgroup_size_; 179 bool varying_subgroup_size_; 180 bool require_full_subgroups_; 181 bool emit_debug_info_; 182 }; 183 184 /// Information on a buffer attached to the pipeline. 185 /// 186 /// The BufferInfo will have either (descriptor_set, binding) or location 187 /// attached. 188 struct BufferInfo { 189 BufferInfo() = default; BufferInfoBufferInfo190 explicit BufferInfo(Buffer* buf) : buffer(buf) {} 191 192 Buffer* buffer = nullptr; 193 uint32_t descriptor_set = 0; 194 uint32_t binding = 0; 195 uint32_t location = 0; 196 uint32_t base_mip_level = 0; 197 uint32_t dynamic_offset = 0; 198 std::string arg_name = ""; 199 uint32_t arg_no = 0; 200 BufferType type = BufferType::kUnknown; 201 InputRate input_rate = InputRate::kVertex; 202 Format* format; 203 uint32_t offset = 0; 204 uint32_t stride = 0; 205 Sampler* sampler = nullptr; 206 uint64_t descriptor_offset = 0; 207 uint64_t descriptor_range = ~0ULL; // ~0ULL == VK_WHOLE_SIZE 208 }; 209 210 /// Information on a sampler attached to the pipeline. 211 struct SamplerInfo { 212 SamplerInfo() = default; SamplerInfoSamplerInfo213 explicit SamplerInfo(Sampler* samp) : sampler(samp) {} 214 215 Sampler* sampler = nullptr; 216 uint32_t descriptor_set = 0; 217 uint32_t binding = 0; 218 std::string arg_name = ""; 219 uint32_t arg_no = 0; 220 uint32_t mask = 0; 221 }; 222 223 static const char* kGeneratedColorBuffer; 224 static const char* kGeneratedDepthBuffer; 225 static const char* kGeneratedPushConstantBuffer; 226 227 explicit Pipeline(PipelineType type); 228 ~Pipeline(); 229 230 std::unique_ptr<Pipeline> Clone() const; 231 IsGraphics()232 bool IsGraphics() const { return pipeline_type_ == PipelineType::kGraphics; } IsCompute()233 bool IsCompute() const { return pipeline_type_ == PipelineType::kCompute; } 234 GetType()235 PipelineType GetType() const { return pipeline_type_; } 236 SetName(const std::string & name)237 void SetName(const std::string& name) { name_ = name; } GetName()238 const std::string& GetName() const { return name_; } 239 SetFramebufferWidth(uint32_t fb_width)240 void SetFramebufferWidth(uint32_t fb_width) { 241 fb_width_ = fb_width; 242 UpdateFramebufferSizes(); 243 } GetFramebufferWidth()244 uint32_t GetFramebufferWidth() const { return fb_width_; } 245 SetFramebufferHeight(uint32_t fb_height)246 void SetFramebufferHeight(uint32_t fb_height) { 247 fb_height_ = fb_height; 248 UpdateFramebufferSizes(); 249 } GetFramebufferHeight()250 uint32_t GetFramebufferHeight() const { return fb_height_; } 251 252 /// Adds |shader| of |type| to the pipeline. 253 Result AddShader(Shader* shader, ShaderType type); 254 /// Returns information on all bound shaders in this pipeline. GetShaders()255 std::vector<ShaderInfo>& GetShaders() { return shaders_; } 256 /// Returns information on all bound shaders in this pipeline. GetShaders()257 const std::vector<ShaderInfo>& GetShaders() const { return shaders_; } 258 259 /// Returns the ShaderInfo for |shader| or nullptr. GetShader(Shader * shader)260 const ShaderInfo* GetShader(Shader* shader) const { 261 for (const auto& info : shaders_) { 262 if (info.GetShader() == shader) 263 return &info; 264 } 265 return nullptr; 266 } 267 268 /// Sets the |type| of |shader| in the pipeline. 269 Result SetShaderType(const Shader* shader, ShaderType type); 270 /// Sets the entry point |name| for |shader| in this pipeline. 271 Result SetShaderEntryPoint(const Shader* shader, const std::string& name); 272 /// Sets the optimizations (|opts|) for |shader| in this pipeline. 273 Result SetShaderOptimizations(const Shader* shader, 274 const std::vector<std::string>& opts); 275 /// Sets the compile options for |shader| in this pipeline. 276 Result SetShaderCompileOptions(const Shader* shader, 277 const std::vector<std::string>& options); 278 /// Sets required subgroup size. 279 Result SetShaderRequiredSubgroupSize(const Shader* shader, 280 const uint32_t subgroupSize); 281 /// Sets required subgroup size to the device minimum supported subgroup size. 282 Result SetShaderRequiredSubgroupSizeToMinimum(const Shader* shader); 283 284 /// Sets required subgroup size to the device maximum supported subgroup size. 285 Result SetShaderRequiredSubgroupSizeToMaximum(const Shader* shader); 286 287 /// Sets varying subgroup size property. 288 Result SetShaderVaryingSubgroupSize(const Shader* shader, const bool isSet); 289 290 /// Sets require full subgroups property. 291 Result SetShaderRequireFullSubgroups(const Shader* shader, const bool isSet); 292 /// Returns a list of all colour attachments in this pipeline. GetColorAttachments()293 const std::vector<BufferInfo>& GetColorAttachments() const { 294 return color_attachments_; 295 } 296 /// Adds |buf| as a colour attachment at |location| in the pipeline. 297 /// Uses |base_mip_level| as the mip level for output. 298 Result AddColorAttachment(Buffer* buf, 299 uint32_t location, 300 uint32_t base_mip_level); 301 /// Retrieves the location that |buf| is bound to in the pipeline. The 302 /// location will be written to |loc|. An error result will be return if 303 /// something goes wrong. 304 Result GetLocationForColorAttachment(Buffer* buf, uint32_t* loc) const; 305 306 /// Returns a list of all resolve targets in this pipeline. GetResolveTargets()307 const std::vector<BufferInfo>& GetResolveTargets() const { 308 return resolve_targets_; 309 } 310 311 /// Adds |buf| as a multisample resolve target in the pipeline. 312 Result AddResolveTarget(Buffer* buf); 313 314 /// Sets |buf| as the depth/stencil buffer for this pipeline. 315 Result SetDepthStencilBuffer(Buffer* buf); 316 /// Returns information on the depth/stencil buffer bound to the pipeline. If 317 /// no depth buffer is bound the |BufferInfo::buffer| parameter will be 318 /// nullptr. GetDepthStencilBuffer()319 const BufferInfo& GetDepthStencilBuffer() const { 320 return depth_stencil_buffer_; 321 } 322 323 /// Returns pipeline data. GetPipelineData()324 PipelineData* GetPipelineData() { return &pipeline_data_; } 325 326 /// Returns information on all vertex buffers bound to the pipeline. GetVertexBuffers()327 const std::vector<BufferInfo>& GetVertexBuffers() const { 328 return vertex_buffers_; 329 } 330 /// Adds |buf| as a vertex buffer at |location| in the pipeline using |rate| 331 /// as the input rate, |format| as vertex data format, |offset| as a starting 332 /// offset for the vertex buffer data, and |stride| for the data stride in 333 /// bytes. 334 Result AddVertexBuffer(Buffer* buf, 335 uint32_t location, 336 InputRate rate, 337 Format* format, 338 uint32_t offset, 339 uint32_t stride); 340 341 /// Binds |buf| as the index buffer for this pipeline. 342 Result SetIndexBuffer(Buffer* buf); 343 /// Returns the index buffer bound to this pipeline or nullptr if no index 344 /// buffer bound. GetIndexBuffer()345 Buffer* GetIndexBuffer() const { return index_buffer_; } 346 347 /// Adds |buf| of |type| to the pipeline at the given |descriptor_set|, 348 /// |binding|, |base_mip_level|, |descriptor_offset|, |descriptor_range| and 349 /// |dynamic_offset|. 350 void AddBuffer(Buffer* buf, 351 BufferType type, 352 uint32_t descriptor_set, 353 uint32_t binding, 354 uint32_t base_mip_level, 355 uint32_t dynamic_offset, 356 uint64_t descriptor_offset, 357 uint64_t descriptor_range); 358 /// Adds |buf| to the pipeline at the given |arg_name|. 359 void AddBuffer(Buffer* buf, BufferType type, const std::string& arg_name); 360 /// Adds |buf| to the pipeline at the given |arg_no|. 361 void AddBuffer(Buffer* buf, BufferType type, uint32_t arg_no); 362 /// Returns information on all buffers in this pipeline. GetBuffers()363 const std::vector<BufferInfo>& GetBuffers() const { return buffers_; } 364 /// Clears all buffer bindings for given |descriptor_set| and |binding|. 365 void ClearBuffers(uint32_t descriptor_set, uint32_t binding); 366 367 /// Adds |sampler| to the pipeline at the given |descriptor_set| and 368 /// |binding|. 369 void AddSampler(Sampler* sampler, uint32_t descriptor_set, uint32_t binding); 370 /// Adds |sampler| to the pipeline at the given |arg_name|. 371 void AddSampler(Sampler* sampler, const std::string& arg_name); 372 /// Adds |sampler| to the pieline at the given |arg_no|. 373 void AddSampler(Sampler* sampler, uint32_t arg_no); 374 /// Adds an entry for an OpenCL literal sampler. 375 void AddSampler(uint32_t sampler_mask, 376 uint32_t descriptor_set, 377 uint32_t binding); 378 /// Clears all sampler bindings for given |descriptor_set| and |binding|. 379 void ClearSamplers(uint32_t descriptor_set, uint32_t binding); 380 381 /// Returns information on all samplers in this pipeline. GetSamplers()382 const std::vector<SamplerInfo>& GetSamplers() const { return samplers_; } 383 384 /// Updates the descriptor set and binding info for the OpenCL-C kernel bound 385 /// to the pipeline. No effect for other shader formats. 386 Result UpdateOpenCLBufferBindings(); 387 388 /// Returns the buffer which is currently bound to this pipeline at 389 /// |descriptor_set| and |binding|. 390 Buffer* GetBufferForBinding(uint32_t descriptor_set, uint32_t binding) const; 391 392 Result SetPushConstantBuffer(Buffer* buf); GetPushConstantBuffer()393 const BufferInfo& GetPushConstantBuffer() const { 394 return push_constant_buffer_; 395 } 396 397 /// Validates that the pipeline has been created correctly. 398 Result Validate() const; 399 400 /// Generates a default color attachment in B8G8R8A8_UNORM. 401 std::unique_ptr<Buffer> GenerateDefaultColorAttachmentBuffer(); 402 /// Generates a default depth/stencil attachment in D32_SFLOAT_S8_UINT format. 403 std::unique_ptr<Buffer> GenerateDefaultDepthStencilAttachmentBuffer(); 404 405 /// Information on values set for OpenCL-C plain-old-data args. 406 struct ArgSetInfo { 407 std::string name; 408 uint32_t ordinal = 0; 409 Format* fmt = nullptr; 410 Value value; 411 }; 412 413 /// Adds value from SET command. SetArg(ArgSetInfo && info)414 void SetArg(ArgSetInfo&& info) { set_arg_values_.push_back(std::move(info)); } SetArgValues()415 const std::vector<ArgSetInfo>& SetArgValues() const { 416 return set_arg_values_; 417 } 418 419 /// Generate the buffers necessary for OpenCL PoD arguments populated via SET 420 /// command. This should be called after all other buffers are bound. 421 Result GenerateOpenCLPodBuffers(); 422 423 /// Generate the samplers necessary for OpenCL literal samplers from the 424 /// descriptor map. This should be called after all other samplers are bound. 425 Result GenerateOpenCLLiteralSamplers(); 426 427 /// Generate the push constant buffers necessary for OpenCL kernels. 428 Result GenerateOpenCLPushConstants(); 429 430 private: 431 void UpdateFramebufferSizes(); 432 433 Result SetShaderRequiredSubgroupSize( 434 const Shader* shader, 435 const ShaderInfo::RequiredSubgroupSizeSetting setting, 436 const uint32_t subgroupSize); 437 438 Result CreatePushConstantBuffer(); 439 440 Result ValidateGraphics() const; 441 Result ValidateCompute() const; 442 443 PipelineType pipeline_type_ = PipelineType::kCompute; 444 std::string name_; 445 std::vector<ShaderInfo> shaders_; 446 std::vector<BufferInfo> color_attachments_; 447 std::vector<BufferInfo> resolve_targets_; 448 std::vector<BufferInfo> vertex_buffers_; 449 std::vector<BufferInfo> buffers_; 450 std::vector<std::unique_ptr<type::Type>> types_; 451 std::vector<SamplerInfo> samplers_; 452 std::vector<std::unique_ptr<Format>> formats_; 453 BufferInfo depth_stencil_buffer_; 454 BufferInfo push_constant_buffer_; 455 Buffer* index_buffer_ = nullptr; 456 PipelineData pipeline_data_; 457 uint32_t fb_width_ = 250; 458 uint32_t fb_height_ = 250; 459 460 std::vector<ArgSetInfo> set_arg_values_; 461 std::vector<std::unique_ptr<Buffer>> opencl_pod_buffers_; 462 /// Maps (descriptor set, binding) to the buffer for that binding pair. 463 std::map<std::pair<uint32_t, uint32_t>, Buffer*> opencl_pod_buffer_map_; 464 std::vector<std::unique_ptr<Sampler>> opencl_literal_samplers_; 465 std::unique_ptr<Buffer> opencl_push_constants_; 466 }; 467 468 } // namespace amber 469 470 #endif // SRC_PIPELINE_H_ 471