bevy_render/render_resource/
gpu_array_buffer.rs1use super::{
2 binding_types::{storage_buffer_read_only, uniform_buffer_sized},
3 BindGroupLayoutEntryBuilder, BufferVec,
4};
5use crate::{
6 render_resource::batched_uniform_buffer::BatchedUniformBuffer,
7 renderer::{RenderDevice, RenderQueue},
8};
9use bevy_ecs::{prelude::Component, resource::Resource};
10use core::marker::PhantomData;
11use encase::{private::WriteInto, ShaderSize, ShaderType};
12use nonmax::NonMaxU32;
13use wgpu::{BindingResource, BufferUsages, Limits};
14
15pub trait GpuArrayBufferable: ShaderType + ShaderSize + WriteInto + Clone {}
17
18impl<T: ShaderType + ShaderSize + WriteInto + Clone> GpuArrayBufferable for T {}
19
20#[derive(Resource)]
36pub enum GpuArrayBuffer<T: GpuArrayBufferable> {
37 Uniform(BatchedUniformBuffer<T>),
38 Storage(BufferVec<T>),
39}
40
41impl<T: GpuArrayBufferable> GpuArrayBuffer<T> {
42 pub fn new(limits: &Limits) -> Self {
43 if limits.max_storage_buffers_per_shader_stage == 0 {
44 GpuArrayBuffer::Uniform(BatchedUniformBuffer::new(limits))
45 } else {
46 GpuArrayBuffer::Storage(BufferVec::new(BufferUsages::STORAGE))
47 }
48 }
49
50 pub fn clear(&mut self) {
51 match self {
52 GpuArrayBuffer::Uniform(buffer) => buffer.clear(),
53 GpuArrayBuffer::Storage(buffer) => buffer.clear(),
54 }
55 }
56
57 pub fn push(&mut self, value: T) -> GpuArrayBufferIndex<T> {
58 match self {
59 GpuArrayBuffer::Uniform(buffer) => buffer.push(value),
60 GpuArrayBuffer::Storage(buffer) => {
61 let index = buffer.push(value) as u32;
62 GpuArrayBufferIndex {
63 index,
64 dynamic_offset: None,
65 element_type: PhantomData,
66 }
67 }
68 }
69 }
70
71 pub fn write_buffer(&mut self, device: &RenderDevice, queue: &RenderQueue) {
72 match self {
73 GpuArrayBuffer::Uniform(buffer) => buffer.write_buffer(device, queue),
74 GpuArrayBuffer::Storage(buffer) => buffer.write_buffer(device, queue),
75 }
76 }
77
78 pub fn binding_layout(limits: &Limits) -> BindGroupLayoutEntryBuilder {
79 if limits.max_storage_buffers_per_shader_stage == 0 {
80 uniform_buffer_sized(
81 true,
82 None,
85 )
86 } else {
87 storage_buffer_read_only::<T>(false)
88 }
89 }
90
91 pub fn binding(&self) -> Option<BindingResource<'_>> {
92 match self {
93 GpuArrayBuffer::Uniform(buffer) => buffer.binding(),
94 GpuArrayBuffer::Storage(buffer) => buffer.binding(),
95 }
96 }
97
98 pub fn batch_size(limits: &Limits) -> Option<u32> {
99 if limits.max_storage_buffers_per_shader_stage == 0 {
100 Some(BatchedUniformBuffer::<T>::batch_size(limits) as u32)
101 } else {
102 None
103 }
104 }
105}
106
107#[derive(Component, Clone)]
109pub struct GpuArrayBufferIndex<T: GpuArrayBufferable> {
110 pub index: u32,
112 pub dynamic_offset: Option<NonMaxU32>,
115 pub element_type: PhantomData<T>,
116}