test(gl): Add OpenGL render test
This commit is contained in:
parent
79513a301e
commit
799d409ddb
72
Cargo.lock
generated
72
Cargo.lock
generated
|
@ -235,7 +235,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "52bca67b61cb81e5553babde81b8211f713cb6db79766f80168f3e5f40ea6c82"
|
||||
dependencies = [
|
||||
"ash",
|
||||
"raw-window-handle 0.6.2",
|
||||
"raw-window-handle",
|
||||
"raw-window-metal",
|
||||
]
|
||||
|
||||
|
@ -880,12 +880,6 @@ dependencies = [
|
|||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cty"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b365fabc795046672053e29c954733ec3b05e4be654ab130fe8f1f94d7051f35"
|
||||
|
||||
[[package]]
|
||||
name = "cursor-icon"
|
||||
version = "1.1.0"
|
||||
|
@ -1194,35 +1188,22 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "glfw"
|
||||
version = "0.47.0"
|
||||
version = "0.58.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2c532509718cb34e0c449ec5ef74529c1af3a33b664e6b8ddfe29252f86f936"
|
||||
checksum = "d1cad81f99085cabd6a4a99403335bc3f3d00d6cf4467e478f13c393ced9259d"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"glfw-sys",
|
||||
"objc",
|
||||
"raw-window-handle 0.4.3",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glfw"
|
||||
version = "0.49.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c70971598fc996224a36fe95256e90335242c00da647f7b0a0b125136613c54b"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"glfw-sys",
|
||||
"objc",
|
||||
"raw-window-handle 0.5.2",
|
||||
"objc2 0.5.2",
|
||||
"raw-window-handle",
|
||||
"winapi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "glfw-sys"
|
||||
version = "4.0.0+3.3.5"
|
||||
version = "5.0.0+3.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5abed6d39a50226676aab893d6b4ad154da7e93fcdfed90d7696758a1b477ed1"
|
||||
checksum = "1dfc32d45fb58ff38b112696907963a7d671e9cf742b16f882062169a053cf88"
|
||||
dependencies = [
|
||||
"cmake",
|
||||
]
|
||||
|
@ -1875,7 +1856,7 @@ version = "0.4.5"
|
|||
dependencies = [
|
||||
"array-init",
|
||||
"bytemuck",
|
||||
"glfw 0.47.0",
|
||||
"glfw",
|
||||
"glow 0.14.1",
|
||||
"librashader-cache",
|
||||
"librashader-common",
|
||||
|
@ -1917,7 +1898,6 @@ dependencies = [
|
|||
"ash",
|
||||
"ash-window",
|
||||
"bytemuck",
|
||||
"glfw 0.49.1",
|
||||
"gpu-allocator 0.27.0",
|
||||
"librashader-cache",
|
||||
"librashader-common",
|
||||
|
@ -1927,7 +1907,7 @@ dependencies = [
|
|||
"librashader-runtime",
|
||||
"num",
|
||||
"parking_lot",
|
||||
"raw-window-handle 0.6.2",
|
||||
"raw-window-handle",
|
||||
"rayon",
|
||||
"thiserror",
|
||||
"winit",
|
||||
|
@ -1949,7 +1929,7 @@ dependencies = [
|
|||
"librashader-runtime",
|
||||
"log",
|
||||
"pollster",
|
||||
"raw-window-handle 0.6.2",
|
||||
"raw-window-handle",
|
||||
"rayon",
|
||||
"thiserror",
|
||||
"wgpu",
|
||||
|
@ -1962,7 +1942,12 @@ version = "0.1.0"
|
|||
dependencies = [
|
||||
"anyhow",
|
||||
"ash",
|
||||
"bitvec",
|
||||
"d3d12-descriptor-heap",
|
||||
"gfx-maths",
|
||||
"glfw",
|
||||
"glow 0.14.1",
|
||||
"gpu-allocator 0.27.0",
|
||||
"image",
|
||||
"image-compare",
|
||||
"librashader",
|
||||
|
@ -2156,7 +2141,7 @@ dependencies = [
|
|||
"log",
|
||||
"ndk-sys",
|
||||
"num_enum",
|
||||
"raw-window-handle 0.6.2",
|
||||
"raw-window-handle",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
|
@ -2837,21 +2822,6 @@ dependencies = [
|
|||
"rgb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.4.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b800beb9b6e7d2df1fe337c9e3d04e3af22a124460fb4c30fcc22c9117cefb41"
|
||||
dependencies = [
|
||||
"cty",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.5.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9"
|
||||
|
||||
[[package]]
|
||||
name = "raw-window-handle"
|
||||
version = "0.6.2"
|
||||
|
@ -2867,7 +2837,7 @@ dependencies = [
|
|||
"cocoa",
|
||||
"core-graphics",
|
||||
"objc",
|
||||
"raw-window-handle 0.6.2",
|
||||
"raw-window-handle",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -3818,7 +3788,7 @@ dependencies = [
|
|||
"naga",
|
||||
"parking_lot",
|
||||
"profiling",
|
||||
"raw-window-handle 0.6.2",
|
||||
"raw-window-handle",
|
||||
"smallvec",
|
||||
"static_assertions",
|
||||
"wasm-bindgen",
|
||||
|
@ -3846,7 +3816,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"parking_lot",
|
||||
"profiling",
|
||||
"raw-window-handle 0.6.2",
|
||||
"raw-window-handle",
|
||||
"rustc-hash 1.1.0",
|
||||
"smallvec",
|
||||
"thiserror",
|
||||
|
@ -3888,7 +3858,7 @@ dependencies = [
|
|||
"parking_lot",
|
||||
"profiling",
|
||||
"range-alloc",
|
||||
"raw-window-handle 0.6.2",
|
||||
"raw-window-handle",
|
||||
"renderdoc-sys",
|
||||
"rustc-hash 1.1.0",
|
||||
"smallvec",
|
||||
|
@ -4271,7 +4241,7 @@ dependencies = [
|
|||
"once_cell",
|
||||
"orbclient",
|
||||
"percent-encoding",
|
||||
"raw-window-handle 0.6.2",
|
||||
"raw-window-handle",
|
||||
"redox_syscall 0.3.5",
|
||||
"rustix",
|
||||
"sctk-adwaita",
|
||||
|
|
|
@ -24,6 +24,8 @@ spirv-cross2 = { version = "0.4", default-features = false }
|
|||
objc2-metal = { version = "0.2" }
|
||||
objc2 = { version = "0.5.0" }
|
||||
glow = { version = "0.14.1" }
|
||||
glfw = { version = "0.58.0"}
|
||||
|
||||
wgpu = { version = "22", default-features = false }
|
||||
wgpu-types = { version = "22" }
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ array-init = "2.1.0"
|
|||
stable = ["librashader-reflect/stable"]
|
||||
|
||||
[dev-dependencies]
|
||||
glfw = "0.47.0"
|
||||
glfw = { workspace = true }
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
features = ["librashader-cache/docsrs"]
|
||||
|
|
|
@ -35,7 +35,6 @@ stable = ["librashader-reflect/stable"]
|
|||
|
||||
[dev-dependencies]
|
||||
num = "0.4.0"
|
||||
glfw = "0.49.0"
|
||||
winit = { version = "0.29.10", features = ["rwh_06"] }
|
||||
raw-window-handle = "0.6.2"
|
||||
ash-window = "0.13.0"
|
||||
|
|
|
@ -17,6 +17,10 @@ pollster = "0.3.0"
|
|||
parking_lot = "0.12.3"
|
||||
image-compare = "0.4.1"
|
||||
gpu-allocator = "0.27.0"
|
||||
bitvec = "1.0.1"
|
||||
d3d12-descriptor-heap = "0.1"
|
||||
glow = "0.14.1"
|
||||
glfw = "0.58.0"
|
||||
|
||||
[features]
|
||||
vulkan-debug = []
|
||||
|
|
72
librashader-test/src/render/gl/context.rs
Normal file
72
librashader-test/src/render/gl/context.rs
Normal file
|
@ -0,0 +1,72 @@
|
|||
// Copyright (c) 2023 Christian Vallentin
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
|
||||
use anyhow::anyhow;
|
||||
use glfw::{fail_on_errors, Context, Glfw, OpenGlProfileHint, PWindow, WindowHint, WindowMode};
|
||||
use glow::HasContext;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct GlfwContext {
|
||||
wnd: PWindow,
|
||||
glfw: Glfw,
|
||||
pub gl: Arc<glow::Context>,
|
||||
}
|
||||
|
||||
fn debug_callback(_source: u32, _err_type: u32, _id: u32, _severity: u32, message: &str) {
|
||||
println!("[gl] {message:?}");
|
||||
}
|
||||
|
||||
impl GlfwContext {
|
||||
pub fn new(version: GLVersion, width: u32, height: u32) -> Result<Self, anyhow::Error> {
|
||||
let mut glfw = glfw::init(fail_on_errors!())?;
|
||||
|
||||
let GLVersion(major, minor) = version;
|
||||
glfw.window_hint(WindowHint::ContextVersion(major, minor));
|
||||
glfw.window_hint(WindowHint::OpenGlProfile(OpenGlProfileHint::Core));
|
||||
glfw.window_hint(WindowHint::OpenGlForwardCompat(true));
|
||||
glfw.window_hint(WindowHint::Visible(false));
|
||||
glfw.window_hint(WindowHint::OpenGlDebugContext(true));
|
||||
|
||||
let (mut wnd, _events) = glfw
|
||||
.create_window(width, height, env!("CARGO_PKG_NAME"), WindowMode::Windowed)
|
||||
.ok_or_else(|| anyhow!("No window"))?;
|
||||
|
||||
wnd.make_current();
|
||||
|
||||
let mut gl =
|
||||
unsafe { glow::Context::from_loader_function(|proc| wnd.get_proc_address(proc) as _) };
|
||||
|
||||
unsafe {
|
||||
gl.enable(glow::DEBUG_OUTPUT);
|
||||
gl.enable(glow::DEBUG_OUTPUT_SYNCHRONOUS);
|
||||
gl.debug_message_callback(debug_callback);
|
||||
gl.debug_message_control(glow::DONT_CARE, glow::DONT_CARE, glow::DONT_CARE, &[], true);
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
wnd,
|
||||
glfw,
|
||||
gl: Arc::new(gl),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct GLVersion(pub u32, pub u32);
|
190
librashader-test/src/render/gl/mod.rs
Normal file
190
librashader-test/src/render/gl/mod.rs
Normal file
|
@ -0,0 +1,190 @@
|
|||
mod context;
|
||||
|
||||
use crate::render::gl::context::{GLVersion, GlfwContext};
|
||||
use crate::render::RenderTest;
|
||||
use anyhow::anyhow;
|
||||
use glow::{HasContext, PixelPackData, PixelUnpackData};
|
||||
use image::RgbaImage;
|
||||
use librashader::runtime::gl::{FilterChain, FilterChainOptions, GLImage};
|
||||
use librashader::runtime::Viewport;
|
||||
use librashader_runtime::image::{Image, UVDirection, RGBA8};
|
||||
use std::path::Path;
|
||||
use std::sync::Arc;
|
||||
|
||||
struct OpenGl {
|
||||
context: GlfwContext,
|
||||
use_dsa: bool,
|
||||
texture: GLImage,
|
||||
image_bytes: Image<RGBA8>,
|
||||
}
|
||||
|
||||
pub struct OpenGl3(OpenGl);
|
||||
pub struct OpenGl4(OpenGl);
|
||||
|
||||
impl RenderTest for OpenGl3 {
|
||||
fn render(&self, path: impl AsRef<Path>, frame_count: usize) -> anyhow::Result<RgbaImage> {
|
||||
let mut filter_chain = unsafe {
|
||||
FilterChain::load_from_path(
|
||||
path,
|
||||
Arc::clone(&self.0.context.gl),
|
||||
Some(&FilterChainOptions {
|
||||
glsl_version: 330,
|
||||
use_dsa: false,
|
||||
force_no_mipmaps: false,
|
||||
disable_cache: true,
|
||||
}),
|
||||
)
|
||||
}?;
|
||||
|
||||
Ok(self.0.render(&mut filter_chain, frame_count)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl RenderTest for OpenGl4 {
|
||||
fn render(&self, path: impl AsRef<Path>, frame_count: usize) -> anyhow::Result<RgbaImage> {
|
||||
let mut filter_chain = unsafe {
|
||||
FilterChain::load_from_path(
|
||||
path,
|
||||
Arc::clone(&self.0.context.gl),
|
||||
Some(&FilterChainOptions {
|
||||
glsl_version: 460,
|
||||
use_dsa: true,
|
||||
force_no_mipmaps: false,
|
||||
disable_cache: true,
|
||||
}),
|
||||
)
|
||||
}?;
|
||||
|
||||
Ok(self.0.render(&mut filter_chain, frame_count)?)
|
||||
}
|
||||
}
|
||||
|
||||
impl OpenGl3 {
|
||||
pub fn new(image_path: impl AsRef<Path>) -> anyhow::Result<Self> {
|
||||
Ok(Self(OpenGl::new(image_path, false)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl OpenGl4 {
|
||||
pub fn new(image_path: impl AsRef<Path>) -> anyhow::Result<Self> {
|
||||
Ok(Self(OpenGl::new(image_path, true)?))
|
||||
}
|
||||
}
|
||||
|
||||
impl OpenGl {
|
||||
pub fn new(image_path: impl AsRef<Path>, use_dsa: bool) -> anyhow::Result<Self> {
|
||||
let image: Image<RGBA8> = Image::load(image_path.as_ref(), UVDirection::TopLeft)?;
|
||||
let height = image.size.height;
|
||||
let width = image.size.width;
|
||||
let version = if use_dsa {
|
||||
GLVersion(4, 6)
|
||||
} else {
|
||||
GLVersion(3, 3)
|
||||
};
|
||||
|
||||
let context = GlfwContext::new(version, width, height)?;
|
||||
|
||||
let texture = unsafe {
|
||||
let tex = context.gl.create_texture().map_err(|s| anyhow!("{}", s))?;
|
||||
context.gl.bind_texture(glow::TEXTURE_2D, Some(tex));
|
||||
context.gl.tex_storage_2d(
|
||||
glow::TEXTURE_2D,
|
||||
1,
|
||||
glow::RGBA8,
|
||||
image.size.width as i32,
|
||||
image.size.height as i32,
|
||||
);
|
||||
|
||||
context.gl.pixel_store_i32(glow::UNPACK_ROW_LENGTH, 0);
|
||||
context.gl.pixel_store_i32(glow::UNPACK_ALIGNMENT, 4);
|
||||
context.gl.bind_buffer(glow::PIXEL_UNPACK_BUFFER, None);
|
||||
|
||||
context.gl.tex_sub_image_2d(
|
||||
glow::TEXTURE_2D,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
image.size.width as i32,
|
||||
image.size.height as i32,
|
||||
glow::RGBA,
|
||||
glow::UNSIGNED_BYTE,
|
||||
PixelUnpackData::Slice(&image.bytes),
|
||||
);
|
||||
|
||||
context.gl.bind_texture(glow::TEXTURE_2D, None);
|
||||
tex
|
||||
};
|
||||
|
||||
Ok(Self {
|
||||
context,
|
||||
use_dsa,
|
||||
texture: GLImage {
|
||||
handle: Some(texture),
|
||||
format: glow::RGBA8,
|
||||
size: image.size,
|
||||
},
|
||||
image_bytes: image,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn render(
|
||||
&self,
|
||||
chain: &mut FilterChain,
|
||||
frame_count: usize,
|
||||
) -> Result<RgbaImage, anyhow::Error> {
|
||||
let render_texture = unsafe {
|
||||
let tex = self
|
||||
.context
|
||||
.gl
|
||||
.create_texture()
|
||||
.map_err(|s| anyhow!("{}", s))?;
|
||||
self.context.gl.bind_texture(glow::TEXTURE_2D, Some(tex));
|
||||
self.context.gl.tex_storage_2d(
|
||||
glow::TEXTURE_2D,
|
||||
1,
|
||||
glow::RGBA8,
|
||||
self.image_bytes.size.width as i32,
|
||||
self.image_bytes.size.height as i32,
|
||||
);
|
||||
self.context.gl.bind_texture(glow::TEXTURE_2D, None);
|
||||
tex
|
||||
};
|
||||
|
||||
let output = GLImage {
|
||||
handle: Some(render_texture),
|
||||
format: glow::RGBA8,
|
||||
size: self.image_bytes.size,
|
||||
};
|
||||
|
||||
unsafe {
|
||||
chain.frame(
|
||||
&self.texture,
|
||||
&Viewport::new_render_target_sized_origin(&output, None)?,
|
||||
frame_count,
|
||||
None,
|
||||
)?;
|
||||
}
|
||||
|
||||
// should be the same size as the input image
|
||||
let mut data = vec![0u8; self.image_bytes.bytes.len()];
|
||||
|
||||
unsafe {
|
||||
self.context
|
||||
.gl
|
||||
.bind_texture(glow::TEXTURE_2D, output.handle);
|
||||
self.context.gl.get_tex_image(
|
||||
glow::TEXTURE_2D,
|
||||
0,
|
||||
glow::RGBA,
|
||||
glow::UNSIGNED_BYTE,
|
||||
PixelPackData::Slice(&mut data),
|
||||
)
|
||||
}
|
||||
Ok(RgbaImage::from_raw(
|
||||
self.image_bytes.size.width,
|
||||
self.image_bytes.size.height,
|
||||
data,
|
||||
)
|
||||
.ok_or(anyhow!("failed to create image from slice"))?)
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
pub mod d3d11;
|
||||
pub mod gl;
|
||||
pub mod vk;
|
||||
pub mod wgpu;
|
||||
|
||||
|
@ -28,10 +29,10 @@ mod test {
|
|||
use std::fs::File;
|
||||
|
||||
const IMAGE_PATH: &str = "../triangle.png";
|
||||
// const FILTER_PATH: &str = "../test/shaders_slang/crt/crt-royale.slangp";
|
||||
const FILTER_PATH: &str = "../test/shaders_slang/crt/crt-royale.slangp";
|
||||
|
||||
const FILTER_PATH: &str =
|
||||
"../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp";
|
||||
// const FILTER_PATH: &str =
|
||||
// "../test/shaders_slang/bezel/Mega_Bezel/Presets/MBZ__0__SMOOTH-ADV.slangp";
|
||||
|
||||
#[test]
|
||||
pub fn test_d3d11() -> anyhow::Result<()> {
|
||||
|
@ -63,6 +64,28 @@ mod test {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_gl3() -> anyhow::Result<()> {
|
||||
|
||||
let gl = super::gl::OpenGl3::new(IMAGE_PATH)?;
|
||||
let image = gl.render(FILTER_PATH, 1000)?;
|
||||
|
||||
let out = File::create("out.png")?;
|
||||
image.write_with_encoder(PngEncoder::new(out))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_gl4() -> anyhow::Result<()> {
|
||||
|
||||
let gl = super::gl::OpenGl4::new(IMAGE_PATH)?;
|
||||
let image = gl.render(FILTER_PATH, 1000)?;
|
||||
|
||||
let out = File::create("out.png")?;
|
||||
image.write_with_encoder(PngEncoder::new(out))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn compare() -> anyhow::Result<()> {
|
||||
let d3d11 = super::d3d11::Direct3D11::new(IMAGE_PATH)?;
|
||||
|
|
Loading…
Reference in a new issue