mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2024-11-28 09:33:01 +00:00
rutabaga_gfx: kumquat: support GPU mappings
- dma-buf mmap does not work on Tesla V-100 - system blob does not work on Tesla V-100 - opaque fd mmap does not work on Tesla V-100 - Opaque fd + VK map does work on Tesla V-100 Since we need to make sure the Nvidia ICD is used when calling VK map + unmap, we save and restore VK_ICD_FILENAMES when loading gralloc. This is not super-robust, but the perhaps the best can that can be done on Nvidia. BUG=b:300140266 TEST=see successful memory access with Nvidia Change-Id: I4f4084921b6267b137e7aeeafbfb8839a120c63e Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/5698370 Reviewed-by: Jason Macnak <natsu@google.com> Commit-Queue: Gurchetan Singh <gurchetansingh@chromium.org>
This commit is contained in:
parent
ea09e79921
commit
1eade7875e
3 changed files with 89 additions and 17 deletions
|
@ -15,8 +15,11 @@ use rutabaga_gfx::kumquat_gpu_protocol::*;
|
|||
use rutabaga_gfx::RutabagaDescriptor;
|
||||
use rutabaga_gfx::RutabagaError;
|
||||
use rutabaga_gfx::RutabagaFromRawDescriptor;
|
||||
use rutabaga_gfx::RutabagaGralloc;
|
||||
use rutabaga_gfx::RutabagaGrallocBackendFlags;
|
||||
use rutabaga_gfx::RutabagaHandle;
|
||||
use rutabaga_gfx::RutabagaIntoRawDescriptor;
|
||||
use rutabaga_gfx::RutabagaMappedRegion;
|
||||
use rutabaga_gfx::RutabagaMapping;
|
||||
use rutabaga_gfx::RutabagaMemoryMapping;
|
||||
use rutabaga_gfx::RutabagaRawDescriptor;
|
||||
|
@ -25,6 +28,7 @@ use rutabaga_gfx::RutabagaResult;
|
|||
use rutabaga_gfx::RutabagaSharedMemory;
|
||||
use rutabaga_gfx::RutabagaStream;
|
||||
use rutabaga_gfx::RutabagaWriter;
|
||||
use rutabaga_gfx::VulkanInfo;
|
||||
use rutabaga_gfx::RUTABAGA_FLAG_FENCE;
|
||||
use rutabaga_gfx::RUTABAGA_FLAG_FENCE_HOST_SHAREABLE;
|
||||
use rutabaga_gfx::RUTABAGA_FLAG_INFO_RING_IDX;
|
||||
|
@ -34,22 +38,33 @@ use rutabaga_gfx::RUTABAGA_MEM_HANDLE_TYPE_OPAQUE_FD;
|
|||
|
||||
use crate::virtgpu::defines::*;
|
||||
|
||||
const VK_ICD_FILENAMES: &str = "VK_ICD_FILENAMES";
|
||||
|
||||
pub struct VirtGpuResource {
|
||||
resource_id: u32,
|
||||
size: usize,
|
||||
handle: RutabagaHandle,
|
||||
mapping: Option<RutabagaMemoryMapping>,
|
||||
attached_fences: Vec<RutabagaHandle>,
|
||||
vulkan_info: VulkanInfo,
|
||||
system_mapping: Option<RutabagaMemoryMapping>,
|
||||
gpu_mapping: Option<Box<dyn RutabagaMappedRegion>>,
|
||||
}
|
||||
|
||||
impl VirtGpuResource {
|
||||
pub fn new(resource_id: u32, size: usize, handle: RutabagaHandle) -> VirtGpuResource {
|
||||
pub fn new(
|
||||
resource_id: u32,
|
||||
size: usize,
|
||||
handle: RutabagaHandle,
|
||||
vulkan_info: VulkanInfo,
|
||||
) -> VirtGpuResource {
|
||||
VirtGpuResource {
|
||||
resource_id,
|
||||
size,
|
||||
handle,
|
||||
mapping: None,
|
||||
attached_fences: Vec::new(),
|
||||
vulkan_info,
|
||||
system_mapping: None,
|
||||
gpu_mapping: None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -61,6 +76,7 @@ pub struct VirtGpuKumquat {
|
|||
stream: RutabagaStream,
|
||||
capsets: Map<u32, Vec<u8>>,
|
||||
resources: Map<u32, VirtGpuResource>,
|
||||
gralloc_opt: Option<RutabagaGralloc>,
|
||||
}
|
||||
|
||||
impl VirtGpuKumquat {
|
||||
|
@ -122,6 +138,7 @@ impl VirtGpuKumquat {
|
|||
stream,
|
||||
capsets,
|
||||
resources: Default::default(),
|
||||
gralloc_opt: None,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -210,7 +227,7 @@ impl VirtGpuKumquat {
|
|||
let resource = match protocols.remove(0) {
|
||||
KumquatGpuProtocol::RespResourceCreate(resp, handle) => {
|
||||
let size: usize = create_3d.size.try_into()?;
|
||||
VirtGpuResource::new(resp.resource_id, size, handle)
|
||||
VirtGpuResource::new(resp.resource_id, size, handle, resp.vulkan_info)
|
||||
}
|
||||
_ => return Err(RutabagaError::Unsupported),
|
||||
};
|
||||
|
@ -268,7 +285,7 @@ impl VirtGpuKumquat {
|
|||
let resource = match protocols.remove(0) {
|
||||
KumquatGpuProtocol::RespResourceCreate(resp, handle) => {
|
||||
let size: usize = create_blob.size.try_into()?;
|
||||
VirtGpuResource::new(resp.resource_id, size, handle)
|
||||
VirtGpuResource::new(resp.resource_id, size, handle, resp.vulkan_info)
|
||||
}
|
||||
_ => {
|
||||
return Err(RutabagaError::Unsupported);
|
||||
|
@ -308,21 +325,50 @@ impl VirtGpuKumquat {
|
|||
.get_mut(&bo_handle)
|
||||
.ok_or(RutabagaError::InvalidResourceId)?;
|
||||
|
||||
if let Some(ref mapping) = resource.mapping {
|
||||
let rutabaga_mapping = mapping.as_rutabaga_mapping();
|
||||
if let Some(ref system_mapping) = resource.system_mapping {
|
||||
let rutabaga_mapping = system_mapping.as_rutabaga_mapping();
|
||||
Ok(rutabaga_mapping)
|
||||
} else if let Some(ref gpu_mapping) = resource.gpu_mapping {
|
||||
let rutabaga_mapping = gpu_mapping.as_rutabaga_mapping();
|
||||
Ok(rutabaga_mapping)
|
||||
} else {
|
||||
let clone = resource.handle.try_clone()?;
|
||||
|
||||
let mapping = RutabagaMemoryMapping::from_safe_descriptor(
|
||||
clone.os_handle,
|
||||
resource.size,
|
||||
RUTABAGA_MAP_CACHE_CACHED | RUTABAGA_MAP_ACCESS_RW,
|
||||
)?;
|
||||
if clone.handle_type == RUTABAGA_MEM_HANDLE_TYPE_OPAQUE_FD {
|
||||
if self.gralloc_opt.is_none() {
|
||||
// The idea is to make sure the gfxstream ICD isn't loaded when gralloc starts
|
||||
// up. The Nvidia ICD should be loaded.
|
||||
let vk_driver = std::env::var(VK_ICD_FILENAMES).unwrap();
|
||||
std::env::remove_var(VK_ICD_FILENAMES);
|
||||
self.gralloc_opt =
|
||||
Some(RutabagaGralloc::new(RutabagaGrallocBackendFlags::new())?);
|
||||
std::env::set_var(VK_ICD_FILENAMES, vk_driver);
|
||||
}
|
||||
|
||||
let rutabaga_mapping = mapping.as_rutabaga_mapping();
|
||||
resource.mapping = Some(mapping);
|
||||
Ok(rutabaga_mapping)
|
||||
if let Some(ref mut gralloc) = self.gralloc_opt {
|
||||
let region = gralloc.import_and_map(
|
||||
clone,
|
||||
resource.vulkan_info,
|
||||
resource.size as u64,
|
||||
)?;
|
||||
|
||||
let rutabaga_mapping = region.as_rutabaga_mapping();
|
||||
resource.gpu_mapping = Some(region);
|
||||
Ok(rutabaga_mapping)
|
||||
} else {
|
||||
return Err(RutabagaError::SpecViolation("no gralloc"));
|
||||
}
|
||||
} else {
|
||||
let mapping = RutabagaMemoryMapping::from_safe_descriptor(
|
||||
clone.os_handle,
|
||||
resource.size,
|
||||
RUTABAGA_MAP_CACHE_CACHED | RUTABAGA_MAP_ACCESS_RW,
|
||||
)?;
|
||||
|
||||
let rutabaga_mapping = mapping.as_rutabaga_mapping();
|
||||
resource.system_mapping = Some(mapping);
|
||||
Ok(rutabaga_mapping)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -332,7 +378,8 @@ impl VirtGpuKumquat {
|
|||
.get_mut(&bo_handle)
|
||||
.ok_or(RutabagaError::InvalidResourceId)?;
|
||||
|
||||
resource.mapping = None;
|
||||
resource.system_mapping = None;
|
||||
resource.gpu_mapping = None;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
@ -582,7 +629,12 @@ impl VirtGpuKumquat {
|
|||
|
||||
self.stream
|
||||
.write(KumquatGpuProtocolWrite::Cmd(attach_resource))?;
|
||||
let resource = VirtGpuResource::new(*resource_handle, VIRTGPU_KUMQUAT_PAGE_SIZE, handle);
|
||||
let resource = VirtGpuResource::new(
|
||||
*resource_handle,
|
||||
VIRTGPU_KUMQUAT_PAGE_SIZE,
|
||||
handle,
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
*bo_handle = self.allocate_id();
|
||||
// Should ask the server about the size long-term.
|
||||
|
|
|
@ -99,6 +99,21 @@ unsafe impl MappedRegion for VulkanoMapping {
|
|||
fn size(&self) -> usize {
|
||||
self.size
|
||||
}
|
||||
|
||||
/// Returns rutabaga mapping representation of the region
|
||||
fn as_rutabaga_mapping(&self) -> RutabagaMapping {
|
||||
let ptr: u64 = unsafe {
|
||||
// Will not panic since the requested range of the device memory was verified on
|
||||
// creation
|
||||
let x = self.mapped_memory.write(0..self.size as u64).unwrap();
|
||||
x.as_mut_ptr() as u64
|
||||
};
|
||||
|
||||
RutabagaMapping {
|
||||
ptr,
|
||||
size: self.size as u64,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
trait DeviceExt {
|
||||
|
|
|
@ -17,6 +17,8 @@ pub use sys::platform::descriptor::RawDescriptor;
|
|||
pub use sys::platform::shm::round_up_to_page_size;
|
||||
pub use sys::platform::wait_context::WaitContext;
|
||||
|
||||
use crate::rutabaga_utils::RutabagaMapping;
|
||||
|
||||
pub struct WaitEvent {
|
||||
pub connection_id: u64,
|
||||
pub hung_up: bool,
|
||||
|
@ -40,4 +42,7 @@ pub unsafe trait MappedRegion: Send + Sync {
|
|||
|
||||
/// Returns the size of the memory region in bytes.
|
||||
fn size(&self) -> usize;
|
||||
|
||||
/// Returns rutabaga mapping representation of the region
|
||||
fn as_rutabaga_mapping(&self) -> RutabagaMapping;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue