gl: start work on frame history

This commit is contained in:
chyyran 2022-11-14 00:14:05 -05:00
parent b1beb0e46f
commit 848d87021c
11 changed files with 451 additions and 206 deletions

4
Cargo.lock generated
View file

@ -458,6 +458,9 @@ checksum = "68783febc7782c6c5cb401fbda4de5a9898be1762314da0bb2c10ced61f18b0c"
[[package]]
name = "librashader"
version = "0.1.0"
dependencies = [
"gl",
]
[[package]]
name = "librashader-preprocess"
@ -472,6 +475,7 @@ dependencies = [
name = "librashader-presets"
version = "0.1.0"
dependencies = [
"librashader",
"nom",
"nom_locate",
"thiserror",

View file

@ -9,3 +9,4 @@ edition = "2021"
thiserror = "1.0.37"
nom = "7.1.1"
nom_locate = "4.0.0"
librashader = { path = "../librashader" }

View file

@ -1,6 +1,6 @@
use crate::error::{ParseErrorKind, ParsePresetError};
use crate::parse::{remove_if, Span, Token};
use crate::{FilterMode, ScaleFactor, ScaleType, WrapMode};
use crate::{ScaleFactor, ScaleType};
use nom::bytes::complete::tag;
use nom::character::complete::digit1;
use nom::combinator::{eof, map_res};
@ -12,6 +12,7 @@ use std::fs::File;
use std::io::Read;
use std::path::{Path, PathBuf};
use std::str::FromStr;
use librashader::{FilterMode, WrapMode};
#[derive(Debug)]
pub enum Value {

View file

@ -2,25 +2,7 @@ use crate::error::ParsePresetError;
use std::convert::Infallible;
use std::path::PathBuf;
use std::str::FromStr;
#[repr(i32)]
#[derive(Copy, Clone, Default, Debug)]
pub enum FilterMode {
#[default]
Linear = 0,
Nearest,
Unspecified,
}
#[repr(i32)]
#[derive(Copy, Clone, Default, Debug)]
pub enum WrapMode {
#[default]
ClampToBorder = 0,
ClampToEdge,
Repeat,
MirroredRepeat,
}
use librashader::{FilterMode, WrapMode};
#[repr(i32)]
#[derive(Default, Copy, Clone, Debug)]
@ -43,20 +25,6 @@ impl Default for ScaleFactor {
}
}
impl FromStr for WrapMode {
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"clamp_to_border" => WrapMode::ClampToBorder,
"clamp_to_edge" => WrapMode::ClampToEdge,
"repeat" => WrapMode::Repeat,
"mirrored_repeat" => WrapMode::MirroredRepeat,
_ => WrapMode::ClampToBorder,
})
}
}
impl FromStr for ScaleType {
type Err = ParsePresetError;

View file

@ -71,7 +71,7 @@ pub fn load(path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>{
for (index, parameter) in preset.parameters.iter().enumerate() {
uniform_semantics.insert(parameter.name.clone(), UniformSemantic::Variable(SemanticMap {
semantics: VariableSemantics::FloatParameter,
index: index as u32
index: ()
}));
}

View file

@ -6,7 +6,7 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
"librashader" = { path = "../librashader" }
"librashader" = { path = "../librashader", features = ["opengl"] }
"librashader-presets" = { path = "../librashader-presets" }
"librashader-preprocess" = { path = "../librashader-preprocess" }
"librashader-reflect" = { path = "../librashader-reflect" }

View file

View file

@ -1,14 +1,17 @@
mod hello_triangle;
mod filter;
use std::collections::HashMap;
use std::error::Error;
use std::iter::Filter;
use std::path::Path;
use gl::types::{GLenum, GLint, GLsizeiptr, GLuint};
use gl::types::{GLenum, GLint, GLsizei, GLsizeiptr, GLuint};
use glfw::Key::P;
use rustc_hash::FxHashMap;
use spirv_cross::spirv::Decoration;
use librashader::ShaderSource;
use librashader_presets::ShaderPassConfig;
use librashader::{ShaderFormat, ShaderSource};
use librashader_presets::{ShaderPassConfig, ShaderPreset};
use librashader_reflect::back::{CompileShader, ShaderCompilerOutput};
use librashader_reflect::back::cross::{GlslangGlslContext, GlVersion};
use librashader_reflect::back::targets::{FromCompilation, GLSL};
@ -18,7 +21,21 @@ use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, ShaderReflec
use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureSemantics, VariableMeta, VariableSemantics};
use librashader_reflect::reflect::{TextureSemanticMap, VariableSemanticMap};
pub fn load_pass_semantics(uniform_semantics: &mut FxHashMap<String, UniformSemantic>, texture_semantics: &mut FxHashMap<String, SemanticMap<TextureSemantics>>,
unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint {
let shader = gl::CreateShader(stage);
gl::ShaderSource(shader, 1, &source.as_bytes().as_ptr().cast(), std::ptr::null());
gl::CompileShader(shader);
let mut compile_status = 0;
gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut compile_status);
if compile_status == 0 {
panic!("failed to compile")
}
shader
}
fn load_pass_semantics(uniform_semantics: &mut FxHashMap<String, UniformSemantic>, texture_semantics: &mut FxHashMap<String, SemanticMap<TextureSemantics>>,
config: &ShaderPassConfig) {
let Some(alias) = &config.alias else {
return;
@ -102,14 +119,149 @@ pub struct FilterPass {
ubo_ring: Option<RingBuffer<GLuint, 16>>,
uniform_buffer: Vec<u8>,
push_buffer: Vec<u8>,
locations: FxHashMap<String, ParameterLocation>
locations: FxHashMap<String, ParameterLocation>,
framebuffer: Framebuffer,
feedback_framebuffer: Framebuffer,
}
pub struct Framebuffer {
image: GLuint,
size: Size,
format: GLenum,
max_levels: u32,
levels: u32,
framebuffer: GLuint,
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);
}
Framebuffer {
image: 0,
size: Size { width: 1, height: 1 },
format: 0,
max_levels,
levels: 0,
framebuffer,
init: false
}
}
fn init(&mut self, mut size: Size, mut format: ShaderFormat) {
if format == ShaderFormat::Unknown {
format = ShaderFormat::R8G8B8A8Unorm;
}
self.format = GLenum::from(format);
self.size = size;
unsafe {
gl::BindFramebuffer(gl::FRAMEBUFFER, self.framebuffer);
// reset the framebuffer image
if self.image != 0 {
gl::FramebufferTexture2D(gl::FRAMEBUFFER, gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, 0, 0);
gl::DeleteTextures(1, &self.image);
}
gl::GenTextures(1, &mut self.image);
gl::BindTexture(1, self.image);
if size.width == 0 {
size.width = 1;
}
if size.height == 0 {
size.height = 1;
}
self.levels = calc_miplevel(size.width, size.height);
if self.levels > self.max_levels {
self.levels = self.max_levels;
}
if self.levels == 0 {
self.levels = 1;
}
gl::TexStorage2D(gl::TEXTURE_2D, self.levels as GLsizei, self.format, size.width as GLsizei, size.height as GLsizei);
gl::FramebufferTexture2D(gl::FRAMEBUFFER,
gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, self.image, 0);
let status = gl::CheckFramebufferStatus(gl::FRAMEBUFFER);
if status != gl::FRAMEBUFFER_COMPLETE {
match status {
gl::FRAMEBUFFER_UNSUPPORTED => {
eprintln!("unsupported fbo");
gl::FramebufferTexture2D(gl::FRAMEBUFFER,
gl::COLOR_ATTACHMENT0, gl::TEXTURE_2D, 0, 0);
gl::DeleteTextures(1, &self.image);
gl::GenTextures(1, &mut self.image);
gl::BindTexture(1, self.image);
self.levels = calc_miplevel(size.width, size.height);
if self.levels > self.max_levels {
self.levels = self.max_levels;
}
if self.levels == 0 {
self.levels = 1;
}
gl::TexStorage2D(gl::TEXTURE_2D, self.levels as GLsizei, gl::RGBA8, 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}")
}
} else {
self.init = true;
}
gl::BindFramebuffer(gl::FRAMEBUFFER, 0);
gl::BindTexture(gl::TEXTURE_2D, 0);
}
}
}
pub fn calc_miplevel(width: u32, height: u32) -> u32 {
let mut size = std::cmp::max(width, height);
let mut levels = 0;
while size != 0 {
levels += 1;
size >>= 1;
}
return levels;
}
pub struct FilterChain {
reflections: Vec<ShaderReflection>,
compiled: Vec<ShaderCompilerOutput<String, GlslangGlslContext>>,
programs: Vec<GLuint>,
ubo_location: Location<GLint>,
passes: Vec<FilterPass>,
semantics: ReflectSemantics,
preset: ShaderPreset,
original_history: Vec<Framebuffer>,
history: Vec<Texture>,
feedback: Vec<Texture>
}
pub fn reflect_parameter(pipeline: GLuint, meta: &VariableMeta) -> ParameterLocation {
@ -144,201 +296,228 @@ pub fn reflect_parameter(pipeline: GLuint, meta: &VariableMeta) -> ParameterLoca
}
}
}
// todo: init gl
pub fn load(path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>{
let preset = librashader_presets::ShaderPreset::try_parse(path)?;
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> = Default::default();
impl FilterChain {
pub fn load(path: impl AsRef<Path>) -> Result<FilterChain, Box<dyn Error>> {
let preset = librashader_presets::ShaderPreset::try_parse(path)?;
let mut uniform_semantics: FxHashMap<String, UniformSemantic> = Default::default();
let mut texture_semantics: FxHashMap<String, SemanticMap<TextureSemantics>> = Default::default();
let mut passes: Vec<(&ShaderPassConfig, ShaderSource, _)> = preset.shaders.iter()
.map(|shader| {
eprintln!("[gl] loading {}", &shader.name.display());
let source: ShaderSource = librashader_preprocess::load_shader_source(&shader.name)
.unwrap();
let mut passes: Vec<(&ShaderPassConfig, ShaderSource, _)> = preset.shaders.iter()
.map(|shader| {
eprintln!("[gl] loading {}", &shader.name.display());
let source: ShaderSource = librashader_preprocess::load_shader_source(&shader.name)
.unwrap();
let spirv = librashader_reflect::front::shaderc::compile_spirv(&source)
.unwrap();
let mut reflect = GLSL::from_compilation(spirv).unwrap();
let spirv = librashader_reflect::front::shaderc::compile_spirv(&source)
.unwrap();
let mut reflect = GLSL::from_compilation(spirv).unwrap();
for parameter in source.parameters.iter() {
uniform_semantics.insert(parameter.id.clone(), UniformSemantic::Variable(SemanticMap {
semantics: VariableSemantics::FloatParameter,
index: ()
}));
}
for parameter in source.parameters.iter() {
uniform_semantics.insert(parameter.id.clone(), UniformSemantic::Variable(SemanticMap {
semantics: VariableSemantics::FloatParameter,
index: ()
}));
}
(shader, source, reflect)
}).collect();
(shader, source, reflect)
}).collect();
// todo: this can probably be extracted out.
// todo: this can probably be extracted out.
for details in &passes {
load_pass_semantics(&mut uniform_semantics, &mut texture_semantics, details.0)
}
for details in &passes {
load_pass_semantics(&mut uniform_semantics, &mut texture_semantics, details.0)
}
// add lut params
for (index, texture) in preset.textures.iter().enumerate() {
texture_semantics.insert(texture.name.clone(), SemanticMap {
semantics: TextureSemantics::User,
index: index as u32
});
// add lut params
for (index, texture) in preset.textures.iter().enumerate() {
texture_semantics.insert(texture.name.clone(), SemanticMap {
semantics: TextureSemantics::User,
index: index as u32
});
uniform_semantics.insert(format!("{}Size", texture.name), UniformSemantic::Texture(SemanticMap {
semantics: TextureSemantics::User,
index: index as u32
}));
}
uniform_semantics.insert(format!("{}Size", texture.name), UniformSemantic::Texture(SemanticMap {
semantics: TextureSemantics::User,
index: index as u32
}));
}
let semantics = ReflectSemantics {
uniform_semantics,
non_uniform_semantics: texture_semantics
};
let semantics = ReflectSemantics {
uniform_semantics,
non_uniform_semantics: texture_semantics
};
let mut filters = Vec::new();
let mut filters = Vec::new();
for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() {
let mut semantics = semantics.clone();
// initialize passes
for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() {
let mut semantics = semantics.clone();
// insert parameters parsed from source
// for (index, parameter) in source.parameters.iter().enumerate() {
// semantics.uniform_semantics.insert(parameter.id.clone(), UniformSemantic::Variable(SemanticMap {
// semantics: VariableSemantics::FloatParameter,
// index: 0
// }));
// }
let reflection = reflect.reflect(index as u32, &semantics)?;
let glsl = reflect.compile(GlVersion::V4_60)?;
let reflection = reflect.reflect(index as u32, &semantics)?;
let vertex_resources = glsl.context.compiler.vertex.get_shader_resources()?;
let glsl = reflect.compile(GlVersion::V4_60)?;
// todo: split this out.
let (program, ubo_location) = unsafe {
let vertex = gl_compile_shader(gl::VERTEX_SHADER, glsl.vertex.as_str());
let fragment = gl_compile_shader(gl::FRAGMENT_SHADER, glsl.fragment.as_str());
let vertex_resources = glsl.context.compiler.vertex.get_shader_resources()?;
let program = gl::CreateProgram();
gl::AttachShader(program, vertex);
gl::AttachShader(program, fragment);
// todo: split this out.
let (program, ubo_location) = unsafe {
let vertex = gl_compile_shader(gl::VERTEX_SHADER, glsl.vertex.as_str());
let fragment = gl_compile_shader(gl::FRAGMENT_SHADER, glsl.fragment.as_str());
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}");
gl::BindAttribLocation(program, loc, loc_name.as_str().as_ptr().cast())
}
gl::LinkProgram(program);
gl::DeleteShader(vertex);
gl::DeleteShader(fragment);
let program = gl::CreateProgram();
gl::AttachShader(program, vertex);
gl::AttachShader(program, fragment);
let mut status = 0;
gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);
if status != 1 {
panic!("failed to link program")
}
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}");
gl::BindAttribLocation(program, loc, loc_name.as_str().as_ptr().cast())
}
gl::LinkProgram(program);
gl::DeleteShader(vertex);
gl::DeleteShader(fragment);
let mut status = 0;
gl::GetProgramiv(program, gl::LINK_STATUS, &mut status);
if status != 1 {
panic!("failed to link program")
}
for binding in &glsl.context.texture_fixups {
let loc_name = format!("RARCH_TEXTURE_{}", *binding);
unsafe {
let location = gl::GetUniformLocation(program, loc_name.as_str().as_ptr().cast());
if location >= 0 {
gl::Uniform1i(location, *binding as GLint);
for binding in &glsl.context.texture_fixups {
let loc_name = format!("RARCH_TEXTURE_{}", *binding);
unsafe {
let location = gl::GetUniformLocation(program, loc_name.as_str().as_ptr().cast());
if location >= 0 {
gl::Uniform1i(location, *binding as GLint);
}
}
}
}
unsafe {
gl::UseProgram(0);
(program, Location {
vertex: gl::GetUniformBlockIndex(program, b"RARCH_UBO_VERTEX\0".as_ptr().cast()),
fragment: gl::GetUniformBlockIndex(program, b"RARCH_UBO_FRAGMENT\0".as_ptr().cast()),
})
}
};
let ubo_ring = if let Some(ubo) = &reflection.ubo {
let size = ubo.size;
let mut ring: RingBuffer<GLuint, 16> = RingBuffer::new();
unsafe {
gl::GenBuffers(16, ring.items.as_mut_ptr());
for buffer in &ring.items {
gl::BindBuffer(gl::UNIFORM_BUFFER, *buffer);
gl::BufferData(gl::UNIFORM_BUFFER, size as GLsizeiptr, std::ptr::null(), gl::STREAM_DRAW);
unsafe {
gl::UseProgram(0);
(program, Location {
vertex: gl::GetUniformBlockIndex(program, b"RARCH_UBO_VERTEX\0".as_ptr().cast()),
fragment: gl::GetUniformBlockIndex(program, b"RARCH_UBO_FRAGMENT\0".as_ptr().cast()),
})
}
gl::BindBuffer(gl::UNIFORM_BUFFER, 0);
};
let ubo_ring = if let Some(ubo) = &reflection.ubo {
let size = ubo.size;
let mut ring: RingBuffer<GLuint, 16> = RingBuffer::new();
unsafe {
gl::GenBuffers(16, ring.items.as_mut_ptr());
for buffer in &ring.items {
gl::BindBuffer(gl::UNIFORM_BUFFER, *buffer);
gl::BufferData(gl::UNIFORM_BUFFER, size as GLsizeiptr, std::ptr::null(), gl::STREAM_DRAW);
}
gl::BindBuffer(gl::UNIFORM_BUFFER, 0);
}
Some(ring)
} else {
None
};
let uniform_buffer = vec![0; reflection.ubo.as_ref().map(|ubo| ubo.size as usize).unwrap_or(0)];
let push_buffer = vec![0; reflection.push_constant.as_ref().map(|push| push.size as usize).unwrap_or(0)];
// todo: reflect indexed parameters
let mut locations = FxHashMap::default();
for param in reflection.meta.parameter_meta.values() {
locations.insert(param.id.clone(), reflect_parameter(program, param));
}
Some(ring)
} else {
None
};
let uniform_buffer = vec![0; reflection.ubo.as_ref().map(|ubo| ubo.size as usize).unwrap_or(0)];
let push_buffer = vec![0; reflection.push_constant.as_ref().map(|push| push.size as usize).unwrap_or(0)];
for param in reflection.meta.variable_meta.values() {
locations.insert(param.id.clone(), reflect_parameter(program, param));
}
// todo: reflect indexed parameters
let mut locations = FxHashMap::default();
for param in reflection.meta.parameter_meta.values() {
locations.insert(param.id.clone(), reflect_parameter(program, param));
// eprintln!("{:#?}", semantics);
eprintln!("{:#?}", reflection.meta);
eprintln!("{:#?}", locations);
eprintln!("{:#?}", reflection.push_constant);
// eprintln!("====fragment====");
// eprintln!("{:#}", glsl.fragment);
// eprintln!("====vertex====");
// eprintln!("{:#}", glsl.vertex);
filters.push(FilterPass {
reflection,
compiled: glsl,
program,
ubo_location,
ubo_ring,
uniform_buffer,
push_buffer,
locations,
// no idea if this works.
// retroarch checks if feedback frames are used but we'll just init it tbh.
framebuffer: Framebuffer::new(1),
feedback_framebuffer: Framebuffer::new(1)
});
}
for param in reflection.meta.variable_meta.values() {
locations.insert(param.id.clone(), reflect_parameter(program, param));
}
// eprintln!("{:#?}", semantics);
eprintln!("{:#?}", reflection.meta);
eprintln!("{:#?}", locations);
eprintln!("{:#?}", reflection.push_constant);
// eprintln!("====fragment====");
// eprintln!("{:#}", glsl.fragment);
// eprintln!("====vertex====");
// eprintln!("{:#}", glsl.vertex);
filters.push(FilterPass {
reflection,
compiled: glsl,
program,
ubo_location,
ubo_ring,
uniform_buffer,
push_buffer,
locations
});
}
// let mut glprogram: Vec<GLuint> = Vec::new();
// for compilation in &compiled {
// // compilation.context.compiler.vertex
// }
eprintln!("{:?}", filters.iter().map(|f| f.program).collect::<Vec<_>>());
// let mut glprogram: Vec<GLuint> = Vec::new();
// for compilation in &compiled {
// // compilation.context.compiler.vertex
// }
// eprintln!("{:#?}", reflections);
// eprintln!("{:#?}", compiled./);
// eprintln!("{:?}", preset);
// eprintln!("{:?}", reflect.reflect(&ReflectOptions {
// pass_number: i as u32,
// uniform_semantics,
// non_uniform_semantics: Default::default(),
// }));
// eprintln!("{:#?}", compiled./);
// eprintln!("{:?}", preset);
// eprintln!("{:?}", reflect.reflect(&ReflectOptions {
// pass_number: i as u32,
// uniform_semantics,
// non_uniform_semantics: Default::default(),
// }));
Ok(())
}
// todo: apply shader pass
// gl3.cpp: 1942
unsafe fn gl_compile_shader(stage: GLenum, source: &str) -> GLuint {
let shader = gl::CreateShader(stage);
gl::ShaderSource(shader, 1, &source.as_bytes().as_ptr().cast(), std::ptr::null());
gl::CompileShader(shader);
let mut compile_status = 0;
gl::GetShaderiv(shader, gl::COMPILE_STATUS, &mut compile_status);
if compile_status == 0 {
panic!("failed to compile")
Ok(FilterChain {
passes: filters,
semantics,
preset,
original_history: vec![],
history: vec![],
feedback: vec![]
})
}
// how much info do we actually need?
fn frame(&mut self, count: u64, vp: &Viewport, input: &Texture, clear: bool) {
// todo: deal with the mess that is frame history
}
shader
}
#[derive(Debug, Copy, Clone)]
struct Viewport {
x: i32,
y: i32,
width: i32,
height: i32
}
#[derive(Debug, Copy, Clone)]
struct Size {
width: u32,
height: u32,
}
#[derive(Debug, Copy, Clone)]
struct Texture {
handle: GLuint,
format: GLenum,
size: Size,
padded_size: Size
}
#[cfg(test)]
mod tests {
use super::*;
@ -346,9 +525,9 @@ mod tests {
#[test]
fn triangle() {
let (glfw, window, events, shader, vao) = hello_triangle::setup();
// load("../test/basic.slangp")
load("../test/slang-shaders/crt/crt-royale.slangp")
.unwrap();
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);
}

View file

@ -5,4 +5,9 @@ edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[features]
default = [ "opengl" ]
opengl = ["gl"]
[dependencies]
gl = { version = "0.14.0", optional = true }

50
librashader/src/gl.rs Normal file
View file

@ -0,0 +1,50 @@
use crate::{FilterMode, ShaderFormat, WrapMode};
impl From<ShaderFormat> for gl::types::GLenum {
fn from(format: ShaderFormat) -> Self {
match format {
ShaderFormat::Unknown => 0 as gl::types::GLenum,
ShaderFormat::R8Unorm => gl::R8,
ShaderFormat::R8Uint => gl::R8UI,
ShaderFormat::R8Sint => gl::R8I,
ShaderFormat::R8G8Unorm => gl::RG8,
ShaderFormat::R8G8Uint => gl::RG8UI,
ShaderFormat::R8G8Sint => gl::RG8I,
ShaderFormat::R8G8B8A8Unorm => gl::RGBA8,
ShaderFormat::R8G8B8A8Uint => gl::RGBA8UI,
ShaderFormat::R8G8B8A8Sint => gl::RGBA8I,
ShaderFormat::R8G8B8A8Srgb => gl::SRGB8_ALPHA8,
ShaderFormat::A2B10G10R10UnormPack32 => gl::RGB10_A2,
ShaderFormat::A2B10G10R10UintPack32 => gl::RGB10_A2UI,
ShaderFormat::R16Uint => gl::R16UI,
ShaderFormat::R16Sint => gl::R16I,
ShaderFormat::R16Sfloat => gl::R16F,
ShaderFormat::R16G16Uint => gl::RG16UI,
ShaderFormat::R16G16Sint => gl::RG16I,
ShaderFormat::R16G16Sfloat => gl::RG16F,
ShaderFormat::R16G16B16A16Uint => gl::RGBA16UI,
ShaderFormat::R16G16B16A16Sint => gl::RGBA16I,
ShaderFormat::R16G16B16A16Sfloat => gl::RGBA16F,
ShaderFormat::R32Uint => gl::R32UI,
ShaderFormat::R32Sint => gl::R32I,
ShaderFormat::R32Sfloat => gl::R32F,
ShaderFormat::R32G32Uint => gl::RG32UI,
ShaderFormat::R32G32Sint => gl::RG32I,
ShaderFormat::R32G32Sfloat => gl::RG32F,
ShaderFormat::R32G32B32A32Uint => gl::RGBA32UI,
ShaderFormat::R32G32B32A32Sint => gl::RGBA32I,
ShaderFormat::R32G32B32A32Sfloat => gl::RGBA32F
}
}
}
impl From<WrapMode> for gl::types::GLenum {
fn from(value: WrapMode) -> Self {
match value {
WrapMode::ClampToBorder => gl::CLAMP_TO_BORDER,
WrapMode::ClampToEdge => gl::CLAMP_TO_EDGE,
WrapMode::Repeat => gl::REPEAT,
WrapMode::MirroredRepeat => gl::MIRRORED_REPEAT
}
}
}

View file

@ -1,3 +1,6 @@
#[cfg(feature = "opengl")]
pub mod gl;
use std::convert::Infallible;
use std::str::FromStr;
@ -65,6 +68,40 @@ pub enum ShaderFormat {
R32G32B32A32Sfloat,
}
#[repr(i32)]
#[derive(Copy, Clone, Default, Debug)]
pub enum FilterMode {
#[default]
Linear = 0,
Nearest,
Unspecified,
}
impl FromStr for WrapMode {
type Err = Infallible;
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"clamp_to_border" => WrapMode::ClampToBorder,
"clamp_to_edge" => WrapMode::ClampToEdge,
"repeat" => WrapMode::Repeat,
"mirrored_repeat" => WrapMode::MirroredRepeat,
_ => WrapMode::ClampToBorder,
})
}
}
#[repr(i32)]
#[derive(Copy, Clone, Default, Debug)]
pub enum WrapMode {
#[default]
ClampToBorder = 0,
ClampToEdge,
Repeat,
MirroredRepeat,
}
impl FromStr for ShaderFormat {
type Err = Infallible;