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/shader.h" 28 29 namespace amber { 30 31 enum class PipelineType { kCompute = 0, kGraphics }; 32 33 /// Stores all information related to a pipeline. 34 class Pipeline { 35 public: 36 /// Information on a shader attached to this pipeline. 37 class ShaderInfo { 38 public: 39 ShaderInfo(Shader*, ShaderType type); 40 ShaderInfo(const ShaderInfo&); 41 ~ShaderInfo(); 42 43 ShaderInfo& operator=(const ShaderInfo&) = default; 44 45 // Set the optimization options for this shader. Optimizations are 46 // specified like command-line arguments to spirv-opt (see its --help). 47 // Parsing is done by spvtools::Optimizer::RegisterPassesFromFlags (see 48 // SPIRV-Tools include/spirv-tools/optimizer.hpp). SetShaderOptimizations(const std::vector<std::string> & opts)49 void SetShaderOptimizations(const std::vector<std::string>& opts) { 50 shader_optimizations_ = opts; 51 } GetShaderOptimizations()52 const std::vector<std::string>& GetShaderOptimizations() const { 53 return shader_optimizations_; 54 } 55 SetCompileOptions(const std::vector<std::string> & options)56 void SetCompileOptions(const std::vector<std::string>& options) { 57 compile_options_ = options; 58 } GetCompileOptions()59 const std::vector<std::string>& GetCompileOptions() const { 60 return compile_options_; 61 } 62 SetShader(Shader * shader)63 void SetShader(Shader* shader) { shader_ = shader; } GetShader()64 const Shader* GetShader() const { return shader_; } 65 SetEntryPoint(const std::string & ep)66 void SetEntryPoint(const std::string& ep) { entry_point_ = ep; } GetEntryPoint()67 const std::string& GetEntryPoint() const { return entry_point_; } 68 SetShaderType(ShaderType type)69 void SetShaderType(ShaderType type) { shader_type_ = type; } GetShaderType()70 ShaderType GetShaderType() const { return shader_type_; } 71 GetData()72 const std::vector<uint32_t> GetData() const { return data_; } SetData(std::vector<uint32_t> && data)73 void SetData(std::vector<uint32_t>&& data) { data_ = std::move(data); } 74 GetSpecialization()75 const std::map<uint32_t, uint32_t>& GetSpecialization() const { 76 return specialization_; 77 } AddSpecialization(uint32_t spec_id,uint32_t value)78 void AddSpecialization(uint32_t spec_id, uint32_t value) { 79 specialization_[spec_id] = value; 80 } 81 82 /// Descriptor information for an OpenCL-C shader. 83 struct DescriptorMapEntry { 84 std::string arg_name = ""; 85 86 enum class Kind : int { 87 UNKNOWN, 88 SSBO, 89 UBO, 90 POD, 91 POD_UBO, 92 } kind; 93 94 uint32_t descriptor_set = 0; 95 uint32_t binding = 0; 96 uint32_t arg_ordinal = 0; 97 uint32_t pod_offset = 0; 98 uint32_t pod_arg_size = 0; 99 }; 100 AddDescriptorEntry(const std::string & kernel,DescriptorMapEntry && entry)101 void AddDescriptorEntry(const std::string& kernel, 102 DescriptorMapEntry&& entry) { 103 descriptor_map_[kernel].emplace_back(std::move(entry)); 104 } 105 const std::unordered_map<std::string, std::vector<DescriptorMapEntry>>& GetDescriptorMap()106 GetDescriptorMap() const { 107 return descriptor_map_; 108 } 109 110 private: 111 Shader* shader_ = nullptr; 112 ShaderType shader_type_; 113 std::vector<std::string> shader_optimizations_; 114 std::string entry_point_; 115 std::vector<uint32_t> data_; 116 std::map<uint32_t, uint32_t> specialization_; 117 std::unordered_map<std::string, std::vector<DescriptorMapEntry>> 118 descriptor_map_; 119 std::vector<std::string> compile_options_; 120 }; 121 122 /// Information on a buffer attached to the pipeline. 123 /// 124 /// The BufferInfo will have either (descriptor_set, binding) or location 125 /// attached. 126 struct BufferInfo { 127 BufferInfo() = default; BufferInfoBufferInfo128 explicit BufferInfo(Buffer* buf) : buffer(buf) {} 129 130 Buffer* buffer = nullptr; 131 uint32_t descriptor_set = 0; 132 uint32_t binding = 0; 133 uint32_t location = 0; 134 std::string arg_name = ""; 135 uint32_t arg_no = 0; 136 }; 137 138 static const char* kGeneratedColorBuffer; 139 static const char* kGeneratedDepthBuffer; 140 141 explicit Pipeline(PipelineType type); 142 ~Pipeline(); 143 144 std::unique_ptr<Pipeline> Clone() const; 145 IsGraphics()146 bool IsGraphics() const { return pipeline_type_ == PipelineType::kGraphics; } IsCompute()147 bool IsCompute() const { return pipeline_type_ == PipelineType::kCompute; } 148 GetType()149 PipelineType GetType() const { return pipeline_type_; } 150 SetName(const std::string & name)151 void SetName(const std::string& name) { name_ = name; } GetName()152 const std::string& GetName() const { return name_; } 153 SetFramebufferWidth(uint32_t fb_width)154 void SetFramebufferWidth(uint32_t fb_width) { 155 fb_width_ = fb_width; 156 UpdateFramebufferSizes(); 157 } GetFramebufferWidth()158 uint32_t GetFramebufferWidth() const { return fb_width_; } 159 SetFramebufferHeight(uint32_t fb_height)160 void SetFramebufferHeight(uint32_t fb_height) { 161 fb_height_ = fb_height; 162 UpdateFramebufferSizes(); 163 } GetFramebufferHeight()164 uint32_t GetFramebufferHeight() const { return fb_height_; } 165 166 /// Adds |shader| of |type| to the pipeline. 167 Result AddShader(Shader* shader, ShaderType type); 168 /// Returns information on all bound shaders in this pipeline. GetShaders()169 std::vector<ShaderInfo>& GetShaders() { return shaders_; } 170 /// Returns information on all bound shaders in this pipeline. GetShaders()171 const std::vector<ShaderInfo>& GetShaders() const { return shaders_; } 172 173 /// Sets the |type| of |shader| in the pipeline. 174 Result SetShaderType(const Shader* shader, ShaderType type); 175 /// Sets the entry point |name| for |shader| in this pipeline. 176 Result SetShaderEntryPoint(const Shader* shader, const std::string& name); 177 /// Sets the optimizations (|opts|) for |shader| in this pipeline. 178 Result SetShaderOptimizations(const Shader* shader, 179 const std::vector<std::string>& opts); 180 /// Sets the compile options for |shader| in this pipeline. 181 Result SetShaderCompileOptions(const Shader* shader, 182 const std::vector<std::string>& options); 183 184 /// Returns a list of all colour attachments in this pipeline. GetColorAttachments()185 const std::vector<BufferInfo>& GetColorAttachments() const { 186 return color_attachments_; 187 } 188 /// Adds |buf| as a colour attachment at |location| in the pipeline. 189 Result AddColorAttachment(Buffer* buf, uint32_t location); 190 /// Retrieves the location that |buf| is bound to in the pipeline. The 191 /// location will be written to |loc|. An error result will be return if 192 /// something goes wrong. 193 Result GetLocationForColorAttachment(Buffer* buf, uint32_t* loc) const; 194 195 /// Sets |buf| as the depth buffer for this pipeline. 196 Result SetDepthBuffer(Buffer* buf); 197 /// Returns information on the depth buffer bound to the pipeline. If no 198 /// depth buffer is bound the |BufferInfo::buffer| parameter will be nullptr. GetDepthBuffer()199 const BufferInfo& GetDepthBuffer() const { return depth_buffer_; } 200 201 /// Returns information on all vertex buffers bound to the pipeline. GetVertexBuffers()202 const std::vector<BufferInfo>& GetVertexBuffers() const { 203 return vertex_buffers_; 204 } 205 /// Adds |buf| as a vertex buffer at |location| in the pipeline. 206 Result AddVertexBuffer(Buffer* buf, uint32_t location); 207 208 /// Binds |buf| as the index buffer for this pipeline. 209 Result SetIndexBuffer(Buffer* buf); 210 /// Returns the index buffer bound to this pipeline or nullptr if no index 211 /// buffer bound. GetIndexBuffer()212 Buffer* GetIndexBuffer() const { return index_buffer_; } 213 214 /// Adds |buf| to the pipeline at the given |descriptor_set| and |binding|. 215 void AddBuffer(Buffer* buf, uint32_t descriptor_set, uint32_t binding); 216 /// Adds |buf| to the pipeline at the given |arg_name|. 217 void AddBuffer(Buffer* buf, const std::string& arg_name); 218 /// Adds |buf| to the pipeline at the given |arg_no|. 219 void AddBuffer(Buffer* buf, uint32_t arg_no); 220 /// Returns information on all buffers in this pipeline. GetBuffers()221 const std::vector<BufferInfo>& GetBuffers() const { return buffers_; } 222 223 /// Updates the descriptor set and binding info for the OpenCL-C kernel bound 224 /// to the pipeline. No effect for other shader formats. 225 Result UpdateOpenCLBufferBindings(); 226 227 /// Returns the buffer which is currently bound to this pipeline at 228 /// |descriptor_set| and |binding|. 229 Buffer* GetBufferForBinding(uint32_t descriptor_set, uint32_t binding) const; 230 231 Result SetPushConstantBuffer(Buffer* buf); GetPushConstantBuffer()232 const BufferInfo& GetPushConstantBuffer() const { 233 return push_constant_buffer_; 234 } 235 236 /// Validates that the pipeline has been created correctly. 237 Result Validate() const; 238 239 /// Generates a default color attachment in B8G8R8A8_UNORM. 240 std::unique_ptr<Buffer> GenerateDefaultColorAttachmentBuffer(); 241 /// Generates a default depth attachment in D32_SFLOAT_S8_UINT format. 242 std::unique_ptr<Buffer> GenerateDefaultDepthAttachmentBuffer(); 243 244 /// Information on values set for OpenCL-C plain-old-data args. 245 struct ArgSetInfo { 246 std::string name; 247 uint32_t ordinal = 0; 248 Format* fmt = nullptr; 249 Value value; 250 }; 251 252 /// Adds value from SET command. SetArg(ArgSetInfo && info)253 void SetArg(ArgSetInfo&& info) { set_arg_values_.push_back(std::move(info)); } SetArgValues()254 const std::vector<ArgSetInfo>& SetArgValues() const { 255 return set_arg_values_; 256 } 257 258 /// Generate the buffers necessary for OpenCL PoD arguments populated via SET 259 /// command. This should be called after all other buffers are bound. 260 Result GenerateOpenCLPodBuffers(); 261 262 private: 263 void UpdateFramebufferSizes(); 264 265 Result ValidateGraphics() const; 266 Result ValidateCompute() const; 267 268 PipelineType pipeline_type_ = PipelineType::kCompute; 269 std::string name_; 270 std::vector<ShaderInfo> shaders_; 271 std::vector<BufferInfo> color_attachments_; 272 std::vector<BufferInfo> vertex_buffers_; 273 std::vector<BufferInfo> buffers_; 274 std::vector<std::unique_ptr<type::Type>> types_; 275 std::vector<std::unique_ptr<Format>> formats_; 276 BufferInfo depth_buffer_; 277 BufferInfo push_constant_buffer_; 278 Buffer* index_buffer_ = nullptr; 279 280 uint32_t fb_width_ = 250; 281 uint32_t fb_height_ = 250; 282 283 std::vector<ArgSetInfo> set_arg_values_; 284 std::vector<std::unique_ptr<Buffer>> opencl_pod_buffers_; 285 /// Maps (descriptor set, binding) to the buffer for that binding pair. 286 std::map<std::pair<uint32_t, uint32_t>, Buffer*> opencl_pod_buffer_map_; 287 }; 288 289 } // namespace amber 290 291 #endif // SRC_PIPELINE_H_ 292