Add Eq and Hash implementations to types used in draw calls (#1314)

* Add Eq and Hash implementations to various buffer and image types

* Changelog entry

* Add Eq and Hash to graphics pipelines too

* Changelog entry

* Remove Eq and Hash from dyn GraphicsPipelineAbstract, as the device cannot be checked

* Add Eq and Hash to GraphicsPipelineAbstract, include size in buffer equality

* Add Eq and Hash to descriptor sets

* Changelog entry

* Add Eq and Hash to Instance, check for it in Device
This commit is contained in:
Rua 2020-02-01 22:33:17 +01:00 committed by GitHub
parent c620aefd29
commit a1176227f7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
20 changed files with 584 additions and 8 deletions

View File

@ -18,6 +18,12 @@
- `Swapchain::acquire_next_image()`` now returns ``(image_id, suboptimal, aquire_future)`` - `Swapchain::acquire_next_image()`` now returns ``(image_id, suboptimal, aquire_future)``
+ *suboptimal indicates that the swapchain is usable, but should be recreated* + *suboptimal indicates that the swapchain is usable, but should be recreated*
- Fixed Join Future implementation to not submit joined command buffers twice. - Fixed Join Future implementation to not submit joined command buffers twice.
- The traits `GraphicsPipelineAbstract` and `DescriptorSet` now require `DeviceOwned`.
- Added `PartialEq`, `Eq` and `Hash` implementations to all types involved in a draw call, including:
- `Instance`, `Device`, `GraphicsPipeline` and `dyn GraphicsPipelineAbstract`
- `UnsafeBuffer` and all types implementing `BufferAccess`
- `UnsafeImage`, `UnsafeImageView` and all types implementing `ImageAccess` or `ImageViewAccess`
- All types implementing `DescriptorSet`
# Version 0.16.0 (2019-11-01) # Version 0.16.0 (2019-11-01)

View File

@ -19,6 +19,8 @@
use smallvec::SmallVec; use smallvec::SmallVec;
use std::error; use std::error;
use std::fmt; use std::fmt;
use std::hash::Hash;
use std::hash::Hasher;
use std::iter; use std::iter;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
@ -458,6 +460,30 @@ unsafe impl<T: ?Sized, A> DeviceOwned for CpuAccessibleBuffer<T, A> {
} }
} }
impl<T: ?Sized, A> PartialEq for CpuAccessibleBuffer<T, A>
where T: 'static + Send + Sync
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner() == other.inner() && self.size() == other.size()
}
}
impl<T: ?Sized, A> Eq for CpuAccessibleBuffer<T, A>
where T: 'static + Send + Sync
{}
impl<T: ?Sized, A> Hash for CpuAccessibleBuffer<T, A>
where T: 'static + Send + Sync
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().hash(state);
self.size().hash(state);
}
}
/// Object that can be used to read or write the content of a `CpuAccessibleBuffer`. /// Object that can be used to read or write the content of a `CpuAccessibleBuffer`.
/// ///
/// Note that this object holds a rwlock read guard on the chunk. If another thread tries to access /// Note that this object holds a rwlock read guard on the chunk. If another thread tries to access

View File

@ -8,6 +8,8 @@
// according to those terms. // according to those terms.
use std::cmp; use std::cmp;
use std::hash::Hash;
use std::hash::Hasher;
use std::iter; use std::iter;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
@ -721,6 +723,29 @@ unsafe impl<T, A> DeviceOwned for CpuBufferPoolChunk<T, A>
} }
} }
impl<T, A> PartialEq for CpuBufferPoolChunk<T, A>
where A: MemoryPool
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner() == other.inner() && self.size() == other.size()
}
}
impl<T, A> Eq for CpuBufferPoolChunk<T, A>
where A: MemoryPool
{}
impl<T, A> Hash for CpuBufferPoolChunk<T, A>
where A: MemoryPool
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().hash(state);
self.size().hash(state);
}
}
impl<T, A> Clone for CpuBufferPoolSubbuffer<T, A> impl<T, A> Clone for CpuBufferPoolSubbuffer<T, A>
where A: MemoryPool where A: MemoryPool
{ {
@ -788,6 +813,29 @@ unsafe impl<T, A> DeviceOwned for CpuBufferPoolSubbuffer<T, A>
} }
} }
impl<T, A> PartialEq for CpuBufferPoolSubbuffer<T, A>
where A: MemoryPool
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner() == other.inner() && self.size() == other.size()
}
}
impl<T, A> Eq for CpuBufferPoolSubbuffer<T, A>
where A: MemoryPool
{}
impl<T, A> Hash for CpuBufferPoolSubbuffer<T, A>
where A: MemoryPool
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().hash(state);
self.size().hash(state);
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use buffer::CpuBufferPool; use buffer::CpuBufferPool;

View File

@ -14,6 +14,8 @@
//! write simultaneously, or write and write simultaneously will block with a semaphore. //! write simultaneously, or write and write simultaneously will block with a semaphore.
use smallvec::SmallVec; use smallvec::SmallVec;
use std::hash::Hash;
use std::hash::Hasher;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
use std::sync::Arc; use std::sync::Arc;
@ -284,3 +286,26 @@ unsafe impl<T: ?Sized, A> TypedBufferAccess for DeviceLocalBuffer<T, A>
{ {
type Content = T; type Content = T;
} }
impl<T: ?Sized, A> PartialEq for DeviceLocalBuffer<T, A>
where T: 'static + Send + Sync
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner() == other.inner() && self.size() == other.size()
}
}
impl<T: ?Sized, A> Eq for DeviceLocalBuffer<T, A>
where T: 'static + Send + Sync
{}
impl<T: ?Sized, A> Hash for DeviceLocalBuffer<T, A>
where T: 'static + Send + Sync
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().hash(state);
self.size().hash(state);
}
}

View File

@ -19,6 +19,8 @@
//! //!
use smallvec::SmallVec; use smallvec::SmallVec;
use std::hash::Hash;
use std::hash::Hasher;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
use std::sync::Arc; use std::sync::Arc;
@ -377,6 +379,23 @@ unsafe impl<T: ?Sized, A> DeviceOwned for ImmutableBuffer<T, A> {
} }
} }
impl<T: ?Sized, A> PartialEq for ImmutableBuffer<T, A> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner() == other.inner() && self.size() == other.size()
}
}
impl<T: ?Sized, A> Eq for ImmutableBuffer<T, A> {}
impl<T: ?Sized, A> Hash for ImmutableBuffer<T, A> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().hash(state);
self.size().hash(state);
}
}
/// Access to the immutable buffer that can be used for the initial upload. /// Access to the immutable buffer that can be used for the initial upload.
//#[derive(Debug)] // TODO: //#[derive(Debug)] // TODO:
pub struct ImmutableBufferInitialization<T: ?Sized, A = PotentialDedicatedAllocation<StdMemoryPoolAlloc>> { pub struct ImmutableBufferInitialization<T: ?Sized, A = PotentialDedicatedAllocation<StdMemoryPoolAlloc>> {
@ -455,6 +474,23 @@ impl<T: ?Sized, A> Clone for ImmutableBufferInitialization<T, A> {
} }
} }
impl<T: ?Sized, A> PartialEq for ImmutableBufferInitialization<T, A> {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner() == other.inner() && self.size() == other.size()
}
}
impl<T: ?Sized, A> Eq for ImmutableBufferInitialization<T, A> {}
impl<T: ?Sized, A> Hash for ImmutableBufferInitialization<T, A> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().hash(state);
self.size().hash(state);
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use buffer::BufferUsage; use buffer::BufferUsage;

View File

@ -7,6 +7,8 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
use std::hash::Hash;
use std::hash::Hasher;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
@ -285,6 +287,29 @@ impl<T, B> From<BufferSlice<T, B>> for BufferSlice<[T], B> {
} }
} }
impl<T: ?Sized, B> PartialEq for BufferSlice<T, B>
where B: BufferAccess
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner() == other.inner() && self.size() == other.size()
}
}
impl<T: ?Sized, B> Eq for BufferSlice<T, B>
where B: BufferAccess
{}
impl<T: ?Sized, B> Hash for BufferSlice<T, B>
where B: BufferAccess
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().hash(state);
self.size().hash(state);
}
}
/// Takes a `BufferSlice` that points to a struct, and returns a `BufferSlice` that points to /// Takes a `BufferSlice` that points to a struct, and returns a `BufferSlice` that points to
/// a specific field of that struct. /// a specific field of that struct.
#[macro_export] #[macro_export]

View File

@ -27,6 +27,8 @@
use smallvec::SmallVec; use smallvec::SmallVec;
use std::error; use std::error;
use std::fmt; use std::fmt;
use std::hash::Hash;
use std::hash::Hasher;
use std::mem; use std::mem;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::ptr; use std::ptr;
@ -338,6 +340,23 @@ impl Drop for UnsafeBuffer {
} }
} }
impl PartialEq for UnsafeBuffer {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.buffer == other.buffer && self.device == other.device
}
}
impl Eq for UnsafeBuffer {}
impl Hash for UnsafeBuffer {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.buffer.hash(state);
self.device.hash(state);
}
}
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct SparseLevel { pub struct SparseLevel {
pub sparse: bool, pub sparse: bool,

View File

@ -8,6 +8,8 @@
// according to those terms. // according to those terms.
use std::ops::Range; use std::ops::Range;
use std::hash::Hash;
use std::hash::Hasher;
use buffer::BufferSlice; use buffer::BufferSlice;
use buffer::sys::UnsafeBuffer; use buffer::sys::UnsafeBuffer;
@ -139,7 +141,7 @@ pub unsafe trait BufferAccess: DeviceOwned {
} }
/// Inner information about a buffer. /// Inner information about a buffer.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct BufferInner<'a> { pub struct BufferInner<'a> {
/// The underlying buffer object. /// The underlying buffer object.
pub buffer: &'a UnsafeBuffer, pub buffer: &'a UnsafeBuffer,
@ -213,3 +215,20 @@ unsafe impl<T> TypedBufferAccess for T
{ {
type Content = <T::Target as TypedBufferAccess>::Content; type Content = <T::Target as TypedBufferAccess>::Content;
} }
impl PartialEq for dyn BufferAccess {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner() == other.inner() && self.size() == other.size()
}
}
impl Eq for dyn BufferAccess {}
impl Hash for dyn BufferAccess {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().hash(state);
self.size().hash(state);
}
}

View File

@ -8,9 +8,12 @@
// according to those terms. // according to those terms.
use crossbeam::queue::SegQueue; use crossbeam::queue::SegQueue;
use std::hash::Hash;
use std::hash::Hasher;
use std::sync::Arc; use std::sync::Arc;
use OomError; use OomError;
use VulkanObject;
use buffer::BufferAccess; use buffer::BufferAccess;
use buffer::BufferViewRef; use buffer::BufferViewRef;
use descriptor::descriptor::DescriptorDesc; use descriptor::descriptor::DescriptorDesc;
@ -141,8 +144,7 @@ unsafe impl<R> DescriptorSet for FixedSizeDescriptorSet<R>
} }
} }
unsafe impl<R> DescriptorSetDesc for FixedSizeDescriptorSet<R> unsafe impl<R> DescriptorSetDesc for FixedSizeDescriptorSet<R> {
{
#[inline] #[inline]
fn num_bindings(&self) -> usize { fn num_bindings(&self) -> usize {
self.inner.num_bindings() self.inner.num_bindings()
@ -154,14 +156,37 @@ unsafe impl<R> DescriptorSetDesc for FixedSizeDescriptorSet<R>
} }
} }
unsafe impl<R> DeviceOwned for FixedSizeDescriptorSet<R> unsafe impl<R> DeviceOwned for FixedSizeDescriptorSet<R> {
{
#[inline] #[inline]
fn device(&self) -> &Arc<Device> { fn device(&self) -> &Arc<Device> {
self.inner.device() self.inner.device()
} }
} }
impl<R> PartialEq for FixedSizeDescriptorSet<R>
where R: PersistentDescriptorSetResources
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner().internal_object() == other.inner().internal_object() &&
self.device() == other.device()
}
}
impl<R> Eq for FixedSizeDescriptorSet<R>
where R: PersistentDescriptorSetResources
{}
impl<R> Hash for FixedSizeDescriptorSet<R>
where R: PersistentDescriptorSetResources
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().internal_object().hash(state);
self.device().hash(state);
}
}
// The fields of this struct can be considered as fields of the `FixedSizeDescriptorSet`. They are // The fields of this struct can be considered as fields of the `FixedSizeDescriptorSet`. They are
// in a separate struct because we don't want to expose the fact that we implement the // in a separate struct because we don't want to expose the fact that we implement the
// `DescriptorPool` trait. // `DescriptorPool` trait.

View File

@ -35,8 +35,13 @@
//! - The `DescriptorSetsCollection` trait is implemented on collections of types that implement //! - The `DescriptorSetsCollection` trait is implemented on collections of types that implement
//! `DescriptorSet`. It is what you pass to the draw functions. //! `DescriptorSet`. It is what you pass to the draw functions.
use std::hash::Hash;
use std::hash::Hasher;
use SafeDeref; use SafeDeref;
use VulkanObject;
use buffer::BufferAccess; use buffer::BufferAccess;
use device::DeviceOwned;
use descriptor::descriptor::DescriptorDesc; use descriptor::descriptor::DescriptorDesc;
use image::ImageViewAccess; use image::ImageViewAccess;
@ -77,7 +82,7 @@ mod unsafe_layout;
/// Trait for objects that contain a collection of resources that will be accessible by shaders. /// Trait for objects that contain a collection of resources that will be accessible by shaders.
/// ///
/// Objects of this type can be passed when submitting a draw command. /// Objects of this type can be passed when submitting a draw command.
pub unsafe trait DescriptorSet: DescriptorSetDesc { pub unsafe trait DescriptorSet: DescriptorSetDesc + DeviceOwned {
/// Returns the inner `UnsafeDescriptorSet`. /// Returns the inner `UnsafeDescriptorSet`.
fn inner(&self) -> &UnsafeDescriptorSet; fn inner(&self) -> &UnsafeDescriptorSet;
@ -130,6 +135,24 @@ unsafe impl<T> DescriptorSet for T
} }
} }
impl PartialEq for dyn DescriptorSet {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner().internal_object() == other.inner().internal_object() &&
self.device() == other.device()
}
}
impl Eq for dyn DescriptorSet {}
impl Hash for dyn DescriptorSet {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().internal_object().hash(state);
self.device().hash(state);
}
}
/// Trait for objects that describe the layout of the descriptors of a set. /// Trait for objects that describe the layout of the descriptors of a set.
pub unsafe trait DescriptorSetDesc { pub unsafe trait DescriptorSetDesc {
/// Returns the number of binding slots in the set. /// Returns the number of binding slots in the set.

View File

@ -9,6 +9,8 @@
use std::error; use std::error;
use std::fmt; use std::fmt;
use std::hash::Hash;
use std::hash::Hasher;
use std::sync::Arc; use std::sync::Arc;
use OomError; use OomError;
@ -130,6 +132,33 @@ unsafe impl<R, P> DeviceOwned for PersistentDescriptorSet<R, P>
} }
} }
impl<R, P> PartialEq for PersistentDescriptorSet<R, P>
where P: DescriptorPoolAlloc,
R: PersistentDescriptorSetResources
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner().internal_object() == other.inner().internal_object() &&
self.device() == other.device()
}
}
impl<R, P> Eq for PersistentDescriptorSet<R, P>
where P: DescriptorPoolAlloc,
R: PersistentDescriptorSetResources
{}
impl<R, P> Hash for PersistentDescriptorSet<R, P>
where P: DescriptorPoolAlloc,
R: PersistentDescriptorSetResources
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().internal_object().hash(state);
self.device().hash(state);
}
}
/// Prototype of a `PersistentDescriptorSet`. /// Prototype of a `PersistentDescriptorSet`.
/// ///
/// The template parameter `R` is an unspecified type that represents the list of resources. /// The template parameter `R` is an unspecified type that represents the list of resources.

View File

@ -96,6 +96,8 @@ use std::collections::hash_map::Entry;
use std::error; use std::error;
use std::fmt; use std::fmt;
use std::hash::BuildHasherDefault; use std::hash::BuildHasherDefault;
use std::hash::Hash;
use std::hash::Hasher;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::ops::Deref; use std::ops::Deref;
use std::ptr; use std::ptr;
@ -539,6 +541,24 @@ impl Drop for Device {
} }
} }
impl PartialEq for Device {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.device == other.device && self.instance == other.instance
}
}
impl Eq for Device {}
impl Hash for Device {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.device.hash(state);
self.instance.hash(state);
}
}
/// Implemented on objects that belong to a Vulkan device. /// Implemented on objects that belong to a Vulkan device.
/// ///
/// # Safety /// # Safety

View File

@ -7,6 +7,8 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
use std::hash::Hash;
use std::hash::Hasher;
use std::iter::Empty; use std::iter::Empty;
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
@ -575,6 +577,28 @@ unsafe impl<F, A> ImageViewAccess for AttachmentImage<F, A>
} }
} }
impl<F, A> PartialEq for AttachmentImage<F, A>
where F: 'static + Send + Sync
{
#[inline]
fn eq(&self, other: &Self) -> bool {
ImageAccess::inner(self) == ImageAccess::inner(other)
}
}
impl<F, A> Eq for AttachmentImage<F, A>
where F: 'static + Send + Sync
{}
impl<F, A> Hash for AttachmentImage<F, A>
where F: 'static + Send + Sync
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
ImageAccess::inner(self).hash(state);
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::AttachmentImage; use super::AttachmentImage;

View File

@ -8,6 +8,8 @@
// according to those terms. // according to those terms.
use smallvec::SmallVec; use smallvec::SmallVec;
use std::hash::Hash;
use std::hash::Hasher;
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
@ -392,6 +394,28 @@ unsafe impl<F: 'static, A> ImageViewAccess for ImmutableImage<F, A>
} }
} }
impl<F, A> PartialEq for ImmutableImage<F, A>
where F: 'static + Send + Sync
{
#[inline]
fn eq(&self, other: &Self) -> bool {
ImageAccess::inner(self) == ImageAccess::inner(other)
}
}
impl<F, A> Eq for ImmutableImage<F, A>
where F: 'static + Send + Sync
{}
impl<F, A> Hash for ImmutableImage<F, A>
where F: 'static + Send + Sync
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
ImageAccess::inner(self).hash(state);
}
}
unsafe impl<F, A> ImageAccess for ImmutableImageInitialization<F, A> unsafe impl<F, A> ImageAccess for ImmutableImageInitialization<F, A>
where F: 'static + Send + Sync where F: 'static + Send + Sync
{ {
@ -457,3 +481,25 @@ unsafe impl<F, A> ImageAccess for ImmutableImageInitialization<F, A>
self.image.initialized.store(true, Ordering::Relaxed); self.image.initialized.store(true, Ordering::Relaxed);
} }
} }
impl<F, A> PartialEq for ImmutableImageInitialization<F, A>
where F: 'static + Send + Sync
{
#[inline]
fn eq(&self, other: &Self) -> bool {
ImageAccess::inner(self) == ImageAccess::inner(other)
}
}
impl<F, A> Eq for ImmutableImageInitialization<F, A>
where F: 'static + Send + Sync
{}
impl<F, A> Hash for ImmutableImageInitialization<F, A>
where F: 'static + Send + Sync
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
ImageAccess::inner(self).hash(state);
}
}

View File

@ -8,6 +8,8 @@
// according to those terms. // according to those terms.
use smallvec::SmallVec; use smallvec::SmallVec;
use std::hash::Hash;
use std::hash::Hasher;
use std::sync::Arc; use std::sync::Arc;
use std::sync::atomic::AtomicUsize; use std::sync::atomic::AtomicUsize;
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
@ -308,6 +310,31 @@ unsafe impl<F, A> ImageViewAccess for StorageImage<F, A>
} }
} }
impl<F, A> PartialEq for StorageImage<F, A>
where F: 'static + Send + Sync,
A: MemoryPool
{
#[inline]
fn eq(&self, other: &Self) -> bool {
ImageAccess::inner(self) == ImageAccess::inner(other)
}
}
impl<F, A> Eq for StorageImage<F, A>
where F: 'static + Send + Sync,
A: MemoryPool
{}
impl<F, A> Hash for StorageImage<F, A>
where F: 'static + Send + Sync,
A: MemoryPool
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
ImageAccess::inner(self).hash(state);
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::StorageImage; use super::StorageImage;

View File

@ -7,6 +7,8 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
use std::hash::Hash;
use std::hash::Hasher;
use std::sync::Arc; use std::sync::Arc;
use buffer::BufferAccess; use buffer::BufferAccess;
@ -210,3 +212,19 @@ unsafe impl<W> ImageViewAccess for SwapchainImage<W> {
true true
} }
} }
impl<W> PartialEq for SwapchainImage<W> {
#[inline]
fn eq(&self, other: &Self) -> bool {
ImageAccess::inner(self) == ImageAccess::inner(other)
}
}
impl<W> Eq for SwapchainImage<W> {}
impl<W> Hash for SwapchainImage<W> {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
ImageAccess::inner(self).hash(state);
}
}

View File

@ -16,6 +16,8 @@
use smallvec::SmallVec; use smallvec::SmallVec;
use std::error; use std::error;
use std::fmt; use std::fmt;
use std::hash::Hash;
use std::hash::Hasher;
use std::mem; use std::mem;
use std::mem::MaybeUninit; use std::mem::MaybeUninit;
use std::ops::Range; use std::ops::Range;
@ -827,6 +829,23 @@ impl Drop for UnsafeImage {
} }
} }
impl PartialEq for UnsafeImage {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.image == other.image && self.device == other.device
}
}
impl Eq for UnsafeImage {}
impl Hash for UnsafeImage {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.image.hash(state);
self.device.hash(state);
}
}
/// Error that can happen when creating an instance. /// Error that can happen when creating an instance.
#[derive(Clone, Debug, PartialEq, Eq)] #[derive(Clone, Debug, PartialEq, Eq)]
pub enum ImageCreationError { pub enum ImageCreationError {
@ -1123,6 +1142,23 @@ impl Drop for UnsafeImageView {
} }
} }
impl PartialEq for UnsafeImageView {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.view == other.view && self.device == other.device
}
}
impl Eq for UnsafeImageView {}
impl Hash for UnsafeImageView {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.view.hash(state);
self.device.hash(state);
}
}
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use std::iter::Empty; use std::iter::Empty;

View File

@ -7,6 +7,9 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
use std::hash::Hash;
use std::hash::Hasher;
use buffer::BufferAccess; use buffer::BufferAccess;
use format::ClearValue; use format::ClearValue;
use format::Format; use format::Format;
@ -232,7 +235,7 @@ pub unsafe trait ImageAccess {
} }
/// Inner information about an image. /// Inner information about an image.
#[derive(Copy, Clone, Debug)] #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct ImageInner<'a> { pub struct ImageInner<'a> {
/// The underlying image object. /// The underlying image object.
pub image: &'a UnsafeImage, pub image: &'a UnsafeImage,
@ -311,6 +314,22 @@ unsafe impl<T> ImageAccess for T
} }
} }
impl PartialEq for dyn ImageAccess {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner() == other.inner()
}
}
impl Eq for dyn ImageAccess {}
impl Hash for dyn ImageAccess {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().hash(state);
}
}
/// Wraps around an object that implements `ImageAccess` and modifies the initial layout /// Wraps around an object that implements `ImageAccess` and modifies the initial layout
/// requirement to be either `Undefined` or `Preinitialized`. /// requirement to be either `Undefined` or `Preinitialized`.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
@ -373,6 +392,28 @@ unsafe impl<I> ImageAccess for ImageAccessFromUndefinedLayout<I>
} }
} }
impl<I> PartialEq for ImageAccessFromUndefinedLayout<I>
where I: ImageAccess
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner() == other.inner()
}
}
impl<I> Eq for ImageAccessFromUndefinedLayout<I>
where I: ImageAccess
{}
impl<I> Hash for ImageAccessFromUndefinedLayout<I>
where I: ImageAccess
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().hash(state);
}
}
/// Extension trait for images. Checks whether the value `T` can be used as a clear value for the /// Extension trait for images. Checks whether the value `T` can be used as a clear value for the
/// given image. /// given image.
// TODO: isn't that for image views instead? // TODO: isn't that for image views instead?
@ -481,6 +522,22 @@ unsafe impl<T> ImageViewAccess for T
} }
} }
impl PartialEq for dyn ImageViewAccess {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner() == other.inner()
}
}
impl Eq for dyn ImageViewAccess {}
impl Hash for dyn ImageViewAccess {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner().hash(state);
}
}
pub unsafe trait AttachmentImageView: ImageViewAccess { pub unsafe trait AttachmentImageView: ImageViewAccess {
fn accept(&self, initial_layout: ImageLayout, final_layout: ImageLayout) -> bool; fn accept(&self, initial_layout: ImageLayout, final_layout: ImageLayout) -> bool;
} }

View File

@ -13,6 +13,8 @@ use std::error;
use std::ffi::CStr; use std::ffi::CStr;
use std::ffi::CString; use std::ffi::CString;
use std::fmt; use std::fmt;
use std::hash::Hash;
use std::hash::Hasher;
use std::mem; use std::mem;
use std::ops::Deref; use std::ops::Deref;
use std::ptr; use std::ptr;
@ -496,6 +498,22 @@ impl Drop for Instance {
} }
} }
impl PartialEq for Instance {
#[inline]
fn eq(&self, other: &Self) -> bool {
self.instance == other.instance
}
}
impl Eq for Instance {}
impl Hash for Instance {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.instance.hash(state);
}
}
// Same as Cow but less annoying. // Same as Cow but less annoying.
enum OwnedOrRef<T: 'static> { enum OwnedOrRef<T: 'static> {
Owned(T), Owned(T),

View File

@ -8,6 +8,8 @@
// according to those terms. // according to those terms.
use std::fmt; use std::fmt;
use std::hash::Hash;
use std::hash::Hasher;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ptr; use std::ptr;
use std::sync::Arc; use std::sync::Arc;
@ -74,6 +76,7 @@ pub struct GraphicsPipeline<VertexDefinition, Layout, RenderP> {
num_viewports: u32, num_viewports: u32,
} }
#[derive(PartialEq, Eq, Hash)]
struct Inner { struct Inner {
pipeline: vk::Pipeline, pipeline: vk::Pipeline,
device: Arc<Device>, device: Arc<Device>,
@ -324,7 +327,7 @@ impl Drop for Inner {
/// object. /// object.
/// When using this trait `AutoCommandBufferBuilder::draw*` calls will need the buffers to be /// When using this trait `AutoCommandBufferBuilder::draw*` calls will need the buffers to be
/// wrapped in a `vec!()`. /// wrapped in a `vec!()`.
pub unsafe trait GraphicsPipelineAbstract: PipelineLayoutAbstract + RenderPassAbstract + VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>> { pub unsafe trait GraphicsPipelineAbstract: PipelineLayoutAbstract + RenderPassAbstract + VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>> + DeviceOwned {
/// Returns an opaque object that represents the inside of the graphics pipeline. /// Returns an opaque object that represents the inside of the graphics pipeline.
fn inner(&self) -> GraphicsPipelineSys; fn inner(&self) -> GraphicsPipelineSys;
@ -474,6 +477,52 @@ unsafe impl<T> GraphicsPipelineAbstract for T
} }
} }
impl<Mv, L, Rp> PartialEq for GraphicsPipeline<Mv, L, Rp>
where L: PipelineLayoutAbstract,
Rp: RenderPassAbstract,
Mv: VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>>
{
#[inline]
fn eq(&self, other: &Self) -> bool {
self.inner == other.inner
}
}
impl<Mv, L, Rp> Eq for GraphicsPipeline<Mv, L, Rp>
where L: PipelineLayoutAbstract,
Rp: RenderPassAbstract,
Mv: VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>>
{}
impl<Mv, L, Rp> Hash for GraphicsPipeline<Mv, L, Rp>
where L: PipelineLayoutAbstract,
Rp: RenderPassAbstract,
Mv: VertexSource<Vec<Arc<dyn BufferAccess + Send + Sync>>>
{
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner.hash(state);
}
}
impl PartialEq for dyn GraphicsPipelineAbstract {
#[inline]
fn eq(&self, other: &Self) -> bool {
GraphicsPipelineAbstract::inner(self).0 == GraphicsPipelineAbstract::inner(other).0 &&
DeviceOwned::device(self) == DeviceOwned::device(other)
}
}
impl Eq for dyn GraphicsPipelineAbstract {}
impl Hash for dyn GraphicsPipelineAbstract {
#[inline]
fn hash<H: Hasher>(&self, state: &mut H) {
GraphicsPipelineAbstract::inner(self).0.hash(state);
DeviceOwned::device(self).hash(state);
}
}
/// Opaque object that represents the inside of the graphics pipeline. /// Opaque object that represents the inside of the graphics pipeline.
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct GraphicsPipelineSys<'a>(vk::Pipeline, PhantomData<&'a ()>); pub struct GraphicsPipelineSys<'a>(vk::Pipeline, PhantomData<&'a ()>);