设计
先 提供 常用 的 参 数 ,允 许默认构建 性能 一般但可用的对象,提供 接 口 对构造 时进行 特 化 指定 大量 使用 流 式 API通 过打包 其他对象,尽 量 减少接 口 调用时的参 数 明 确哪些对象 和 其他对象的 约束关系,在 接 口中 体 现这种约束 关系,尽 量 使 得 不 符合 约束关系的 调用无法被 编译使用 模 板 减少代 码量
#define VKB_IMPL
#include "vkbuilder.hpp"
class Render {
public:
void init(void *window) {
// 首 先 创建构造器 ,选择API版本 ,需要 的 layer,配置 debug messenger
vkb::InstanceBuilder builder;
inst = builder.require_api_version(1, 0)
.request_validation_layers() // validate correctness
.use_default_debug_messenger() // use DebugUtilsMessage
.build();
// 创建surface用 于渲染
auto surface = (VkSurfaceKHR)create_surface_glfw(inst.instance, window);
// 创建一 个PhysicalDeviceSelector用 来 选择渲染设备
vkb::PhysicalDeviceSelector selector{inst};
auto phys = selector.set_surface(surface)
.set_minimum_version(1, 0) // require a vulkan 1.0 capable device
.select();
vkb::DeviceBuilder device_builder{phys};
// 构造设备
// automatically propagate needed data from instance & physical device
device = device_builder.build();
create_swapchain();
create_pipeline();
}
void create_swapchain() {
// 创建默 认交换链
vkb::SwapchainBuilder swapchain_builder{device};
auto swap_ret = swapchain_builder.set_old_swapchain(swapchain).build();
swapchain.destroy();
swapchain = swap_ret;
}
void create_pipeline() {
// 创建渲染Pass
vkb::RenderPassBuilder renderpass_builder{device};
renderpass = renderpass_builder
.addPresentAttachment(swapchain.image_format, vk::AttachmentLoadOp::eClear)
.addSubpass(vkb::SubpassBuilder()
.addAttachmentRef(0, vk::ImageLayout::eColorAttachmentOptimal))
.addDependency(VK_SUBPASS_EXTERNAL, 0)
.build();
auto vert_code = readFile("vert.spv");
auto frag_code = readFile("frag.spv");
// 创建渲染流水 线
vkb::PipelineBuilder pipeline_builder{device, swapchain};
pipeline = pipeline_builder
.useClassicPipeline(vert_code, frag_code)
.setVertexInputState(
vkb::VertexInputStateBuilder() // VertexInputStateBuilder 可 以根据 Vertex上 的 函数 进行创建
.addInputBinding<Vertex>()
.addAttributeDescription<Vertex>()
)
.build(renderpass);
vkb::PresentBuilder present_builder{device, swapchain};
present = present_builder.build(renderpass);
initVertex();
}
vkb::Instance inst;
vkb::Device device;
vkb::Swapchain swapchain;
vk::RenderPass renderpass;
vk::Pipeline pipeline;
vkb::Present present;
std::vector<Vertex> v;
vkb::HostVertexBuffer buffer;
};
Render render;
void onRender() {
render.render();
}
void initVulkan(void *window) {
render.init(window);
}
int main() {
GLFW_Window window;
window.createWindow();
initVulkan(window.getWindow());
window.mainLoop();
return 0;
}
对于顶点getBindingDescription
getAttributeDescription
struct Vertex {
glm::vec2 pos;
glm::vec3 color;
static vk::VertexInputBindingDescription
getBindingDescription(uint32_t binding) {
vk::VertexInputBindingDescription bindingDescription{};
bindingDescription.binding = binding;
bindingDescription.stride = sizeof(Vertex);
bindingDescription.inputRate = vk::VertexInputRate::eVertex;
return bindingDescription;
}
static std::vector<vk::VertexInputAttributeDescription>
getAttributeDescription(uint32_t binding) {
std::vector<vk::VertexInputAttributeDescription> attrs = {
vk::VertexInputAttributeDescription(0, binding, vk::Format::eR32G32Sfloat, offsetof(Vertex, pos)),
vk::VertexInputAttributeDescription(1, binding, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, color))
};
return attrs;
}
};
void initVertex() {
v.resize(3);
v[0].pos = {0, 0.5}; v[0].color = {1,0,0};
v[1].pos = {-0.5, -0.5}; v[1].color = {0,1,0};
v[2].pos = {0.5, -0.5}; v[2].color = {0,0,1};
// create Vertex buffer
buffer.allocate<Vertex>(device, v);
}
渲染
void render() {
present.begin();
present.beginRenderPass(renderpass);
vk::DeviceSize offset(0);
auto& cb = present.getCurrentCommandBuffer();
cb.bindPipeline(vk::PipelineBindPoint::eGraphics, pipeline);
cb.bindVertexBuffers(0, 1, buffer, &offset);
cb.draw(3, 1, 0, 0);
present.endRenderPass();
present.end();
present.drawFrame();
}