initial
This commit is contained in:
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
|
||||
/**
|
||||
* Defines blending operations for a graphics pipeline.
|
||||
*/
|
||||
struct BlendingInfo {
|
||||
VkBlendOp colorBlendOp;
|
||||
VkBlendFactor srcColorBlendFactor;
|
||||
VkBlendFactor dstColorBlendFactor;
|
||||
|
||||
VkBlendOp alphaBlendOp;
|
||||
VkBlendFactor srcAlphaBlendFactor;
|
||||
VkBlendFactor dstAlphaBlendFactor;
|
||||
|
||||
BlendingInfo() :
|
||||
colorBlendOp(VK_BLEND_OP_ADD),
|
||||
srcColorBlendFactor(VK_BLEND_FACTOR_SRC_ALPHA),
|
||||
dstColorBlendFactor(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA),
|
||||
alphaBlendOp(VK_BLEND_OP_ADD),
|
||||
srcAlphaBlendFactor(VK_BLEND_FACTOR_SRC_ALPHA),
|
||||
dstAlphaBlendFactor(VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA) {
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,21 @@
|
||||
#pragma once
|
||||
|
||||
#include "Shader.hpp"
|
||||
#include "Pipeline.hpp"
|
||||
|
||||
#include <volk.h>
|
||||
|
||||
namespace lft {
|
||||
|
||||
class ComputePipelineBuilder {
|
||||
private:
|
||||
const Shader* m_shader;
|
||||
VkPipelineLayout m_layout;
|
||||
|
||||
public:
|
||||
ComputePipelineBuilder(const Shader* shader, VkPipelineLayout layout);
|
||||
|
||||
Pipeline build(const Gpu* gpu);
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "ShaderBuilder.hpp"
|
||||
|
||||
class GlslShaderBuilder : public ShaderBuilder {
|
||||
public:
|
||||
Shader from_file(std::string path) override;
|
||||
};
|
||||
@@ -0,0 +1,66 @@
|
||||
#pragma once
|
||||
|
||||
#include <volk.h>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
#include "RenderContext.hpp"
|
||||
#include "Shader.hpp"
|
||||
#include "Gpu.hpp"
|
||||
|
||||
/**
|
||||
* Abstracts a Vulkan pipeline
|
||||
*/
|
||||
class Pipeline {
|
||||
VkPipeline m_pipeline;
|
||||
VkPipelineLayout m_layout;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Wraps new pipeline with layout
|
||||
* @param layout pipeline layout
|
||||
* @param pipeline pipeline
|
||||
*/
|
||||
Pipeline(VkPipelineLayout layout, VkPipeline pipeline) :
|
||||
m_layout(layout), m_pipeline(pipeline) {
|
||||
|
||||
}
|
||||
|
||||
VkPipeline pipeline() const {
|
||||
return m_pipeline;
|
||||
}
|
||||
|
||||
VkPipelineLayout pipeline_layout() const {
|
||||
return m_layout;
|
||||
}
|
||||
|
||||
Pipeline& use(RenderContext *pRenderContext) {
|
||||
vkCmdBindPipeline(pRenderContext->command_buffer(),
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
m_pipeline);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Pipeline& bind_input_set(RenderContext *pRenderContext, uint32_t idx, uint32_t num, VkDescriptorSet *pSets) {
|
||||
vkCmdBindDescriptorSets(pRenderContext->command_buffer(),
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS,
|
||||
m_layout,
|
||||
idx, num, pSets,
|
||||
0, nullptr);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline void set_debug_name(const Gpu* gpu, const std::string name) const {
|
||||
#if LOFT_DEBUG
|
||||
VkDebugUtilsObjectNameInfoEXT nameInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
|
||||
.objectType = VK_OBJECT_TYPE_PIPELINE,
|
||||
.objectHandle = (uint64_t)pipeline(),
|
||||
.pObjectName = name.c_str(),
|
||||
};
|
||||
|
||||
vkSetDebugUtilsObjectNameEXT(gpu->dev(), &nameInfo);
|
||||
#endif
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,147 @@
|
||||
#pragma once
|
||||
|
||||
#include "Gpu.hpp"
|
||||
#include "Shader.hpp"
|
||||
#include "VertexBinding.h"
|
||||
#include "VertexAttribute.h"
|
||||
#include "BlendingInfo.h"
|
||||
#include "Pipeline.hpp"
|
||||
#include <volk.h>
|
||||
#include <stdexcept>
|
||||
#include <algorithm>
|
||||
#include <utility>
|
||||
|
||||
class PipelineLayoutBuilder {
|
||||
private:
|
||||
std::vector<VkDescriptorSetLayout> m_layouts;
|
||||
std::vector<VkPushConstantRange> m_pushConstantRanges;
|
||||
|
||||
uint32_t m_numLayouts;
|
||||
|
||||
public:
|
||||
PipelineLayoutBuilder() :
|
||||
m_layouts(4), m_pushConstantRanges(), m_numLayouts(0) {
|
||||
}
|
||||
|
||||
PipelineLayoutBuilder& input_set(uint32_t idx, VkDescriptorSetLayout setLayout) {
|
||||
if(idx >= m_layouts.size()) {
|
||||
throw std::runtime_error("As of now, only 4 descriptor set layouts are supported");
|
||||
}
|
||||
|
||||
m_layouts[idx] = setLayout;
|
||||
m_numLayouts = std::max(m_numLayouts, idx + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PipelineLayoutBuilder& push_constant_range(uint32_t offset, uint32_t size, VkShaderStageFlags stages) {
|
||||
m_pushConstantRanges.push_back({
|
||||
.stageFlags = stages,
|
||||
.offset = offset,
|
||||
.size = size,
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
VkPipelineLayout build(const Gpu* gpu) {
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = m_numLayouts,
|
||||
.pSetLayouts = m_layouts.data(),
|
||||
.pushConstantRangeCount = (uint32_t)m_pushConstantRanges.size(),
|
||||
.pPushConstantRanges = m_pushConstantRanges.data(),
|
||||
};
|
||||
|
||||
VkPipelineLayout inputLayout = VK_NULL_HANDLE;
|
||||
if (vkCreatePipelineLayout(gpu->dev(), &pipelineLayoutInfo, nullptr, &inputLayout)) {
|
||||
throw std::runtime_error("Failed to build pipeline layout");
|
||||
}
|
||||
|
||||
return inputLayout;
|
||||
}
|
||||
};
|
||||
|
||||
class PipelineBuilder {
|
||||
private:
|
||||
const Gpu* m_gpu;
|
||||
|
||||
VkPipelineLayout m_layout;
|
||||
VkRenderPass m_renderpass;
|
||||
|
||||
VkViewport m_viewport;
|
||||
VkRect2D m_scissor;
|
||||
|
||||
VkPipelineRasterizationStateCreateInfo m_rasterInfo;
|
||||
VkPipelineInputAssemblyStateCreateInfo m_inputAssemblyInfo;
|
||||
VkPipelineDepthStencilStateCreateInfo m_depthStencilInfo;
|
||||
VkPipelineVertexInputStateCreateInfo m_vertexInputInfo;
|
||||
|
||||
std::vector<VkPipelineColorBlendAttachmentState> m_blendingInfo;
|
||||
std::vector<VkPipelineShaderStageCreateInfo> stages;
|
||||
|
||||
std::vector<VertexBinding> m_vertexBindings;
|
||||
std::vector<VertexAttribute> m_vertexAttributes;
|
||||
|
||||
public:
|
||||
inline size_t num_attachments() { return m_blendingInfo.size(); }
|
||||
|
||||
PipelineBuilder(const Gpu* gpu, const VkViewport& viewport,
|
||||
VkPipelineLayout layout, VkRenderPass outputLayout,
|
||||
uint32_t numAttachments,
|
||||
const Shader* vertexShader, const Shader* fragmentShader);
|
||||
|
||||
inline PipelineBuilder& set_vertex_input_info(std::vector<VertexBinding> bindings,
|
||||
std::vector<VertexAttribute> attributes) {
|
||||
m_vertexBindings = std::move(bindings);
|
||||
m_vertexAttributes = std::move(attributes);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* Rasterization */
|
||||
inline PipelineBuilder& polygon_mode(VkPolygonMode mode) {
|
||||
this->m_rasterInfo.polygonMode = mode;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PipelineBuilder& cull_mode(VkCullModeFlags flags) {
|
||||
this->m_rasterInfo.cullMode = flags;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PipelineBuilder& topology(VkPrimitiveTopology topology) {
|
||||
this->m_inputAssemblyInfo.topology = topology;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PipelineBuilder& set_depth_bias(float depthBiasConstantFactor, float depthBiasClamp,
|
||||
float depthBiasSlopeFactor) {
|
||||
m_rasterInfo.depthBiasEnable = true,
|
||||
m_rasterInfo.depthBiasConstantFactor = depthBiasConstantFactor;
|
||||
m_rasterInfo.depthBiasClamp = depthBiasClamp;
|
||||
m_rasterInfo.depthBiasSlopeFactor = depthBiasSlopeFactor;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PipelineBuilder& unset_blending(uint32_t attachmentIdx) {
|
||||
m_blendingInfo[attachmentIdx].blendEnable = false;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline PipelineBuilder& set_blending(uint32_t attachmentIdx, BlendingInfo blendingInfo) {
|
||||
m_blendingInfo[attachmentIdx] = {
|
||||
.blendEnable = true,
|
||||
.srcColorBlendFactor = blendingInfo.srcColorBlendFactor,
|
||||
.dstColorBlendFactor = blendingInfo.dstColorBlendFactor,
|
||||
.colorBlendOp = blendingInfo.colorBlendOp,
|
||||
.srcAlphaBlendFactor = blendingInfo.srcAlphaBlendFactor,
|
||||
.dstAlphaBlendFactor = blendingInfo.dstAlphaBlendFactor,
|
||||
.alphaBlendOp = blendingInfo.alphaBlendOp,
|
||||
.colorWriteMask = VK_COLOR_COMPONENT_R_BIT |
|
||||
VK_COLOR_COMPONENT_G_BIT |
|
||||
VK_COLOR_COMPONENT_B_BIT |
|
||||
VK_COLOR_COMPONENT_A_BIT
|
||||
};
|
||||
return *this;
|
||||
}
|
||||
|
||||
Pipeline build();
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
#include <stdexcept>
|
||||
|
||||
#include <volk.h>
|
||||
|
||||
#include "Gpu.hpp"
|
||||
|
||||
namespace lft {
|
||||
class PipelineLayoutBuilder {
|
||||
private:
|
||||
std::vector<VkDescriptorSetLayout> m_layouts;
|
||||
std::vector<VkPushConstantRange> m_pushConstantRanges;
|
||||
|
||||
uint32_t m_numLayouts;
|
||||
|
||||
public:
|
||||
PipelineLayoutBuilder() :
|
||||
m_layouts(4), m_pushConstantRanges(), m_numLayouts(0) {
|
||||
}
|
||||
|
||||
PipelineLayoutBuilder& input_set(uint32_t idx, VkDescriptorSetLayout setLayout) {
|
||||
if(idx >= m_layouts.size()) {
|
||||
throw std::runtime_error("As of now, only 4 descriptor set layouts are supported");
|
||||
}
|
||||
|
||||
m_layouts[idx] = setLayout;
|
||||
m_numLayouts = std::max(m_numLayouts, idx + 1);
|
||||
return *this;
|
||||
}
|
||||
|
||||
PipelineLayoutBuilder& push_constant_range(uint32_t offset, uint32_t size, VkShaderStageFlags stages) {
|
||||
m_pushConstantRanges.push_back({
|
||||
.stageFlags = stages,
|
||||
.offset = offset,
|
||||
.size = size,
|
||||
});
|
||||
return *this;
|
||||
}
|
||||
|
||||
VkPipelineLayout build(const Gpu* gpu) {
|
||||
VkPipelineLayoutCreateInfo pipelineLayoutInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,
|
||||
.setLayoutCount = m_numLayouts,
|
||||
.pSetLayouts = m_layouts.data(),
|
||||
.pushConstantRangeCount = (uint32_t)m_pushConstantRanges.size(),
|
||||
.pPushConstantRanges = m_pushConstantRanges.data(),
|
||||
};
|
||||
|
||||
VkPipelineLayout inputLayout = VK_NULL_HANDLE;
|
||||
if (vkCreatePipelineLayout(gpu->dev(), &pipelineLayoutInfo, nullptr, &inputLayout)) {
|
||||
throw std::runtime_error("Failed to build pipeline layout");
|
||||
}
|
||||
|
||||
return inputLayout;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include <volk.h>
|
||||
|
||||
#include <memory>
|
||||
#include <vulkan/vulkan_core.h>
|
||||
|
||||
#include "Gpu.hpp"
|
||||
|
||||
namespace lft {
|
||||
class SamplerBuilder {
|
||||
VkSamplerCreateInfo m_sampler_info = {};
|
||||
|
||||
public:
|
||||
SamplerBuilder() {
|
||||
m_sampler_info.sType = VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO;
|
||||
}
|
||||
|
||||
inline SamplerBuilder& mag_filter(VkFilter filter) {
|
||||
m_sampler_info.magFilter = filter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline SamplerBuilder& min_filter(VkFilter filter) {
|
||||
m_sampler_info.minFilter = filter;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline SamplerBuilder& filter(VkFilter filter) {
|
||||
mag_filter(filter);
|
||||
min_filter(filter);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline SamplerBuilder& address_mode_u(VkSamplerAddressMode address_mode) {
|
||||
m_sampler_info.addressModeU = address_mode;
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
inline SamplerBuilder& address_mode_v(VkSamplerAddressMode address_mode) {
|
||||
m_sampler_info.addressModeV = address_mode;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline SamplerBuilder& address_mode_w(VkSamplerAddressMode address_mode) {
|
||||
m_sampler_info.addressModeW = address_mode;
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline SamplerBuilder& address_mode(VkSamplerAddressMode address_mode) {
|
||||
address_mode_u(address_mode);
|
||||
address_mode_v(address_mode);
|
||||
address_mode_w(address_mode);
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline SamplerBuilder& border_color(VkBorderColor border_color) {
|
||||
m_sampler_info.borderColor = border_color;
|
||||
return *this;
|
||||
}
|
||||
|
||||
VkSampler build(std::shared_ptr<Gpu> gpu) {
|
||||
VkSampler sampler = VK_NULL_HANDLE;
|
||||
if(vkCreateSampler(gpu->dev(), &m_sampler_info, nullptr, &sampler)) {
|
||||
throw std::runtime_error("failed to create sampler");
|
||||
}
|
||||
|
||||
return sampler;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
//
|
||||
// Created by martin on 10/24/23.
|
||||
//
|
||||
|
||||
#ifndef LOFT_SHADER_HPP
|
||||
#define LOFT_SHADER_HPP
|
||||
|
||||
#include "Gpu.hpp"
|
||||
#include "io/ShaderBinary.h"
|
||||
|
||||
#include <volk.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
|
||||
struct Shader {
|
||||
private:
|
||||
VkShaderModule m_module;
|
||||
|
||||
public:
|
||||
Shader(Shader&& s) :
|
||||
m_module(s.m_module) {
|
||||
}
|
||||
|
||||
Shader(VkShaderModule m) :
|
||||
m_module(m) {
|
||||
|
||||
}
|
||||
|
||||
const inline Shader& set_name(const Gpu* gpu, const std::string &name) {
|
||||
#if LOFT_DEBUG
|
||||
VkDebugUtilsObjectNameInfoEXT nameInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT,
|
||||
.objectType = VK_OBJECT_TYPE_SHADER_MODULE,
|
||||
.objectHandle = (uint64_t) m_module,
|
||||
.pObjectName = name.c_str(),
|
||||
};
|
||||
vkSetDebugUtilsObjectNameEXT(gpu->dev(), &nameInfo);
|
||||
#endif
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
[[nodiscard]] inline VkShaderModule module() const {
|
||||
return m_module;
|
||||
}
|
||||
};
|
||||
|
||||
#endif //LOFT_SHADER_HPP
|
||||
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// Created by martin on 10/24/23.
|
||||
//
|
||||
|
||||
#ifndef LOFT_SHADERBUILDER_HPP
|
||||
#define LOFT_SHADERBUILDER_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "Shader.hpp"
|
||||
|
||||
class ShaderBuilder {
|
||||
public:
|
||||
virtual Shader from_file(std::string path) = 0;
|
||||
};
|
||||
|
||||
#endif //LOFT_SHADERBUILDER_HPP
|
||||
@@ -0,0 +1,279 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
#include <volk.h>
|
||||
#include <memory>
|
||||
#include <exception>
|
||||
#include <assert.h>
|
||||
#include <stdexcept>
|
||||
#include <print>
|
||||
|
||||
#include "resources/Buffer.hpp"
|
||||
#include "resources/Image.hpp"
|
||||
#include "Gpu.hpp"
|
||||
|
||||
|
||||
/**
|
||||
* ShaderInputSetBufferWrite
|
||||
* For having uniform buffer
|
||||
*/
|
||||
struct ShaderInputSetBufferWrite {
|
||||
private:
|
||||
VkDescriptorType m_type;
|
||||
uint32_t m_binding;
|
||||
VkDescriptorBufferInfo m_bufferInfo;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Creates new shader input set write for Buffer
|
||||
*/
|
||||
ShaderInputSetBufferWrite(VkDescriptorType type, uint32_t binding, const Buffer& buffer,
|
||||
uint32_t offset, uint32_t size) :
|
||||
m_bufferInfo(
|
||||
{
|
||||
.buffer = buffer.buf,
|
||||
.offset = offset,
|
||||
.range = size
|
||||
}
|
||||
),
|
||||
m_binding(binding),
|
||||
m_type(type) {
|
||||
|
||||
}
|
||||
|
||||
const VkDescriptorBufferInfo* info() {
|
||||
return &m_bufferInfo;
|
||||
}
|
||||
};
|
||||
|
||||
struct ShaderInputSetImageWrite {
|
||||
private:
|
||||
VkDescriptorType m_type;
|
||||
uint32_t m_binding;
|
||||
VkDescriptorImageInfo m_imageInfo;
|
||||
|
||||
public:
|
||||
ShaderInputSetImageWrite(uint32_t binding, const ImageView& view, VkSampler sampler) :
|
||||
m_imageInfo(
|
||||
{
|
||||
.sampler = sampler,
|
||||
.imageView = view.view,
|
||||
.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
|
||||
}
|
||||
),
|
||||
m_binding(binding),
|
||||
m_type(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER) {
|
||||
|
||||
}
|
||||
|
||||
const VkDescriptorImageInfo* info() {
|
||||
return &m_imageInfo;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
union ShaderInputSetWrite {
|
||||
private:
|
||||
struct {
|
||||
VkDescriptorType type;
|
||||
uint32_t binding;
|
||||
} common;
|
||||
ShaderInputSetBufferWrite buffer;
|
||||
ShaderInputSetImageWrite image;
|
||||
|
||||
public:
|
||||
ShaderInputSetWrite() :
|
||||
common() {
|
||||
}
|
||||
|
||||
explicit ShaderInputSetWrite(ShaderInputSetBufferWrite bufferWrite) :
|
||||
buffer(bufferWrite) {
|
||||
|
||||
}
|
||||
|
||||
explicit ShaderInputSetWrite(ShaderInputSetImageWrite imageWrite) :
|
||||
image(imageWrite) {
|
||||
|
||||
}
|
||||
|
||||
uint32_t is_buffer_write(VkDescriptorType type) {
|
||||
return type > VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER;
|
||||
}
|
||||
|
||||
VkWriteDescriptorSet to_write(VkDescriptorSet set) {
|
||||
return {
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = set,
|
||||
.dstBinding = common.binding,
|
||||
.dstArrayElement = 0,
|
||||
.descriptorCount = 1,
|
||||
.descriptorType = common.type,
|
||||
.pImageInfo = is_buffer_write(common.type) ? nullptr : image.info(),
|
||||
.pBufferInfo = is_buffer_write(common.type) ? buffer.info() : nullptr,
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* ShaderInputSetBuilder
|
||||
*
|
||||
* Builds descriptor sets
|
||||
*/
|
||||
struct ShaderInputSetBuilder {
|
||||
private:
|
||||
std::vector<ShaderInputSetWrite> m_writes;
|
||||
|
||||
public:
|
||||
explicit ShaderInputSetBuilder() :
|
||||
m_writes() {
|
||||
|
||||
}
|
||||
|
||||
ShaderInputSetBuilder& image(uint32_t binding, const ImageView& imageView, VkSampler sampler) {
|
||||
assert(imageView.view != VK_NULL_HANDLE);
|
||||
assert(sampler != VK_NULL_HANDLE);
|
||||
|
||||
m_writes.push_back(ShaderInputSetWrite(ShaderInputSetImageWrite(binding, imageView, sampler)));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ShaderInputSetBuilder& buffer(const VkDescriptorType type, const uint32_t binding, const Buffer& buffer, const uint32_t offset, const uint32_t size) {
|
||||
assert(buffer.buf != VK_NULL_HANDLE);
|
||||
|
||||
m_writes.push_back(ShaderInputSetWrite(ShaderInputSetBufferWrite(type, binding, buffer, offset, size)));
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates new descriptor sets from layout.
|
||||
* All the writes must be set already.
|
||||
* @param pGpu Gpu on which to perform
|
||||
* @param layout Descriptor set layout
|
||||
* @return Allocated descriptor set with all the writes.
|
||||
*/
|
||||
VkDescriptorSet build(const Gpu* gpu, VkDescriptorSetLayout layout) {
|
||||
VkDescriptorSetAllocateInfo descriptorInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.descriptorPool = gpu->descriptor_pool(),
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = &layout
|
||||
};
|
||||
|
||||
VkDescriptorSet set = VK_NULL_HANDLE;
|
||||
if(vkAllocateDescriptorSets(gpu->dev(), &descriptorInfo, &set)) {
|
||||
throw std::runtime_error("Failed to allocate descriptor set");
|
||||
}
|
||||
|
||||
std::vector<VkWriteDescriptorSet> writes(m_writes.size());
|
||||
for(uint32_t i = 0; i < m_writes.size(); i++) {
|
||||
writes[i] = m_writes[i].to_write(set);
|
||||
}
|
||||
|
||||
vkUpdateDescriptorSets(gpu->dev(), writes.size(), writes.data(),
|
||||
0, nullptr);
|
||||
|
||||
return set;
|
||||
}
|
||||
};
|
||||
|
||||
struct ShaderInputSet {
|
||||
private:
|
||||
VkDescriptorSet m_descriptorSet;
|
||||
|
||||
public:
|
||||
inline const VkDescriptorSet descriptor_set() const {
|
||||
return m_descriptorSet;
|
||||
}
|
||||
|
||||
ShaderInputSet(VkDescriptorSet descriptorSet) :
|
||||
m_descriptorSet(descriptorSet) {
|
||||
|
||||
}
|
||||
|
||||
ShaderInputSet(const Gpu* gpu, VkDescriptorSetLayout layout) :
|
||||
m_descriptorSet(VK_NULL_HANDLE) {
|
||||
|
||||
VkDescriptorSetAllocateInfo descriptorInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
|
||||
.descriptorPool = gpu->descriptor_pool(),
|
||||
.descriptorSetCount = 1,
|
||||
.pSetLayouts = &layout
|
||||
};
|
||||
|
||||
if(vkAllocateDescriptorSets(gpu->dev(), &descriptorInfo, &m_descriptorSet)) {
|
||||
throw std::runtime_error("Failed to allocate descriptor set");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
enum ShaderInputWriteType {
|
||||
|
||||
};
|
||||
|
||||
class ShaderInputSetWriter {
|
||||
private:
|
||||
const Gpu* m_gpu;
|
||||
std::vector<VkWriteDescriptorSet> m_writes;
|
||||
|
||||
std::vector<std::vector<VkDescriptorImageInfo>> m_imageWrites;
|
||||
std::vector<std::vector<VkDescriptorBufferInfo>> m_bufferWrites;
|
||||
|
||||
public:
|
||||
explicit ShaderInputSetWriter(const Gpu* gpu) :
|
||||
m_gpu(gpu) {
|
||||
|
||||
}
|
||||
|
||||
ShaderInputSetWriter& write_images(const ShaderInputSet& dstInputSet,
|
||||
const uint32_t dstBinding,
|
||||
const uint32_t dstArrayElement,
|
||||
const VkDescriptorType type,
|
||||
const std::vector<VkDescriptorImageInfo>& writes) {
|
||||
/* copy write data, to not lose it */
|
||||
m_imageWrites.push_back(writes);
|
||||
|
||||
m_writes.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = dstInputSet.descriptor_set(),
|
||||
.dstBinding = dstBinding,
|
||||
.dstArrayElement = dstArrayElement,
|
||||
.descriptorCount = (uint32_t)writes.size(),
|
||||
.descriptorType = type,
|
||||
.pImageInfo = m_imageWrites[m_imageWrites.size() - 1].data()
|
||||
});
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ShaderInputSetWriter& write_buffer(const ShaderInputSet& dstInputSet,
|
||||
const uint32_t dstBinding,
|
||||
const uint32_t dstArrayElement,
|
||||
const VkDescriptorType type,
|
||||
const std::vector<VkDescriptorBufferInfo>& writes) {
|
||||
/* copy write data, to not lose it */
|
||||
m_bufferWrites.push_back(writes);
|
||||
|
||||
m_writes.push_back({
|
||||
.sType = VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
.dstSet = dstInputSet.descriptor_set(),
|
||||
.dstBinding = dstBinding,
|
||||
.dstArrayElement = dstArrayElement,
|
||||
.descriptorCount = (uint32_t)writes.size(),
|
||||
.descriptorType = type,
|
||||
.pBufferInfo = m_bufferWrites[m_bufferWrites.size() - 1].data()
|
||||
});
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ShaderInputSetWriter& write() {
|
||||
vkUpdateDescriptorSets(m_gpu->dev(), m_writes.size(), m_writes.data(), 0, nullptr);
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,98 @@
|
||||
#pragma once
|
||||
|
||||
#include "Gpu.hpp"
|
||||
|
||||
#include <vector>
|
||||
#include <volk.h>
|
||||
#include <assert.h>
|
||||
#include <stdexcept>
|
||||
|
||||
|
||||
class ShaderInputSetLayoutBuilder {
|
||||
private:
|
||||
std::vector<VkDescriptorSetLayoutBinding> m_bindings;
|
||||
|
||||
public:
|
||||
ShaderInputSetLayoutBuilder() :
|
||||
m_bindings() {
|
||||
}
|
||||
|
||||
ShaderInputSetLayoutBuilder(std::vector<VkDescriptorSetLayoutBinding> bindings) :
|
||||
m_bindings(bindings) {
|
||||
}
|
||||
|
||||
ShaderInputSetLayoutBuilder& uniform_buffer(
|
||||
uint32_t binding,
|
||||
VkShaderStageFlags shader_stages = VK_SHADER_STAGE_ALL
|
||||
) {
|
||||
m_bindings.push_back({
|
||||
.binding = binding,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = shader_stages,
|
||||
});
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ShaderInputSetLayoutBuilder& image(
|
||||
uint32_t binding,
|
||||
VkShaderStageFlags shader_stages = VK_SHADER_STAGE_ALL
|
||||
) {
|
||||
m_bindings.push_back({
|
||||
.binding = binding,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = 1,
|
||||
.stageFlags = shader_stages,
|
||||
});
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
ShaderInputSetLayoutBuilder& n_images(
|
||||
uint32_t binding,
|
||||
uint32_t count,
|
||||
VkShaderStageFlags shader_stages = VK_SHADER_STAGE_ALL
|
||||
) {
|
||||
m_bindings.push_back({
|
||||
.binding = binding,
|
||||
.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
|
||||
.descriptorCount = count,
|
||||
.stageFlags = shader_stages,
|
||||
});
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
ShaderInputSetLayoutBuilder& binding(
|
||||
uint32_t binding,
|
||||
VkDescriptorType type,
|
||||
uint32_t count,
|
||||
VkShaderStageFlags stages
|
||||
) {
|
||||
m_bindings.push_back({
|
||||
.binding = binding,
|
||||
.descriptorType = type,
|
||||
.descriptorCount = count,
|
||||
.stageFlags = stages,
|
||||
});
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
VkDescriptorSetLayout build(const Gpu* gpu) const {
|
||||
VkDescriptorSetLayoutCreateInfo layoutInfo = {
|
||||
.sType = VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
|
||||
.bindingCount = (uint32_t)m_bindings.size(),
|
||||
.pBindings = m_bindings.data(),
|
||||
};
|
||||
|
||||
VkDescriptorSetLayout layout = VK_NULL_HANDLE;
|
||||
if(vkCreateDescriptorSetLayout(gpu->dev(), &layoutInfo, nullptr, &layout)) {
|
||||
throw std::runtime_error("Failed to create descriptor set layout");
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,23 @@
|
||||
//
|
||||
// Created by martin on 10/24/23.
|
||||
//
|
||||
|
||||
#ifndef LOFT_SPIRVSHADERBUILDER_HPP
|
||||
#define LOFT_SPIRVSHADERBUILDER_HPP
|
||||
|
||||
#include "ShaderBuilder.hpp"
|
||||
#include "Gpu.hpp"
|
||||
|
||||
class SpirvShaderBuilder : public ShaderBuilder {
|
||||
private:
|
||||
const Gpu* m_gpu;
|
||||
|
||||
public:
|
||||
SpirvShaderBuilder(const Gpu* gpu);
|
||||
|
||||
Shader from_binary(const std::vector<uint32_t>& code) const;
|
||||
|
||||
Shader from_file(std::string path) override;
|
||||
};
|
||||
|
||||
#endif //LOFT_SPIRVSHADERBUILDER_HPP
|
||||
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
#include <volk.h>
|
||||
|
||||
struct VertexAttribute {
|
||||
uint32_t location;
|
||||
uint32_t binding;
|
||||
VkFormat format;
|
||||
uint32_t offset;
|
||||
|
||||
VkVertexInputAttributeDescription get_vk() {
|
||||
return *(VkVertexInputAttributeDescription*)this;
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include <volk.h>
|
||||
|
||||
struct VertexBinding {
|
||||
uint32_t binding;
|
||||
uint32_t stride;
|
||||
VkVertexInputRate inputRate;
|
||||
|
||||
VkVertexInputBindingDescription get_vk() {
|
||||
return *(VkVertexInputBindingDescription*)this;
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user