• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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