Improve shader version selection

This commit is contained in:
Richard 2021-11-11 01:10:47 -03:00
parent afdf3e799a
commit e31566d430
17 changed files with 179 additions and 69 deletions

View file

@ -18,9 +18,7 @@ use preset::Preset;
use std::time::{Duration, Instant}; use std::time::{Duration, Instant};
pub fn main() -> iced::Result { pub fn main() -> iced::Result {
env_logger::builder() env_logger::builder().format_timestamp(None).init();
.format_timestamp(None)
.init();
GameOfLife::run(Settings { GameOfLife::run(Settings {
antialiasing: true, antialiasing: true,

View file

@ -3,6 +3,7 @@ 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};
@ -30,8 +31,60 @@ impl Backend {
settings.text_multithreading, settings.text_multithreading,
); );
let quad_pipeline = quad::Pipeline::new(gl); let version = gl.version();
let triangle_pipeline = triangle::Pipeline::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 triangle_pipeline = triangle::Pipeline::new(gl, &shader_version);
Self { Self {
quad_pipeline, quad_pipeline,

View file

@ -3,6 +3,7 @@ use glow::HasContext;
pub unsafe fn create( pub unsafe fn create(
gl: &glow::Context, gl: &glow::Context,
shader_sources: &[(u32, &str)], shader_sources: &[(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");
@ -25,6 +26,10 @@ pub unsafe fn create(
shaders.push(shader); shaders.push(shader);
} }
for (i, name) in attributes {
gl.bind_attrib_location(program, *i, name);
}
gl.link_program(program); gl.link_program(program);
if !gl.get_program_link_status(program) { if !gl.get_program_link_status(program) {
panic!("{}", gl.get_program_info_log(program)); panic!("{}", gl.get_program_info_log(program));

View file

@ -13,14 +13,22 @@ pub enum Pipeline {
} }
impl Pipeline { impl Pipeline {
pub fn new(gl: &glow::Context) -> Pipeline { pub fn new(
gl: &glow::Context,
shader_version: &(String, String),
) -> Pipeline {
let version = gl.version(); let version = gl.version();
if version.is_embedded || version.major == 2 {
log::info!("Mode: compatibility"); // OpenGL 3.0+ and OpenGL ES 3.0+ have instancing (which is what separates `core` from `compatibility`)
Pipeline::Compatibility(compatibility::Pipeline::new(gl)) if version.major >= 3 {
} else {
log::info!("Mode: core"); log::info!("Mode: core");
Pipeline::Core(core::Pipeline::new(gl)) Pipeline::Core(core::Pipeline::new(gl, shader_version))
} else {
log::info!("Mode: compatibility");
Pipeline::Compatibility(compatibility::Pipeline::new(
gl,
shader_version,
))
} }
} }

View file

@ -25,20 +25,39 @@ pub struct Pipeline {
} }
impl Pipeline { impl Pipeline {
pub fn new(gl: &glow::Context) -> Pipeline { pub fn new(
gl: &glow::Context,
(vertex_version, fragment_version): &(String, String),
) -> Pipeline {
let program = unsafe { let program = unsafe {
program::create( program::create(
gl, gl,
&[ &[
( (
glow::VERTEX_SHADER, glow::VERTEX_SHADER,
include_str!("../shader/compatibility/quad.vert"), &format!(
"{}\n{}",
vertex_version,
include_str!("../shader/compatibility/quad.vert")
),
), ),
( (
glow::FRAGMENT_SHADER, glow::FRAGMENT_SHADER,
include_str!("../shader/compatibility/quad.frag"), &format!(
"{}\n{}",
fragment_version,
include_str!("../shader/compatibility/quad.frag")
),
), ),
], ],
&[
(0, "i_Pos"),
(1, "i_Scale"),
(2, "i_Color"),
(3, "i_BorderColor"),
(4, "i_BorderRadius"),
(5, "i_BorderWidth"),
],
) )
}; };

View file

@ -20,20 +20,39 @@ pub struct Pipeline {
} }
impl Pipeline { impl Pipeline {
pub fn new(gl: &glow::Context) -> Pipeline { pub fn new(
gl: &glow::Context,
(vertex_version, fragment_version): &(String, String),
) -> Pipeline {
let program = unsafe { let program = unsafe {
program::create( program::create(
gl, gl,
&[ &[
( (
glow::VERTEX_SHADER, glow::VERTEX_SHADER,
include_str!("../shader/core/quad.vert"), &format!(
"{}\n{}",
vertex_version,
include_str!("../shader/core/quad.vert")
),
), ),
( (
glow::FRAGMENT_SHADER, glow::FRAGMENT_SHADER,
include_str!("../shader/core/quad.frag"), &format!(
"{}\n{}",
fragment_version,
include_str!("../shader/core/quad.frag")
),
), ),
], ],
&[
(0, "i_Pos"),
(1, "i_Scale"),
(2, "i_Color"),
(3, "i_BorderColor"),
(4, "i_BorderRadius"),
(5, "i_BorderWidth"),
],
) )
}; };

View file

@ -0,0 +1,18 @@
#ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#endif
#ifdef HIGHER_THAN_300
out vec4 fragColor;
#define gl_FragColor fragColor
#endif
in vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}

View file

@ -1,5 +1,3 @@
#version 130
uniform mat4 u_Transform; uniform mat4 u_Transform;
in vec2 i_Position; in vec2 i_Position;

View file

@ -1,5 +1,10 @@
#version 100 #ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float; precision mediump float;
#endif
#endif
uniform float u_ScreenHeight; uniform float u_ScreenHeight;
@ -10,7 +15,7 @@ varying vec2 v_Scale;
varying float v_BorderRadius; varying float v_BorderRadius;
varying float v_BorderWidth; varying float v_BorderWidth;
float _distance(in vec2 frag_coord, in vec2 position, in vec2 size, float radius) float _distance(vec2 frag_coord, vec2 position, vec2 size, float radius)
{ {
// TODO: Try SDF approach: https://www.shadertoy.com/view/wd3XRN // TODO: Try SDF approach: https://www.shadertoy.com/view/wd3XRN
vec2 inner_size = size - vec2(radius, radius) * 2.0; vec2 inner_size = size - vec2(radius, radius) * 2.0;

View file

@ -1,5 +1,3 @@
#version 100
uniform mat4 u_Transform; uniform mat4 u_Transform;
uniform float u_Scale; uniform float u_Scale;

View file

@ -1,8 +0,0 @@
#version 100
precision mediump float;
varying vec4 v_Color;
void main() {
gl_FragColor = v_Color;
}

View file

@ -1,13 +0,0 @@
#version 100
uniform mat4 u_Transform;
attribute vec2 i_Position;
attribute vec4 i_Color;
varying vec4 v_Color;
void main() {
v_Color = i_Color;
gl_Position = u_Transform * vec4(i_Position, 0.0, 1.0);
}

View file

@ -1,4 +1,15 @@
#version 130 #ifdef GL_ES
#ifdef GL_FRAGMENT_PRECISION_HIGH
precision highp float;
#else
precision mediump float;
#endif
#endif
#ifdef HIGHER_THAN_300
out vec4 fragColor;
#define gl_FragColor fragColor
#endif
uniform float u_ScreenHeight; uniform float u_ScreenHeight;
@ -9,9 +20,7 @@ in vec2 v_Scale;
in float v_BorderRadius; in float v_BorderRadius;
in float v_BorderWidth; in float v_BorderWidth;
out vec4 o_Color; float fDistance(vec2 frag_coord, vec2 position, vec2 size, float radius)
float distance(in vec2 frag_coord, in vec2 position, in vec2 size, float radius)
{ {
// TODO: Try SDF approach: https://www.shadertoy.com/view/wd3XRN // TODO: Try SDF approach: https://www.shadertoy.com/view/wd3XRN
vec2 inner_size = size - vec2(radius, radius) * 2.0; vec2 inner_size = size - vec2(radius, radius) * 2.0;
@ -35,10 +44,10 @@ void main() {
vec2 fragCoord = vec2(gl_FragCoord.x, u_ScreenHeight - gl_FragCoord.y); vec2 fragCoord = vec2(gl_FragCoord.x, u_ScreenHeight - gl_FragCoord.y);
// TODO: Remove branching (?) // TODO: Remove branching (?)
if(v_BorderWidth > 0) { if(v_BorderWidth > 0.0) {
float internal_border = max(v_BorderRadius - v_BorderWidth, 0.0); float internal_border = max(v_BorderRadius - v_BorderWidth, 0.0);
float internal_distance = distance( float internal_distance = fDistance(
fragCoord, fragCoord,
v_Pos + vec2(v_BorderWidth), v_Pos + vec2(v_BorderWidth),
v_Scale - vec2(v_BorderWidth * 2.0), v_Scale - vec2(v_BorderWidth * 2.0),
@ -56,7 +65,7 @@ void main() {
mixed_color = v_Color; mixed_color = v_Color;
} }
float d = distance( float d = fDistance(
fragCoord, fragCoord,
v_Pos, v_Pos,
v_Scale, v_Scale,
@ -66,5 +75,5 @@ void main() {
float radius_alpha = float radius_alpha =
1.0 - smoothstep(max(v_BorderRadius - 0.5, 0.0), v_BorderRadius + 0.5, d); 1.0 - smoothstep(max(v_BorderRadius - 0.5, 0.0), v_BorderRadius + 0.5, d);
o_Color = vec4(mixed_color.xyz, mixed_color.w * radius_alpha); gl_FragColor = vec4(mixed_color.xyz, mixed_color.w * radius_alpha);
} }

View file

@ -1,5 +1,3 @@
#version 130
uniform mat4 u_Transform; uniform mat4 u_Transform;
uniform float u_Scale; uniform float u_Scale;
@ -17,7 +15,7 @@ out vec2 v_Scale;
out float v_BorderRadius; out float v_BorderRadius;
out float v_BorderWidth; out float v_BorderWidth;
const vec2 positions[4] = vec2[]( vec2 positions[4] = vec2[](
vec2(0.0, 0.0), vec2(0.0, 0.0),
vec2(0.0, 1.0), vec2(0.0, 1.0),
vec2(1.0, 0.0), vec2(1.0, 0.0),

View file

@ -1,9 +0,0 @@
#version 130
in vec4 v_Color;
out vec4 o_Color;
void main() {
o_Color = v_Color;
}

View file

@ -21,20 +21,32 @@ pub(crate) struct Pipeline {
} }
impl Pipeline { impl Pipeline {
pub fn new(gl: &glow::Context) -> Pipeline { pub fn new(
gl: &glow::Context,
(vertex_version, fragment_version): &(String, String),
) -> Pipeline {
let program = unsafe { let program = unsafe {
program::create( program::create(
gl, gl,
&[ &[
( (
glow::VERTEX_SHADER, glow::VERTEX_SHADER,
include_str!("shader/compatibility/triangle.vert"), &format!(
"{}\n{}",
vertex_version,
include_str!("shader/common/triangle.vert")
),
), ),
( (
glow::FRAGMENT_SHADER, glow::FRAGMENT_SHADER,
include_str!("shader/compatibility/triangle.frag"), &format!(
"{}\n{}",
fragment_version,
include_str!("shader/common/triangle.frag")
),
), ),
], ],
&[(0, "i_Position"), (1, "i_Color")],
) )
}; };