ensure CpuBufferPoolChunk::conflict_key is unique (#995)

This commit is contained in:
Lucas Kent 2018-08-08 01:18:26 +10:00 committed by Pierre Krieger
parent 257994c7e8
commit ab59ca7461
7 changed files with 23 additions and 17 deletions

View File

@ -328,8 +328,8 @@ unsafe impl<T: ?Sized, A> BufferAccess for CpuAccessibleBuffer<T, A>
} }
#[inline] #[inline]
fn conflict_key(&self) -> u64 { fn conflict_key(&self) -> (u64, usize) {
self.inner.key() (self.inner.key(), 0)
} }
#[inline] #[inline]

View File

@ -618,8 +618,12 @@ unsafe impl<T, A> BufferAccess for CpuBufferPoolChunk<T, A>
} }
#[inline] #[inline]
fn conflict_key(&self) -> u64 { fn conflict_key(&self) -> (u64, usize) {
self.buffer.inner.key() + self.index as u64 (
self.buffer.inner.key(),
// ensure the special cased empty buffers dont collide with a regular buffer starting at 0
if self.requested_len == 0 { usize::max_value() } else { self.index }
)
} }
#[inline] #[inline]
@ -749,7 +753,7 @@ unsafe impl<T, A> BufferAccess for CpuBufferPoolSubbuffer<T, A>
} }
#[inline] #[inline]
fn conflict_key(&self) -> u64 { fn conflict_key(&self) -> (u64, usize) {
self.chunk.conflict_key() self.chunk.conflict_key()
} }

View File

@ -206,8 +206,8 @@ unsafe impl<T: ?Sized, A> BufferAccess for DeviceLocalBuffer<T, A>
} }
#[inline] #[inline]
fn conflict_key(&self) -> u64 { fn conflict_key(&self) -> (u64, usize) {
self.inner.key() (self.inner.key(), 0)
} }
#[inline] #[inline]

View File

@ -338,8 +338,8 @@ unsafe impl<T: ?Sized, A> BufferAccess for ImmutableBuffer<T, A> {
} }
#[inline] #[inline]
fn conflict_key(&self) -> u64 { fn conflict_key(&self) -> (u64, usize) {
self.inner.key() (self.inner.key(), 0)
} }
#[inline] #[inline]
@ -404,8 +404,8 @@ unsafe impl<T: ?Sized, A> BufferAccess for ImmutableBufferInitialization<T, A> {
} }
#[inline] #[inline]
fn conflict_key(&self) -> u64 { fn conflict_key(&self) -> (u64, usize) {
self.buffer.inner.key() (self.buffer.inner.key(), 0)
} }
#[inline] #[inline]

View File

@ -205,7 +205,7 @@ unsafe impl<T: ?Sized, B> BufferAccess for BufferSlice<T, B>
} }
#[inline] #[inline]
fn conflict_key(&self) -> u64 { fn conflict_key(&self) -> (u64, usize) {
self.resource.conflict_key() self.resource.conflict_key()
} }

View File

@ -108,7 +108,7 @@ pub unsafe trait BufferAccess: DeviceOwned {
/// Since it is possible to accidentally return the same key for memory ranges that don't /// Since it is possible to accidentally return the same key for memory ranges that don't
/// overlap, the `conflicts_buffer` or `conflicts_image` function should always be called to /// overlap, the `conflicts_buffer` or `conflicts_image` function should always be called to
/// verify whether they actually overlap. /// verify whether they actually overlap.
fn conflict_key(&self) -> u64; fn conflict_key(&self) -> (u64, usize);
/// Locks the resource for usage on the GPU. Returns an error if the lock can't be acquired. /// Locks the resource for usage on the GPU. Returns an error if the lock can't be acquired.
/// ///
@ -173,7 +173,7 @@ unsafe impl<T> BufferAccess for T
} }
#[inline] #[inline]
fn conflict_key(&self) -> u64 { fn conflict_key(&self) -> (u64, usize) {
(**self).conflict_key() (**self).conflict_key()
} }

View File

@ -318,13 +318,13 @@ impl<P> Hash for BuilderKey<P> {
match self.resource_ty { match self.resource_ty {
KeyTy::Buffer => { KeyTy::Buffer => {
let c = &commands_lock.commands[self.command_id]; let c = &commands_lock.commands[self.command_id];
c.buffer(self.resource_index).conflict_key() c.buffer(self.resource_index).conflict_key().hash(state)
}, },
KeyTy::Image => { KeyTy::Image => {
let c = &commands_lock.commands[self.command_id]; let c = &commands_lock.commands[self.command_id];
c.image(self.resource_index).conflict_key() c.image(self.resource_index).conflict_key().hash(state)
}, },
}.hash(state) }
} }
} }
@ -1064,6 +1064,8 @@ impl<P> SyncCommandBuffer<P> {
let cmd = &commands_lock[command_id]; let cmd = &commands_lock[command_id];
let buf = cmd.buffer(resource_index); let buf = cmd.buffer(resource_index);
// Because try_gpu_lock needs to be called first,
// this should never return Ok without first returning Err
let prev_err = match future.check_buffer_access(&buf, entry.exclusive, queue) { let prev_err = match future.check_buffer_access(&buf, entry.exclusive, queue) {
Ok(_) => { Ok(_) => {
unsafe { unsafe {