From 5078015605bbc7d15d1b1c859c99b88c03de75e6 Mon Sep 17 00:00:00 2001 From: chyyran Date: Mon, 28 Nov 2022 18:56:35 -0500 Subject: [PATCH] gl46: implement DSA version of gl runtime --- .idea/src.iml | 1 + Cargo.lock | 17 +++ Cargo.toml | 1 + README.md | 11 +- librashader-runtime-gl/src/filter_pass.rs | 1 + librashader-runtime-gl46/src/filter_chain.rs | 69 +++++------ librashader-runtime-gl46/src/filter_pass.rs | 60 ++------- librashader-runtime-gl46/src/framebuffer.rs | 114 ++++-------------- .../src/hello_triangle.rs | 12 +- librashader-runtime-gl46/src/quad_render.rs | 47 ++++++-- librashader/Cargo.toml | 1 + librashader/src/lib.rs | 13 +- 12 files changed, 157 insertions(+), 190 deletions(-) diff --git a/.idea/src.iml b/.idea/src.iml index e7382d5..8c2d7a9 100644 --- a/.idea/src.iml +++ b/.idea/src.iml @@ -13,6 +13,7 @@ + diff --git a/Cargo.lock b/Cargo.lock index b401e0a..48ad59b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -418,6 +418,7 @@ dependencies = [ "librashader-reflect", "librashader-runtime-d3d11", "librashader-runtime-gl", + "librashader-runtime-gl46", ] [[package]] @@ -496,6 +497,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "librashader-runtime-gl46" +version = "0.1.0" +dependencies = [ + "bytemuck", + "gl", + "glfw", + "librashader-common", + "librashader-preprocess", + "librashader-presets", + "librashader-reflect", + "rustc-hash", + "spirv_cross", + "thiserror", +] + [[package]] name = "lock_api" version = "0.4.9" diff --git a/Cargo.toml b/Cargo.toml index 030eace..2f5760d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ members = [ "librashader-reflect", "librashader-runtime-d3d11", "librashader-runtime-gl", + "librashader-runtime-gl46", ] \ No newline at end of file diff --git a/README.md b/README.md index f4b8bba..7a6373b 100644 --- a/README.md +++ b/README.md @@ -9,12 +9,13 @@ librashader (*/ˈli:brəʃeɪdɚ/*) is a preprocessor, compiler, and runtime for Heavily WIP. ## Supported Render APIs -librashader supports OpenGL 3, Vulkan, DirectX 11, and DirectX 12. Support is WIP for all runtimes except OpenGL 3. Older versions +librashader supports OpenGL 3, OpenGL 4.6, Vulkan, DirectX 11, and DirectX 12. Support is WIP for all runtimes except OpenGL 3. Older versions of DirectX and OpenGL, as well as Metal, are not supported (but pull-requests are welcome). | **API** | **Status** | **`librashader` feature** | |-------------|------------|---------------------------| | OpenGL 3.3+ | ✔ | `gl` | +| OpenGL 4.6 | ✔ | `gl46` | | Vulkan | 🚧 | `vk` | | Direct3D11 | 🚧 | `d3d11` | | Direct3D12 | 🚧 | `d3d12` | @@ -54,11 +55,17 @@ Please report an issue if you run into a shader that works in RetroArch, but not * Sampler objects are used rather than `glTexParameter`. * Sampler inputs and outputs are not renamed. This is useful for debugging shaders in RenderDoc. * UBO and Push Constant Buffer sizes are padded to 16-byte boundaries. - * + * OpenGL 4.6+ + * All caveats from the OpenGL 3.3+ section should be considered. + * Should work on OpenGL 4.5 but this is not guaranteed. The OpenGL 4.6 runtime may eventually switch to using `ARB_spirv_extensions` for loading shaders, and this will not be marked as a breaking change. + * The OpenGL 4.6 runtime uses Direct State Access to minimize changes to the OpenGL state. For recent GPUs, this may improve performance. * Direct3D 11 * The staging buffer is not kept around when loading static textures (LUTs). * HDR10 support is not part of the shader runtime and is not supported. +Most, if not all shader presets should work fine on librashader. The runtime specific differences should not affect the output, +and are more a heads-up for integrating librashader into your project. + ## License The core parts of librashader such as the preprocessor, the preset parser, the reflection library, and the runtimes, are all licensed under the Mozilla Public License version 2.0. diff --git a/librashader-runtime-gl/src/filter_pass.rs b/librashader-runtime-gl/src/filter_pass.rs index 46762df..8c85ab0 100644 --- a/librashader-runtime-gl/src/filter_pass.rs +++ b/librashader-runtime-gl/src/filter_pass.rs @@ -183,6 +183,7 @@ impl FilterPass { } unsafe { + // can't use framebuffer.clear because it will unbind. gl::ColorMask(gl::TRUE, gl::TRUE, gl::TRUE, gl::TRUE); gl::ClearColor(0.0f32, 0.0f32, 0.0f32, 0.0f32); gl::Clear(gl::COLOR_BUFFER_BIT); diff --git a/librashader-runtime-gl46/src/filter_chain.rs b/librashader-runtime-gl46/src/filter_chain.rs index 1fec799..eac1648 100644 --- a/librashader-runtime-gl46/src/filter_chain.rs +++ b/librashader-runtime-gl46/src/filter_chain.rs @@ -29,7 +29,7 @@ use crate::texture::Texture; pub struct FilterChain { passes: Box<[FilterPass]>, common: FilterCommon, - filter_vao: GLuint, + pub(crate) draw_quad: DrawQuad, output_framebuffers: Box<[Framebuffer]>, feedback_framebuffers: Box<[Framebuffer]>, history_framebuffers: VecDeque, @@ -43,7 +43,6 @@ pub struct FilterCommon { pub output_textures: Box<[Texture]>, pub feedback_textures: Box<[Texture]>, pub history_textures: Box<[Texture]>, - pub(crate) draw_quad: DrawQuad, } pub struct FilterMutable { @@ -177,17 +176,12 @@ impl FilterChain { // create VBO objects let draw_quad = DrawQuad::new(); - let mut filter_vao = 0; - unsafe { - gl::GenVertexArrays(1, &mut filter_vao); - } - Ok(FilterChain { passes: filters, output_framebuffers: output_framebuffers.into_boxed_slice(), feedback_framebuffers: feedback_framebuffers.into_boxed_slice(), history_framebuffers, - filter_vao, + draw_quad, common: FilterCommon { config: FilterMutable { passes_enabled: preset.shader_count as usize, @@ -199,7 +193,6 @@ impl FilterChain { output_textures: output_textures.into_boxed_slice(), feedback_textures: feedback_textures.into_boxed_slice(), history_textures, - draw_quad, }, }) } @@ -279,6 +272,15 @@ impl FilterChain { fn load_luts(textures: &[TextureConfig]) -> Result> { let mut luts = FxHashMap::default(); + let pixel_unpack = unsafe { + let mut binding = 0; + gl::GetIntegerv(gl::PIXEL_UNPACK_BUFFER_BINDING, &mut binding); + binding + }; + + unsafe { + gl::BindBuffer(gl::PIXEL_UNPACK_BUFFER, 0); + } for (index, texture) in textures.iter().enumerate() { let image = Image::load(&texture.path)?; @@ -290,10 +292,10 @@ impl FilterChain { let mut handle = 0; unsafe { - gl::GenTextures(1, &mut handle); - gl::BindTexture(gl::TEXTURE_2D, handle); - gl::TexStorage2D( - gl::TEXTURE_2D, + gl::CreateTextures(gl::TEXTURE_2D,1, &mut handle); + + gl::TextureStorage2D( + handle, levels as GLsizei, gl::RGBA8, image.size.width as GLsizei, @@ -302,12 +304,10 @@ impl FilterChain { gl::PixelStorei(gl::UNPACK_ROW_LENGTH, 0); gl::PixelStorei(gl::UNPACK_ALIGNMENT, 4); - gl::BindBuffer(gl::PIXEL_UNPACK_BUFFER, 0); - gl::TexSubImage2D( - gl::TEXTURE_2D, - 0, - 0, - 0, + + gl::TextureSubImage2D( + handle, + 0, 0, 0, image.size.width as GLsizei, image.size.height as GLsizei, gl::RGBA, @@ -317,10 +317,8 @@ impl FilterChain { let mipmap = levels > 1; if mipmap { - gl::GenerateMipmap(gl::TEXTURE_2D); + gl::GenerateTextureMipmap(handle); } - - gl::BindTexture(gl::TEXTURE_2D, 0); } luts.insert( @@ -338,6 +336,10 @@ impl FilterChain { }, ); } + + unsafe { + gl::BindBuffer(gl::PIXEL_UNPACK_BUFFER, pixel_unpack as GLuint); + }; Ok(luts) } @@ -416,17 +418,15 @@ impl FilterChain { let size = ubo.size; let mut ring: InlineRingBuffer = InlineRingBuffer::new(); unsafe { - gl::GenBuffers(16, ring.items_mut().as_mut_ptr()); + gl::CreateBuffers(16, ring.items_mut().as_mut_ptr()); for buffer in ring.items() { - gl::BindBuffer(gl::UNIFORM_BUFFER, *buffer); - gl::BufferData( - gl::UNIFORM_BUFFER, + gl::NamedBufferData( + *buffer, size as GLsizeiptr, std::ptr::null(), gl::STREAM_DRAW, ); } - gl::BindBuffer(gl::UNIFORM_BUFFER, 0); } Some(ring) } else { @@ -593,11 +593,9 @@ impl FilterChain { return Ok(()); } - unsafe { - // do not need to rebind FBO 0 here since first `draw` will - // bind automatically. - gl::BindVertexArray(self.filter_vao); - } + // do not need to rebind FBO 0 here since first `draw` will + // bind automatically. + self.draw_quad.bind_vao(); let filter = passes[0].config.filter; let wrap_mode = passes[0].config.wrap_mode; @@ -710,10 +708,9 @@ impl FilterChain { self.push_history(input)?; - // pass.draw should return framebuffer bound to 0. - unsafe { - gl::BindVertexArray(0); - } + // do not need to rebind FBO 0 here since first `draw` will + // bind automatically. + self.draw_quad.unbind_vao(); Ok(()) } diff --git a/librashader-runtime-gl46/src/filter_pass.rs b/librashader-runtime-gl46/src/filter_pass.rs index 40dd89f..5dfdef5 100644 --- a/librashader-runtime-gl46/src/filter_pass.rs +++ b/librashader-runtime-gl46/src/filter_pass.rs @@ -104,9 +104,7 @@ impl FilterPass { fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture) { unsafe { // eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding); - gl::ActiveTexture(gl::TEXTURE0 + binding.binding); - - gl::BindTexture(gl::TEXTURE_2D, texture.image.handle); + gl::BindTextureUnit(binding.binding, texture.image.handle); gl::BindSampler(binding.binding, samplers.get(texture.wrap_mode, texture.filter, texture.mip_filter)); } @@ -137,7 +135,7 @@ impl FilterPass { let framebuffer = output.framebuffer; unsafe { - gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.handle); + // gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.handle); gl::UseProgram(self.program); } @@ -162,14 +160,12 @@ impl FilterPass { let buffer = ring.current(); unsafe { - gl::BindBuffer(gl::UNIFORM_BUFFER, *buffer); - gl::BufferSubData( - gl::UNIFORM_BUFFER, + gl::NamedBufferSubData( + *buffer, 0, size as GLsizeiptr, self.uniform_buffer.as_ptr().cast(), ); - gl::BindBuffer(gl::UNIFORM_BUFFER, 0); if self.ubo_location.vertex != gl::INVALID_INDEX { gl::BindBufferBase(gl::UNIFORM_BUFFER, self.ubo_location.vertex, *buffer); @@ -183,10 +179,9 @@ impl FilterPass { } unsafe { - gl::ColorMask(gl::TRUE, gl::TRUE, gl::TRUE, gl::TRUE); - gl::ClearColor(0.0f32, 0.0f32, 0.0f32, 0.0f32); - gl::Clear(gl::COLOR_BUFFER_BIT); - // + // can use because DSA + framebuffer.clear(); + gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.handle); gl::Viewport( output.x, output.y, @@ -204,36 +199,7 @@ impl FilterPass { gl::Disable(gl::BLEND); gl::Disable(gl::DEPTH_TEST); - gl::EnableVertexAttribArray(0); - gl::EnableVertexAttribArray(1); - - gl::BindBuffer(gl::ARRAY_BUFFER, parent.draw_quad.vbo); - - // the provided pointers are of OpenGL provenance with respect to the buffer bound to quad_vbo, - // and not a known provenance to the Rust abstract machine, therefore we give it invalid pointers. - // that are inexpressible in Rust - gl::VertexAttribPointer( - 0, - 2, - gl::FLOAT, - gl::FALSE, - (4 * std::mem::size_of::()) as GLsizei, - std::ptr::invalid(0), - ); - gl::VertexAttribPointer( - 1, - 2, - gl::FLOAT, - gl::FALSE, - (4 * std::mem::size_of::()) as GLsizei, - std::ptr::invalid(2 * std::mem::size_of::()), - ); gl::DrawArrays(gl::TRIANGLE_STRIP, 0, 4); - - gl::BindBuffer(gl::ARRAY_BUFFER, 0); - gl::DisableVertexAttribArray(0); - gl::DisableVertexAttribArray(1); - gl::Disable(gl::FRAMEBUFFER_SRGB); gl::BindFramebuffer(gl::FRAMEBUFFER, 0); } @@ -483,12 +449,12 @@ impl FilterPass { // bind float parameters for (id, (location, offset)) in - self.uniform_bindings - .iter() - .filter_map(|(binding, value)| match binding { - UniformBinding::Parameter(id) => Some((id, value)), - _ => None, - }) + self.uniform_bindings + .iter() + .filter_map(|(binding, value)| match binding { + UniformBinding::Parameter(id) => Some((id, value)), + _ => None, + }) { let id = id.as_str(); let (buffer, offset) = match offset { diff --git a/librashader-runtime-gl46/src/framebuffer.rs b/librashader-runtime-gl46/src/framebuffer.rs index 4df40dc..bdfdaba 100644 --- a/librashader-runtime-gl46/src/framebuffer.rs +++ b/librashader-runtime-gl46/src/framebuffer.rs @@ -21,9 +21,7 @@ impl Framebuffer { pub fn new(max_levels: u32) -> Framebuffer { let mut framebuffer = 0; unsafe { - gl::GenFramebuffers(1, &mut framebuffer); - gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer); - gl::BindFramebuffer(gl::FRAMEBUFFER, 0); + gl::CreateFramebuffers(1, &mut framebuffer); } Framebuffer { @@ -139,11 +137,9 @@ impl Framebuffer { pub(crate) fn clear(&self) { unsafe { - gl::BindFramebuffer(gl::FRAMEBUFFER, self.handle); - gl::ColorMask(gl::TRUE, gl::TRUE, gl::TRUE, gl::TRUE); - gl::ClearColor(0.0, 0.0, 0.0, 0.0); - gl::Clear(gl::COLOR_BUFFER_BIT); - gl::BindFramebuffer(gl::FRAMEBUFFER, 0); + gl::ClearNamedFramebufferfv(self.handle, + gl::COLOR, 0, + [0.0f32, 0.0, 0.0, 0.0].as_ptr().cast()); } } @@ -154,64 +150,15 @@ impl Framebuffer { } unsafe { - gl::BindFramebuffer(gl::FRAMEBUFFER, self.handle); + // gl::NamedFramebufferDrawBuffer(self.handle, gl::COLOR_ATTACHMENT1); + gl::NamedFramebufferReadBuffer(image.handle, gl::COLOR_ATTACHMENT0); + gl::NamedFramebufferDrawBuffer(self.handle, gl::COLOR_ATTACHMENT1); - gl::FramebufferTexture2D( - gl::READ_FRAMEBUFFER, - gl::COLOR_ATTACHMENT0, - gl::TEXTURE_2D, - image.handle, - 0, - ); + gl::BlitNamedFramebuffer(image.handle, self.handle, + 0, 0, image.size.width as GLint, image.size.height as GLint, + 0, 0, self.size.width as GLint, self.size.height as GLint, + gl::COLOR_BUFFER_BIT, gl::NEAREST); - gl::FramebufferTexture2D( - gl::DRAW_FRAMEBUFFER, - gl::COLOR_ATTACHMENT1, - gl::TEXTURE_2D, - self.image, - 0, - ); - gl::DrawBuffer(gl::COLOR_ATTACHMENT1); - gl::BlitFramebuffer( - 0, - 0, - self.size.width as GLint, - self.size.height as GLint, - 0, - 0, - self.size.width as GLint, - self.size.height as GLint, - gl::COLOR_BUFFER_BIT, - gl::NEAREST, - ); - - // cleanup after ourselves. - gl::FramebufferTexture2D( - gl::READ_FRAMEBUFFER, - gl::COLOR_ATTACHMENT0, - gl::TEXTURE_2D, - 0, - 0, - ); - - gl::FramebufferTexture2D( - gl::DRAW_FRAMEBUFFER, - gl::COLOR_ATTACHMENT1, - gl::TEXTURE_2D, - 0, - 0, - ); - - // set this back to color_attachment 0 - gl::FramebufferTexture2D( - gl::FRAMEBUFFER, - gl::COLOR_ATTACHMENT0, - gl::TEXTURE_2D, - self.image, - 0, - ); - - gl::BindFramebuffer(gl::FRAMEBUFFER, 0); } Ok(()) @@ -225,22 +172,18 @@ impl Framebuffer { self.size = size; unsafe { - gl::BindFramebuffer(gl::FRAMEBUFFER, self.handle); - // reset the framebuffer image if self.image != 0 { - gl::FramebufferTexture2D( - gl::FRAMEBUFFER, + gl::NamedFramebufferTexture( + self.handle, gl::COLOR_ATTACHMENT0, - gl::TEXTURE_2D, 0, 0, ); gl::DeleteTextures(1, &self.image); } - gl::GenTextures(1, &mut self.image); - gl::BindTexture(gl::TEXTURE_2D, self.image); + gl::CreateTextures(gl::TEXTURE_2D,1, &mut self.image); if size.width == 0 { size.width = 1; @@ -257,18 +200,17 @@ impl Framebuffer { self.levels = 1; } - gl::TexStorage2D( - gl::TEXTURE_2D, + gl::TextureStorage2D( + self.image, self.levels as GLsizei, self.format, size.width as GLsizei, size.height as GLsizei, ); - gl::FramebufferTexture2D( - gl::FRAMEBUFFER, + gl::NamedFramebufferTexture( + self.handle, gl::COLOR_ATTACHMENT0, - gl::TEXTURE_2D, self.image, 0, ); @@ -279,16 +221,14 @@ impl Framebuffer { gl::FRAMEBUFFER_UNSUPPORTED => { eprintln!("unsupported fbo"); - gl::FramebufferTexture2D( - gl::FRAMEBUFFER, + gl::NamedFramebufferTexture( + self.handle, gl::COLOR_ATTACHMENT0, - gl::TEXTURE_2D, 0, 0, ); gl::DeleteTextures(1, &self.image); - gl::GenTextures(1, &mut self.image); - gl::BindTexture(1, self.image); + gl::CreateTextures(gl::TEXTURE_2D, 1, &mut self.image); self.levels = util::calc_miplevel(size); if self.levels > self.max_levels { @@ -298,17 +238,16 @@ impl Framebuffer { self.levels = 1; } - gl::TexStorage2D( - gl::TEXTURE_2D, + gl::TextureStorage2D( + self.image, self.levels as GLsizei, ShaderFormat::R8G8B8A8Unorm.into(), size.width as GLsizei, size.height as GLsizei, ); - gl::FramebufferTexture2D( - gl::FRAMEBUFFER, + gl::NamedFramebufferTexture( + self.handle, gl::COLOR_ATTACHMENT0, - gl::TEXTURE_2D, self.image, 0, ); @@ -318,9 +257,6 @@ impl Framebuffer { _ => return Err(FilterChainError::FramebufferInit(status)) } } - - gl::BindFramebuffer(gl::FRAMEBUFFER, 0); - gl::BindTexture(gl::TEXTURE_2D, 0); } Ok(()) diff --git a/librashader-runtime-gl46/src/hello_triangle.rs b/librashader-runtime-gl46/src/hello_triangle.rs index c1760bf..7b475ff 100644 --- a/librashader-runtime-gl46/src/hello_triangle.rs +++ b/librashader-runtime-gl46/src/hello_triangle.rs @@ -12,7 +12,7 @@ use crate::framebuffer::{Framebuffer, GlImage, Viewport}; const WIDTH: u32 = 900; const HEIGHT: u32 = 700; -const TITLE: &str = "librashader OpenGL"; +const TITLE: &str = "librashader OpenGL 4.6"; pub fn compile_program(vertex: &str, fragment: &str) -> GLuint { let vertex_shader = unsafe { gl::CreateShader(gl::VERTEX_SHADER) }; @@ -215,7 +215,7 @@ void main() gl::ObjectLabel(gl::VERTEX_ARRAY, vao, -1, b"triangle_vao\0".as_ptr().cast()); gl::VertexArrayVertexBuffer(vao, 0, - vbo, 0, (6 * std::mem::size_of::()) as GLint + vbo, 0, 6 * std::mem::size_of::() as GLint ); gl::EnableVertexArrayAttrib(vao, 0); // this is "layout (location = 0)" in vertex shader @@ -226,7 +226,7 @@ void main() gl::EnableVertexArrayAttrib(vao, 1); gl::VertexArrayAttribFormat(vao, 1, 3, - gl::FLOAT, gl::FALSE, (3 * std::mem::size_of::() as GLuint)); + gl::FLOAT, gl::FALSE, 3 * std::mem::size_of::() as GLuint); gl::VertexArrayAttribBinding(vao, 0, 0); @@ -461,13 +461,11 @@ void main() unsafe { // render to fb + + gl::ClearNamedFramebufferfv(rendered_framebuffer, gl::COLOR, 0, [0.3f32, 0.4, 0.6, 1.0].as_ptr().cast()); gl::BindFramebuffer(gl::FRAMEBUFFER, rendered_framebuffer); gl::Viewport(0, 0, vp_width, vp_height); - // clear color - clear_color(Color(0.3, 0.4, 0.6, 1.0)); - gl::Clear(gl::COLOR_BUFFER_BIT); - // do the drawing gl::UseProgram(triangle_program); // select vertices diff --git a/librashader-runtime-gl46/src/quad_render.rs b/librashader-runtime-gl46/src/quad_render.rs index 272fd97..064fdff 100644 --- a/librashader-runtime-gl46/src/quad_render.rs +++ b/librashader-runtime-gl46/src/quad_render.rs @@ -1,4 +1,4 @@ -use gl::types::{GLsizeiptr, GLuint}; +use gl::types::{GLint, GLsizei, GLsizeiptr, GLuint}; #[rustfmt::skip] static QUAD_VBO_DATA: &[f32; 16] = &[ @@ -9,24 +9,55 @@ static QUAD_VBO_DATA: &[f32; 16] = &[ ]; pub struct DrawQuad { - pub vbo: GLuint, + vbo: GLuint, + vao: GLuint, } impl DrawQuad { pub fn new() -> DrawQuad { let mut vbo = 0; + let mut vao = 0; + unsafe { - gl::GenBuffers(1, &mut vbo); - gl::BindBuffer(gl::ARRAY_BUFFER, vbo); - gl::BufferData( - gl::ARRAY_BUFFER, + gl::CreateBuffers(1, &mut vbo); + gl::NamedBufferData( + vbo, std::mem::size_of_val(QUAD_VBO_DATA) as GLsizeiptr, QUAD_VBO_DATA.as_ptr().cast(), gl::STATIC_DRAW, ); - gl::BindBuffer(gl::ARRAY_BUFFER, 0); + gl::CreateVertexArrays(1, &mut vao); + + gl::EnableVertexArrayAttrib(vao, 0); + gl::EnableVertexArrayAttrib(vao, 1); + + gl::VertexArrayVertexBuffer(vao, 0, + vbo, 0, 4 * std::mem::size_of::() as GLint + ); + + gl::VertexArrayAttribFormat(vao, 0, 2, + gl::FLOAT, gl::FALSE, 0); + gl::VertexArrayAttribFormat(vao, 1, 2, + gl::FLOAT, gl::FALSE, + 2 * std::mem::size_of::() as GLuint); + + gl::VertexArrayAttribBinding(vao, 0, 0); + gl::VertexArrayAttribBinding(vao, 1, 0); + } - DrawQuad { vbo } + DrawQuad { vbo, vao } + } + + pub fn bind_vao(&self) { + unsafe { + gl::BindVertexArray(self.vao); + } + } + + pub fn unbind_vao(&self) { + unsafe { + gl::BindVertexArray(0); + } } } diff --git a/librashader/Cargo.toml b/librashader/Cargo.toml index 9e9e681..9039800 100644 --- a/librashader/Cargo.toml +++ b/librashader/Cargo.toml @@ -11,6 +11,7 @@ librashader-preprocess = { path = "../librashader-preprocess" } librashader-reflect = { path = "../librashader-reflect" } librashader-runtime-d3d11 = { path = "../librashader-runtime-d3d11" } librashader-runtime-gl = { path = "../librashader-runtime-gl" } +librashader-runtime-gl46 = { path = "../librashader-runtime-gl46" } [features] diff --git a/librashader/src/lib.rs b/librashader/src/lib.rs index e155258..9ca9d61 100644 --- a/librashader/src/lib.rs +++ b/librashader/src/lib.rs @@ -27,7 +27,7 @@ pub mod reflect { } pub mod targets { - /// Shader compiler targets and runtime for OpenGL. + /// Shader compiler targets and runtime for OpenGL 3.3+. pub mod gl { /// Shader compiler target for GLSL. pub use librashader_reflect::back::targets::GLSL; @@ -38,6 +38,17 @@ pub mod targets { } } + /// Shader compiler targets and runtime for OpenGL 4.6. + pub mod gl46 { + /// Shader compiler target for GLSL. + pub use librashader_reflect::back::targets::GLSL; + + /// Shader runtime for OpenGL. + pub mod runtime { + pub use librashader_runtime_gl46::*; + } + } + /// Shader compiler targets and runtime for DirectX. pub mod dx { /// Shader compiler target for HLSL.