pub mod backend;
pub mod buffer;
pub mod memory;
pub mod pool;
pub mod staging;
pub mod transfer;
pub mod sync;
pub use backend::{MkGpuBackend, MkGpuCapabilities, DummyBackend, DummyBackendConfig, DummyError};
pub use buffer::{MkDeviceBuffer, MkBufferUsage};
pub use memory::MkMemoryType;
pub use staging::MkStagingBuffer;
pub use transfer::{MkGpuTransfer, MkTransferBuilder};
pub use sync::MkFence;
pub use pool::MkGpuPool;
#[cfg(feature = "vulkan")]
pub mod vulkan;
#[cfg(feature = "vulkan")]
pub use vulkan::{VulkanBackend, VulkanConfig};
pub struct MkGpu<B: MkGpuBackend> {
backend: B,
transfer_id: std::sync::atomic::AtomicU64,
}
impl<B: MkGpuBackend> MkGpu<B> {
pub fn new(backend: B) -> Self {
Self {
backend,
transfer_id: std::sync::atomic::AtomicU64::new(0),
}
}
pub fn backend(&self) -> &B {
&self.backend
}
pub fn create_device_buffer(&self, size: usize, usage: MkBufferUsage) -> Result<MkDeviceBuffer<B>, B::Error> {
let handle = self.backend.create_buffer(size, usage, MkMemoryType::DeviceLocal)?;
Ok(MkDeviceBuffer::new(handle, size, usage))
}
pub fn create_staging_buffer(&self, size: usize) -> Result<MkStagingBuffer<B>, B::Error> {
let usage = MkBufferUsage::TRANSFER_SRC;
let handle = self.backend.create_buffer(size, usage, MkMemoryType::HostVisible)?;
Ok(MkStagingBuffer::new(handle, size))
}
pub fn staging_buffer_with_data<T: Copy>(&self, data: &[T]) -> Result<MkStagingBuffer<B>, B::Error> {
let size = std::mem::size_of_val(data);
let mut staging = self.create_staging_buffer(size)?;
if let Some(ptr) = self.backend.map(&staging.handle()) {
unsafe {
std::ptr::copy_nonoverlapping(
data.as_ptr() as *const u8,
ptr,
size,
);
}
self.backend.unmap(&staging.handle());
}
Ok(staging)
}
pub fn transfer(&self, src: &MkStagingBuffer<B>, dst: &MkDeviceBuffer<B>) -> Result<MkGpuTransfer, B::Error> {
let size = src.size().min(dst.size());
self.backend.copy_buffer(&src.handle(), &dst.handle(), size)?;
let id = self.transfer_id.fetch_add(1, std::sync::atomic::Ordering::Relaxed);
Ok(MkGpuTransfer::new(id))
}
pub fn batch_transfer(&self) -> transfer::MkBatchTransfer<'_, B> {
transfer::MkBatchTransfer::new(self)
}
pub fn wait_idle(&self) -> Result<(), B::Error> {
self.backend.wait_idle()
}
}