Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 19 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
[workspace]
members = [
"graphics/mygraphics",
"graphics/mygraphics-shaders",
"xtask",
"graphics/mygraphics",
"graphics/mygraphics-shaders",
"xtask",
]
resolver = "3"

Expand All @@ -20,6 +20,7 @@ unexpected_cfgs = { level = "allow", check-cfg = ['cfg(target_arch, values("spir
# API
ash = "0.38"
ash-window = "0.13"
gpu-allocator = { version = "0.28.0", default-features = false, features = ["std", "vulkan"] }
wgpu = { version = "27.0.1", default-features = false, features = ["std", "parking_lot", "vulkan", "vulkan-portability", "spirv", "wgsl"] }
pollster = "0.4.0"

Expand Down
1 change: 1 addition & 0 deletions generated/graphics/ash/cargo-gpu/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ unexpected_cfgs = { level = "allow", check-cfg = ['cfg(target_arch, values("spir
# API
ash = "0.38"
ash-window = "0.13"
gpu-allocator = { version = "0.28.0", default-features = false, features = ["std", "vulkan"] }

# rust-gpu
cargo-gpu = { git = "https://github.com/Rust-GPU/cargo-gpu", rev = "bb74342b90066ce8b7d50ba8e058df356a54acf4" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub fn main_fs(vtx_color: Vec3, output: &mut Vec4) {
#[spirv(vertex)]
pub fn main_vs(
#[spirv(vertex_index)] vert_id: i32,
#[spirv(push_constant)] constants: &ShaderConstants,
#[spirv(descriptor_set = 0, binding = 0, storage_buffer)] constants: &ShaderConstants,
#[spirv(position)] vtx_pos: &mut Vec4,
vtx_color: &mut Vec3,
) {
Expand Down
1 change: 1 addition & 0 deletions generated/graphics/ash/cargo-gpu/mygraphics/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ mygraphics-shaders = { path = "../mygraphics-shaders" }
# API
ash.workspace = true
ash-window.workspace = true
gpu-allocator.workspace = true

# other
raw-window-handle.workspace = true
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use crate::ash_renderer::device::MyDevice;
use ash::vk;
use bytemuck::NoUninit;
use gpu_allocator::MemoryLocation;
use gpu_allocator::vulkan::{Allocation, AllocationCreateDesc, AllocationScheme};
use std::borrow::Cow;
use std::sync::Arc;

pub struct MyBuffer {
pub buffer: vk::Buffer,
pub allocation: Allocation,
pub name: String,
destroyed: bool,
}

#[derive(Clone)]
pub struct BufferCreateInfo<'a> {
pub usage: vk::BufferUsageFlags,
pub location: MemoryLocation,
pub name: Option<Cow<'a, str>>,
}

impl MyBuffer {
pub fn from_data<T: NoUninit>(
device: &Arc<MyDevice>,
info: BufferCreateInfo<'_>,
data: &T,
) -> anyhow::Result<Self> {
Self::from_slice(device, info, bytemuck::bytes_of(data))
}

pub fn from_slice<T: NoUninit>(
device: &Arc<MyDevice>,
info: BufferCreateInfo<'_>,
data: &[T],
) -> anyhow::Result<Self> {
unsafe {
let buffer = device.create_buffer(
&vk::BufferCreateInfo::default()
.size(size_of_val(data) as u64)
.usage(vk::BufferUsageFlags::STORAGE_BUFFER),
None,
)?;
let name = info.name.map(|a| a.into_owned()).unwrap_or_default();
let mut allocation = device.borrow_allocator().allocate(&AllocationCreateDesc {
name: &name,
requirements: device.get_buffer_memory_requirements(buffer),
location: MemoryLocation::CpuToGpu,
linear: true,
allocation_scheme: AllocationScheme::GpuAllocatorManaged,
})?;
device.bind_buffer_memory(buffer, allocation.memory(), allocation.offset())?;
let mapped = &mut allocation.mapped_slice_mut().unwrap()[..size_of_val(data)];
mapped.copy_from_slice(bytemuck::cast_slice(data));
Ok(Self {
buffer,
allocation,
name,
destroyed: false,
})
}
}

/// Destroy this buffer
///
/// # Safety
/// Buffer must not be in use
pub unsafe fn destroy(&mut self, device: &Arc<MyDevice>) {
if !self.destroyed {
self.destroyed = true;
unsafe {
device.destroy_buffer(self.buffer, None);
}
}
}
}

impl Drop for MyBuffer {
fn drop(&mut self) {
if !self.destroyed {
panic!("dropping Buffer {} without destroying it", &self.name);
}
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
use anyhow::{Context, anyhow};
use ash::{ext, khr, vk};
use gpu_allocator::vulkan::{Allocator, AllocatorCreateDesc};
use std::borrow::Cow;
use std::ffi::{CStr, c_char};
use std::ops::Deref;
use std::sync::Arc;
use std::sync::{Arc, Mutex, MutexGuard};

/// Central struct containing the Vulkan instance and device, among others
pub struct MyDevice {
Expand All @@ -13,6 +14,7 @@ pub struct MyDevice {
pub device: ash::Device,
pub main_queue_family: u32,
pub main_queue: vk::Queue,
allocator: Option<Mutex<Allocator>>,
pub debug_ext_instance: ext::debug_utils::Instance,
pub debug_ext_device: ext::debug_utils::Device,
pub surface_ext: khr::surface::Instance,
Expand Down Expand Up @@ -134,6 +136,15 @@ impl MyDevice {
.context("create_device")?;
let main_queue = device.get_device_queue(main_queue_family, 0);

let allocator = Allocator::new(&AllocatorCreateDesc {
instance: instance.clone(),
device: device.clone(),
physical_device,
debug_settings: Default::default(),
buffer_device_address: false,
allocation_sizes: Default::default(),
})?;

Ok(Arc::new(Self {
debug_ext_device: ext::debug_utils::Device::new(&instance, &device),
surface_ext: khr::surface::Instance::new(&entry, &instance),
Expand All @@ -144,16 +155,22 @@ impl MyDevice {
device,
main_queue_family,
main_queue,
allocator: Some(Mutex::new(allocator)),
debug_ext_instance: debug_instance,
debug_callback,
}))
}
}

pub fn borrow_allocator(&self) -> MutexGuard<'_, Allocator> {
self.allocator.as_ref().unwrap().lock().unwrap()
}
}

impl Drop for MyDevice {
fn drop(&mut self) {
unsafe {
drop(self.allocator.take());
self.debug_ext_instance
.destroy_debug_utils_messenger(self.debug_callback, None);
self.device.destroy_device(None);
Expand All @@ -178,6 +195,12 @@ unsafe extern "system" fn vulkan_debug_callback(
.map_or(Cow::Borrowed(""), CStr::to_string_lossy);

println!("{message_severity:?}: [{message_id_name}] : {message}");
vk::FALSE
if message_severity.contains(vk::DebugUtilsMessageSeverityFlagsEXT::WARNING)
| message_severity.contains(vk::DebugUtilsMessageSeverityFlagsEXT::ERROR)
{
vk::TRUE
} else {
vk::FALSE
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
use crate::ash_renderer::device::MyDevice;
use ash::vk;
use std::sync::Arc;

pub struct GlobalDescriptorSetLayout {
pub device: Arc<MyDevice>,
pub layout: vk::DescriptorSetLayout,
}

impl GlobalDescriptorSetLayout {
pub fn new(device: Arc<MyDevice>) -> anyhow::Result<Arc<Self>> {
unsafe {
Ok(Arc::new(Self {
layout: device.create_descriptor_set_layout(
&vk::DescriptorSetLayoutCreateInfo::default().bindings(&[
vk::DescriptorSetLayoutBinding::default()
.binding(0)
.descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
.stage_flags(vk::ShaderStageFlags::ALL_GRAPHICS)
.descriptor_count(1),
]),
None,
)?,
device,
}))
}
}
}

impl Drop for GlobalDescriptorSetLayout {
fn drop(&mut self) {
unsafe {
self.device.destroy_descriptor_set_layout(self.layout, None);
}
}
}

/// This implementation of descriptor sets is kept simple on purpose, even at the cost of being quite inefficient.
/// Don't use this as a reference on how it should be done!
pub struct GlobalDescriptorSet {
pub layout: Arc<GlobalDescriptorSetLayout>,
pub pool: vk::DescriptorPool,
pub set: vk::DescriptorSet,
destroyed: bool,
}

impl GlobalDescriptorSet {
/// # Safety
/// * `shader_constants` must not be dropped before `GlobalDescriptorSet` is dropped
/// * you must only drop this `GlobalDescriptorSet` when it is unused, e.g. by GPU execution
pub unsafe fn new(
layout: &Arc<GlobalDescriptorSetLayout>,
shader_constants: vk::Buffer,
) -> anyhow::Result<Self> {
unsafe {
let device = &layout.device;
let pool = device.create_descriptor_pool(
&vk::DescriptorPoolCreateInfo::default()
.pool_sizes(&[vk::DescriptorPoolSize::default()
.ty(vk::DescriptorType::STORAGE_BUFFER)
.descriptor_count(1)])
.max_sets(1),
None,
)?;
let set = device.allocate_descriptor_sets(
&vk::DescriptorSetAllocateInfo::default()
.descriptor_pool(pool)
.set_layouts(&[layout.layout]),
)?[0];
device.update_descriptor_sets(
&[vk::WriteDescriptorSet::default()
.dst_set(set)
.dst_binding(0)
.descriptor_type(vk::DescriptorType::STORAGE_BUFFER)
.descriptor_count(1)
.buffer_info(&[vk::DescriptorBufferInfo::default()
.buffer(shader_constants)
.offset(0)
.range(vk::WHOLE_SIZE)])],
&[],
);
Ok(Self {
layout: layout.clone(),
pool,
set,
destroyed: false,
})
}
}

pub fn destroy(&mut self) {
if !self.destroyed {
self.destroyed = true;
unsafe {
let device = &self.layout.device;
device
.reset_descriptor_pool(self.pool, vk::DescriptorPoolResetFlags::empty())
.ok();
device.destroy_descriptor_pool(self.pool, None);
}
}
}
}

impl Drop for GlobalDescriptorSet {
fn drop(&mut self) {
if !self.destroyed {
panic!("dropping GlobalDescriptorSet without destroying it");
}
}
}
Loading