bevy_render/renderer/
render_device.rs1use crate::render_resource::{
2 BindGroup, BindGroupLayout, Buffer, ComputePipeline, RawRenderPipelineDescriptor,
3 RenderPipeline, Sampler, Texture,
4};
5use bevy_ecs::system::Resource;
6use wgpu::{
7 util::DeviceExt, BindGroupDescriptor, BindGroupEntry, BindGroupLayoutDescriptor,
8 BindGroupLayoutEntry, BufferAsyncError, BufferBindingType, MaintainResult,
9};
10
11use super::RenderQueue;
12
13use crate::render_resource::resource_macros::*;
14use crate::WgpuWrapper;
15
16render_resource_wrapper!(ErasedRenderDevice, wgpu::Device);
17
18#[derive(Resource, Clone)]
20pub struct RenderDevice {
21 device: WgpuWrapper<ErasedRenderDevice>,
22}
23
24impl From<wgpu::Device> for RenderDevice {
25 fn from(device: wgpu::Device) -> Self {
26 Self {
27 device: WgpuWrapper::new(ErasedRenderDevice::new(device)),
28 }
29 }
30}
31
32impl RenderDevice {
33 #[inline]
37 pub fn features(&self) -> wgpu::Features {
38 self.device.features()
39 }
40
41 #[inline]
45 pub fn limits(&self) -> wgpu::Limits {
46 self.device.limits()
47 }
48
49 #[inline]
51 pub fn create_shader_module(&self, desc: wgpu::ShaderModuleDescriptor) -> wgpu::ShaderModule {
52 self.device.create_shader_module(desc)
53 }
54
55 #[inline]
65 pub fn poll(&self, maintain: wgpu::Maintain) -> MaintainResult {
66 self.device.poll(maintain)
67 }
68
69 #[inline]
71 pub fn create_command_encoder(
72 &self,
73 desc: &wgpu::CommandEncoderDescriptor,
74 ) -> wgpu::CommandEncoder {
75 self.device.create_command_encoder(desc)
76 }
77
78 #[inline]
80 pub fn create_render_bundle_encoder(
81 &self,
82 desc: &wgpu::RenderBundleEncoderDescriptor,
83 ) -> wgpu::RenderBundleEncoder {
84 self.device.create_render_bundle_encoder(desc)
85 }
86
87 #[inline]
89 pub fn create_bind_group<'a>(
90 &self,
91 label: impl Into<wgpu::Label<'a>>,
92 layout: &'a BindGroupLayout,
93 entries: &'a [BindGroupEntry<'a>],
94 ) -> BindGroup {
95 let wgpu_bind_group = self.device.create_bind_group(&BindGroupDescriptor {
96 label: label.into(),
97 layout,
98 entries,
99 });
100 BindGroup::from(wgpu_bind_group)
101 }
102
103 #[inline]
105 pub fn create_bind_group_layout<'a>(
106 &self,
107 label: impl Into<wgpu::Label<'a>>,
108 entries: &'a [BindGroupLayoutEntry],
109 ) -> BindGroupLayout {
110 BindGroupLayout::from(
111 self.device
112 .create_bind_group_layout(&BindGroupLayoutDescriptor {
113 label: label.into(),
114 entries,
115 }),
116 )
117 }
118
119 #[inline]
121 pub fn create_pipeline_layout(
122 &self,
123 desc: &wgpu::PipelineLayoutDescriptor,
124 ) -> wgpu::PipelineLayout {
125 self.device.create_pipeline_layout(desc)
126 }
127
128 #[inline]
130 pub fn create_render_pipeline(&self, desc: &RawRenderPipelineDescriptor) -> RenderPipeline {
131 let wgpu_render_pipeline = self.device.create_render_pipeline(desc);
132 RenderPipeline::from(wgpu_render_pipeline)
133 }
134
135 #[inline]
137 pub fn create_compute_pipeline(
138 &self,
139 desc: &wgpu::ComputePipelineDescriptor,
140 ) -> ComputePipeline {
141 let wgpu_compute_pipeline = self.device.create_compute_pipeline(desc);
142 ComputePipeline::from(wgpu_compute_pipeline)
143 }
144
145 pub fn create_buffer(&self, desc: &wgpu::BufferDescriptor) -> Buffer {
147 let wgpu_buffer = self.device.create_buffer(desc);
148 Buffer::from(wgpu_buffer)
149 }
150
151 pub fn create_buffer_with_data(&self, desc: &wgpu::util::BufferInitDescriptor) -> Buffer {
153 let wgpu_buffer = self.device.create_buffer_init(desc);
154 Buffer::from(wgpu_buffer)
155 }
156
157 pub fn create_texture_with_data(
162 &self,
163 render_queue: &RenderQueue,
164 desc: &wgpu::TextureDescriptor,
165 order: wgpu::util::TextureDataOrder,
166 data: &[u8],
167 ) -> Texture {
168 let wgpu_texture =
169 self.device
170 .create_texture_with_data(render_queue.as_ref(), desc, order, data);
171 Texture::from(wgpu_texture)
172 }
173
174 pub fn create_texture(&self, desc: &wgpu::TextureDescriptor) -> Texture {
178 let wgpu_texture = self.device.create_texture(desc);
179 Texture::from(wgpu_texture)
180 }
181
182 pub fn create_sampler(&self, desc: &wgpu::SamplerDescriptor) -> Sampler {
186 let wgpu_sampler = self.device.create_sampler(desc);
187 Sampler::from(wgpu_sampler)
188 }
189
190 pub fn configure_surface(&self, surface: &wgpu::Surface, config: &wgpu::SurfaceConfiguration) {
197 surface.configure(&self.device, config);
198 }
199
200 pub fn wgpu_device(&self) -> &wgpu::Device {
202 &self.device
203 }
204
205 pub fn map_buffer(
206 &self,
207 buffer: &wgpu::BufferSlice,
208 map_mode: wgpu::MapMode,
209 callback: impl FnOnce(Result<(), BufferAsyncError>) + Send + 'static,
210 ) {
211 buffer.map_async(map_mode, callback);
212 }
213
214 pub fn align_copy_bytes_per_row(row_bytes: usize) -> usize {
215 let align = wgpu::COPY_BYTES_PER_ROW_ALIGNMENT as usize;
216 let padded_bytes_per_row_padding = (align - row_bytes % align) % align;
217 row_bytes + padded_bytes_per_row_padding
218 }
219
220 pub fn get_supported_read_only_binding_type(
221 &self,
222 buffers_per_shader_stage: u32,
223 ) -> BufferBindingType {
224 if self.limits().max_storage_buffers_per_shader_stage >= buffers_per_shader_stage {
225 BufferBindingType::Storage { read_only: true }
226 } else {
227 BufferBindingType::Uniform
228 }
229 }
230}