Skip to content

Commit

Permalink
Add Shader and Version
Browse files Browse the repository at this point in the history
to simplify and constrain `program::create`
  • Loading branch information
derezzedex committed Jan 20, 2022
1 parent 230db88 commit 424e1d3
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 134 deletions.
54 changes: 2 additions & 52 deletions glow/src/backend.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use crate::program;
use crate::quad;
use crate::text;
use crate::triangle;
use crate::{Settings, Transformation, Viewport};

use glow::HasContext;
use iced_graphics::backend;
use iced_graphics::font;
use iced_graphics::{Layer, Primitive};
Expand Down Expand Up @@ -31,57 +31,7 @@ impl Backend {
settings.text_multithreading,
);

let version = gl.version();
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 shader_version = program::Version::new(gl);

let quad_pipeline = quad::Pipeline::new(gl, &shader_version);
let triangle_pipeline = triangle::Pipeline::new(gl, &shader_version);
Expand Down
127 changes: 108 additions & 19 deletions glow/src/program.rs
Original file line number Diff line number Diff line change
@@ -1,29 +1,118 @@
use glow::HasContext;

pub unsafe fn create(
gl: &glow::Context,
shader_sources: &[(u32, &str)],
attributes: &[(u32, &str)],
) -> <glow::Context as HasContext>::Program {
let program = gl.create_program().expect("Cannot create program");
/// 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 mut shaders = Vec::with_capacity(shader_sources.len());
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),
};

for (shader_type, shader_source) in shader_sources.iter() {
let shader = gl
.create_shader(*shader_type)
.expect("Cannot create shader");
log::info!("Shader directive: {}", vertex.lines().next().unwrap());

gl.shader_source(shader, shader_source);
gl.compile_shader(shader);
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");

if !gl.get_shader_compile_status(shader) {
panic!("{}", gl.get_shader_info_log(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)
}
}

gl.attach_shader(program, shader);
/// Creates a vertex [`Shader`].
pub fn vertex(
gl: &glow::Context,
version: &Version,
content: &'static str,
) -> Self {
let content = format!("{}\n{}", version.vertex, content);

shaders.push(shader);
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(
gl: &glow::Context,
shaders: &[Shader],
attributes: &[(u32, &str)],
) -> <glow::Context as HasContext>::Program {
let program = gl.create_program().expect("Cannot create program");

for shader in shaders {
gl.attach_shader(program, shader.0);
}

for (i, name) in attributes {
Expand All @@ -36,8 +125,8 @@ pub unsafe fn create(
}

for shader in shaders {
gl.detach_shader(program, shader);
gl.delete_shader(shader);
gl.detach_shader(program, shader.0);
gl.delete_shader(shader.0);
}

program
Expand Down
7 changes: 4 additions & 3 deletions glow/src/quad.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
mod compatibility;
mod core;

use crate::program;
use crate::Transformation;
use glow::HasContext;
use iced_graphics::layer;
Expand All @@ -15,12 +16,12 @@ pub enum Pipeline {
impl Pipeline {
pub fn new(
gl: &glow::Context,
shader_version: &(String, String),
shader_version: &program::Version,
) -> 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`)
if version.major >= 3 {
if gl_version.major >= 3 {
log::info!("Mode: core");
Pipeline::Core(core::Pipeline::new(gl, shader_version))
} else {
Expand Down
34 changes: 14 additions & 20 deletions glow/src/quad/compatibility.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::program;
use crate::program::{self, Shader};
use crate::Transformation;
use glow::HasContext;
use iced_graphics::layer;
Expand Down Expand Up @@ -27,29 +27,23 @@ pub struct Pipeline {
impl Pipeline {
pub fn new(
gl: &glow::Context,
(vertex_version, fragment_version): &(String, String),
shader_version: &program::Version,
) -> Pipeline {
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(
gl,
&[
(
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")
),
),
],
&[vertex_shader, fragment_shader],
&[
(0, "i_Pos"),
(1, "i_Scale"),
Expand Down
34 changes: 14 additions & 20 deletions glow/src/quad/core.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::program;
use crate::program::{self, Shader};
use crate::Transformation;
use glow::HasContext;
use iced_graphics::layer;
Expand All @@ -22,29 +22,23 @@ pub struct Pipeline {
impl Pipeline {
pub fn new(
gl: &glow::Context,
(vertex_version, fragment_version): &(String, String),
shader_version: &program::Version,
) -> Pipeline {
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(
gl,
&[
(
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")
),
),
],
&[vertex_shader, fragment_shader],
&[
(0, "i_Pos"),
(1, "i_Scale"),
Expand Down
34 changes: 14 additions & 20 deletions glow/src/triangle.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
//! Draw meshes of triangles.
use crate::program;
use crate::program::{self, Shader};
use crate::Transformation;
use glow::HasContext;
use iced_graphics::layer;
Expand All @@ -23,29 +23,23 @@ pub(crate) struct Pipeline {
impl Pipeline {
pub fn new(
gl: &glow::Context,
(vertex_version, fragment_version): &(String, String),
shader_version: &program::Version,
) -> Pipeline {
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(
gl,
&[
(
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")
),
),
],
&[vertex_shader, fragment_shader],
&[(0, "i_Position"), (1, "i_Color")],
)
};
Expand Down

0 comments on commit 424e1d3

Please sign in to comment.