34 个版本 (9 个重大变更)
0.10.0 | 2023年7月6日 |
---|---|
0.8.0 | 2023年5月24日 |
0.5.2 | 2023年3月26日 |
#196 in 图形 API
每月165次下载
在 egui-winit-phobos 中使用
580KB
11K SLoC
Phobos
Phobos 是一个旨在使创建 Vulkan 应用程序更加容易的 Vulkan 抽象库。它提供了抽象来自动管理常见的 Vulkan 问题,如同步和资源管理。同时,它旨在完全公开 Vulkan API,而不受重大限制。
目前,该项目处于高度 WIP 状态,并不是所有目标都已被完全实现。它与一个使用它的渲染引擎一起开发,因此功能目前按需添加。
Phobos 做了什么?
- 从单个配置结构初始化所有 Vulkan。
- 与显示引擎管理每帧同步。
- GPU 期货,与 Rust 期货完全集成。
- 更正式地说,为
phobos::Fence<T>
实现了Future<Output = T>
。
- 更正式地说,为
- 提供可用于在渲染器中自动同步资源的任务图。
- 自动图像布局转换。
- 自动 renderpass 声明。
- 自动对缓冲区执行内存屏障。
- 虚拟资源,意味着实际资源仅在记录时绑定到图。这允许通用图在需要时重用。
- 对 Vulkan 对象的保险包装。
- 公共 API 中没有
unsafe
,除非访问原始 Vulkan 处理。 - 完全隐藏描述符集。只需将资源直接绑定到命令缓冲区。
- 自动管道管理。
- 着色器反射以自动生成管道布局。
- 适用于 GLSL 和 HLSL。
- 目前一次只能启用一个。
- 自动为需要双缓冲的资源执行双缓冲。
- 用于每帧分配(如统一缓冲区)的线性分配器。
- 每个队列类型的类型化命令缓冲区。
- 自动线程安全命令缓冲区记录。
- 使用
SubmitBatch
工具将提交批量提交到一个vkQueueSubmit
调用中,并使用信号量进行同步。 - 自动为您的光线追踪管道创建着色器绑定表。
- 对象池用于重用栅栏、本地分配器等。
- 通过
fsr2-sys
包件轻松集成FSR2。
Phobos不做什么?
- 为您实现渲染器。它只是暴露Vulkan API。
- 支持移动GPU。Phobos针对桌面GPU进行优化,不努力支持移动GPU。
示例
更多详细示例,请查看 示例 文件夹。
use phobos::prelude::*;
fn main() {
// Fill out app settings for initialization
let settings = AppBuilder::new()
.version((1, 0, 0))
.name("Phobos example app")
.validation(true)
.window(&window) // Your winit window, or some other interface.
.present_mode(vk::PresentModeKHR::MAILBOX)
.scratch_size(1024u64)
.gpu(ph::GPURequirements {
dedicated: true,
queues: vec![
QueueRequest { dedicated: false, queue_type: QueueType::Graphics },
QueueRequest { dedicated: true, queue_type: QueueType::Transfer },
QueueRequest { dedicated: true, queue_type: QueueType::Compute }
],
..Default::default()
})
.build();
// Initialize Vulkan. There are other ways to initialize, for example
// with a custom allocator, or without a window context. See the core::init module for this
// functionality.
use phobos::prelude::*;
let (
instance,
physical_device,
surface,
device
allocator,
exec,
frame,
Some(debug_messenger)
) = WindowedContext::init(&settings)? else {
panic!("Asked for debug messenger but didn't get one.")
};
// Create a new pass graph for rendering. Note how we only do this once, as
// we are using virtual resources that do not depend on the frame.
let swapchain = VirtualResource::image("swapchain");
let clear_pass = PassBuilder::render("clear")
.color_attachment(&swapchain,
vk::AttachmentLoadOp::CLEAR,
// Clear the swapchain to red.
Some(vk::ClearColorValue { float32: [1.0, 0.0, 0.0, 1.0] }))?
.build();
let present_pass = PassBuilder::present("present", clear_pass.output(&swapchain).unwrap());
let graph = PassGraph::new()
.add_pass(clear_pass)?
.add_pass(present_pass)?
.build()?;
// Your event loop goes here
while event_loop {
// Wait for a new frame to be available. Once there is one, the provided
// callback will be called.
futures::executor::block_on(frame.new_frame(exec.clone(), window, &surface, |mut ifc| {
// Bind some physical resources to the render graph.
let mut bindings = PhysicalResourceBindings::new();
bindings.bind_image("swapchain", &ifc.swapchain_image.as_ref().unwrap());
let cmd = exec.on_domain::<domain::Graphics, DefaultAllocator>(None, None)?;
// Record render graph to our command buffer
graph.record(cmd, &bindings, &mut ifc, None, &mut ()).finish()
}))?;
}
}
支持
访问 docs.rs 页面,或打开一个问题。
计划中的功能
- 暴露更多Vulkan API功能。
依赖项
~14–34MB
~522K SLoC