aboutsummaryrefslogtreecommitdiff
path: root/stockton-render/src/draw/buffers/mod.rs
blob: dc7df65b7ef82f77d8e73236c129e2e45b7db9e1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
//! All sorts of buffers

use std::ops::IndexMut;

use crate::{error::EnvironmentError, types::*};

use anyhow::{Context, Result};
use hal::{
    buffer::Usage,
    memory::{Properties, SparseFlags},
    MemoryTypeId,
};

pub mod dedicated_image;
pub mod draw_buffers;
pub mod staged;

pub use dedicated_image::DedicatedLoadedImage;
pub use draw_buffers::DrawBuffers;
pub use staged::StagedBuffer;

/// Create a buffer of the given specifications, allocating more device memory.
// TODO: Use a different memory allocator?
pub(crate) fn create_buffer(
    device: &mut DeviceT,
    adapter: &Adapter,
    usage: Usage,
    properties: Properties,
    size: u64,
) -> Result<(BufferT, MemoryT)> {
    let mut buffer = unsafe { device.create_buffer(size, usage, SparseFlags::empty()) }
        .context("Error creating buffer")?;

    let requirements = unsafe { device.get_buffer_requirements(&buffer) };
    let memory_type_id = adapter
        .physical_device
        .memory_properties()
        .memory_types
        .iter()
        .enumerate()
        .find(|&(id, memory_type)| {
            requirements.type_mask & (1 << id) != 0 && memory_type.properties.contains(properties)
        })
        .map(|(id, _)| MemoryTypeId(id))
        .ok_or(EnvironmentError::NoMemoryTypes)?;

    let memory = unsafe { device.allocate_memory(memory_type_id, requirements.size) }
        .context("Error allocating memory")?;

    unsafe { device.bind_buffer_memory(&memory, 0, &mut buffer) }
        .context("Error binding memory to buffer")?;

    Ok((buffer, memory))
}

/// A buffer that can be modified by the CPU
pub trait ModifiableBuffer: IndexMut<usize> {
    /// Get a handle to the underlying GPU buffer
    fn get_buffer(&mut self) -> &BufferT;

    /// Record the command(s) required to commit changes to this buffer to the given command buffer.
    fn record_commit_cmds<'a>(&'a mut self, cmd_buffer: &mut CommandBufferT) -> Result<()>;
}