gl46: implement DSA version of gl runtime

This commit is contained in:
chyyran 2022-11-28 18:56:35 -05:00
parent 7b2721aa19
commit 5078015605
12 changed files with 157 additions and 190 deletions

View file

@ -13,6 +13,7 @@
<sourceFolder url="file://$MODULE_DIR$/librashader-compiler/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/librashader-compiler/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/librashader-common/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/librashader-common/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/librashader-runtime-d3d11/src" isTestSource="false" /> <sourceFolder url="file://$MODULE_DIR$/librashader-runtime-d3d11/src" isTestSource="false" />
<sourceFolder url="file://$MODULE_DIR$/librashader-runtime-gl46/src" isTestSource="false" />
<excludeFolder url="file://$MODULE_DIR$/target" /> <excludeFolder url="file://$MODULE_DIR$/target" />
</content> </content>
<orderEntry type="inheritedJdk" /> <orderEntry type="inheritedJdk" />

17
Cargo.lock generated
View file

@ -418,6 +418,7 @@ dependencies = [
"librashader-reflect", "librashader-reflect",
"librashader-runtime-d3d11", "librashader-runtime-d3d11",
"librashader-runtime-gl", "librashader-runtime-gl",
"librashader-runtime-gl46",
] ]
[[package]] [[package]]
@ -496,6 +497,22 @@ dependencies = [
"thiserror", "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]] [[package]]
name = "lock_api" name = "lock_api"
version = "0.4.9" version = "0.4.9"

View file

@ -7,4 +7,5 @@ members = [
"librashader-reflect", "librashader-reflect",
"librashader-runtime-d3d11", "librashader-runtime-d3d11",
"librashader-runtime-gl", "librashader-runtime-gl",
"librashader-runtime-gl46",
] ]

View file

@ -9,12 +9,13 @@ librashader (*/ˈli:brəʃeɪdɚ/*) is a preprocessor, compiler, and runtime for
Heavily WIP. Heavily WIP.
## Supported Render APIs ## 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). of DirectX and OpenGL, as well as Metal, are not supported (but pull-requests are welcome).
| **API** | **Status** | **`librashader` feature** | | **API** | **Status** | **`librashader` feature** |
|-------------|------------|---------------------------| |-------------|------------|---------------------------|
| OpenGL 3.3+ | ✔ | `gl` | | OpenGL 3.3+ | ✔ | `gl` |
| OpenGL 4.6 | ✔ | `gl46` |
| Vulkan | 🚧 | `vk` | | Vulkan | 🚧 | `vk` |
| Direct3D11 | 🚧 | `d3d11` | | Direct3D11 | 🚧 | `d3d11` |
| Direct3D12 | 🚧 | `d3d12` | | 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 objects are used rather than `glTexParameter`.
* Sampler inputs and outputs are not renamed. This is useful for debugging shaders in RenderDoc. * 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. * 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 * Direct3D 11
* The staging buffer is not kept around when loading static textures (LUTs). * 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. * 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 ## License
The core parts of librashader such as the preprocessor, the preset parser, 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. the reflection library, and the runtimes, are all licensed under the Mozilla Public License version 2.0.

View file

@ -183,6 +183,7 @@ impl FilterPass {
} }
unsafe { unsafe {
// can't use framebuffer.clear because it will unbind.
gl::ColorMask(gl::TRUE, gl::TRUE, gl::TRUE, gl::TRUE); gl::ColorMask(gl::TRUE, gl::TRUE, gl::TRUE, gl::TRUE);
gl::ClearColor(0.0f32, 0.0f32, 0.0f32, 0.0f32); gl::ClearColor(0.0f32, 0.0f32, 0.0f32, 0.0f32);
gl::Clear(gl::COLOR_BUFFER_BIT); gl::Clear(gl::COLOR_BUFFER_BIT);

View file

@ -29,7 +29,7 @@ use crate::texture::Texture;
pub struct FilterChain { pub struct FilterChain {
passes: Box<[FilterPass]>, passes: Box<[FilterPass]>,
common: FilterCommon, common: FilterCommon,
filter_vao: GLuint, pub(crate) draw_quad: DrawQuad,
output_framebuffers: Box<[Framebuffer]>, output_framebuffers: Box<[Framebuffer]>,
feedback_framebuffers: Box<[Framebuffer]>, feedback_framebuffers: Box<[Framebuffer]>,
history_framebuffers: VecDeque<Framebuffer>, history_framebuffers: VecDeque<Framebuffer>,
@ -43,7 +43,6 @@ pub struct FilterCommon {
pub output_textures: Box<[Texture]>, pub output_textures: Box<[Texture]>,
pub feedback_textures: Box<[Texture]>, pub feedback_textures: Box<[Texture]>,
pub history_textures: Box<[Texture]>, pub history_textures: Box<[Texture]>,
pub(crate) draw_quad: DrawQuad,
} }
pub struct FilterMutable { pub struct FilterMutable {
@ -177,17 +176,12 @@ impl FilterChain {
// create VBO objects // create VBO objects
let draw_quad = DrawQuad::new(); let draw_quad = DrawQuad::new();
let mut filter_vao = 0;
unsafe {
gl::GenVertexArrays(1, &mut filter_vao);
}
Ok(FilterChain { Ok(FilterChain {
passes: filters, passes: filters,
output_framebuffers: output_framebuffers.into_boxed_slice(), output_framebuffers: output_framebuffers.into_boxed_slice(),
feedback_framebuffers: feedback_framebuffers.into_boxed_slice(), feedback_framebuffers: feedback_framebuffers.into_boxed_slice(),
history_framebuffers, history_framebuffers,
filter_vao, draw_quad,
common: FilterCommon { common: FilterCommon {
config: FilterMutable { config: FilterMutable {
passes_enabled: preset.shader_count as usize, passes_enabled: preset.shader_count as usize,
@ -199,7 +193,6 @@ impl FilterChain {
output_textures: output_textures.into_boxed_slice(), output_textures: output_textures.into_boxed_slice(),
feedback_textures: feedback_textures.into_boxed_slice(), feedback_textures: feedback_textures.into_boxed_slice(),
history_textures, history_textures,
draw_quad,
}, },
}) })
} }
@ -279,6 +272,15 @@ impl FilterChain {
fn load_luts(textures: &[TextureConfig]) -> Result<FxHashMap<usize, Texture>> { fn load_luts(textures: &[TextureConfig]) -> Result<FxHashMap<usize, Texture>> {
let mut luts = FxHashMap::default(); 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() { for (index, texture) in textures.iter().enumerate() {
let image = Image::load(&texture.path)?; let image = Image::load(&texture.path)?;
@ -290,10 +292,10 @@ impl FilterChain {
let mut handle = 0; let mut handle = 0;
unsafe { unsafe {
gl::GenTextures(1, &mut handle); gl::CreateTextures(gl::TEXTURE_2D,1, &mut handle);
gl::BindTexture(gl::TEXTURE_2D, handle);
gl::TexStorage2D( gl::TextureStorage2D(
gl::TEXTURE_2D, handle,
levels as GLsizei, levels as GLsizei,
gl::RGBA8, gl::RGBA8,
image.size.width as GLsizei, image.size.width as GLsizei,
@ -302,12 +304,10 @@ impl FilterChain {
gl::PixelStorei(gl::UNPACK_ROW_LENGTH, 0); gl::PixelStorei(gl::UNPACK_ROW_LENGTH, 0);
gl::PixelStorei(gl::UNPACK_ALIGNMENT, 4); gl::PixelStorei(gl::UNPACK_ALIGNMENT, 4);
gl::BindBuffer(gl::PIXEL_UNPACK_BUFFER, 0);
gl::TexSubImage2D( gl::TextureSubImage2D(
gl::TEXTURE_2D, handle,
0, 0, 0, 0,
0,
0,
image.size.width as GLsizei, image.size.width as GLsizei,
image.size.height as GLsizei, image.size.height as GLsizei,
gl::RGBA, gl::RGBA,
@ -317,10 +317,8 @@ impl FilterChain {
let mipmap = levels > 1; let mipmap = levels > 1;
if mipmap { if mipmap {
gl::GenerateMipmap(gl::TEXTURE_2D); gl::GenerateTextureMipmap(handle);
} }
gl::BindTexture(gl::TEXTURE_2D, 0);
} }
luts.insert( luts.insert(
@ -338,6 +336,10 @@ impl FilterChain {
}, },
); );
} }
unsafe {
gl::BindBuffer(gl::PIXEL_UNPACK_BUFFER, pixel_unpack as GLuint);
};
Ok(luts) Ok(luts)
} }
@ -416,17 +418,15 @@ impl FilterChain {
let size = ubo.size; let size = ubo.size;
let mut ring: InlineRingBuffer<GLuint, 16> = InlineRingBuffer::new(); let mut ring: InlineRingBuffer<GLuint, 16> = InlineRingBuffer::new();
unsafe { unsafe {
gl::GenBuffers(16, ring.items_mut().as_mut_ptr()); gl::CreateBuffers(16, ring.items_mut().as_mut_ptr());
for buffer in ring.items() { for buffer in ring.items() {
gl::BindBuffer(gl::UNIFORM_BUFFER, *buffer); gl::NamedBufferData(
gl::BufferData( *buffer,
gl::UNIFORM_BUFFER,
size as GLsizeiptr, size as GLsizeiptr,
std::ptr::null(), std::ptr::null(),
gl::STREAM_DRAW, gl::STREAM_DRAW,
); );
} }
gl::BindBuffer(gl::UNIFORM_BUFFER, 0);
} }
Some(ring) Some(ring)
} else { } else {
@ -593,11 +593,9 @@ impl FilterChain {
return Ok(()); return Ok(());
} }
unsafe { // do not need to rebind FBO 0 here since first `draw` will
// do not need to rebind FBO 0 here since first `draw` will // bind automatically.
// bind automatically. self.draw_quad.bind_vao();
gl::BindVertexArray(self.filter_vao);
}
let filter = passes[0].config.filter; let filter = passes[0].config.filter;
let wrap_mode = passes[0].config.wrap_mode; let wrap_mode = passes[0].config.wrap_mode;
@ -710,10 +708,9 @@ impl FilterChain {
self.push_history(input)?; self.push_history(input)?;
// pass.draw should return framebuffer bound to 0. // do not need to rebind FBO 0 here since first `draw` will
unsafe { // bind automatically.
gl::BindVertexArray(0); self.draw_quad.unbind_vao();
}
Ok(()) Ok(())
} }

View file

@ -104,9 +104,7 @@ impl FilterPass {
fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture) { fn bind_texture(samplers: &SamplerSet, binding: &TextureBinding, texture: &Texture) {
unsafe { unsafe {
// eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding); // eprintln!("setting {} to texunit {}", texture.image.handle, binding.binding);
gl::ActiveTexture(gl::TEXTURE0 + binding.binding); gl::BindTextureUnit(binding.binding, texture.image.handle);
gl::BindTexture(gl::TEXTURE_2D, texture.image.handle);
gl::BindSampler(binding.binding, gl::BindSampler(binding.binding,
samplers.get(texture.wrap_mode, texture.filter, texture.mip_filter)); samplers.get(texture.wrap_mode, texture.filter, texture.mip_filter));
} }
@ -137,7 +135,7 @@ impl FilterPass {
let framebuffer = output.framebuffer; let framebuffer = output.framebuffer;
unsafe { unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.handle); // gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.handle);
gl::UseProgram(self.program); gl::UseProgram(self.program);
} }
@ -162,14 +160,12 @@ impl FilterPass {
let buffer = ring.current(); let buffer = ring.current();
unsafe { unsafe {
gl::BindBuffer(gl::UNIFORM_BUFFER, *buffer); gl::NamedBufferSubData(
gl::BufferSubData( *buffer,
gl::UNIFORM_BUFFER,
0, 0,
size as GLsizeiptr, size as GLsizeiptr,
self.uniform_buffer.as_ptr().cast(), self.uniform_buffer.as_ptr().cast(),
); );
gl::BindBuffer(gl::UNIFORM_BUFFER, 0);
if self.ubo_location.vertex != gl::INVALID_INDEX { if self.ubo_location.vertex != gl::INVALID_INDEX {
gl::BindBufferBase(gl::UNIFORM_BUFFER, self.ubo_location.vertex, *buffer); gl::BindBufferBase(gl::UNIFORM_BUFFER, self.ubo_location.vertex, *buffer);
@ -183,10 +179,9 @@ impl FilterPass {
} }
unsafe { unsafe {
gl::ColorMask(gl::TRUE, gl::TRUE, gl::TRUE, gl::TRUE); // can use because DSA
gl::ClearColor(0.0f32, 0.0f32, 0.0f32, 0.0f32); framebuffer.clear();
gl::Clear(gl::COLOR_BUFFER_BIT); gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer.handle);
//
gl::Viewport( gl::Viewport(
output.x, output.x,
output.y, output.y,
@ -204,36 +199,7 @@ impl FilterPass {
gl::Disable(gl::BLEND); gl::Disable(gl::BLEND);
gl::Disable(gl::DEPTH_TEST); 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::<f32>()) as GLsizei,
std::ptr::invalid(0),
);
gl::VertexAttribPointer(
1,
2,
gl::FLOAT,
gl::FALSE,
(4 * std::mem::size_of::<f32>()) as GLsizei,
std::ptr::invalid(2 * std::mem::size_of::<f32>()),
);
gl::DrawArrays(gl::TRIANGLE_STRIP, 0, 4); 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::Disable(gl::FRAMEBUFFER_SRGB);
gl::BindFramebuffer(gl::FRAMEBUFFER, 0); gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
} }
@ -483,12 +449,12 @@ impl FilterPass {
// bind float parameters // bind float parameters
for (id, (location, offset)) in for (id, (location, offset)) in
self.uniform_bindings self.uniform_bindings
.iter() .iter()
.filter_map(|(binding, value)| match binding { .filter_map(|(binding, value)| match binding {
UniformBinding::Parameter(id) => Some((id, value)), UniformBinding::Parameter(id) => Some((id, value)),
_ => None, _ => None,
}) })
{ {
let id = id.as_str(); let id = id.as_str();
let (buffer, offset) = match offset { let (buffer, offset) = match offset {

View file

@ -21,9 +21,7 @@ impl Framebuffer {
pub fn new(max_levels: u32) -> Framebuffer { pub fn new(max_levels: u32) -> Framebuffer {
let mut framebuffer = 0; let mut framebuffer = 0;
unsafe { unsafe {
gl::GenFramebuffers(1, &mut framebuffer); gl::CreateFramebuffers(1, &mut framebuffer);
gl::BindFramebuffer(gl::FRAMEBUFFER, framebuffer);
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
} }
Framebuffer { Framebuffer {
@ -139,11 +137,9 @@ impl Framebuffer {
pub(crate) fn clear(&self) { pub(crate) fn clear(&self) {
unsafe { unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, self.handle); gl::ClearNamedFramebufferfv(self.handle,
gl::ColorMask(gl::TRUE, gl::TRUE, gl::TRUE, gl::TRUE); gl::COLOR, 0,
gl::ClearColor(0.0, 0.0, 0.0, 0.0); [0.0f32, 0.0, 0.0, 0.0].as_ptr().cast());
gl::Clear(gl::COLOR_BUFFER_BIT);
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
} }
} }
@ -154,64 +150,15 @@ impl Framebuffer {
} }
unsafe { 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::BlitNamedFramebuffer(image.handle, self.handle,
gl::READ_FRAMEBUFFER, 0, 0, image.size.width as GLint, image.size.height as GLint,
gl::COLOR_ATTACHMENT0, 0, 0, self.size.width as GLint, self.size.height as GLint,
gl::TEXTURE_2D, gl::COLOR_BUFFER_BIT, gl::NEAREST);
image.handle,
0,
);
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(()) Ok(())
@ -225,22 +172,18 @@ impl Framebuffer {
self.size = size; self.size = size;
unsafe { unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, self.handle);
// reset the framebuffer image // reset the framebuffer image
if self.image != 0 { if self.image != 0 {
gl::FramebufferTexture2D( gl::NamedFramebufferTexture(
gl::FRAMEBUFFER, self.handle,
gl::COLOR_ATTACHMENT0, gl::COLOR_ATTACHMENT0,
gl::TEXTURE_2D,
0, 0,
0, 0,
); );
gl::DeleteTextures(1, &self.image); gl::DeleteTextures(1, &self.image);
} }
gl::GenTextures(1, &mut self.image); gl::CreateTextures(gl::TEXTURE_2D,1, &mut self.image);
gl::BindTexture(gl::TEXTURE_2D, self.image);
if size.width == 0 { if size.width == 0 {
size.width = 1; size.width = 1;
@ -257,18 +200,17 @@ impl Framebuffer {
self.levels = 1; self.levels = 1;
} }
gl::TexStorage2D( gl::TextureStorage2D(
gl::TEXTURE_2D, self.image,
self.levels as GLsizei, self.levels as GLsizei,
self.format, self.format,
size.width as GLsizei, size.width as GLsizei,
size.height as GLsizei, size.height as GLsizei,
); );
gl::FramebufferTexture2D( gl::NamedFramebufferTexture(
gl::FRAMEBUFFER, self.handle,
gl::COLOR_ATTACHMENT0, gl::COLOR_ATTACHMENT0,
gl::TEXTURE_2D,
self.image, self.image,
0, 0,
); );
@ -279,16 +221,14 @@ impl Framebuffer {
gl::FRAMEBUFFER_UNSUPPORTED => { gl::FRAMEBUFFER_UNSUPPORTED => {
eprintln!("unsupported fbo"); eprintln!("unsupported fbo");
gl::FramebufferTexture2D( gl::NamedFramebufferTexture(
gl::FRAMEBUFFER, self.handle,
gl::COLOR_ATTACHMENT0, gl::COLOR_ATTACHMENT0,
gl::TEXTURE_2D,
0, 0,
0, 0,
); );
gl::DeleteTextures(1, &self.image); gl::DeleteTextures(1, &self.image);
gl::GenTextures(1, &mut self.image); gl::CreateTextures(gl::TEXTURE_2D, 1, &mut self.image);
gl::BindTexture(1, self.image);
self.levels = util::calc_miplevel(size); self.levels = util::calc_miplevel(size);
if self.levels > self.max_levels { if self.levels > self.max_levels {
@ -298,17 +238,16 @@ impl Framebuffer {
self.levels = 1; self.levels = 1;
} }
gl::TexStorage2D( gl::TextureStorage2D(
gl::TEXTURE_2D, self.image,
self.levels as GLsizei, self.levels as GLsizei,
ShaderFormat::R8G8B8A8Unorm.into(), ShaderFormat::R8G8B8A8Unorm.into(),
size.width as GLsizei, size.width as GLsizei,
size.height as GLsizei, size.height as GLsizei,
); );
gl::FramebufferTexture2D( gl::NamedFramebufferTexture(
gl::FRAMEBUFFER, self.handle,
gl::COLOR_ATTACHMENT0, gl::COLOR_ATTACHMENT0,
gl::TEXTURE_2D,
self.image, self.image,
0, 0,
); );
@ -318,9 +257,6 @@ impl Framebuffer {
_ => return Err(FilterChainError::FramebufferInit(status)) _ => return Err(FilterChainError::FramebufferInit(status))
} }
} }
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
gl::BindTexture(gl::TEXTURE_2D, 0);
} }
Ok(()) Ok(())

View file

@ -12,7 +12,7 @@ use crate::framebuffer::{Framebuffer, GlImage, Viewport};
const WIDTH: u32 = 900; const WIDTH: u32 = 900;
const HEIGHT: u32 = 700; 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 { pub fn compile_program(vertex: &str, fragment: &str) -> GLuint {
let vertex_shader = unsafe { gl::CreateShader(gl::VERTEX_SHADER) }; 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::ObjectLabel(gl::VERTEX_ARRAY, vao, -1, b"triangle_vao\0".as_ptr().cast());
gl::VertexArrayVertexBuffer(vao, 0, gl::VertexArrayVertexBuffer(vao, 0,
vbo, 0, (6 * std::mem::size_of::<f32>()) as GLint vbo, 0, 6 * std::mem::size_of::<f32>() as GLint
); );
gl::EnableVertexArrayAttrib(vao, 0); // this is "layout (location = 0)" in vertex shader gl::EnableVertexArrayAttrib(vao, 0); // this is "layout (location = 0)" in vertex shader
@ -226,7 +226,7 @@ void main()
gl::EnableVertexArrayAttrib(vao, 1); gl::EnableVertexArrayAttrib(vao, 1);
gl::VertexArrayAttribFormat(vao, 1, 3, gl::VertexArrayAttribFormat(vao, 1, 3,
gl::FLOAT, gl::FALSE, (3 * std::mem::size_of::<f32>() as GLuint)); gl::FLOAT, gl::FALSE, 3 * std::mem::size_of::<f32>() as GLuint);
gl::VertexArrayAttribBinding(vao, 0, 0); gl::VertexArrayAttribBinding(vao, 0, 0);
@ -461,13 +461,11 @@ void main()
unsafe { unsafe {
// render to fb // 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::BindFramebuffer(gl::FRAMEBUFFER, rendered_framebuffer);
gl::Viewport(0, 0, vp_width, vp_height); 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 // do the drawing
gl::UseProgram(triangle_program); gl::UseProgram(triangle_program);
// select vertices // select vertices

View file

@ -1,4 +1,4 @@
use gl::types::{GLsizeiptr, GLuint}; use gl::types::{GLint, GLsizei, GLsizeiptr, GLuint};
#[rustfmt::skip] #[rustfmt::skip]
static QUAD_VBO_DATA: &[f32; 16] = &[ static QUAD_VBO_DATA: &[f32; 16] = &[
@ -9,24 +9,55 @@ static QUAD_VBO_DATA: &[f32; 16] = &[
]; ];
pub struct DrawQuad { pub struct DrawQuad {
pub vbo: GLuint, vbo: GLuint,
vao: GLuint,
} }
impl DrawQuad { impl DrawQuad {
pub fn new() -> DrawQuad { pub fn new() -> DrawQuad {
let mut vbo = 0; let mut vbo = 0;
let mut vao = 0;
unsafe { unsafe {
gl::GenBuffers(1, &mut vbo); gl::CreateBuffers(1, &mut vbo);
gl::BindBuffer(gl::ARRAY_BUFFER, vbo); gl::NamedBufferData(
gl::BufferData( vbo,
gl::ARRAY_BUFFER,
std::mem::size_of_val(QUAD_VBO_DATA) as GLsizeiptr, std::mem::size_of_val(QUAD_VBO_DATA) as GLsizeiptr,
QUAD_VBO_DATA.as_ptr().cast(), QUAD_VBO_DATA.as_ptr().cast(),
gl::STATIC_DRAW, 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::<f32>() 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::<f32>() 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);
}
} }
} }

View file

@ -11,6 +11,7 @@ librashader-preprocess = { path = "../librashader-preprocess" }
librashader-reflect = { path = "../librashader-reflect" } librashader-reflect = { path = "../librashader-reflect" }
librashader-runtime-d3d11 = { path = "../librashader-runtime-d3d11" } librashader-runtime-d3d11 = { path = "../librashader-runtime-d3d11" }
librashader-runtime-gl = { path = "../librashader-runtime-gl" } librashader-runtime-gl = { path = "../librashader-runtime-gl" }
librashader-runtime-gl46 = { path = "../librashader-runtime-gl46" }
[features] [features]

View file

@ -27,7 +27,7 @@ pub mod reflect {
} }
pub mod targets { pub mod targets {
/// Shader compiler targets and runtime for OpenGL. /// Shader compiler targets and runtime for OpenGL 3.3+.
pub mod gl { pub mod gl {
/// Shader compiler target for GLSL. /// Shader compiler target for GLSL.
pub use librashader_reflect::back::targets::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. /// Shader compiler targets and runtime for DirectX.
pub mod dx { pub mod dx {
/// Shader compiler target for HLSL. /// Shader compiler target for HLSL.