• 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   /// Sets |buf| as the depth/stencil buffer for this pipeline.
307   Result SetDepthStencilBuffer(Buffer* buf);
308   /// Returns information on the depth/stencil buffer bound to the pipeline. If
309   /// no depth buffer is bound the |BufferInfo::buffer| parameter will be
310   /// nullptr.
GetDepthStencilBuffer()311   const BufferInfo& GetDepthStencilBuffer() const {
312     return depth_stencil_buffer_;
313   }
314 
315   /// Returns pipeline data.
GetPipelineData()316   PipelineData* GetPipelineData() { return &pipeline_data_; }
317 
318   /// Returns information on all vertex buffers bound to the pipeline.
GetVertexBuffers()319   const std::vector<BufferInfo>& GetVertexBuffers() const {
320     return vertex_buffers_;
321   }
322   /// Adds |buf| as a vertex buffer at |location| in the pipeline using |rate|
323   /// as the input rate, |format| as vertex data format, |offset| as a starting
324   /// offset for the vertex buffer data, and |stride| for the data stride in
325   /// bytes.
326   Result AddVertexBuffer(Buffer* buf,
327                          uint32_t location,
328                          InputRate rate,
329                          Format* format,
330                          uint32_t offset,
331                          uint32_t stride);
332 
333   /// Binds |buf| as the index buffer for this pipeline.
334   Result SetIndexBuffer(Buffer* buf);
335   /// Returns the index buffer bound to this pipeline or nullptr if no index
336   /// buffer bound.
GetIndexBuffer()337   Buffer* GetIndexBuffer() const { return index_buffer_; }
338 
339   /// Adds |buf| of |type| to the pipeline at the given |descriptor_set|,
340   /// |binding|, |base_mip_level|, |descriptor_offset|, |descriptor_range| and
341   /// |dynamic_offset|.
342   void AddBuffer(Buffer* buf,
343                  BufferType type,
344                  uint32_t descriptor_set,
345                  uint32_t binding,
346                  uint32_t base_mip_level,
347                  uint32_t dynamic_offset,
348                  uint64_t descriptor_offset,
349                  uint64_t descriptor_range);
350   /// Adds |buf| to the pipeline at the given |arg_name|.
351   void AddBuffer(Buffer* buf, BufferType type, const std::string& arg_name);
352   /// Adds |buf| to the pipeline at the given |arg_no|.
353   void AddBuffer(Buffer* buf, BufferType type, uint32_t arg_no);
354   /// Returns information on all buffers in this pipeline.
GetBuffers()355   const std::vector<BufferInfo>& GetBuffers() const { return buffers_; }
356   /// Clears all buffer bindings for given |descriptor_set| and |binding|.
357   void ClearBuffers(uint32_t descriptor_set, uint32_t binding);
358 
359   /// Adds |sampler| to the pipeline at the given |descriptor_set| and
360   /// |binding|.
361   void AddSampler(Sampler* sampler, uint32_t descriptor_set, uint32_t binding);
362   /// Adds |sampler| to the pipeline at the given |arg_name|.
363   void AddSampler(Sampler* sampler, const std::string& arg_name);
364   /// Adds |sampler| to the pieline at the given |arg_no|.
365   void AddSampler(Sampler* sampler, uint32_t arg_no);
366   /// Adds an entry for an OpenCL literal sampler.
367   void AddSampler(uint32_t sampler_mask,
368                   uint32_t descriptor_set,
369                   uint32_t binding);
370   /// Clears all sampler bindings for given |descriptor_set| and |binding|.
371   void ClearSamplers(uint32_t descriptor_set, uint32_t binding);
372 
373   /// Returns information on all samplers in this pipeline.
GetSamplers()374   const std::vector<SamplerInfo>& GetSamplers() const { return samplers_; }
375 
376   /// Updates the descriptor set and binding info for the OpenCL-C kernel bound
377   /// to the pipeline. No effect for other shader formats.
378   Result UpdateOpenCLBufferBindings();
379 
380   /// Returns the buffer which is currently bound to this pipeline at
381   /// |descriptor_set| and |binding|.
382   Buffer* GetBufferForBinding(uint32_t descriptor_set, uint32_t binding) const;
383 
384   Result SetPushConstantBuffer(Buffer* buf);
GetPushConstantBuffer()385   const BufferInfo& GetPushConstantBuffer() const {
386     return push_constant_buffer_;
387   }
388 
389   /// Validates that the pipeline has been created correctly.
390   Result Validate() const;
391 
392   /// Generates a default color attachment in B8G8R8A8_UNORM.
393   std::unique_ptr<Buffer> GenerateDefaultColorAttachmentBuffer();
394   /// Generates a default depth/stencil attachment in D32_SFLOAT_S8_UINT format.
395   std::unique_ptr<Buffer> GenerateDefaultDepthStencilAttachmentBuffer();
396 
397   /// Information on values set for OpenCL-C plain-old-data args.
398   struct ArgSetInfo {
399     std::string name;
400     uint32_t ordinal = 0;
401     Format* fmt = nullptr;
402     Value value;
403   };
404 
405   /// Adds value from SET command.
SetArg(ArgSetInfo && info)406   void SetArg(ArgSetInfo&& info) { set_arg_values_.push_back(std::move(info)); }
SetArgValues()407   const std::vector<ArgSetInfo>& SetArgValues() const {
408     return set_arg_values_;
409   }
410 
411   /// Generate the buffers necessary for OpenCL PoD arguments populated via SET
412   /// command. This should be called after all other buffers are bound.
413   Result GenerateOpenCLPodBuffers();
414 
415   /// Generate the samplers necessary for OpenCL literal samplers from the
416   /// descriptor map. This should be called after all other samplers are bound.
417   Result GenerateOpenCLLiteralSamplers();
418 
419   /// Generate the push constant buffers necessary for OpenCL kernels.
420   Result GenerateOpenCLPushConstants();
421 
422  private:
423   void UpdateFramebufferSizes();
424 
425   Result SetShaderRequiredSubgroupSize(
426       const Shader* shader,
427       const ShaderInfo::RequiredSubgroupSizeSetting setting,
428       const uint32_t subgroupSize);
429 
430   Result CreatePushConstantBuffer();
431 
432   Result ValidateGraphics() const;
433   Result ValidateCompute() const;
434 
435   PipelineType pipeline_type_ = PipelineType::kCompute;
436   std::string name_;
437   std::vector<ShaderInfo> shaders_;
438   std::vector<BufferInfo> color_attachments_;
439   std::vector<BufferInfo> vertex_buffers_;
440   std::vector<BufferInfo> buffers_;
441   std::vector<std::unique_ptr<type::Type>> types_;
442   std::vector<SamplerInfo> samplers_;
443   std::vector<std::unique_ptr<Format>> formats_;
444   BufferInfo depth_stencil_buffer_;
445   BufferInfo push_constant_buffer_;
446   Buffer* index_buffer_ = nullptr;
447   PipelineData pipeline_data_;
448   uint32_t fb_width_ = 250;
449   uint32_t fb_height_ = 250;
450 
451   std::vector<ArgSetInfo> set_arg_values_;
452   std::vector<std::unique_ptr<Buffer>> opencl_pod_buffers_;
453   /// Maps (descriptor set, binding) to the buffer for that binding pair.
454   std::map<std::pair<uint32_t, uint32_t>, Buffer*> opencl_pod_buffer_map_;
455   std::vector<std::unique_ptr<Sampler>> opencl_literal_samplers_;
456   std::unique_ptr<Buffer> opencl_push_constants_;
457 };
458 
459 }  // namespace amber
460 
461 #endif  // SRC_PIPELINE_H_
462