gl: use texture storage
This commit is contained in:
parent
afc750c37c
commit
3aee36a361
|
@ -1,15 +1,15 @@
|
|||
use std::iter::Filter;
|
||||
use gl::types::{GLenum, GLint, GLuint};
|
||||
use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint};
|
||||
use librashader_reflect::back::cross::GlslangGlslContext;
|
||||
use librashader_reflect::back::ShaderCompilerOutput;
|
||||
use librashader_reflect::reflect::ShaderReflection;
|
||||
use librashader_reflect::reflect::TextureSemanticMap;
|
||||
use librashader_reflect::reflect::VariableSemanticMap;
|
||||
use rustc_hash::FxHashMap;
|
||||
use librashader::ShaderSource;
|
||||
use librashader::{ShaderFormat, ShaderSource};
|
||||
use librashader_presets::{Scale2D, ScaleType, Scaling, ShaderPassConfig, ShaderPreset};
|
||||
use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureImage, TextureSemantics, VariableMeta, VariableSemantics};
|
||||
use crate::FilterChain;
|
||||
use crate::{FilterChain, FilterCommon};
|
||||
use crate::framebuffer::Framebuffer;
|
||||
use crate::util::{Location, VariableLocation, RingBuffer, Size, GlImage, Texture, Viewport};
|
||||
|
||||
|
@ -84,6 +84,7 @@ impl FilterPass {
|
|||
|
||||
fn set_texture(binding: &TextureImage, texture: &Texture) {
|
||||
unsafe {
|
||||
// eprintln!("binding {} = texture {}", binding.binding, texture.image.handle);
|
||||
gl::ActiveTexture((gl::TEXTURE0 + binding.binding) as GLenum);
|
||||
gl::BindTexture(gl::TEXTURE_2D, texture.image.handle);
|
||||
|
||||
|
@ -94,7 +95,7 @@ impl FilterPass {
|
|||
}
|
||||
}
|
||||
|
||||
fn scale_framebuffer(&mut self, viewport: &Viewport, original: &Texture, source: &Texture) -> Size {
|
||||
fn scale_framebuffer(&mut self, format: ShaderFormat, viewport: &Viewport, original: &Texture, source: &Texture) -> Size {
|
||||
let mut width = 0f32;
|
||||
let mut height = 0f32;
|
||||
|
||||
|
@ -145,20 +146,107 @@ impl FilterPass {
|
|||
height: height.round() as u32
|
||||
};
|
||||
|
||||
if self.framebuffer.size != size {
|
||||
self.framebuffer.size = size;
|
||||
|
||||
self.framebuffer.init(size,if format == ShaderFormat::Unknown {
|
||||
ShaderFormat::R8G8B8A8Unorm
|
||||
} else {
|
||||
format
|
||||
});
|
||||
}
|
||||
size
|
||||
}
|
||||
|
||||
pub fn build_commands(&mut self, parent: &FilterChain, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, viewport: &Viewport, original: &Texture, source: &Texture) {
|
||||
pub fn build_commands(&mut self, parent: &FilterCommon, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, viewport: &Viewport, original: &Texture, source: &Texture) {
|
||||
let mut fb_format = ShaderFormat::R8G8B8A8Unorm;
|
||||
if self.config.srgb_framebuffer {
|
||||
fb_format = ShaderFormat::R8G8B8A8Srgb;
|
||||
} else if self.config.float_framebuffer {
|
||||
fb_format = ShaderFormat::R16G16B16A16Sfloat;
|
||||
}
|
||||
|
||||
let fb_size = self.scale_framebuffer(fb_format, viewport, original, source);
|
||||
|
||||
// println!("[frame] Using framebuffer {}, image {}", self.framebuffer.framebuffer, self.framebuffer.image);
|
||||
unsafe {
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, self.framebuffer.framebuffer);
|
||||
gl::UseProgram(self.program);
|
||||
}
|
||||
|
||||
self.build_semantics(parent, mvp, frame_count, frame_direction, fb_size, viewport, original, source);
|
||||
// shader_gl3:1514
|
||||
|
||||
if !self.ubo_location.vertex == gl::INVALID_INDEX && !self.ubo_location.fragment == gl::INVALID_INDEX {
|
||||
if let (Some(ubo), Some(ring)) = (&self.reflection.ubo, &mut self.ubo_ring) {
|
||||
let size = ubo.size;
|
||||
let buffer = ring.current();
|
||||
|
||||
unsafe {
|
||||
gl::BindBuffer(gl::UNIFORM_BUFFER, *buffer);
|
||||
gl::BufferSubData(gl::UNIFORM_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);
|
||||
}
|
||||
if self.ubo_location.vertex != gl::INVALID_INDEX {
|
||||
gl::BindBufferBase(gl::UNIFORM_BUFFER, self.ubo_location.fragment, *buffer);
|
||||
}
|
||||
}
|
||||
ring.next()
|
||||
}
|
||||
}
|
||||
|
||||
// todo: final pass?
|
||||
|
||||
unsafe {
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, self.framebuffer.framebuffer);
|
||||
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);
|
||||
//
|
||||
gl::Viewport(viewport.x, viewport.y, fb_size.width as GLsizei, fb_size.height as GLsizei);
|
||||
|
||||
if self.framebuffer.format == gl::SRGB8_ALPHA8 {
|
||||
gl::Enable(gl::FRAMEBUFFER_SRGB);
|
||||
} else {
|
||||
gl::Disable(gl::FRAMEBUFFER_SRGB);
|
||||
}
|
||||
|
||||
gl::Disable(gl::CULL_FACE);
|
||||
gl::Disable(gl::BLEND);
|
||||
gl::Disable(gl::DEPTH_TEST);
|
||||
|
||||
gl::EnableVertexAttribArray(0);
|
||||
gl::EnableVertexAttribArray(1);
|
||||
gl::BindBuffer(gl::ARRAY_BUFFER, parent.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::BindBuffer(gl::ARRAY_BUFFER, 0);
|
||||
gl::DisableVertexAttribArray(0);
|
||||
gl::DisableVertexAttribArray(1);
|
||||
|
||||
gl::Disable(gl::FRAMEBUFFER_SRGB);
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
|
||||
// todo: draw image onto fbo
|
||||
// shader_gl3 1579
|
||||
}
|
||||
|
||||
// framecount should be pre-modded
|
||||
fn build_semantics(&mut self, parent: &FilterChain, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, viewport: &Viewport, original: &Texture, source: &Texture) {
|
||||
let fb_size = self.scale_framebuffer(viewport, original, source);
|
||||
fn build_semantics(&mut self, parent: &FilterCommon, mvp: Option<&[f32]>, frame_count: u32, frame_direction: u32, fb_size: Size, viewport: &Viewport, original: &Texture, source: &Texture) {
|
||||
|
||||
if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::MVP) {
|
||||
let mvp = mvp.unwrap_or(&[
|
||||
|
@ -172,7 +260,7 @@ impl FilterPass {
|
|||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
|
||||
};
|
||||
FilterPass::build_mvp(&mut buffer[offset..][..mvp.len()], mvp)
|
||||
FilterPass::build_mvp(&mut buffer[offset..][..mvp.len() * std::mem::size_of::<f32>()], mvp)
|
||||
}
|
||||
|
||||
if let Some(variable) = self.reflection.meta.variable_meta.get(&VariableSemantics::Output) {
|
||||
|
@ -215,6 +303,11 @@ impl FilterPass {
|
|||
FilterPass::build_uint(location, &mut buffer[offset..][..4], frame_direction)
|
||||
}
|
||||
|
||||
|
||||
if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Original.semantics(0)) {
|
||||
eprintln!("setting original binding to {}", binding.binding);
|
||||
FilterPass::set_texture(binding, original);
|
||||
}
|
||||
if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::Original.semantics(0)) {
|
||||
let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location();
|
||||
let (buffer, offset) = match variable.offset {
|
||||
|
@ -223,11 +316,13 @@ impl FilterPass {
|
|||
};
|
||||
FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size);
|
||||
|
||||
if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Original.semantics(0)) {
|
||||
FilterPass::set_texture(binding, original);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Source.semantics(0)) {
|
||||
// eprintln!("setting source binding to {}", binding.binding);
|
||||
FilterPass::set_texture(binding, source);
|
||||
}
|
||||
if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::Source.semantics(0)) {
|
||||
let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location();
|
||||
let (buffer, offset) = match variable.offset {
|
||||
|
@ -235,24 +330,22 @@ impl FilterPass {
|
|||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
|
||||
};
|
||||
FilterPass::build_vec4(location, &mut buffer[offset..][..4], source.image.size);
|
||||
|
||||
if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::Source.semantics(0)) {
|
||||
FilterPass::set_texture(binding, source);
|
||||
}
|
||||
}
|
||||
|
||||
if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) {
|
||||
let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location();
|
||||
let (buffer, offset) = match variable.offset {
|
||||
MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset),
|
||||
MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
|
||||
};
|
||||
FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size);
|
||||
|
||||
if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) {
|
||||
FilterPass::set_texture(binding, original);
|
||||
}
|
||||
}
|
||||
// todo: history
|
||||
|
||||
// if let Some(binding) = self.reflection.meta.texture_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) {
|
||||
// FilterPass::set_texture(binding, original);
|
||||
// }
|
||||
// if let Some(variable) = self.reflection.meta.texture_size_meta.get(&TextureSemantics::OriginalHistory.semantics(0)) {
|
||||
// let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location();
|
||||
// let (buffer, offset) = match variable.offset {
|
||||
// MemberOffset::Ubo(offset) => (&mut self.uniform_buffer, offset),
|
||||
// MemberOffset::PushConstant(offset) => (&mut self.push_buffer, offset)
|
||||
// };
|
||||
// FilterPass::build_vec4(location, &mut buffer[offset..][..4], original.image.size);
|
||||
// }
|
||||
|
||||
for variable in self.reflection.meta.parameter_meta.values() {
|
||||
let location = self.locations.get(&variable.id).expect("variable did not have location mapped").location();
|
||||
|
|
|
@ -13,29 +13,13 @@ pub struct Framebuffer {
|
|||
pub init: bool
|
||||
}
|
||||
|
||||
impl Drop for Framebuffer {
|
||||
fn drop(&mut self) {
|
||||
if self.framebuffer != 0 {
|
||||
unsafe {
|
||||
gl::DeleteFramebuffers(1, &self.framebuffer);
|
||||
}
|
||||
}
|
||||
|
||||
if self.image != 0 {
|
||||
unsafe {
|
||||
gl::DeleteTextures(1, &self.image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, framebuffer);
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||
}
|
||||
|
||||
Framebuffer {
|
||||
|
@ -49,12 +33,8 @@ impl Framebuffer {
|
|||
}
|
||||
}
|
||||
|
||||
fn init(&mut self, mut size: Size, mut format: ShaderFormat) {
|
||||
if format == ShaderFormat::Unknown {
|
||||
format = ShaderFormat::R8G8B8A8Unorm;
|
||||
}
|
||||
|
||||
self.format = GLenum::from(format);
|
||||
pub(crate) fn init(&mut self, mut size: Size, mut format: impl Into<GLenum>) {
|
||||
self.format = format.into();
|
||||
self.size = size;
|
||||
|
||||
unsafe {
|
||||
|
@ -67,7 +47,7 @@ impl Framebuffer {
|
|||
}
|
||||
|
||||
gl::GenTextures(1, &mut self.image);
|
||||
gl::BindTexture(1, self.image);
|
||||
gl::BindTexture(gl::TEXTURE_2D, self.image);
|
||||
|
||||
if size.width == 0 {
|
||||
size.width = 1;
|
||||
|
@ -108,12 +88,12 @@ impl Framebuffer {
|
|||
self.levels = 1;
|
||||
}
|
||||
|
||||
gl::TexStorage2D(gl::TEXTURE_2D, self.levels as GLsizei, gl::RGBA8, size.width as GLsizei, size.height as GLsizei);
|
||||
gl::TexStorage2D(gl::TEXTURE_2D, self.levels as GLsizei, ShaderFormat::R8G8B8A8Unorm.into(), size.width as GLsizei, size.height as GLsizei);
|
||||
gl::FramebufferTexture2D(gl::FRAMEBUFFER,
|
||||
gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, self.image, 0);
|
||||
self.init = gl::CheckFramebufferStatus(gl::FRAMEBUFFER) == gl::FRAMEBUFFER_COMPLETE;
|
||||
}
|
||||
_ => panic!("failed to complete: {status}")
|
||||
_ => panic!("failed to complete: {status:x}")
|
||||
}
|
||||
} else {
|
||||
self.init = true;
|
||||
|
@ -124,3 +104,16 @@ impl Framebuffer {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Framebuffer {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
if self.framebuffer != 0 {
|
||||
gl::DeleteFramebuffers(1, &self.framebuffer);
|
||||
}
|
||||
if self.image != 0 {
|
||||
gl::DeleteTextures(1, &self.image);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,11 +1,14 @@
|
|||
use std::convert::TryInto;
|
||||
use std::ffi::{c_void, CStr};
|
||||
use std::sync::mpsc::Receiver;
|
||||
|
||||
use glfw;
|
||||
use glfw::{Context, Glfw, Window, WindowEvent};
|
||||
use gl;
|
||||
use gl::types::{GLint, GLsizei, GLuint};
|
||||
use gl::types::{GLchar, GLenum, GLint, GLsizei, GLuint};
|
||||
use glfw::Key::P;
|
||||
use crate::FilterChain;
|
||||
use crate::util::{GlImage, Size, Viewport};
|
||||
|
||||
const WIDTH: u32 = 900;
|
||||
const HEIGHT: u32 = 700;
|
||||
|
@ -72,12 +75,21 @@ pub fn compile_program(vertex: &str, fragment: &str) -> GLuint {
|
|||
shader_program
|
||||
}
|
||||
|
||||
|
||||
extern "system" fn debug_callback(source: GLenum, err_type: GLenum, id: GLuint, severity: GLenum, length: GLsizei, message: *const GLchar, _user: *mut c_void) {
|
||||
unsafe {
|
||||
let message = CStr::from_ptr(message);
|
||||
eprintln!("{:?}", message);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn setup() -> (Glfw, Window, Receiver<(f64, WindowEvent)>, GLuint, GLuint) {
|
||||
let mut glfw = glfw::init(glfw::FAIL_ON_ERRORS).unwrap();
|
||||
glfw.window_hint(glfw::WindowHint::ContextVersion(3, 3));
|
||||
glfw.window_hint(glfw::WindowHint::OpenGlProfile(glfw::OpenGlProfileHint::Core));
|
||||
glfw.window_hint(glfw::WindowHint::OpenGlForwardCompat(true));
|
||||
glfw.window_hint(glfw::WindowHint::Resizable(false));
|
||||
glfw.window_hint(glfw::WindowHint::OpenGlDebugContext(true));
|
||||
|
||||
let (mut window, events) = glfw.create_window(WIDTH, HEIGHT, TITLE, glfw::WindowMode::Windowed).unwrap();
|
||||
let (screen_width, screen_height) = window.get_framebuffer_size();
|
||||
|
@ -86,6 +98,18 @@ pub fn setup() -> (Glfw, Window, Receiver<(f64, WindowEvent)>, GLuint, GLuint) {
|
|||
window.set_key_polling(true);
|
||||
gl::load_with(|ptr| window.get_proc_address(ptr) as *const _);
|
||||
|
||||
|
||||
unsafe {
|
||||
gl::Enable(gl::DEBUG_OUTPUT);
|
||||
gl::Enable(gl::DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
|
||||
gl::DebugMessageCallback(Some(debug_callback), std::ptr::null_mut());
|
||||
gl::DebugMessageControl(gl::DONT_CARE,
|
||||
gl::DONT_CARE,
|
||||
gl::DONT_CARE,
|
||||
0, std::ptr::null(), gl::TRUE);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
gl::Viewport(0, 0, screen_width, screen_height);
|
||||
clear_color(Color(0.4, 0.4, 0.4, 1.0));
|
||||
|
@ -192,7 +216,7 @@ void main()
|
|||
(glfw, window, events, shader_program, vao)
|
||||
}
|
||||
|
||||
pub fn do_loop(mut glfw: Glfw, mut window: Window, events: Receiver<(f64, WindowEvent)>, shader_program: GLuint, vao: GLuint) {
|
||||
pub fn do_loop(mut glfw: Glfw, mut window: Window, events: Receiver<(f64, WindowEvent)>, triangle_program: GLuint, vao: GLuint, filter: &mut FilterChain) {
|
||||
let mut framebuffer_handle = 0;
|
||||
let mut rendered_texture = 0;
|
||||
let mut quad_vbuf = 0;
|
||||
|
@ -207,7 +231,7 @@ pub fn do_loop(mut glfw: Glfw, mut window: Window, events: Receiver<(f64, Window
|
|||
gl::BindTexture(gl::TEXTURE_2D, rendered_texture);
|
||||
|
||||
// empty image
|
||||
gl::TexImage2D(gl::TEXTURE_2D, 0, gl::RGB as GLint, WIDTH as GLsizei, HEIGHT as GLsizei, 0, gl::RGB, gl::UNSIGNED_BYTE, std::ptr::null_mut());
|
||||
gl::TexStorage2D(gl::TEXTURE_2D, 1, gl::RGBA8, WIDTH as GLsizei, HEIGHT as GLsizei);
|
||||
|
||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MAG_FILTER, gl::NEAREST as GLint);
|
||||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_MIN_FILTER, gl::NEAREST as GLint);
|
||||
|
@ -215,7 +239,7 @@ pub fn do_loop(mut glfw: Glfw, mut window: Window, events: Receiver<(f64, Window
|
|||
gl::TexParameteri(gl::TEXTURE_2D, gl::TEXTURE_WRAP_T, gl::CLAMP_TO_EDGE as GLint);
|
||||
|
||||
// set color attachment
|
||||
gl::FramebufferTexture(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, rendered_texture, 0);
|
||||
gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, rendered_texture, 0);
|
||||
|
||||
let buffers = [gl::COLOR_ATTACHMENT0];
|
||||
gl::DrawBuffers(1, buffers.as_ptr());
|
||||
|
@ -290,12 +314,12 @@ void main()
|
|||
gl::Viewport(0, 0, WIDTH as GLsizei, HEIGHT as GLsizei);
|
||||
|
||||
// clear color
|
||||
// clear_color(Color(0.3, 0.4, 0.6, 1.0));
|
||||
clear_color(Color(0.3, 0.4, 0.6, 1.0));
|
||||
gl::Clear(gl::COLOR_BUFFER_BIT);
|
||||
|
||||
|
||||
// do the drawing
|
||||
gl::UseProgram(shader_program);
|
||||
gl::UseProgram(triangle_program);
|
||||
// select vertices
|
||||
gl::BindVertexArray(vao);
|
||||
|
||||
|
@ -305,7 +329,33 @@ void main()
|
|||
// unselect vertices
|
||||
gl::BindVertexArray(0);
|
||||
|
||||
// unselect fbo
|
||||
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||
|
||||
}
|
||||
|
||||
// eprintln!("[core] rendered texture is {rendered_texture}");
|
||||
|
||||
unsafe {
|
||||
filter.frame(0, &Viewport {
|
||||
x: 0,
|
||||
y: 0,
|
||||
size: Size {
|
||||
width: WIDTH,
|
||||
height: HEIGHT
|
||||
}
|
||||
}, GlImage {
|
||||
handle: rendered_texture,
|
||||
format: gl::RGBA,
|
||||
size: Size {
|
||||
width: WIDTH,
|
||||
height: HEIGHT
|
||||
},
|
||||
padded_size: Default::default()
|
||||
}, false)
|
||||
}
|
||||
|
||||
unsafe {
|
||||
// texture is done now.
|
||||
|
||||
// todo: insert postprocessing stuff to rendered_texture
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
#![feature(strict_provenance)]
|
||||
|
||||
mod hello_triangle;
|
||||
mod filter;
|
||||
mod filter_pass;
|
||||
|
@ -42,6 +44,13 @@ unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint {
|
|||
shader
|
||||
}
|
||||
|
||||
static QUAD_VBO_DATA: &'static [f32; 16] = &[
|
||||
0.0f32, 0.0f32, 0.0f32, 0.0f32,
|
||||
1.0f32, 0.0f32, 1.0f32, 0.0f32,
|
||||
0.0f32, 1.0f32, 0.0f32, 1.0f32,
|
||||
1.0f32, 1.0f32, 1.0f32, 1.0f32,
|
||||
];
|
||||
|
||||
impl FilterChain {
|
||||
fn load_pass_semantics(uniform_semantics: &mut FxHashMap<String, UniformSemantic>, texture_semantics: &mut FxHashMap<String, SemanticMap<TextureSemantics>>,
|
||||
config: &ShaderPassConfig) {
|
||||
|
@ -114,12 +123,19 @@ impl FilterChain {
|
|||
|
||||
pub struct FilterChain {
|
||||
passes: Vec<FilterPass>,
|
||||
common: FilterCommon,
|
||||
pub quad_vao: GLuint,
|
||||
}
|
||||
|
||||
pub struct FilterCommon {
|
||||
semantics: ReflectSemantics,
|
||||
preset: ShaderPreset,
|
||||
original_history: Vec<Framebuffer>,
|
||||
history: Vec<Texture>,
|
||||
feedback: Vec<Texture>,
|
||||
luts: FxHashMap<String, Texture>
|
||||
luts: FxHashMap<String, Texture>,
|
||||
pub quad_vbo: GLuint,
|
||||
pub input_framebuffer: Framebuffer,
|
||||
}
|
||||
|
||||
impl FilterChain {
|
||||
|
@ -194,7 +210,8 @@ impl FilterChain {
|
|||
|
||||
for res in &vertex_resources.stage_inputs {
|
||||
let loc = glsl.context.compiler.vertex.get_decoration(res.id, Decoration::Location)?;
|
||||
let loc_name = format!("RARCH_ATTRIBUTE_{loc}");
|
||||
let loc_name = format!("RARCH_ATTRIBUTE_{loc}\0");
|
||||
eprintln!("{loc_name}");
|
||||
gl::BindAttribLocation(program, loc, loc_name.as_str().as_ptr().cast())
|
||||
}
|
||||
gl::LinkProgram(program);
|
||||
|
@ -208,7 +225,7 @@ impl FilterChain {
|
|||
}
|
||||
|
||||
for binding in &glsl.context.texture_fixups {
|
||||
let loc_name = format!("RARCH_TEXTURE_{}", *binding);
|
||||
let loc_name = format!("RARCH_TEXTURE_{}\0", *binding);
|
||||
unsafe {
|
||||
let location = gl::GetUniformLocation(program, loc_name.as_str().as_ptr().cast());
|
||||
if location >= 0 {
|
||||
|
@ -373,24 +390,51 @@ impl FilterChain {
|
|||
});
|
||||
}
|
||||
|
||||
let mut quad_vbo = 0;
|
||||
unsafe {
|
||||
gl::GenBuffers(1, &mut quad_vbo);
|
||||
gl::BindBuffer(gl::ARRAY_BUFFER, quad_vbo);
|
||||
gl::BufferData(gl::ARRAY_BUFFER, 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);
|
||||
}
|
||||
|
||||
let mut quad_vao = 0;
|
||||
unsafe {
|
||||
gl::GenVertexArrays(1, &mut quad_vao);
|
||||
}
|
||||
|
||||
// todo: split params
|
||||
Ok(FilterChain {
|
||||
passes: filters,
|
||||
quad_vao,
|
||||
common: FilterCommon {
|
||||
semantics,
|
||||
preset,
|
||||
original_history: vec![],
|
||||
history: vec![],
|
||||
feedback: vec![],
|
||||
luts,
|
||||
quad_vbo,
|
||||
input_framebuffer: Framebuffer::new(1)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
// how much info do we actually need?
|
||||
fn frame(&mut self, count: u32, vp: &Viewport, input: GlImage, clear: bool) {
|
||||
pub fn frame(&mut self, count: u32, vp: &Viewport, input: GlImage, clear: bool) {
|
||||
//
|
||||
// unsafe {
|
||||
// gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||
// gl::BindVertexArray(self.quad_vao);
|
||||
// }
|
||||
|
||||
// todo: copy framebuffer
|
||||
// shader_gl3: 2067
|
||||
let filter = self.common.preset.shaders.first().map(|f| f.filter).unwrap_or_default();
|
||||
let wrap_mode = self.common.preset.shaders.first().map(|f| f.wrap_mode).unwrap_or_default();
|
||||
|
||||
let filter = self.preset.shaders.first().map(|f| f.filter).unwrap_or_default();
|
||||
let wrap_mode = self.preset.shaders.first().map(|f| f.wrap_mode).unwrap_or_default();
|
||||
let original = Texture {
|
||||
image: input,
|
||||
filter,
|
||||
|
@ -401,9 +445,15 @@ impl FilterChain {
|
|||
let mut source = original.clone();
|
||||
|
||||
for passes in &mut self.passes {
|
||||
passes.build_commands(&self.common, None, count, 1, vp, &original, &source);
|
||||
// passes.build_semantics(&self, None, count, 1, vp, &original, &source);
|
||||
}
|
||||
|
||||
|
||||
// unsafe {
|
||||
// gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
|
||||
// gl::BindVertexArray(0);
|
||||
// }
|
||||
// todo: deal with the mess that is frame history
|
||||
}
|
||||
|
||||
|
@ -412,8 +462,8 @@ impl FilterChain {
|
|||
// todo: make copy
|
||||
|
||||
// todo: get filter info from pass data.
|
||||
let filter = self.preset.shaders.first().map(|f| f.filter).unwrap_or_default();
|
||||
let wrap_mode = self.preset.shaders.first().map(|f| f.wrap_mode).unwrap_or_default();
|
||||
let filter = self.common.preset.shaders.first().map(|f| f.filter).unwrap_or_default();
|
||||
let wrap_mode = self.common.preset.shaders.first().map(|f| f.wrap_mode).unwrap_or_default();
|
||||
let original = Texture {
|
||||
image: input,
|
||||
filter,
|
||||
|
@ -437,10 +487,12 @@ mod tests {
|
|||
#[test]
|
||||
fn triangle() {
|
||||
let (glfw, window, events, shader, vao) = hello_triangle::setup();
|
||||
FilterChain::load("../test/basic.slangp").unwrap();
|
||||
let mut filter = FilterChain::load("../test/basic.slangp").unwrap();
|
||||
|
||||
|
||||
// FilterChain::load("../test/slang-shaders/crt/crt-royale.slangp").unwrap();
|
||||
|
||||
hello_triangle::do_loop(glfw, window, events, shader, vao);
|
||||
hello_triangle::do_loop(glfw, window, events, shader, vao, &mut filter );
|
||||
}
|
||||
|
||||
// #[test]
|
||||
|
|
|
@ -47,7 +47,7 @@ pub struct Viewport {
|
|||
pub size: Size,
|
||||
}
|
||||
|
||||
#[derive(Default, Debug, Copy, Clone)]
|
||||
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
|
||||
pub struct Size {
|
||||
pub width: u32,
|
||||
pub height: u32,
|
||||
|
|
Loading…
Reference in a new issue