blob: 5cb63d4069d37ae73752d917d6c3c4308ec2b8f7 [file] [log] [blame]
// Copyright 2018 The Amber Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
#ifndef SRC_PIPELINE_H_
#define SRC_PIPELINE_H_
#include <map>
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include <vector>
#include "amber/result.h"
#include "src/buffer.h"
#include "src/shader.h"
namespace amber {
enum class PipelineType { kCompute = 0, kGraphics };
/// Stores all information related to a pipeline.
class Pipeline {
public:
/// Information on a shader attached to this pipeline.
class ShaderInfo {
public:
ShaderInfo(Shader*, ShaderType type);
ShaderInfo(const ShaderInfo&);
~ShaderInfo();
ShaderInfo& operator=(const ShaderInfo&) = default;
// Set the optimization options for this shader. Optimizations are
// specified like command-line arguments to spirv-opt (see its --help).
// Parsing is done by spvtools::Optimizer::RegisterPassesFromFlags (see
// SPIRV-Tools include/spirv-tools/optimizer.hpp).
void SetShaderOptimizations(const std::vector<std::string>& opts) {
shader_optimizations_ = opts;
}
const std::vector<std::string>& GetShaderOptimizations() const {
return shader_optimizations_;
}
void SetCompileOptions(const std::vector<std::string>& options) {
compile_options_ = options;
}
const std::vector<std::string>& GetCompileOptions() const {
return compile_options_;
}
void SetShader(Shader* shader) { shader_ = shader; }
const Shader* GetShader() const { return shader_; }
void SetEntryPoint(const std::string& ep) { entry_point_ = ep; }
const std::string& GetEntryPoint() const { return entry_point_; }
void SetShaderType(ShaderType type) { shader_type_ = type; }
ShaderType GetShaderType() const { return shader_type_; }
const std::vector<uint32_t> GetData() const { return data_; }
void SetData(std::vector<uint32_t>&& data) { data_ = std::move(data); }
const std::map<uint32_t, uint32_t>& GetSpecialization() const {
return specialization_;
}
void AddSpecialization(uint32_t spec_id, uint32_t value) {
specialization_[spec_id] = value;
}
/// Descriptor information for an OpenCL-C shader.
struct DescriptorMapEntry {
std::string arg_name = "";
enum class Kind : int {
UNKNOWN,
SSBO,
UBO,
POD,
POD_UBO,
} kind;
uint32_t descriptor_set = 0;
uint32_t binding = 0;
uint32_t arg_ordinal = 0;
uint32_t pod_offset = 0;
uint32_t pod_arg_size = 0;
};
void AddDescriptorEntry(const std::string& kernel,
DescriptorMapEntry&& entry) {
descriptor_map_[kernel].emplace_back(std::move(entry));
}
const std::unordered_map<std::string, std::vector<DescriptorMapEntry>>&
GetDescriptorMap() const {
return descriptor_map_;
}
private:
Shader* shader_ = nullptr;
ShaderType shader_type_;
std::vector<std::string> shader_optimizations_;
std::string entry_point_;
std::vector<uint32_t> data_;
std::map<uint32_t, uint32_t> specialization_;
std::unordered_map<std::string, std::vector<DescriptorMapEntry>>
descriptor_map_;
std::vector<std::string> compile_options_;
};
/// Information on a buffer attached to the pipeline.
///
/// The BufferInfo will have either (descriptor_set, binding) or location
/// attached.
struct BufferInfo {
BufferInfo() = default;
explicit BufferInfo(Buffer* buf) : buffer(buf) {}
Buffer* buffer = nullptr;
uint32_t descriptor_set = 0;
uint32_t binding = 0;
uint32_t location = 0;
std::string arg_name = "";
uint32_t arg_no = 0;
};
static const char* kGeneratedColorBuffer;
static const char* kGeneratedDepthBuffer;
explicit Pipeline(PipelineType type);
~Pipeline();
std::unique_ptr<Pipeline> Clone() const;
bool IsGraphics() const { return pipeline_type_ == PipelineType::kGraphics; }
bool IsCompute() const { return pipeline_type_ == PipelineType::kCompute; }
PipelineType GetType() const { return pipeline_type_; }
void SetName(const std::string& name) { name_ = name; }
const std::string& GetName() const { return name_; }
void SetFramebufferWidth(uint32_t fb_width) {
fb_width_ = fb_width;
UpdateFramebufferSizes();
}
uint32_t GetFramebufferWidth() const { return fb_width_; }
void SetFramebufferHeight(uint32_t fb_height) {
fb_height_ = fb_height;
UpdateFramebufferSizes();
}
uint32_t GetFramebufferHeight() const { return fb_height_; }
/// Adds |shader| of |type| to the pipeline.
Result AddShader(Shader* shader, ShaderType type);
/// Returns information on all bound shaders in this pipeline.
std::vector<ShaderInfo>& GetShaders() { return shaders_; }
/// Returns information on all bound shaders in this pipeline.
const std::vector<ShaderInfo>& GetShaders() const { return shaders_; }
/// Sets the |type| of |shader| in the pipeline.
Result SetShaderType(const Shader* shader, ShaderType type);
/// Sets the entry point |name| for |shader| in this pipeline.
Result SetShaderEntryPoint(const Shader* shader, const std::string& name);
/// Sets the optimizations (|opts|) for |shader| in this pipeline.
Result SetShaderOptimizations(const Shader* shader,
const std::vector<std::string>& opts);
/// Sets the compile options for |shader| in this pipeline.
Result SetShaderCompileOptions(const Shader* shader,
const std::vector<std::string>& options);
/// Returns a list of all colour attachments in this pipeline.
const std::vector<BufferInfo>& GetColorAttachments() const {
return color_attachments_;
}
/// Adds |buf| as a colour attachment at |location| in the pipeline.
Result AddColorAttachment(Buffer* buf, uint32_t location);
/// Retrieves the location that |buf| is bound to in the pipeline. The
/// location will be written to |loc|. An error result will be return if
/// something goes wrong.
Result GetLocationForColorAttachment(Buffer* buf, uint32_t* loc) const;
/// Sets |buf| as the depth buffer for this pipeline.
Result SetDepthBuffer(Buffer* buf);
/// Returns information on the depth buffer bound to the pipeline. If no
/// depth buffer is bound the |BufferInfo::buffer| parameter will be nullptr.
const BufferInfo& GetDepthBuffer() const { return depth_buffer_; }
/// Returns information on all vertex buffers bound to the pipeline.
const std::vector<BufferInfo>& GetVertexBuffers() const {
return vertex_buffers_;
}
/// Adds |buf| as a vertex buffer at |location| in the pipeline.
Result AddVertexBuffer(Buffer* buf, uint32_t location);
/// Binds |buf| as the index buffer for this pipeline.
Result SetIndexBuffer(Buffer* buf);
/// Returns the index buffer bound to this pipeline or nullptr if no index
/// buffer bound.
Buffer* GetIndexBuffer() const { return index_buffer_; }
/// Adds |buf| to the pipeline at the given |descriptor_set| and |binding|.
void AddBuffer(Buffer* buf, uint32_t descriptor_set, uint32_t binding);
/// Adds |buf| to the pipeline at the given |arg_name|.
void AddBuffer(Buffer* buf, const std::string& arg_name);
/// Adds |buf| to the pipeline at the given |arg_no|.
void AddBuffer(Buffer* buf, uint32_t arg_no);
/// Returns information on all buffers in this pipeline.
const std::vector<BufferInfo>& GetBuffers() const { return buffers_; }
/// Updates the descriptor set and binding info for the OpenCL-C kernel bound
/// to the pipeline. No effect for other shader formats.
Result UpdateOpenCLBufferBindings();
/// Returns the buffer which is currently bound to this pipeline at
/// |descriptor_set| and |binding|.
Buffer* GetBufferForBinding(uint32_t descriptor_set, uint32_t binding) const;
Result SetPushConstantBuffer(Buffer* buf);
const BufferInfo& GetPushConstantBuffer() const {
return push_constant_buffer_;
}
/// Validates that the pipeline has been created correctly.
Result Validate() const;
/// Generates a default color attachment in B8G8R8A8_UNORM.
std::unique_ptr<Buffer> GenerateDefaultColorAttachmentBuffer() const;
/// Generates a default depth attachment in D32_SFLOAT_S8_UINT format.
std::unique_ptr<Buffer> GenerateDefaultDepthAttachmentBuffer() const;
/// Information on values set for OpenCL-C plain-old-data args.
struct ArgSetInfo {
std::string name;
uint32_t ordinal = 0;
std::unique_ptr<Format> fmt;
Value value;
};
/// Adds value from SET command.
void SetArg(ArgSetInfo&& info) { set_arg_values_.push_back(std::move(info)); }
const std::vector<ArgSetInfo>& SetArgValues() const {
return set_arg_values_;
}
/// Generate the buffers necessary for OpenCL PoD arguments populated via SET
/// command. This should be called after all other buffers are bound.
Result GenerateOpenCLPodBuffers();
private:
void UpdateFramebufferSizes();
Result ValidateGraphics() const;
Result ValidateCompute() const;
PipelineType pipeline_type_ = PipelineType::kCompute;
std::string name_;
std::vector<ShaderInfo> shaders_;
std::vector<BufferInfo> color_attachments_;
std::vector<BufferInfo> vertex_buffers_;
std::vector<BufferInfo> buffers_;
BufferInfo depth_buffer_;
BufferInfo push_constant_buffer_;
Buffer* index_buffer_ = nullptr;
uint32_t fb_width_ = 250;
uint32_t fb_height_ = 250;
std::vector<ArgSetInfo> set_arg_values_;
std::vector<std::unique_ptr<Buffer>> opencl_pod_buffers_;
/// Maps (descriptor set, binding) to the buffer for that binding pair.
std::map<std::pair<uint32_t, uint32_t>, Buffer*> opencl_pod_buffer_map_;
};
} // namespace amber
#endif // SRC_PIPELINE_H_