180 lines
6.3 KiB
C++

/**
* Workflow partition module is responsible for configuration of rendering stages
* including pipelines, render passes and so on.
*/
export module vulkan_render:workflow;
import :hardware;
import :resources;
import :data;
import std;
import vulkan_hpp;
export namespace vulkan_render {
using DescriptorBindings = std::vector<vk::DescriptorSetLayoutBinding>;
using DescriptorCounts = std::unordered_map<vk::DescriptorType /*type*/, std::uint8_t /*count*/>;
/**
* Content of SPIR-V shaders binary data for a single pipeline.
*/
struct ShaderProgram {
std::span<std::byte> vertex;
std::span<std::byte> fragment;
/**
* Name of vertex shader entry point.
*/
const char* vertexMainFun = "main";
/**
* Name of fragment shader entry point.
*/
const char* fragmentMainFun = "main";
};
struct ShaderAttributeFormat {
static constexpr vk::Format FLOAT = vk::Format::eR32Sfloat;
static constexpr vk::Format VEC2 = vk::Format::eR32G32Sfloat;
static constexpr vk::Format VEC3 = vk::Format::eR32G32B32Sfloat;
static constexpr vk::Format VEC4 = vk::Format::eR32G32B32A32Sfloat;
static constexpr vk::Format UVEC4 = vk::Format::eR8G8B8A8Unorm;
ShaderAttributeFormat() = delete;
};
/**
* Shaders input attributes binding.
*/
struct ShaderBindings {
vk::VertexInputBindingDescription vertexBinding;
std::uint32_t vertexAttributesCount;
std::vector<vk::VertexInputAttributeDescription> vertexAttributes;
};
/**
* Set of descriptions needed for Vulkan pipeline initialization.
*/
struct PipelineConfig {
vk::PipelineVertexInputStateCreateInfo vertexInputInfo;
vk::PipelineInputAssemblyStateCreateInfo inputAssemblyInfo;
vk::PipelineViewportStateCreateInfo viewportStateInfo;
vk::PipelineRasterizationStateCreateInfo rasterizerInfo;
vk::PipelineMultisampleStateCreateInfo multisamplingInfo;
vk::PipelineDepthStencilStateCreateInfo depthStencilInfo;
vk::PipelineColorBlendStateCreateInfo colorBlendInfo;
vk::PipelineDynamicStateCreateInfo dynamicStateInfo;
vk::DescriptorSetLayoutCreateInfo descriptorsInfo;
// SRC - new color, DST - old color
std::vector<vk::PipelineColorBlendAttachmentState> colorBlendAttachmentStates;
std::vector<vk::DynamicState> dynamicStates;
std::vector<vk::DescriptorSetLayoutBinding> descriptors;
std::uint32_t maxExtraDescriptorSets = 0;
vk::Viewport defaultViewport;
vk::Rect2D defaultScissors;
vk::PushConstantRange pushConstantRange;
};
struct DescriptorInfo {
std::variant<
vk::DescriptorBufferInfo,
vk::DescriptorImageInfo
> info;
std::uint32_t bindingPosition;
vk::DescriptorType type;
};
}
export namespace vulkan_render {
class RenderPass {
public:
const Context &context;
const Swapchain &swapchain;
const Surface &surface;
vk::raii::RenderPass handle;
std::vector<vk::raii::Framebuffer> framebuffers;
RenderPass(
const Context &context,
const Swapchain &swapchain,
const Surface &surface,
const Texture<TextureMode::DEPTH> &depth
);
private:
vk::raii::RenderPass MakeInstance() const;
void MakeFramebuffers(const Texture<TextureMode::DEPTH> &depth);
};
/**
* Vulkan pipeline constructed on context, shaders and descriptors.
*/
class Pipeline {
public:
const Context &context;
const Surface &surface;
const Swapchain &swapchain;
const RenderPass &renderPass;
const std::uint32_t maxFramesInFlight;
DescriptorCounts descriptorCounts;
vk::raii::DescriptorSetLayout descriptorsLayout;
vk::raii::PipelineLayout layout;
vk::raii::Pipeline handle;
vk::Viewport viewport;
vk::Rect2D scissors;
vk::raii::DescriptorPool descriptorPool;
vk::raii::DescriptorSets descriptorSets;
/**
* Initialize Pipeline on shaders and their input.
* @param context Vulkan context with ready device.
* @param surface
* @param swapchain swapchain frame images used to allocate descriptors.
* @param config pipeline configuration.
* @param shaderProgram SPIR-V shaders binaries.
* @param maxFramesInFlight max number of frames in flight used to allocate descriptors .
*/
Pipeline(
const Context &context,
const Surface &surface,
const Swapchain &swapchain,
const PipelineConfig &config,
const RenderPass &renderPass,
const ShaderProgram &shaderProgram,
std::uint32_t maxFramesInFlight
);
void UpdateDescriptors(const std::vector<DescriptorInfo> &descriptors, vk::DescriptorSet set) const;
void UpdateDescriptors(const std::vector<DescriptorInfo> &descriptors, std::uint32_t frame);
vk::raii::DescriptorSets AllocateDescriptorSet() const;
/**
* Construct default pipeline configuration for given shaders input layout.
* @param surface surface origin.
* @param bindings shaders input attributes binding definition.
* @param descriptors descriptors binding definition (e.g. uniforms).
* @param pushConstants definition for small performant data set.
* @return default pipeline configuration.
*/
static PipelineConfig MakeConfig(
const Surface &surface,
const ShaderBindings &bindings,
const DescriptorBindings &descriptors,
const vk::PushConstantRange& pushConstants
);
private:
vk::raii::DescriptorSetLayout MakeDescriptorsLayout(const PipelineConfig &config) const;
vk::raii::PipelineLayout MakeLayout(const PipelineConfig &config) const;
vk::raii::Pipeline MakeInstance(const PipelineConfig &config, const ShaderProgram &shaderProgram) const;
vk::raii::DescriptorPool MakeDescriptorPool(
const DescriptorBindings &descriptors,
std::uint32_t maxExtraDescriptorSet
);
vk::raii::DescriptorSets MakeDescriptorSets() const;
};
}