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
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
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 {
        #[allow(non_upper_case_globals)]
        const VertexAttribArray = gl::VERTEX_ATTRIB_ARRAY_BARRIER_BIT;
        #[allow(non_upper_case_globals)]
        const ElementArray = gl::ELEMENT_ARRAY_BARRIER_BIT;
        #[allow(non_upper_case_globals)]
        const UniformBarrier = gl::UNIFORM_BARRIER_BIT;
        #[allow(non_upper_case_globals)]
        const TextureFetch = gl::TEXTURE_FETCH_BARRIER_BIT;
        #[allow(non_upper_case_globals)]
        const ShaderImageAccess = gl::SHADER_IMAGE_ACCESS_BARRIER_BIT;
        #[allow(non_upper_case_globals)]
        const Command = gl::COMMAND_BARRIER_BIT;
        #[allow(non_upper_case_globals)]
        const PixelBuffer = gl::PIXEL_BUFFER_BARRIER_BIT;
        #[allow(non_upper_case_globals)]
        const TextureUpdate = gl::TEXTURE_UPDATE_BARRIER_BIT;
        #[allow(non_upper_case_globals)]
        const BufferUpdate = gl::BUFFER_UPDATE_BARRIER_BIT;
        #[allow(non_upper_case_globals)]
        const Framebuffer = gl::FRAMEBUFFER_BARRIER_BIT;
        #[allow(non_upper_case_globals)]
        const TransformFeedback = gl::TRANSFORM_FEEDBACK_BARRIER_BIT;
        #[allow(non_upper_case_globals)]
        const AtomicCounter = gl::ATOMIC_COUNTER_BARRIER_BIT;
        #[allow(non_upper_case_globals)]
        const ShaderStorage = gl::SHADER_STORAGE_BARRIER_BIT;
        #[allow(non_upper_case_globals)]
        const QueryBuffer = gl::QUERY_BUFFER_BARRIER_BIT;
        #[allow(non_upper_case_globals)]
        const All = gl::ALL_BARRIER_BITS;
    }
}

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());
}