1use std::sync::Arc;
2
3use raw_window_handle::{HasDisplayHandle, HasWindowHandle};
4
5use crate::{
6 GpuSamplerSet, GraphicsApiInitSettings,
7 bitflags::BufferFlags,
8 buffer::Buffer,
9 debug::{error, fmt_size, log, setup_startup_time},
10 errors::{GraphicsError, GraphicsResult},
11 layout::Layout,
12 mesh::{AttributeDescriptor, Mesh},
13 object::Object,
14 proxies::*,
15 render_target::RenderTarget,
16 texture::Texture,
17 vulkan::VulkanEntry,
18};
19
20pub struct Device {
22 inner: Box<dyn DeviceProxy>,
23}
24
25impl Device {
26 pub fn compute() -> GraphicsResult<Self> {
28 setup_startup_time();
29 log!("creating compute device");
30 Ok(Self {
31 inner: VulkanEntry::no_presentation()?,
32 })
33 }
34
35 pub fn graphics<T: HasWindowHandle + HasDisplayHandle>(
37 settings: &GraphicsApiInitSettings,
38 window: &T,
39 ) -> GraphicsResult<Self> {
40 setup_startup_time();
41 log!("creating graphics device");
42 Ok(Self {
43 inner: VulkanEntry::with_presentation(settings, window)?,
44 })
45 }
46
47 pub fn dispatch_and_present(&self, objects: &[Arc<Object>]) -> GraphicsResult<()> {
49 self.inner.dispatch_and_present(objects)
50 }
51
52 pub fn dispatch_compute(&self, objects: &[Arc<Object>]) -> GraphicsResult<()> {
54 self.inner.dispatch_compute(objects)
55 }
56
57 pub fn resize_resources(&self, width: u32, height: u32) -> GraphicsResult<()> {
59 self.inner.resize_resources(width, height)
60 }
61
62 pub fn get_presentation_render_target(&self) -> Option<RenderTarget> {
64 self.inner
65 .get_presentation_render_target()
66 .map(RenderTarget::new)
67 }
68
69 pub fn create_layout(
71 &self,
72 double_buffering: bool,
73 texture_num: usize,
74 sampler_num: usize,
75 uniform_num: usize,
76 storage_num: usize,
77 ) -> GraphicsResult<Layout> {
78 if (sampler_num == 0 && texture_num == 0) == (sampler_num > 0 && texture_num > 0) {
79 error!("textures cannot exist without samplers");
80 return Err(GraphicsError::DataError);
81 }
82
83 if !(uniform_num > 0 || storage_num > 0) {
84 error!("cannot create layout without buffers (WARN vulkan specific, todo fix)");
85 return Err(GraphicsError::DataError);
86 } log!("creating layout [ double_buffering: {} ]", double_buffering);
89
90 Ok(Layout::new(self.inner.create_layout(
91 double_buffering,
92 texture_num,
93 sampler_num,
94 uniform_num,
95 storage_num,
96 )?))
97 }
98
99 pub fn create_buffer<T>(&self, len: u64, flags: BufferFlags) -> GraphicsResult<Buffer<T>> {
101 let size = len * size_of::<T>() as u64;
102
103 log!(
104 "creating buffer [ size: {} bits: {:?} ]",
105 fmt_size!(size),
106 flags
107 );
108
109 let uniform = !(flags & BufferFlags::UNIFORM).is_none();
110 let transfer = !(flags & BufferFlags::TRANSFER).is_none();
111 let enable_sync = !(flags & BufferFlags::SYNCED).is_none();
112
113 Ok(Buffer::new(self.inner.create_buffer(
114 size,
115 uniform,
116 transfer,
117 enable_sync,
118 )?))
119 }
120
121 pub fn create_buffer_mesh<V: AttributeDescriptor, I>(
123 &self,
124 mesh: &Mesh<V, I>,
125 ) -> GraphicsResult<crate::mesh::MeshBuffer<V, I>> {
126 log!("creating mesh [ size: {} ] ", {
127 let size = mesh.size();
128 fmt_size!(size)
129 });
130
131 let vertices = unsafe {
132 std::slice::from_raw_parts(
133 mesh.vertices.as_ptr() as *const u8,
134 mesh.vertices.len() * size_of::<V>(),
135 )
136 };
137 let indices = unsafe {
138 std::slice::from_raw_parts(
139 mesh.indices.as_ptr() as *const u8,
140 mesh.indices.len() * size_of::<I>(),
141 )
142 };
143 let buffer_mesh = self
144 .inner
145 .create_buffer_mesh(vertices, indices, size_of::<I>())?;
146
147 Ok(crate::mesh::MeshBuffer::new(buffer_mesh))
148 }
149
150 pub fn create_sampler_set(
152 &self,
153 textures: &[(u32, &Texture)],
154 layouts: &[&Layout],
155 ) -> GraphicsResult<Arc<GpuSamplerSet>> {
156 log!(
157 "creating sampler [ bindings: {:?} ]",
158 textures
159 .iter()
160 .map(|(binding, _)| *binding)
161 .collect::<Vec<_>>()
162 );
163
164 self.inner.create_sampler_set(
165 &textures
166 .iter()
167 .map(|(b, texture)| (*b, texture.inner.clone()))
168 .collect::<Vec<(u32, Arc<dyn TextureProxy>)>>(),
169 &layouts
170 .iter()
171 .map(|layout| layout.inner.clone())
172 .collect::<Vec<Arc<dyn LayoutProxy>>>(),
173 )
174 }
175
176 pub fn create_texture(
178 &self,
179 buffer: &Buffer<u8>,
180 extent: [u32; 2],
181 anisotropy_texels: f32,
182 ) -> GraphicsResult<Texture> {
183 let size = buffer.len();
184 log!(
185 "creating texture [ size: {} extent: {}x{} ]",
186 fmt_size!(size),
187 extent[0],
188 extent[1]
189 );
190 Ok(Texture::new(self.inner.create_texture(
191 buffer.inner.clone(),
192 extent,
193 anisotropy_texels,
194 )?))
195 }
196
197 pub fn get_delta_time(&self) -> std::time::Duration {
199 self.inner.get_delta_time()
200 }
201}