gl: get some more reflection work done

This commit is contained in:
chyyran 2022-11-12 01:23:49 -05:00
parent 6fcee1691f
commit 66d1c872ee
4 changed files with 217 additions and 46 deletions

View file

@ -6,14 +6,14 @@ use crate::reflect::cross::{CompiledAst, CrossReflect, GlslReflect, HlslReflect}
use crate::reflect::ReflectShader; use crate::reflect::ReflectShader;
pub type GlVersion = spirv_cross::glsl::Version; pub type GlVersion = spirv_cross::glsl::Version;
pub struct GlslangCompileContext { pub struct GlslangGlslContext {
pub texture_fixups: Vec<u32>, pub texture_fixups: Vec<u32>,
pub compiler: CompiledAst<spirv_cross::glsl::Target> pub compiler: CompiledAst<spirv_cross::glsl::Target>
} }
impl FromCompilation<GlslangCompilation> for GLSL { impl FromCompilation<GlslangCompilation> for GLSL {
type Target = GLSL; type Target = GLSL;
type Options = GlVersion; type Options = GlVersion;
type Context = GlslangCompileContext; type Context = GlslangGlslContext;
fn from_compilation( fn from_compilation(
compile: GlslangCompilation, compile: GlslangCompilation,

View file

@ -15,7 +15,7 @@ use spirv_cross::{glsl, hlsl, ErrorCode};
use crate::back::targets::{GLSL, HLSL}; use crate::back::targets::{GLSL, HLSL};
use crate::back::{CompileShader, ShaderCompilerOutput}; use crate::back::{CompileShader, ShaderCompilerOutput};
use crate::back::cross::GlslangCompileContext; use crate::back::cross::GlslangGlslContext;
pub struct CrossReflect<T> pub struct CrossReflect<T>
where where
@ -291,7 +291,6 @@ where
blame: SemanticErrorBlame, blame: SemanticErrorBlame,
) -> Result<(), ShaderReflectError> { ) -> Result<(), ShaderReflectError> {
let ranges = ast.get_active_buffer_ranges(resource.id)?; let ranges = ast.get_active_buffer_ranges(resource.id)?;
eprintln!("{ranges:?}");
for range in ranges { for range in ranges {
let name = ast.get_member_name(resource.base_type_id, range.index)?; let name = ast.get_member_name(resource.base_type_id, range.index)?;
let ubo_type = ast.get_type(resource.base_type_id)?; let ubo_type = ast.get_type(resource.base_type_id)?;
@ -333,6 +332,7 @@ where
meta.parameter_meta.insert( meta.parameter_meta.insert(
parameter.index, parameter.index,
VariableMeta { VariableMeta {
id: name,
offset, offset,
components: typeinfo.size, components: typeinfo.size,
}, },
@ -360,6 +360,7 @@ where
meta.variable_meta.insert( meta.variable_meta.insert(
*semantics, *semantics,
VariableMeta { VariableMeta {
id: name,
offset, offset,
components: typeinfo.size * typeinfo.columns, components: typeinfo.size * typeinfo.columns,
}, },
@ -381,6 +382,7 @@ where
} }
} }
// this will break if range is both ubo and push buf whatever
let offset = offset_type(range.offset); let offset = offset_type(range.offset);
if let Some(meta) = meta.texture_size_meta.get_mut(&texture) { if let Some(meta) = meta.texture_size_meta.get_mut(&texture) {
if offset != meta.offset { if offset != meta.offset {
@ -405,6 +407,7 @@ where
SemanticErrorBlame::Vertex => BindingStage::VERTEX, SemanticErrorBlame::Vertex => BindingStage::VERTEX,
SemanticErrorBlame::Fragment => BindingStage::FRAGMENT, SemanticErrorBlame::Fragment => BindingStage::FRAGMENT,
}, },
id: name
}, },
); );
} }
@ -683,7 +686,7 @@ where
impl CompileShader<GLSL> for CrossReflect<glsl::Target> { impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
type Options = glsl::Version; type Options = glsl::Version;
type Context = GlslangCompileContext; type Context = GlslangGlslContext;
fn compile( fn compile(
mut self, mut self,
@ -745,9 +748,9 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
)); ));
} }
for res in &vertex_resources.uniform_buffers { for res in &vertex_resources.uniform_buffers {
if flatten { // if flatten {
self.vertex.flatten_buffer_block(res.id)?; // self.vertex.flatten_buffer_block(res.id)?;
} // }
self.vertex.set_name(res.id, "RARCH_UBO_VERTEX_INSTANCE")?; self.vertex.set_name(res.id, "RARCH_UBO_VERTEX_INSTANCE")?;
self.vertex.set_name(res.base_type_id, "RARCH_UBO_VERTEX")?; self.vertex.set_name(res.base_type_id, "RARCH_UBO_VERTEX")?;
self.vertex self.vertex
@ -778,9 +781,9 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
} }
for res in &fragment_resources.uniform_buffers { for res in &fragment_resources.uniform_buffers {
if flatten { // if flatten {
self.fragment.flatten_buffer_block(res.id)?; // self.fragment.flatten_buffer_block(res.id)?;
} // }
self.fragment self.fragment
.set_name(res.id, "RARCH_UBO_FRAGMENT_INSTANCE")?; .set_name(res.id, "RARCH_UBO_FRAGMENT_INSTANCE")?;
self.fragment self.fragment
@ -806,7 +809,7 @@ impl CompileShader<GLSL> for CrossReflect<glsl::Target> {
Ok(ShaderCompilerOutput { Ok(ShaderCompilerOutput {
vertex: self.vertex.compile()?, vertex: self.vertex.compile()?,
fragment: self.fragment.compile()?, fragment: self.fragment.compile()?,
context: GlslangCompileContext { context: GlslangGlslContext {
texture_fixups, texture_fixups,
compiler: CompiledAst { compiler: CompiledAst {
vertex: self.vertex, vertex: self.vertex,

View file

@ -122,6 +122,7 @@ pub struct VariableMeta {
// this might bite us in the back because retroarch keeps separate UBO/push offsets.. eh // this might bite us in the back because retroarch keeps separate UBO/push offsets.. eh
pub offset: MemberOffset, pub offset: MemberOffset,
pub components: u32, pub components: u32,
pub id: String,
} }
#[derive(Debug)] #[derive(Debug)]
@ -129,6 +130,7 @@ pub struct TextureSizeMeta {
// this might bite us in the back because retroarch keeps separate UBO/push offsets.. // this might bite us in the back because retroarch keeps separate UBO/push offsets..
pub offset: MemberOffset, pub offset: MemberOffset,
pub stage_mask: BindingStage, pub stage_mask: BindingStage,
pub id: String,
} }
#[derive(Debug)] #[derive(Debug)]

View file

@ -3,18 +3,19 @@ mod hello_triangle;
use std::collections::HashMap; use std::collections::HashMap;
use std::error::Error; use std::error::Error;
use std::path::Path; use std::path::Path;
use gl::types::{GLenum, GLuint}; use gl::types::{GLenum, GLint, GLsizeiptr, GLuint};
use rustc_hash::FxHashMap; use rustc_hash::FxHashMap;
use spirv_cross::spirv::Decoration;
use librashader::ShaderSource; use librashader::ShaderSource;
use librashader_presets::ShaderPassConfig; use librashader_presets::ShaderPassConfig;
use librashader_reflect::back::CompileShader; use librashader_reflect::back::{CompileShader, ShaderCompilerOutput};
use librashader_reflect::back::cross::GlVersion; use librashader_reflect::back::cross::{GlslangGlslContext, GlVersion};
use librashader_reflect::back::targets::{FromCompilation, GLSL}; use librashader_reflect::back::targets::{FromCompilation, GLSL};
use librashader_reflect::front::shaderc::GlslangCompilation; use librashader_reflect::front::shaderc::GlslangCompilation;
use librashader_reflect::reflect::cross::CrossReflect; use librashader_reflect::reflect::cross::CrossReflect;
use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, UniformSemantic}; use librashader_reflect::reflect::{ReflectSemantics, ReflectShader, ShaderReflection, UniformSemantic};
use librashader_reflect::reflect::semantics::{SemanticMap, TextureSemantics, VariableSemantics}; use librashader_reflect::reflect::semantics::{MemberOffset, SemanticMap, TextureSemantics, VariableMeta, VariableSemantics};
use librashader_reflect::reflect::{TextureSemanticMap, VariableSemanticMap}; use librashader_reflect::reflect::{TextureSemanticMap, VariableSemanticMap};
pub fn load_pass_semantics(uniform_semantics: &mut FxHashMap<String, UniformSemantic>, texture_semantics: &mut FxHashMap<String, SemanticMap<TextureSemantics>>, pub fn load_pass_semantics(uniform_semantics: &mut FxHashMap<String, UniformSemantic>, texture_semantics: &mut FxHashMap<String, SemanticMap<TextureSemantics>>,
@ -52,7 +53,97 @@ pub fn load_pass_semantics(uniform_semantics: &mut FxHashMap<String, UniformSema
} }
pub struct RingBuffer<T, const SIZE: usize> {
items: [T; SIZE],
index: usize
}
impl <T, const SIZE: usize> RingBuffer<T, SIZE>
where T: Copy, T: Default
{
pub fn new() -> Self {
Self {
items: [T::default(); SIZE],
index: 0
}
}
}
impl <T, const SIZE: usize> RingBuffer<T, SIZE> {
pub fn current(&self) -> &T {
&self.items[self.index]
}
pub fn next(&mut self) {
self.index += 1;
if self.index >= SIZE {
self.index = 0
}
}
}
#[derive(Debug)]
pub struct Location<T> {
vertex: T,
fragment: T,
}
#[derive(Debug)]
pub enum ParameterLocation {
Ubo(Location<GLint>),
Push(Location<GLint>),
}
pub struct FilterPass {
reflection: ShaderReflection,
compiled: ShaderCompilerOutput<String, GlslangGlslContext>,
program: GLuint,
ubo_location: Location<GLuint>,
ubo_ring: Option<RingBuffer<GLuint, 16>>,
uniform_buffer: Vec<u8>,
push_buffer: Vec<u8>,
locations: FxHashMap<String, ParameterLocation>
}
pub struct FilterChain {
reflections: Vec<ShaderReflection>,
compiled: Vec<ShaderCompilerOutput<String, GlslangGlslContext>>,
programs: Vec<GLuint>,
ubo_location: Location<GLint>,
}
pub fn reflect_parameter(pipeline: GLuint, meta: &VariableMeta) -> ParameterLocation {
// todo: support both ubo and pushco
// todo: fix this.
match meta.offset {
MemberOffset::Ubo(_) => {
let vert_name = format!("RARCH_UBO_VERTEX_INSTANCE.{}\0", meta.id);
let frag_name = format!("RARCH_UBO_FRAGMENT_INSTANCE.{}\0", meta.id);
unsafe {
let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast());
let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast());
ParameterLocation::Ubo(Location {
vertex,
fragment
})
}
}
MemberOffset::PushConstant(_) => {
let vert_name = format!("RARCH_PUSH_VERTEX_INSTANCE.{}\0", meta.id);
let frag_name = format!("RARCH_PUSH_FRAGMENT_INSTANCE.{}\0", meta.id);
unsafe {
let vertex = gl::GetUniformLocation(pipeline, vert_name.as_ptr().cast());
let fragment = gl::GetUniformLocation(pipeline, frag_name.as_ptr().cast());
ParameterLocation::Push(Location {
vertex,
fragment
})
}
}
}
}
// todo: init gl // todo: init gl
pub fn load(path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>{ pub fn load(path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>{
@ -96,41 +187,114 @@ pub fn load(path: impl AsRef<Path>) -> Result<(), Box<dyn Error>>{
non_uniform_semantics: texture_semantics non_uniform_semantics: texture_semantics
}; };
let mut reflections = Vec::new(); let mut filters = Vec::new();
let mut compiled = Vec::new();
for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() { for (index, (config, source, mut reflect)) in passes.into_iter().enumerate() {
let reflection = reflect.reflect(index as u32, &semantics)?; let reflection = reflect.reflect(index as u32, &semantics)?;
let glsl = reflect.compile(GlVersion::V4_60)?; let glsl = reflect.compile(GlVersion::V4_60)?;
let vertex_resources = glsl.context.compiler.vertex.get_shader_resources()?;
// shader_gl3: 1375 // todo: split this out.
reflection.meta.texture_meta.get(&SemanticMap { let (program, ubo_location) = unsafe {
semantics: TextureSemantics::Source, let vertex = gl_compile_shader(gl::VERTEX_SHADER, glsl.vertex.as_str());
index: 0 let fragment = gl_compile_shader(gl::FRAGMENT_SHADER, glsl.fragment.as_str());
}).unwrap().binding;
// unsafe { let program = gl::CreateProgram();
// let vertex = gl_compile_shader(gl::VERTEX_SHADER, glsl.vertex.as_str()); gl::AttachShader(program, vertex);
// let fragment = gl_compile_shader(gl::FRAGMENT_SHADER, glsl.fragment.as_str()); gl::AttachShader(program, fragment);
//
// let program = gl::CreateProgram(); for res in &vertex_resources.stage_inputs {
// gl::AttachShader(program, vertex); let loc = glsl.context.compiler.vertex.get_decoration(res.id, Decoration::Location)?;
// gl::AttachShader(program, fragment); 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);
}
}
}
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);
}
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));
}
for param in reflection.meta.variable_meta.values() {
locations.insert(param.id.clone(), reflect_parameter(program, param));
}
compiled.push(glsl); eprintln!("{:#?}", semantics);
reflections.push(reflection); 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(); // let mut glprogram: Vec<GLuint> = Vec::new();
for compilation in &compiled { // for compilation in &compiled {
// compilation.context.compiler.vertex // // compilation.context.compiler.vertex
} // }
eprintln!("{:#?}", reflections); // eprintln!("{:#?}", reflections);
// eprintln!("{:#?}", compiled./); // eprintln!("{:#?}", compiled./);
// eprintln!("{:?}", preset); // eprintln!("{:?}", preset);
@ -164,13 +328,15 @@ mod tests {
#[test] #[test]
fn triangle() { fn triangle() {
let (glfw, window, events, shader, vao) = hello_triangle::setup(); let (glfw, window, events, shader, vao) = hello_triangle::setup();
load("../test/basic.slangp")
.unwrap();
hello_triangle::do_loop(glfw, window, events, shader, vao); hello_triangle::do_loop(glfw, window, events, shader, vao);
} }
#[test] // #[test]
fn load_preset() { // fn load_preset() {
//
load("../test/basic.slangp") // load("../test/basic.slangp")
.unwrap(); // .unwrap();
} // }
} }