Update the OpenGL backend
This commit is contained in:
parent
7771fd877d
commit
21a82ae049
115
gl/src/lib.rs
115
gl/src/lib.rs
|
@ -21,15 +21,18 @@ use pathfinder_geometry::vector::Vector2I;
|
||||||
use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, BufferUploadMode, ClearOps};
|
use pathfinder_gpu::{BlendFactor, BlendOp, BufferData, BufferTarget, BufferUploadMode, ClearOps};
|
||||||
use pathfinder_gpu::{ComputeDimensions, ComputeState, DepthFunc, Device, FeatureLevel};
|
use pathfinder_gpu::{ComputeDimensions, ComputeState, DepthFunc, Device, FeatureLevel};
|
||||||
use pathfinder_gpu::{ImageAccess, ImageBinding, Primitive, ProgramKind, RenderOptions};
|
use pathfinder_gpu::{ImageAccess, ImageBinding, Primitive, ProgramKind, RenderOptions};
|
||||||
use pathfinder_gpu::{RenderState, RenderTarget, ShaderKind, StencilFunc, TextureBinding, TextureData};
|
use pathfinder_gpu::{RenderState, RenderTarget, ShaderKind, StencilFunc, TextureBinding};
|
||||||
use pathfinder_gpu::{TextureDataRef, TextureFormat, TextureSamplingFlags, UniformData};
|
use pathfinder_gpu::{TextureData, TextureDataRef, TextureFormat, TextureSamplingFlags, UniformData};
|
||||||
use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
|
use pathfinder_gpu::{VertexAttrClass, VertexAttrDescriptor, VertexAttrType};
|
||||||
use pathfinder_resources::ResourceLoader;
|
use pathfinder_resources::ResourceLoader;
|
||||||
use pathfinder_simd::default::F32x4;
|
use pathfinder_simd::default::F32x4;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
use std::ffi::CString;
|
use std::ffi::{CStr, CString};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
|
use std::ops::Range;
|
||||||
|
use std::os::raw::c_char;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
|
use std::rc::Rc;
|
||||||
use std::str;
|
use std::str;
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
|
|
||||||
|
@ -83,6 +86,10 @@ impl GLDevice {
|
||||||
&render_state.textures,
|
&render_state.textures,
|
||||||
&render_state.images);
|
&render_state.images);
|
||||||
|
|
||||||
|
for &(storage_buffer, buffer) in render_state.storage_buffers {
|
||||||
|
self.set_storage_buffer(storage_buffer, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
render_state.uniforms.iter().for_each(|(uniform, data)| self.set_uniform(uniform, data));
|
render_state.uniforms.iter().for_each(|(uniform, data)| self.set_uniform(uniform, data));
|
||||||
|
|
||||||
self.set_render_options(&render_state.options);
|
self.set_render_options(&render_state.options);
|
||||||
|
@ -241,7 +248,7 @@ impl GLDevice {
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::BindBufferBase(gl::SHADER_STORAGE_BUFFER,
|
gl::BindBufferBase(gl::SHADER_STORAGE_BUFFER,
|
||||||
storage_buffer.location as GLuint,
|
storage_buffer.location as GLuint,
|
||||||
buffer.gl_buffer);
|
buffer.object.gl_buffer);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -254,6 +261,10 @@ impl GLDevice {
|
||||||
fn reset_render_state(&self, render_state: &RenderState<GLDevice>) {
|
fn reset_render_state(&self, render_state: &RenderState<GLDevice>) {
|
||||||
self.reset_render_options(&render_state.options);
|
self.reset_render_options(&render_state.options);
|
||||||
|
|
||||||
|
for &(storage_buffer, _) in render_state.storage_buffers {
|
||||||
|
self.unset_storage_buffer(storage_buffer);
|
||||||
|
}
|
||||||
|
|
||||||
unsafe {
|
unsafe {
|
||||||
for image_binding in render_state.images {
|
for image_binding in render_state.images {
|
||||||
self.unbind_image(image_binding.0.image_unit);
|
self.unbind_image(image_binding.0.image_unit);
|
||||||
|
@ -310,6 +321,7 @@ impl GLDevice {
|
||||||
|
|
||||||
impl Device for GLDevice {
|
impl Device for GLDevice {
|
||||||
type Buffer = GLBuffer;
|
type Buffer = GLBuffer;
|
||||||
|
type BufferDataReceiver = GLBufferDataReceiver;
|
||||||
type Fence = GLFence;
|
type Fence = GLFence;
|
||||||
type Framebuffer = GLFramebuffer;
|
type Framebuffer = GLFramebuffer;
|
||||||
type ImageParameter = GLImageParameter;
|
type ImageParameter = GLImageParameter;
|
||||||
|
@ -324,6 +336,19 @@ impl Device for GLDevice {
|
||||||
type VertexArray = GLVertexArray;
|
type VertexArray = GLVertexArray;
|
||||||
type VertexAttr = GLVertexAttr;
|
type VertexAttr = GLVertexAttr;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn backend_name(&self) -> &'static str {
|
||||||
|
"OpenGL"
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn device_name(&self) -> String {
|
||||||
|
unsafe {
|
||||||
|
CStr::from_ptr(gl::GetString(gl::RENDERER) as *const c_char).to_string_lossy()
|
||||||
|
.to_string()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn feature_level(&self) -> FeatureLevel {
|
fn feature_level(&self) -> FeatureLevel {
|
||||||
match self.version {
|
match self.version {
|
||||||
GLVersion::GL3 | GLVersion::GLES3 => FeatureLevel::D3D10,
|
GLVersion::GL3 | GLVersion::GLES3 => FeatureLevel::D3D10,
|
||||||
|
@ -582,14 +607,12 @@ impl Device for GLDevice {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut gl_buffer = 0;
|
let mut gl_buffer = 0;
|
||||||
gl::GenBuffers(1, &mut gl_buffer); ck();
|
gl::GenBuffers(1, &mut gl_buffer); ck();
|
||||||
GLBuffer { gl_buffer, mode }
|
let object = Rc::new(GLBufferObject { gl_buffer });
|
||||||
|
GLBuffer { object, mode }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn allocate_buffer<T>(&self,
|
fn allocate_buffer<T>(&self, buffer: &GLBuffer, data: BufferData<T>, target: BufferTarget) {
|
||||||
buffer: &GLBuffer,
|
|
||||||
data: BufferData<T>,
|
|
||||||
target: BufferTarget) {
|
|
||||||
let target = target.to_gl_target();
|
let target = target.to_gl_target();
|
||||||
let (ptr, len) = match data {
|
let (ptr, len) = match data {
|
||||||
BufferData::Uninitialized(len) => (ptr::null(), len),
|
BufferData::Uninitialized(len) => (ptr::null(), len),
|
||||||
|
@ -598,7 +621,7 @@ impl Device for GLDevice {
|
||||||
let len = (len * mem::size_of::<T>()) as GLsizeiptr;
|
let len = (len * mem::size_of::<T>()) as GLsizeiptr;
|
||||||
let usage = buffer.mode.to_gl_usage();
|
let usage = buffer.mode.to_gl_usage();
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::BindBuffer(target, buffer.gl_buffer); ck();
|
gl::BindBuffer(target, buffer.object.gl_buffer); ck();
|
||||||
gl::BufferData(target, len, ptr, usage); ck();
|
gl::BufferData(target, len, ptr, usage); ck();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -611,7 +634,7 @@ impl Device for GLDevice {
|
||||||
let target = target.to_gl_target();
|
let target = target.to_gl_target();
|
||||||
let len = (data.len() * mem::size_of::<T>()) as GLsizeiptr;
|
let len = (data.len() * mem::size_of::<T>()) as GLsizeiptr;
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::BindBuffer(target, buffer.gl_buffer); ck();
|
gl::BindBuffer(target, buffer.object.gl_buffer); ck();
|
||||||
gl::BufferSubData(target,
|
gl::BufferSubData(target,
|
||||||
position as GLintptr,
|
position as GLintptr,
|
||||||
len,
|
len,
|
||||||
|
@ -748,6 +771,14 @@ impl Device for GLDevice {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn read_buffer(&self, buffer: &GLBuffer, target: BufferTarget, range: Range<usize>)
|
||||||
|
-> GLBufferDataReceiver {
|
||||||
|
unsafe {
|
||||||
|
let gl_sync = gl::FenceSync(gl::SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
|
GLBufferDataReceiver { object: buffer.object.clone(), gl_sync, range, target }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn begin_commands(&self) {
|
fn begin_commands(&self) {
|
||||||
// TODO(pcwalton): Add some checks in debug mode to make sure render commands are bracketed
|
// TODO(pcwalton): Add some checks in debug mode to make sure render commands are bracketed
|
||||||
// by these?
|
// by these?
|
||||||
|
@ -867,11 +898,34 @@ impl Device for GLDevice {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn try_recv_buffer(&self, receiver: &Self::BufferDataReceiver) -> Option<Vec<u8>> {
|
||||||
|
unsafe {
|
||||||
|
let result = gl::ClientWaitSync(receiver.gl_sync,
|
||||||
|
gl::SYNC_FLUSH_COMMANDS_BIT,
|
||||||
|
0); ck();
|
||||||
|
if result == gl::TIMEOUT_EXPIRED || result == gl::WAIT_FAILED {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.get_buffer_data(receiver))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn recv_buffer(&self, receiver: &Self::BufferDataReceiver) -> Vec<u8> {
|
||||||
|
unsafe {
|
||||||
|
let result = gl::ClientWaitSync(receiver.gl_sync,
|
||||||
|
gl::SYNC_FLUSH_COMMANDS_BIT,
|
||||||
|
!0); ck();
|
||||||
|
debug_assert!(result != gl::TIMEOUT_EXPIRED && result != gl::WAIT_FAILED);
|
||||||
|
self.get_buffer_data(receiver)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn bind_buffer(&self, vertex_array: &GLVertexArray, buffer: &GLBuffer, target: BufferTarget) {
|
fn bind_buffer(&self, vertex_array: &GLVertexArray, buffer: &GLBuffer, target: BufferTarget) {
|
||||||
self.bind_vertex_array(vertex_array);
|
self.bind_vertex_array(vertex_array);
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::BindBuffer(target.to_gl_target(), buffer.gl_buffer); ck();
|
gl::BindBuffer(target.to_gl_target(), buffer.object.gl_buffer); ck();
|
||||||
}
|
}
|
||||||
self.unbind_vertex_array();
|
self.unbind_vertex_array();
|
||||||
}
|
}
|
||||||
|
@ -964,7 +1018,7 @@ impl GLDevice {
|
||||||
|
|
||||||
fn unbind_image(&self, unit: u32) {
|
fn unbind_image(&self, unit: u32) {
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::BindImageTexture(unit, 0, 0, gl::FALSE, 0, 0, 0); ck();
|
gl::BindImageTexture(unit, 0, 0, gl::FALSE, 0, gl::READ_ONLY, gl::RGBA8); ck();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1092,6 +1146,19 @@ impl GLDevice {
|
||||||
texture_data
|
texture_data
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_buffer_data(&self, receiver: &GLBufferDataReceiver) -> Vec<u8> {
|
||||||
|
let mut dest = vec![0; receiver.range.end - receiver.range.start];
|
||||||
|
let gl_target = receiver.target.to_gl_target();
|
||||||
|
unsafe {
|
||||||
|
gl::BindBuffer(gl_target, receiver.object.gl_buffer); ck();
|
||||||
|
gl::GetBufferSubData(gl_target,
|
||||||
|
receiver.range.start as GLintptr,
|
||||||
|
(receiver.range.end - receiver.range.start) as GLsizeiptr,
|
||||||
|
dest.as_mut_ptr() as *mut GLvoid); ck();
|
||||||
|
}
|
||||||
|
dest
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GLVertexArray {
|
pub struct GLVertexArray {
|
||||||
|
@ -1175,11 +1242,15 @@ impl Drop for GLFramebuffer {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct GLBuffer {
|
pub struct GLBuffer {
|
||||||
pub gl_buffer: GLuint,
|
pub object: Rc<GLBufferObject>,
|
||||||
pub mode: BufferUploadMode,
|
pub mode: BufferUploadMode,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for GLBuffer {
|
pub struct GLBufferObject {
|
||||||
|
pub gl_buffer: GLuint,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Drop for GLBufferObject {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
unsafe {
|
||||||
gl::DeleteBuffers(1, &mut self.gl_buffer); ck();
|
gl::DeleteBuffers(1, &mut self.gl_buffer); ck();
|
||||||
|
@ -1397,7 +1468,7 @@ impl TextureFormatExt for TextureFormat {
|
||||||
match self {
|
match self {
|
||||||
TextureFormat::R8 => gl::R8 as GLint,
|
TextureFormat::R8 => gl::R8 as GLint,
|
||||||
TextureFormat::R16F => gl::R16F as GLint,
|
TextureFormat::R16F => gl::R16F as GLint,
|
||||||
TextureFormat::RGBA8 => gl::RGBA as GLint,
|
TextureFormat::RGBA8 => gl::RGBA8 as GLint,
|
||||||
TextureFormat::RGBA16F => gl::RGBA16F as GLint,
|
TextureFormat::RGBA16F => gl::RGBA16F as GLint,
|
||||||
TextureFormat::RGBA32F => gl::RGBA32F as GLint,
|
TextureFormat::RGBA32F => gl::RGBA32F as GLint,
|
||||||
}
|
}
|
||||||
|
@ -1427,14 +1498,22 @@ impl VertexAttrTypeExt for VertexAttrType {
|
||||||
fn to_gl_type(self) -> GLuint {
|
fn to_gl_type(self) -> GLuint {
|
||||||
match self {
|
match self {
|
||||||
VertexAttrType::F32 => gl::FLOAT,
|
VertexAttrType::F32 => gl::FLOAT,
|
||||||
VertexAttrType::I16 => gl::SHORT,
|
|
||||||
VertexAttrType::I8 => gl::BYTE,
|
VertexAttrType::I8 => gl::BYTE,
|
||||||
VertexAttrType::U16 => gl::UNSIGNED_SHORT,
|
VertexAttrType::I16 => gl::SHORT,
|
||||||
|
VertexAttrType::I32 => gl::INT,
|
||||||
VertexAttrType::U8 => gl::UNSIGNED_BYTE,
|
VertexAttrType::U8 => gl::UNSIGNED_BYTE,
|
||||||
|
VertexAttrType::U16 => gl::UNSIGNED_SHORT,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct GLBufferDataReceiver {
|
||||||
|
object: Rc<GLBufferObject>,
|
||||||
|
gl_sync: GLsync,
|
||||||
|
range: Range<usize>,
|
||||||
|
target: BufferTarget,
|
||||||
|
}
|
||||||
|
|
||||||
pub struct GLTextureDataReceiver {
|
pub struct GLTextureDataReceiver {
|
||||||
gl_pixel_buffer: GLuint,
|
gl_pixel_buffer: GLuint,
|
||||||
gl_sync: GLsync,
|
gl_sync: GLsync,
|
||||||
|
|
Loading…
Reference in New Issue