hook up rendy-memory

This commit is contained in:
Dzmitry Malyshau 2019-05-30 13:33:38 -04:00
parent 9c408f919c
commit 351432aae2
6 changed files with 152 additions and 126 deletions

39
Cargo.lock generated
View File

@ -42,6 +42,11 @@ dependencies = [
"shared_library 0.1.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "atom"
version = "0.3.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "autocfg"
version = "0.1.2"
@ -134,6 +139,11 @@ dependencies = [
"objc 0.2.6 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "colorful"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "copyless"
version = "0.1.2"
@ -490,6 +500,14 @@ dependencies = [
"gl_generator 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "hibitset"
version = "0.5.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"atom 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "iovec"
version = "0.1.2"
@ -990,6 +1008,22 @@ dependencies = [
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rendy-memory"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"colorful 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)",
"derivative 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)",
"failure 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
"gfx-hal 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"relevant 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"slab 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)",
"smallvec 0.6.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "rustc-demangle"
version = "0.1.14"
@ -1266,6 +1300,7 @@ dependencies = [
"log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
"parking_lot 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rendy-descriptor 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"rendy-memory 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"serde 1.0.91 (registry+https://github.com/rust-lang/crates.io-index)",
"vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)",
"winit 0.19.1 (registry+https://github.com/rust-lang/crates.io-index)",
@ -1411,6 +1446,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum approx 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)" = "f0e60b75072ecd4168020818c0107f2857bb6c4e64252d8d3983f6263b40a5c3"
"checksum arrayvec 0.4.10 (registry+https://github.com/rust-lang/crates.io-index)" = "92c7fb76bc8826a8b33b4ee5bb07a247a81e76764ab4d55e8f73e3a4d8808c71"
"checksum ash 0.29.0 (registry+https://github.com/rust-lang/crates.io-index)" = "003d1fb2eb12eb06d4a03dbe02eea67a9fac910fa97932ab9e3a75b96a1ea5e5"
"checksum atom 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "3c86699c3f02778ec07158376991c8f783dd1f2f95c579ffaf0738dc984b2fe2"
"checksum autocfg 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "a6d640bee2da49f60a4068a7fae53acde8982514ab7bae8b8cea9e88cbcfd799"
"checksum backtrace 0.3.18 (registry+https://github.com/rust-lang/crates.io-index)" = "f92d5d536fa03dc3d93711d97bac1fae2eb59aba467ca4c6600c0119da614f51"
"checksum backtrace-sys 0.1.28 (registry+https://github.com/rust-lang/crates.io-index)" = "797c830ac25ccc92a7f8a7b9862bde440715531514594a6154e3d4a54dd769b6"
@ -1423,6 +1459,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum cgl 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "55e7ec0b74fe5897894cbc207092c577e87c52f8a59e8ca8d97ef37551f60a49"
"checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f"
"checksum cocoa 0.18.4 (registry+https://github.com/rust-lang/crates.io-index)" = "cf79daa4e11e5def06e55306aa3601b87de6b5149671529318da048f67cdd77b"
"checksum colorful 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "0bca1619ff57dd7a56b58a8e25ef4199f123e78e503fe1653410350a1b98ae65"
"checksum copyless 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "59de7722d3b5c7b35dd519d617fe5116c9b879a0f145dc5431d78ab1f61d7c23"
"checksum core-foundation 0.6.4 (registry+https://github.com/rust-lang/crates.io-index)" = "25b9e03f145fd4f2bf705e07b900cd41fc636598fe5dc452fd0db1441c3f496d"
"checksum core-foundation-sys 0.6.2 (registry+https://github.com/rust-lang/crates.io-index)" = "e7ca8a5221364ef15ce201e8ed2f609fc312682a8f4e0e3d4aa5879764e0fa3b"
@ -1459,6 +1496,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum glutin_gles2_sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "89996c30857ae1b4de4b5189abf1ea822a20a9fe9e1c93e5e7b862ff0bdd5cdf"
"checksum glutin_glx_sys 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "1290a5ca5e46fcfa7f66f949cc9d9194b2cb6f2ed61892c8c2b82343631dba57"
"checksum glutin_wgl_sys 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "f801bbc91efc22dd1c4818a47814fc72bf74d024510451b119381579bfa39021"
"checksum hibitset 0.5.4 (registry+https://github.com/rust-lang/crates.io-index)" = "6527bc88f32e0d3926c7572874b2bf17a19b36978aacd0aacf75f7d27a5992d0"
"checksum iovec 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "dbe6e417e7d0975db6512b90796e8ce223145ac4e33c377e4a42882a0e88bb08"
"checksum ipc-channel 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "79d98ee7dd1d2e796d254807fd86ea7189d07571aeaa74007603e29a79d15217"
"checksum kernel32-sys 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "7507624b29483431c0ba2d82aece8ca6cdba9382bff4ddd0f7490560c056098d"
@ -1514,6 +1552,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
"checksum relevant 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "bbc232e13d37f4547f5b9b42a5efc380cabe5dbc1807f8b893580640b2ab0308"
"checksum remove_dir_all 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "3488ba1b9a2084d38645c4c08276a1752dcbf2c7130d74f1569681ad5d2799c5"
"checksum rendy-descriptor 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d994004622af2fe3848fde527258dd6bee8cf089a51e2e83fe5f2b7aeb09f6c0"
"checksum rendy-memory 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fbdab806e4d349037b60ff6a25dad1260da58eb4b43ecac31350443278d5c002"
"checksum rustc-demangle 0.1.14 (registry+https://github.com/rust-lang/crates.io-index)" = "ccc78bfd5acd7bf3e89cffcf899e5cb1a52d6fafa8dec2739ad70c9577a57288"
"checksum rustc_version 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a"
"checksum rusttype 0.7.6 (registry+https://github.com/rust-lang/crates.io-index)" = "25951e85bb2647960969f72c559392245a5bd07446a589390bf427dda31cdc4a"

View File

@ -1,6 +1,6 @@
/* Generated with cbindgen:0.8.6 */
/* Generated with cbindgen:0.8.7 */
#include <stdarg.h>
#include <stdbool.h>

View File

@ -1,6 +1,6 @@
#define WGPU_LOCAL
/* Generated with cbindgen:0.8.6 */
/* Generated with cbindgen:0.8.7 */
#include <stdarg.h>
#include <stdbool.h>

View File

@ -36,7 +36,7 @@ gfx-backend-dx12 = { version = "0.2", optional = true }
gfx-backend-metal = { version = "0.2", optional = true }
gfx-backend-gl = { version = "0.2", optional = true }
parking_lot = { version = "0.8" }
#rendy-memory = "0.2"
rendy-memory = "0.2"
rendy-descriptor = "0.2"
serde = { version = "1.0", features = ["serde_derive"], optional = true }
vec_map = "0.8"

View File

@ -49,12 +49,12 @@ use hal::{
};
use log::{info, trace};
use parking_lot::Mutex;
//use rendy_memory::{allocator, Config, Heaps};
use rendy_descriptor::{DescriptorAllocator, DescriptorRanges};
use rendy_memory::{Block, Heaps, MemoryBlock};
#[cfg(feature = "local")]
use std::sync::atomic::AtomicBool;
use std::{collections::hash_map::Entry, ffi, iter, ptr, slice, sync::atomic::Ordering};
use std::{collections::hash_map::Entry, ffi, iter, ptr, ops::Range, slice, sync::atomic::Ordering};
const CLEANUP_WAIT_MS: u64 = 5000;
pub const MAX_COLOR_TARGETS: usize = 4;
@ -111,8 +111,8 @@ enum ResourceId {
}
enum NativeResource<B: hal::Backend> {
Buffer(B::Buffer, B::Memory),
Image(B::Image, B::Memory),
Buffer(B::Buffer, MemoryBlock<B>),
Image(B::Image, MemoryBlock<B>),
ImageView(B::ImageView),
Framebuffer(B::Framebuffer),
}
@ -168,7 +168,12 @@ impl<B: hal::Backend> PendingResources<B> {
}
/// Returns the last submission index that is done.
fn cleanup(&mut self, device: &B::Device, force_wait: bool) -> SubmissionIndex {
fn cleanup(
&mut self,
device: &B::Device,
heaps_mutex: &Mutex<Heaps<B>>,
force_wait: bool,
) -> SubmissionIndex {
if force_wait {
let status = unsafe {
device.wait_for_fences(
@ -190,7 +195,7 @@ impl<B: hal::Backend> PendingResources<B> {
let last_done = if done_count != 0 {
self.active[done_count - 1].index
} else {
0
return 0
};
for a in self.active.drain(.. done_count) {
@ -202,15 +207,16 @@ impl<B: hal::Backend> PendingResources<B> {
}
}
let mut heaps = heaps_mutex.lock();
for resource in self.free.drain(..) {
match resource {
NativeResource::Buffer(raw, memory) => unsafe {
device.destroy_buffer(raw);
device.free_memory(memory);
heaps.free(device, memory);
},
NativeResource::Image(raw, memory) => unsafe {
device.destroy_image(raw);
device.free_memory(memory);
heaps.free(device, memory);
},
NativeResource::ImageView(raw) => unsafe {
device.destroy_image_view(raw);
@ -342,7 +348,6 @@ impl PendingResources<back::Backend> {
fn handle_mapping(
&mut self,
raw: &<back::Backend as hal::Backend>::Device,
limits: &hal::Limits,
) -> Vec<BufferMapPendingCallback> {
self.ready_to_map
.drain(..)
@ -352,10 +357,10 @@ impl PendingResources<back::Backend> {
let operation = buffer.pending_map_operation.take().unwrap();
let result = match operation {
BufferMapOperation::Read(ref range, ..) => {
map_buffer(raw, limits, buffer, range, HostMap::Read)
map_buffer(raw, buffer, range.clone(), HostMap::Read)
}
BufferMapOperation::Write(ref range, ..) => {
map_buffer(raw, limits, buffer, range, HostMap::Write)
map_buffer(raw, buffer, range.clone(), HostMap::Write)
}
};
(operation, result)
@ -369,58 +374,47 @@ type BufferMapPendingCallback = (BufferMapOperation, BufferMapResult);
fn map_buffer(
raw: &<back::Backend as hal::Backend>::Device,
limits: &hal::Limits,
buffer: &mut resource::Buffer<back::Backend>,
original_range: &std::ops::Range<BufferAddress>,
buffer_range: Range<BufferAddress>,
kind: HostMap,
) -> BufferMapResult {
// gfx-rs requires mapping and flushing/invalidation ranges to be done at `non_coherent_atom_size`
// granularity for memory types that aren't coherent. We achieve that by flooring the start offset
// and ceiling the end offset to those atom sizes, using bitwise operations on an `atom_mask`.
let is_coherent = buffer
.memory_properties
let is_coherent = buffer.memory
.properties()
.contains(hal::memory::Properties::COHERENT);
let atom_mask = if is_coherent {
0
} else {
limits.non_coherent_atom_size as u64 - 1
let (ptr, mapped_range) = {
let mapped = buffer.memory.map(raw, buffer_range)?;
(mapped.ptr(), mapped.range())
};
let atom_offset = original_range.start & atom_mask;
let range = (original_range.start & !atom_mask) .. ((original_range.end - 1) | atom_mask) + 1;
let pointer = unsafe { raw.map_memory(&buffer.memory, range.clone()) }?;
if !is_coherent {
match kind {
HostMap::Read => unsafe {
raw.invalidate_mapped_memory_ranges(iter::once((&buffer.memory, range)))
raw.invalidate_mapped_memory_ranges(
iter::once((buffer.memory.memory(), mapped_range)),
)
.unwrap();
},
HostMap::Write => {
buffer.mapped_write_ranges.push(range);
buffer.mapped_write_ranges.push(mapped_range);
}
}
}
Ok(unsafe {
// Since we map with a potentially smaller offset than the user requested,
// we adjust the returned pointer to compensate.
pointer.offset(atom_offset as isize)
})
Ok(ptr.as_ptr())
}
pub struct Device<B: hal::Backend> {
pub(crate) raw: B::Device,
adapter_id: AdapterId,
limits: hal::Limits,
pub(crate) queue_group: hal::QueueGroup<B, hal::General>,
//mem_allocator: Heaps<B::Memory>,
pub(crate) com_allocator: command::CommandAllocator<B>,
mem_allocator: Mutex<Heaps<B>>,
desc_allocator: Mutex<DescriptorAllocator<B>>,
life_guard: LifeGuard,
pub(crate) trackers: Mutex<TrackerSet>,
mem_props: hal::MemoryProperties,
limits: hal::Limits,
pub(crate) render_passes: Mutex<FastHashMap<RenderPassKey, B::RenderPass>>,
pub(crate) framebuffers: Mutex<FastHashMap<FramebufferKey, B::Framebuffer>>,
desc_allocator: Mutex<DescriptorAllocator<B>>,
pending: Mutex<PendingResources<B>>,
}
@ -432,44 +426,48 @@ impl<B: hal::Backend> Device<B> {
mem_props: hal::MemoryProperties,
limits: hal::Limits,
) -> Self {
// TODO: These values are just taken from rendy's test
// Need to set reasonable values per memory type instead
/*let arena = Some(allocator::ArenaConfig {
arena_size: 32 * 1024,
});
let dynamic = Some(allocator::DynamicConfig {
blocks_per_chunk: 64,
block_size_granularity: 256,
max_block_size: 32 * 1024,
});
let config = Config { arena, dynamic };
let mem_allocator = unsafe {
Heaps::new(
mem_props
.memory_types
.iter()
.map(|mt| (mt.properties.into(), mt.heap_index as u32, config)),
mem_props.memory_heaps.clone(),
)
};*/
// don't start submission index at zero
let life_guard = LifeGuard::new();
life_guard.submission_index.fetch_add(1, Ordering::Relaxed);
let heaps = {
let types = mem_props.memory_types
.iter()
.map(|mt| {
use rendy_memory::{HeapsConfig, LinearConfig, DynamicConfig};
let config = HeapsConfig {
linear: if mt.properties.contains(hal::memory::Properties::CPU_VISIBLE) {
Some(LinearConfig {
linear_size: 0x10_00_00,
})
} else {
None
},
dynamic: Some(DynamicConfig {
block_size_granularity: 0x1_00,
max_chunk_size: 0x1_00_00_00,
min_device_allocation: 0x1_00_00,
}),
};
(mt.properties.into(), mt.heap_index as u32, config)
});
unsafe {
Heaps::new(types, mem_props.memory_heaps.iter().cloned())
}
};
Device {
raw,
adapter_id,
//mem_allocator,
limits,
com_allocator: command::CommandAllocator::new(queue_group.family()),
mem_allocator: Mutex::new(heaps),
desc_allocator: Mutex::new(DescriptorAllocator::new()),
queue_group,
life_guard,
trackers: Mutex::new(TrackerSet::new()),
mem_props,
limits,
render_passes: Mutex::new(FastHashMap::default()),
framebuffers: Mutex::new(FastHashMap::default()),
desc_allocator: Mutex::new(DescriptorAllocator::new()),
pending: Mutex::new(PendingResources {
mapped: Vec::new(),
referenced: Vec::new(),
@ -488,8 +486,8 @@ impl Device<back::Backend> {
pending.triage_referenced(&mut *trackers);
pending.triage_framebuffers(&mut *self.framebuffers.lock());
let last_done = pending.cleanup(&self.raw, force_wait);
let callbacks = pending.handle_mapping(&self.raw, &self.limits);
let last_done = pending.cleanup(&self.raw, &self.mem_allocator, force_wait);
let callbacks = pending.handle_mapping(&self.raw);
if last_done != 0 {
self.com_allocator.maintain(last_done);
@ -527,37 +525,39 @@ pub fn device_create_buffer(
) -> resource::Buffer<back::Backend> {
let device_guard = HUB.devices.read();
let device = &device_guard[device_id];
let (usage, memory_properties) = conv::map_buffer_usage(desc.usage);
let (usage, _memory_properties) = conv::map_buffer_usage(desc.usage);
let rendy_usage = {
use resource::BufferUsage as Bu;
use rendy_memory::MemoryUsageValue as Muv;
if (Bu::MAP_WRITE | Bu::TRANSFER_SRC).contains(desc.usage) {
Muv::Upload
} else if (Bu::MAP_READ | Bu::TRANSFER_DST).contains(desc.usage) {
Muv::Download
} else if !desc.usage.contains(Bu::MAP_READ | Bu::MAP_WRITE) {
Muv::Data
} else {
Muv::Dynamic
}
};
let mut buffer = unsafe { device.raw.create_buffer(desc.size, usage).unwrap() };
let requirements = unsafe { device.raw.get_buffer_requirements(&buffer) };
let device_type = device
.mem_props
.memory_types
.iter()
.enumerate()
.position(|(id, memory_type)| {
requirements.type_mask & (1 << id) != 0
&& memory_type.properties.contains(memory_properties)
})
.unwrap()
.into();
// TODO: allocate with rendy
let memory = device.mem_allocator
.lock()
.allocate(
&device.raw,
requirements.type_mask as u32,
rendy_usage,
requirements.size,
requirements.alignment,
)
.unwrap();
// if the memory is mapped but not coherent, round up to the atom size
let mut mem_size = requirements.size;
if memory_properties.contains(hal::memory::Properties::CPU_VISIBLE)
&& !memory_properties.contains(hal::memory::Properties::COHERENT)
{
let mask = device.limits.non_coherent_atom_size as u64 - 1;
mem_size = ((mem_size - 1) | mask) + 1;
}
let memory = unsafe { device.raw.allocate_memory(device_type, mem_size).unwrap() };
unsafe {
device
.raw
.bind_buffer_memory(&memory, 0, &mut buffer)
device.raw
.bind_buffer_memory(memory.memory(), memory.range().start, &mut buffer)
.unwrap()
};
@ -567,7 +567,6 @@ pub fn device_create_buffer(
value: device_id,
ref_count: device.life_guard.ref_count.clone(),
},
memory_properties,
memory,
size: desc.size,
mapped_write_ranges: Vec::new(),
@ -617,13 +616,11 @@ pub extern "C" fn wgpu_device_create_buffer_mapped(
{
let device_guard = HUB.devices.read();
let device = &device_guard[device_id];
let range = 0 .. desc.size;
match map_buffer(
&device.raw,
&device.limits,
&mut buffer,
&range,
0 .. desc.size,
HostMap::Write,
) {
Ok(ptr) => unsafe {
@ -678,31 +675,21 @@ pub fn device_create_texture(
}
.unwrap();
let requirements = unsafe { device.raw.get_image_requirements(&image) };
let device_type = device
.mem_props
.memory_types
.iter()
.enumerate()
.position(|(id, memory_type)| {
// TODO
requirements.type_mask & (1 << id) != 0
&& memory_type
.properties
.contains(hal::memory::Properties::DEVICE_LOCAL)
})
.unwrap()
.into();
// TODO: allocate with rendy
let memory = unsafe {
device
.raw
.allocate_memory(device_type, requirements.size)
.unwrap()
};
let memory = device.mem_allocator
.lock()
.allocate(
&device.raw,
requirements.type_mask as u32,
rendy_memory::Data,
requirements.size,
requirements.alignment,
)
.unwrap();
unsafe {
device
.raw
.bind_image_memory(&memory, 0, &mut image)
device.raw
.bind_image_memory(memory.memory(), memory.range().start, &mut image)
.unwrap()
};
@ -1940,12 +1927,12 @@ pub extern "C" fn wgpu_buffer_unmap(buffer_id: BufferId) {
buffer
.mapped_write_ranges
.iter()
.map(|r| (&buffer.memory, r.clone())),
.map(|r| (buffer.memory.memory(), r.clone())),
)
.unwrap()
}; // TODO
};
buffer.mapped_write_ranges.clear();
}
unsafe { device_raw.unmap_memory(&buffer.memory) };
buffer.memory.unmap(device_raw);
}

View File

@ -14,6 +14,7 @@ use crate::{
use bitflags::bitflags;
use hal;
use parking_lot::Mutex;
use rendy_memory::MemoryBlock;
use std::borrow::Borrow;
@ -60,8 +61,7 @@ unsafe impl Sync for BufferMapOperation {}
pub struct Buffer<B: hal::Backend> {
pub(crate) raw: B::Buffer,
pub(crate) device_id: Stored<DeviceId>,
pub(crate) memory_properties: hal::memory::Properties,
pub(crate) memory: B::Memory,
pub(crate) memory: MemoryBlock<B>,
pub(crate) size: BufferAddress,
pub(crate) mapped_write_ranges: Vec<std::ops::Range<u64>>,
pub(crate) pending_map_operation: Option<BufferMapOperation>,
@ -179,7 +179,7 @@ pub struct TextureDescriptor {
pub(crate) enum TexturePlacement<B: hal::Backend> {
#[cfg_attr(feature = "remote", allow(unused))]
SwapChain(SwapChainLink<Mutex<SwapImageEpoch>>),
Memory(B::Memory),
Memory(MemoryBlock<B>),
Void,
}