Skip to content

Commit

Permalink
Merge pull request #248 from mahkoh/jorth/vulkan-allocator
Browse files Browse the repository at this point in the history
vulkan: create a vulkan allocator
  • Loading branch information
mahkoh authored Sep 2, 2024
2 parents 952bd31 + 766a093 commit 940aeca
Show file tree
Hide file tree
Showing 15 changed files with 984 additions and 101 deletions.
76 changes: 63 additions & 13 deletions src/cli/screenshot.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use {
crate::{
allocator::{Allocator, AllocatorError, BO_USE_LINEAR, BO_USE_RENDERING},
allocator::{Allocator, AllocatorError, BufferUsage, MappedBuffer},
cli::{GlobalArgs, ScreenshotArgs, ScreenshotFormat},
format::XRGB8888,
gfx_apis,
tools::tool_client::{with_tool_client, Handle, ToolClient},
udmabuf::{Udmabuf, UdmabufError},
utils::{errorfmt::ErrorFmt, queue::AsyncQueue, windows::WindowsExt},
Expand Down Expand Up @@ -138,28 +139,77 @@ pub enum ScreenshotError {
ImportDmabuf(#[source] AllocatorError),
#[error("Could not map a dmabuf")]
MapDmabuf(#[source] AllocatorError),
#[error("Could not create a vulkan allocator")]
CreateVulkanAllocator(#[source] AllocatorError),
#[error("Could not map the dmabuf with any allocator")]
MapDmabufAny,
}

fn map(
allocator: Rc<dyn Allocator>,
buf: &DmaBuf,
) -> Result<Box<dyn MappedBuffer>, ScreenshotError> {
let bo = allocator
.import_dmabuf(buf, BufferUsage::none())
.map_err(ScreenshotError::ImportDmabuf)?;
let bo_map = bo.map_read().map_err(ScreenshotError::MapDmabuf)?;
Ok(bo_map)
}

pub fn buf_to_bytes(
drm_dev: Option<&Rc<OwnedFd>>,
buf: &DmaBuf,
format: ScreenshotFormat,
) -> Result<Vec<u8>, ScreenshotError> {
let allocator: Rc<dyn Allocator> = match drm_dev {
match drm_dev {
None => {}
Some(_) => {}
}
let mut allocators =
Vec::<Box<dyn FnOnce() -> Result<Rc<dyn Allocator>, ScreenshotError>>>::new();
match drm_dev {
Some(drm_dev) => {
let drm = Drm::reopen(drm_dev.raw(), false).map_err(ScreenshotError::OpenDrmDevice)?;
GbmDevice::new(&drm)
.map(Rc::new)
.map_err(ScreenshotError::CreateGbmDevice)?
let drm = || Drm::reopen(drm_dev.raw(), false).map_err(ScreenshotError::OpenDrmDevice);
let gbm = Box::new(move || {
GbmDevice::new(&drm()?)
.map(|d| Rc::new(d) as _)
.map_err(ScreenshotError::CreateGbmDevice)
});
let vulkan = Box::new(move || {
gfx_apis::create_vulkan_allocator(&drm()?)
.map_err(ScreenshotError::CreateVulkanAllocator)
});
allocators.push(vulkan);
allocators.push(gbm);
}
None => {
let udmabuf = Box::new(|| {
Udmabuf::new()
.map(|u| Rc::new(u) as _)
.map_err(ScreenshotError::CreateUdmabuf)
});
allocators.push(udmabuf);
}
None => Udmabuf::new()
.map(Rc::new)
.map_err(ScreenshotError::CreateUdmabuf)?,
}
let bo_map = 'create_bo_map: {
for allocator in allocators {
let allocator = match allocator() {
Ok(a) => a,
Err(e) => {
log::error!("Could not create allocator: {}", ErrorFmt(e));
continue;
}
};
match map(allocator, buf) {
Ok(m) => break 'create_bo_map m,
Err(e) => {
log::error!("Could not map dmabuf: {}", ErrorFmt(e));
continue;
}
};
}
return Err(ScreenshotError::MapDmabufAny);
};
let bo = allocator
.import_dmabuf(buf, BO_USE_LINEAR | BO_USE_RENDERING)
.map_err(ScreenshotError::ImportDmabuf)?;
let bo_map = bo.map_read().map_err(ScreenshotError::MapDmabuf)?;
let data = unsafe { bo_map.data() };
if format == ScreenshotFormat::Qoi {
return Ok(xrgb8888_encode_qoi(
Expand Down
1 change: 1 addition & 0 deletions src/gfx_apis.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub use vulkan::create_vulkan_allocator;
use {
crate::{
async_engine::AsyncEngine,
Expand Down
29 changes: 26 additions & 3 deletions src/gfx_apis/vulkan.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
mod allocator;
mod bo_allocator;
mod command;
mod descriptor;
mod device;
Expand All @@ -17,7 +18,7 @@ mod util;

use {
crate::{
allocator::Allocator,
allocator::{Allocator, AllocatorError},
async_engine::AsyncEngine,
format::Format,
gfx_api::{
Expand All @@ -39,6 +40,7 @@ use {
ash::{vk, LoadingError},
gpu_alloc::{AllocationError, MapError},
jay_config::video::GfxApi,
log::Level,
once_cell::sync::Lazy,
std::{
cell::Cell,
Expand Down Expand Up @@ -180,6 +182,20 @@ pub enum VulkanError {
GfxError(GfxError),
#[error("Buffer format {0} is not supported for shm buffers in Vulkan context")]
UnsupportedShmFormat(&'static str),
#[error("Only BO_USE_RENDERING and BO_USE_WRITE are supported")]
UnsupportedBufferUsage,
#[error("None of the supplied modifiers are supported")]
NoSupportedModifiers,
#[error("Could not retrieve the image modifier")]
GetModifier(#[source] vk::Result),
#[error("Vulkan allocated the image with an invalid modifier")]
InvalidModifier,
#[error("Could not export the DmaBuf")]
GetDmaBuf(#[source] vk::Result),
#[error("Could not wait for the device to become idle")]
WaitIdle(#[source] vk::Result),
#[error("Could not dup a DRM device")]
DupDrm(#[source] DrmError),
}

impl From<VulkanError> for GfxError {
Expand All @@ -196,12 +212,19 @@ pub fn create_graphics_context(
ring: &Rc<IoUring>,
drm: &Drm,
) -> Result<Rc<dyn GfxContext>, GfxError> {
let instance = VulkanInstance::new(eng, ring, *VULKAN_VALIDATION)?;
let instance = VulkanInstance::new(Level::Info, *VULKAN_VALIDATION)?;
let device = instance.create_device(drm)?;
let renderer = device.create_renderer()?;
let renderer = device.create_renderer(eng, ring)?;
Ok(Rc::new(Context(renderer)))
}

pub fn create_vulkan_allocator(drm: &Drm) -> Result<Rc<dyn Allocator>, AllocatorError> {
let instance = VulkanInstance::new(Level::Debug, *VULKAN_VALIDATION)?;
let device = instance.create_device(drm)?;
let allocator = device.create_bo_allocator(drm)?;
Ok(Rc::new(allocator))
}

#[derive(Debug)]
struct Context(Rc<VulkanRenderer>);

Expand Down
Loading

0 comments on commit 940aeca

Please sign in to comment.