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
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
use super::*;
use super::errors::*;

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum SyncStatus {
    AlreadySignaled,
    TimeoutExpired,
    ConditionSatisfied,
    WaitFailed,
}

impl From<SyncStatus> for u32 {
    fn from(sync_status: SyncStatus) -> Self {
        match sync_status {
            SyncStatus::AlreadySignaled => gl::ALREADY_SIGNALED,
            SyncStatus::TimeoutExpired => gl::TIMEOUT_EXPIRED,
            SyncStatus::ConditionSatisfied => gl::CONDITION_SATISFIED,
            SyncStatus::WaitFailed => gl::WAIT_FAILED,
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
pub enum SyncFlushCommands {
    True,
    False,
}

impl From<SyncFlushCommands> for u32 {
    fn from(sync_status: SyncFlushCommands) -> Self {
        match sync_status {
            SyncFlushCommands::True => gl::SYNC_FLUSH_COMMANDS_BIT,
            SyncFlushCommands::False => 0,
        }
    }
}

bitflags! {
    pub struct MemoryBarriers: u32 {
        const VERTEX_ATTRIB_ARRAY_BARRIER = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        const GL_ELEMENT_ARRAY_BARRIER = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        const GL_UNIFORM_BARRIER = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        const GL_TEXTURE_FETCH_BARRIER = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        const GL_SHADER_IMAGE_ACCESS_BARRIER = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        const GL_COMMAND_BARRIER = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        const GL_PIXEL_BUFFER_BARRIER = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        const GL_TEXTURE_UPDATE_BARRIER = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        const GL_BUFFER_UPDATE_BARRIER = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        const GL_FRAMEBUFFER_BARRIER = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        const GL_TRANSFORM_FEEDBACK_BARRIER = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        const GL_ATOMIC_COUNTER_BARRIER = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        const GL_SHADER_STORAGE_BARRIER = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        const GL_QUERY_BUFFER_BARRIER = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        const GL_ALL_BARRIER_BITS = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
    }
}

pub unsafe fn fence_sync() -> Result<gl::types::GLsync> {
    let result = gl::FenceSync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0);

    if result.is_null() {
        bail!("Creation of sync object failed");
    }

    Ok(result)
}

pub unsafe fn delete_sync(sync_ptr: gl::types::GLsync) {
    gl::DeleteSync(sync_ptr);
}

pub unsafe fn wait_sync(sync_ptr: gl::types::GLsync) {
    gl::WaitSync(sync_ptr, 0, gl::TIMEOUT_IGNORED)
}

pub unsafe fn client_wait_sync(
    sync_ptr: gl::types::GLsync,
    flush_commands: SyncFlushCommands,
    timeout: u64,
) -> Result<SyncStatus> {
    let result: gl::types::GLenum = gl::ClientWaitSync(sync_ptr, flush_commands.into(), timeout);

    get_error(match result {
        gl::ALREADY_SIGNALED => SyncStatus::AlreadySignaled,
        gl::TIMEOUT_EXPIRED => SyncStatus::TimeoutExpired,
        gl::CONDITION_SATISFIED => SyncStatus::ConditionSatisfied,
        gl::WAIT_FAILED => SyncStatus::WaitFailed,
        _ => bail!("Unknown sync status"),
    })
}

pub unsafe fn memory_barrier(barriers: MemoryBarriers) {
    gl::MemoryBarrier(barriers.bits());
}