Vulkan Tutorial의 Rust 버전을 해 보았다 ~Window편~
Vulkan으로 그리기
전회는 Vulkan이라고 하면서 일절 GUI가 나오지 않는 회였습니다만, 드디어 윈도우를 그립니다. 라고 해도, 윈도우 그 자체는 Vulkan 관계 없습니다만.
winit으로 창 표시
Rust의 경우 윈도우 표시에는 winit을 사용하는 경우가 많으므로 여기에서도 winit을 사용합니다. 이하에서는, 최소한의 윈도우 표시와 위도를 닫는 처리를 하고 있습니다.
let event_loop = EventLoop::new();
let _window = WindowBuilder::new().build(&event_loop).unwrap();
event_loop.run(|event, _, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
_ => {}
};
});
winit은 비교적 자주 API가 바뀌고 있기 때문에 언제나 익숙하지 않은 느낌입니다만, winit = "0.22.0"
의 단계에서는 이렇게 쓰는 것이 올바른 것 같습니다.
Surface 만들기
Vulkan이 그리는 것은 VkSurfaceKHR
에 대해서이며, 이것은 각 플랫폼 고유의 부분과 Vulkan를 연결하기 위해, 각 윈도우 라이브러리에 대응한 Surface
를 준비할 필요가 있습니다. 이 경우 vulkano-win이 그것에 해당하므로 그것을 사용하여 Surface
를 만듭니다.
먼저 InstanceExtensions
를 변경합니다. 지금까지는
InstanceExtensions::supported_by_core().unwrap()
라고 쓰고 있던 곳을,
vulkano_win::required_extensions()
합니다. 그런 다음 위에서
WindowBuilder::new().build(&event_loop)
곳을
WindowBuilder::new().build_vk_surface(&event_loop, instance)
로 변경합니다. 이것으로 얻을 수 있는 값이 Window
로부터 Surface<Window>
로 바뀝니다.
Queue 추가
전회에서는 논리 디바이스의 작성시에 supports_graphics
를 만족하는 Queue
만을 요구하고 있었습니다만, 이번은 표시용의 Queue
도 필요이므로 이것을 추가합니다.
[추기] 여기서 QueueFamily
가 중복되지 않도록 하십시오. 그렇지 않으면 런타임 오류로 강제 종료됩니다. [추기 종료]
let (_device, mut queues) = PhysicalDevice::enumerate(&instance)
.filter_map(|device| {
let graphics_queue_family = device
.queue_families()
.find(|queue_family| queue_family.supports_graphics());
let present_queue_family = device
.queue_families()
.find(|queue_family| surface.is_supported(*queue_family) == Ok(true));
let mut queue_families_set = HashSet::new();
let unique_queue_families: Vec<_> = vec![graphics_queue_family, present_queue_family]
.iter()
.filter_map(|queue_family| *queue_family)
.filter(|queue_family| queue_families_set.insert(queue_family.id()))
.collect();
Some((device, unique_queue_families))
})
.filter_map(|(device, queue_families)| {
Device::new(
device,
&Features::none(),
&DeviceExtensions::supported_by_device(device),
queue_families
.iter()
.map(|queue_family| (*queue_family, 1.0)),
)
.ok()
})
.next()
.expect("Could not find any GPU");
조금 길어져 버렸습니다만, 전회는 1개만 건네주고 있던 QueueFamily
를 복수 건네줄 수 있도록(듯이) 했기 때문입니다.
swap chain 만들기
swap chain이란 이른바 더블 버퍼링이나 트리플 버퍼링이라고 생각합니다. [추기] 아무래도 다른 것 같습니다. 단순히 표시 대기의 이미지의 큐라고 하는 것 같습니다만, 이해 부족입니다. [추기 종료]
(이미지는 h tps://ゔヵ응.ぅ나 rg. 이 m/도 c/sdk/1. 2.131. HTML에서 인용)
swap chain을 지원하는지 확인
장치가 swap chain을 지원하지 않을 수 있으므로 논리 장치를 만들 때 DeviceExtensions
로 swap chain을 요청합니다.
let extensions = DeviceExtensions {
khr_swapchain: true,
..DeviceExtensions::supported_by_device(device)
};
Device::new(
device,
&Features::none(),
&extensions,
queue_families
.iter()
.map(|queue_family| (*queue_family, 1.0)),
)
.ok()
swap chain 요구
위에서 얻은 디바이스는 swap chain에 대응하고 있으므로, 다음은 만들고 싶은 swap chain의 설정을 해, 요구합니다. 덧붙여 Swapchain::new
로 모든 설정을 인수에 건네 가는데 수가 많아, 또 참고원의 값을 거의 그대로 찍고 있을 뿐이므로 개개의 설정에 대해서는 생략합니다.
let (_swapchain, _swapchain_image) = Swapchain::new(...).unwrap();
정리와 감상
이번에는 창을 표시하고 스왑 체인을 만들었습니다. swap chain은 확실히 세세하게 설정할 수 있을 것 같습니다만 그만큼 기술량이 많아 대단하다는, Vulkan다움(?)을 맛보았습니다. 아직 실질 아무것도 표시되어 있지 않습니다만, 다음 번부터 드디어 셰이더에 관련될 것 같습니다.
Reference
이 문제에 관하여(Vulkan Tutorial의 Rust 버전을 해 보았다 ~Window편~), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/kbone/items/9cefcb960fc1f58e9131
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
let event_loop = EventLoop::new();
let _window = WindowBuilder::new().build(&event_loop).unwrap();
event_loop.run(|event, _, control_flow| {
*control_flow = ControlFlow::Wait;
match event {
Event::WindowEvent {
event: WindowEvent::CloseRequested,
..
} => {
*control_flow = ControlFlow::Exit;
}
_ => {}
};
});
InstanceExtensions::supported_by_core().unwrap()
vulkano_win::required_extensions()
WindowBuilder::new().build(&event_loop)
WindowBuilder::new().build_vk_surface(&event_loop, instance)
let (_device, mut queues) = PhysicalDevice::enumerate(&instance)
.filter_map(|device| {
let graphics_queue_family = device
.queue_families()
.find(|queue_family| queue_family.supports_graphics());
let present_queue_family = device
.queue_families()
.find(|queue_family| surface.is_supported(*queue_family) == Ok(true));
let mut queue_families_set = HashSet::new();
let unique_queue_families: Vec<_> = vec![graphics_queue_family, present_queue_family]
.iter()
.filter_map(|queue_family| *queue_family)
.filter(|queue_family| queue_families_set.insert(queue_family.id()))
.collect();
Some((device, unique_queue_families))
})
.filter_map(|(device, queue_families)| {
Device::new(
device,
&Features::none(),
&DeviceExtensions::supported_by_device(device),
queue_families
.iter()
.map(|queue_family| (*queue_family, 1.0)),
)
.ok()
})
.next()
.expect("Could not find any GPU");
let extensions = DeviceExtensions {
khr_swapchain: true,
..DeviceExtensions::supported_by_device(device)
};
Device::new(
device,
&Features::none(),
&extensions,
queue_families
.iter()
.map(|queue_family| (*queue_family, 1.0)),
)
.ok()
let (_swapchain, _swapchain_image) = Swapchain::new(...).unwrap();
이번에는 창을 표시하고 스왑 체인을 만들었습니다. swap chain은 확실히 세세하게 설정할 수 있을 것 같습니다만 그만큼 기술량이 많아 대단하다는, Vulkan다움(?)을 맛보았습니다. 아직 실질 아무것도 표시되어 있지 않습니다만, 다음 번부터 드디어 셰이더에 관련될 것 같습니다.
Reference
이 문제에 관하여(Vulkan Tutorial의 Rust 버전을 해 보았다 ~Window편~), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/kbone/items/9cefcb960fc1f58e9131텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)