Add Shader and Version
to simplify and constrain `program::create`
This commit is contained in:
parent
230db88fb2
commit
424e1d3fda
6 changed files with 157 additions and 135 deletions
|
|
@ -1,9 +1,9 @@
|
||||||
|
use crate::program;
|
||||||
use crate::quad;
|
use crate::quad;
|
||||||
use crate::text;
|
use crate::text;
|
||||||
use crate::triangle;
|
use crate::triangle;
|
||||||
use crate::{Settings, Transformation, Viewport};
|
use crate::{Settings, Transformation, Viewport};
|
||||||
|
|
||||||
use glow::HasContext;
|
|
||||||
use iced_graphics::backend;
|
use iced_graphics::backend;
|
||||||
use iced_graphics::font;
|
use iced_graphics::font;
|
||||||
use iced_graphics::{Layer, Primitive};
|
use iced_graphics::{Layer, Primitive};
|
||||||
|
|
@ -31,57 +31,7 @@ impl Backend {
|
||||||
settings.text_multithreading,
|
settings.text_multithreading,
|
||||||
);
|
);
|
||||||
|
|
||||||
let version = gl.version();
|
let shader_version = program::Version::new(gl);
|
||||||
let shader_version = match (
|
|
||||||
version.major,
|
|
||||||
version.minor,
|
|
||||||
version.is_embedded,
|
|
||||||
) {
|
|
||||||
// OpenGL 3.0+
|
|
||||||
(3, 0 | 1 | 2, false) => (
|
|
||||||
format!("#version 1{}0", version.minor + 3),
|
|
||||||
format!(
|
|
||||||
"#version 1{}0\n#define HIGHER_THAN_300 1",
|
|
||||||
version.minor + 3
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// OpenGL 3.3+
|
|
||||||
(3 | 4, _, false) => (
|
|
||||||
format!("#version {}{}0", version.major, version.minor),
|
|
||||||
format!(
|
|
||||||
"#version {}{}0\n#define HIGHER_THAN_300 1",
|
|
||||||
version.major, version.minor
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// OpenGL ES 3.0+
|
|
||||||
(3, _, true) => (
|
|
||||||
format!("#version 3{}0 es", version.minor),
|
|
||||||
format!(
|
|
||||||
"#version 3{}0 es\n#define HIGHER_THAN_300 1",
|
|
||||||
version.minor
|
|
||||||
),
|
|
||||||
),
|
|
||||||
// OpenGL ES 2.0+
|
|
||||||
(2, _, true) => (
|
|
||||||
String::from(
|
|
||||||
"#version 100\n#define in attribute\n#define out varying",
|
|
||||||
),
|
|
||||||
String::from("#version 100\n#define in varying"),
|
|
||||||
),
|
|
||||||
// OpenGL 2.1
|
|
||||||
(2, _, false) => (
|
|
||||||
String::from(
|
|
||||||
"#version 120\n#define in attribute\n#define out varying",
|
|
||||||
),
|
|
||||||
String::from("#version 120\n#define in varying"),
|
|
||||||
),
|
|
||||||
// OpenGL 1.1+
|
|
||||||
_ => panic!("Incompatible context version: {:?}", version),
|
|
||||||
};
|
|
||||||
log::info!(
|
|
||||||
"Shader directive: {}",
|
|
||||||
shader_version.0.lines().next().unwrap()
|
|
||||||
);
|
|
||||||
|
|
||||||
let quad_pipeline = quad::Pipeline::new(gl, &shader_version);
|
let quad_pipeline = quad::Pipeline::new(gl, &shader_version);
|
||||||
let triangle_pipeline = triangle::Pipeline::new(gl, &shader_version);
|
let triangle_pipeline = triangle::Pipeline::new(gl, &shader_version);
|
||||||
|
|
|
||||||
|
|
@ -1,29 +1,118 @@
|
||||||
use glow::HasContext;
|
use glow::HasContext;
|
||||||
|
|
||||||
|
/// The [`Version`] of a `Program`.
|
||||||
|
pub struct Version {
|
||||||
|
vertex: String,
|
||||||
|
fragment: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Version {
|
||||||
|
pub fn new(gl: &glow::Context) -> Version {
|
||||||
|
let version = gl.version();
|
||||||
|
|
||||||
|
let (vertex, fragment) = match (
|
||||||
|
version.major,
|
||||||
|
version.minor,
|
||||||
|
version.is_embedded,
|
||||||
|
) {
|
||||||
|
// OpenGL 3.0+
|
||||||
|
(3, 0 | 1 | 2, false) => (
|
||||||
|
format!("#version 1{}0", version.minor + 3),
|
||||||
|
format!(
|
||||||
|
"#version 1{}0\n#define HIGHER_THAN_300 1",
|
||||||
|
version.minor + 3
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// OpenGL 3.3+
|
||||||
|
(3 | 4, _, false) => (
|
||||||
|
format!("#version {}{}0", version.major, version.minor),
|
||||||
|
format!(
|
||||||
|
"#version {}{}0\n#define HIGHER_THAN_300 1",
|
||||||
|
version.major, version.minor
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// OpenGL ES 3.0+
|
||||||
|
(3, _, true) => (
|
||||||
|
format!("#version 3{}0 es", version.minor),
|
||||||
|
format!(
|
||||||
|
"#version 3{}0 es\n#define HIGHER_THAN_300 1",
|
||||||
|
version.minor
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// OpenGL ES 2.0+
|
||||||
|
(2, _, true) => (
|
||||||
|
String::from(
|
||||||
|
"#version 100\n#define in attribute\n#define out varying",
|
||||||
|
),
|
||||||
|
String::from("#version 100\n#define in varying"),
|
||||||
|
),
|
||||||
|
// OpenGL 2.1
|
||||||
|
(2, _, false) => (
|
||||||
|
String::from(
|
||||||
|
"#version 120\n#define in attribute\n#define out varying",
|
||||||
|
),
|
||||||
|
String::from("#version 120\n#define in varying"),
|
||||||
|
),
|
||||||
|
// OpenGL 1.1+
|
||||||
|
_ => panic!("Incompatible context version: {:?}", version),
|
||||||
|
};
|
||||||
|
|
||||||
|
log::info!("Shader directive: {}", vertex.lines().next().unwrap());
|
||||||
|
|
||||||
|
Version { vertex, fragment }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct Shader(<glow::Context as HasContext>::Shader);
|
||||||
|
|
||||||
|
impl Shader {
|
||||||
|
fn compile(gl: &glow::Context, stage: u32, content: &str) -> Shader {
|
||||||
|
unsafe {
|
||||||
|
let shader = gl.create_shader(stage).expect("Cannot create shader");
|
||||||
|
|
||||||
|
gl.shader_source(shader, &content);
|
||||||
|
gl.compile_shader(shader);
|
||||||
|
|
||||||
|
if !gl.get_shader_compile_status(shader) {
|
||||||
|
panic!("{}", gl.get_shader_info_log(shader));
|
||||||
|
}
|
||||||
|
|
||||||
|
Shader(shader)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a vertex [`Shader`].
|
||||||
|
pub fn vertex(
|
||||||
|
gl: &glow::Context,
|
||||||
|
version: &Version,
|
||||||
|
content: &'static str,
|
||||||
|
) -> Self {
|
||||||
|
let content = format!("{}\n{}", version.vertex, content);
|
||||||
|
|
||||||
|
Shader::compile(gl, glow::VERTEX_SHADER, &content)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Creates a fragment [`Shader`].
|
||||||
|
pub fn fragment(
|
||||||
|
gl: &glow::Context,
|
||||||
|
version: &Version,
|
||||||
|
content: &'static str,
|
||||||
|
) -> Self {
|
||||||
|
let content = format!("{}\n{}", version.fragment, content);
|
||||||
|
|
||||||
|
Shader::compile(gl, glow::FRAGMENT_SHADER, &content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub unsafe fn create(
|
pub unsafe fn create(
|
||||||
gl: &glow::Context,
|
gl: &glow::Context,
|
||||||
shader_sources: &[(u32, &str)],
|
shaders: &[Shader],
|
||||||
attributes: &[(u32, &str)],
|
attributes: &[(u32, &str)],
|
||||||
) -> <glow::Context as HasContext>::Program {
|
) -> <glow::Context as HasContext>::Program {
|
||||||
let program = gl.create_program().expect("Cannot create program");
|
let program = gl.create_program().expect("Cannot create program");
|
||||||
|
|
||||||
let mut shaders = Vec::with_capacity(shader_sources.len());
|
for shader in shaders {
|
||||||
|
gl.attach_shader(program, shader.0);
|
||||||
for (shader_type, shader_source) in shader_sources.iter() {
|
|
||||||
let shader = gl
|
|
||||||
.create_shader(*shader_type)
|
|
||||||
.expect("Cannot create shader");
|
|
||||||
|
|
||||||
gl.shader_source(shader, shader_source);
|
|
||||||
gl.compile_shader(shader);
|
|
||||||
|
|
||||||
if !gl.get_shader_compile_status(shader) {
|
|
||||||
panic!("{}", gl.get_shader_info_log(shader));
|
|
||||||
}
|
|
||||||
|
|
||||||
gl.attach_shader(program, shader);
|
|
||||||
|
|
||||||
shaders.push(shader);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i, name) in attributes {
|
for (i, name) in attributes {
|
||||||
|
|
@ -36,8 +125,8 @@ pub unsafe fn create(
|
||||||
}
|
}
|
||||||
|
|
||||||
for shader in shaders {
|
for shader in shaders {
|
||||||
gl.detach_shader(program, shader);
|
gl.detach_shader(program, shader.0);
|
||||||
gl.delete_shader(shader);
|
gl.delete_shader(shader.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
program
|
program
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,7 @@
|
||||||
mod compatibility;
|
mod compatibility;
|
||||||
mod core;
|
mod core;
|
||||||
|
|
||||||
|
use crate::program;
|
||||||
use crate::Transformation;
|
use crate::Transformation;
|
||||||
use glow::HasContext;
|
use glow::HasContext;
|
||||||
use iced_graphics::layer;
|
use iced_graphics::layer;
|
||||||
|
|
@ -15,12 +16,12 @@ pub enum Pipeline {
|
||||||
impl Pipeline {
|
impl Pipeline {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
gl: &glow::Context,
|
gl: &glow::Context,
|
||||||
shader_version: &(String, String),
|
shader_version: &program::Version,
|
||||||
) -> Pipeline {
|
) -> Pipeline {
|
||||||
let version = gl.version();
|
let gl_version = gl.version();
|
||||||
|
|
||||||
// OpenGL 3.0+ and OpenGL ES 3.0+ have instancing (which is what separates `core` from `compatibility`)
|
// OpenGL 3.0+ and OpenGL ES 3.0+ have instancing (which is what separates `core` from `compatibility`)
|
||||||
if version.major >= 3 {
|
if gl_version.major >= 3 {
|
||||||
log::info!("Mode: core");
|
log::info!("Mode: core");
|
||||||
Pipeline::Core(core::Pipeline::new(gl, shader_version))
|
Pipeline::Core(core::Pipeline::new(gl, shader_version))
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::program;
|
use crate::program::{self, Shader};
|
||||||
use crate::Transformation;
|
use crate::Transformation;
|
||||||
use glow::HasContext;
|
use glow::HasContext;
|
||||||
use iced_graphics::layer;
|
use iced_graphics::layer;
|
||||||
|
|
@ -27,29 +27,23 @@ pub struct Pipeline {
|
||||||
impl Pipeline {
|
impl Pipeline {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
gl: &glow::Context,
|
gl: &glow::Context,
|
||||||
(vertex_version, fragment_version): &(String, String),
|
shader_version: &program::Version,
|
||||||
) -> Pipeline {
|
) -> Pipeline {
|
||||||
let program = unsafe {
|
let program = unsafe {
|
||||||
|
let vertex_shader = Shader::vertex(
|
||||||
|
gl,
|
||||||
|
shader_version,
|
||||||
|
include_str!("../shader/compatibility/quad.vert"),
|
||||||
|
);
|
||||||
|
let fragment_shader = Shader::fragment(
|
||||||
|
gl,
|
||||||
|
shader_version,
|
||||||
|
include_str!("../shader/compatibility/quad.frag"),
|
||||||
|
);
|
||||||
|
|
||||||
program::create(
|
program::create(
|
||||||
gl,
|
gl,
|
||||||
&[
|
&[vertex_shader, fragment_shader],
|
||||||
(
|
|
||||||
glow::VERTEX_SHADER,
|
|
||||||
&format!(
|
|
||||||
"{}\n{}",
|
|
||||||
vertex_version,
|
|
||||||
include_str!("../shader/compatibility/quad.vert")
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
glow::FRAGMENT_SHADER,
|
|
||||||
&format!(
|
|
||||||
"{}\n{}",
|
|
||||||
fragment_version,
|
|
||||||
include_str!("../shader/compatibility/quad.frag")
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
&[
|
&[
|
||||||
(0, "i_Pos"),
|
(0, "i_Pos"),
|
||||||
(1, "i_Scale"),
|
(1, "i_Scale"),
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,4 @@
|
||||||
use crate::program;
|
use crate::program::{self, Shader};
|
||||||
use crate::Transformation;
|
use crate::Transformation;
|
||||||
use glow::HasContext;
|
use glow::HasContext;
|
||||||
use iced_graphics::layer;
|
use iced_graphics::layer;
|
||||||
|
|
@ -22,29 +22,23 @@ pub struct Pipeline {
|
||||||
impl Pipeline {
|
impl Pipeline {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
gl: &glow::Context,
|
gl: &glow::Context,
|
||||||
(vertex_version, fragment_version): &(String, String),
|
shader_version: &program::Version,
|
||||||
) -> Pipeline {
|
) -> Pipeline {
|
||||||
let program = unsafe {
|
let program = unsafe {
|
||||||
|
let vertex_shader = Shader::vertex(
|
||||||
|
gl,
|
||||||
|
shader_version,
|
||||||
|
include_str!("../shader/core/quad.vert"),
|
||||||
|
);
|
||||||
|
let fragment_shader = Shader::fragment(
|
||||||
|
gl,
|
||||||
|
shader_version,
|
||||||
|
include_str!("../shader/core/quad.frag"),
|
||||||
|
);
|
||||||
|
|
||||||
program::create(
|
program::create(
|
||||||
gl,
|
gl,
|
||||||
&[
|
&[vertex_shader, fragment_shader],
|
||||||
(
|
|
||||||
glow::VERTEX_SHADER,
|
|
||||||
&format!(
|
|
||||||
"{}\n{}",
|
|
||||||
vertex_version,
|
|
||||||
include_str!("../shader/core/quad.vert")
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
glow::FRAGMENT_SHADER,
|
|
||||||
&format!(
|
|
||||||
"{}\n{}",
|
|
||||||
fragment_version,
|
|
||||||
include_str!("../shader/core/quad.frag")
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
&[
|
&[
|
||||||
(0, "i_Pos"),
|
(0, "i_Pos"),
|
||||||
(1, "i_Scale"),
|
(1, "i_Scale"),
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,5 @@
|
||||||
//! Draw meshes of triangles.
|
//! Draw meshes of triangles.
|
||||||
use crate::program;
|
use crate::program::{self, Shader};
|
||||||
use crate::Transformation;
|
use crate::Transformation;
|
||||||
use glow::HasContext;
|
use glow::HasContext;
|
||||||
use iced_graphics::layer;
|
use iced_graphics::layer;
|
||||||
|
|
@ -23,29 +23,23 @@ pub(crate) struct Pipeline {
|
||||||
impl Pipeline {
|
impl Pipeline {
|
||||||
pub fn new(
|
pub fn new(
|
||||||
gl: &glow::Context,
|
gl: &glow::Context,
|
||||||
(vertex_version, fragment_version): &(String, String),
|
shader_version: &program::Version,
|
||||||
) -> Pipeline {
|
) -> Pipeline {
|
||||||
let program = unsafe {
|
let program = unsafe {
|
||||||
|
let vertex_shader = Shader::vertex(
|
||||||
|
gl,
|
||||||
|
shader_version,
|
||||||
|
include_str!("shader/common/triangle.vert"),
|
||||||
|
);
|
||||||
|
let fragment_shader = Shader::fragment(
|
||||||
|
gl,
|
||||||
|
shader_version,
|
||||||
|
include_str!("shader/common/triangle.frag"),
|
||||||
|
);
|
||||||
|
|
||||||
program::create(
|
program::create(
|
||||||
gl,
|
gl,
|
||||||
&[
|
&[vertex_shader, fragment_shader],
|
||||||
(
|
|
||||||
glow::VERTEX_SHADER,
|
|
||||||
&format!(
|
|
||||||
"{}\n{}",
|
|
||||||
vertex_version,
|
|
||||||
include_str!("shader/common/triangle.vert")
|
|
||||||
),
|
|
||||||
),
|
|
||||||
(
|
|
||||||
glow::FRAGMENT_SHADER,
|
|
||||||
&format!(
|
|
||||||
"{}\n{}",
|
|
||||||
fragment_version,
|
|
||||||
include_str!("shader/common/triangle.frag")
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
&[(0, "i_Position"), (1, "i_Color")],
|
&[(0, "i_Position"), (1, "i_Color")],
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue