Using headless opengl context to lint files, removed last bits of glslangValidator

This commit is contained in:
Noah Santschi-Cooney 2021-01-10 23:42:14 +00:00
parent 26c855f016
commit dc1495686a
No known key found for this signature in database
GPG key ID: 3B22282472C8AE48
3 changed files with 107 additions and 241 deletions

View file

@ -107,6 +107,18 @@ impl Display for IncludePosition {
}
}
pub enum TreeType {
Fragment, Vertex
}
impl Into<&'static str> for TreeType {
fn into(self) -> &'static str {
match self {
TreeType::Vertex => "vert",
_ => "frag"
}
}
}
impl MinecraftShaderLanguageServer {
pub fn error_not_available<DATA>(data: DATA) -> MethodError<DATA> {
@ -252,14 +264,24 @@ impl MinecraftShaderLanguageServer {
Err(e) => return Err(e),
};
eprintln!("ancestors for {}:\n{:?}", uri, file_ancestors.iter().map(|e| self.graph.borrow().graph.node_weight(*e).unwrap().clone()).collect::<Vec<String>>());
eprintln!("ancestors for {}:\n\t{:?}", uri, file_ancestors.iter().map(|e| self.graph.borrow().graph.node_weight(*e).unwrap().clone()).collect::<Vec<String>>());
// the set of all filepath->content. TODO: change to Url?
let mut all_sources: HashMap<String, String> = HashMap::new();
let mut diagnostics: HashMap<Url, Vec<Diagnostic>> = HashMap::new();//Vec::new();
// the set of filepath->list of diagnostics to report
let mut diagnostics: HashMap<Url, Vec<Diagnostic>> = HashMap::new();
// we want to backfill the diagnostics map with all linked sources
let back_fill = |all_sources: &HashMap<String, String>, diagnostics: &mut HashMap<Url, Vec<Diagnostic>>| {
for (path, _) in all_sources {
diagnostics.entry(Url::from_file_path(path).unwrap()).or_default();
}
};
// if we are a top-level file (this has to be one of the set defined by Optifine, right?)
if file_ancestors.is_empty() {
// gather the list of all descendants
let root = self.graph.borrow_mut().find_node(uri).unwrap();
let tree = match self.get_dfs_for_node(root) {
Ok(tree) => tree,
Err(e) => {
@ -273,24 +295,42 @@ impl MinecraftShaderLanguageServer {
let graph = self.graph.borrow();
let views = merge_views::generate_merge_list(&tree, &all_sources, &graph);
let views = merger.generate_merge_list(&tree);
let tree_type = if uri.ends_with(".fsh") {
TreeType::Fragment
} else {
TreeType::Vertex
};
let stdout = self.invoke_validator(views)?;
let stdout = match opengl::validate(tree_type, views) {
Some(s) => s,
None => {
back_fill(&all_sources, &mut diagnostics);
return Ok(diagnostics)
},
};
eprintln!("glslangValidator output: {}\n", stdout);
diagnostics.extend(self.parse_validator_stdout(&stdout, ""));
diagnostics.extend(self.parse_validator_stdout(stdout, ""));
} else {
let mut all_trees = Vec::new();
let mut all_trees: Vec<(TreeType, Vec<(NodeIndex, Option<_>)>)> = Vec::new();
for root in &file_ancestors {
let nodes = match self.get_dfs_for_node(*root) {
Ok(nodes) => nodes,
Err(e) => {
diagnostics.insert(Url::from_file_path(uri).unwrap(), vec![e.into()]);
back_fill(&all_sources, &mut diagnostics); // TODO: confirm
return Ok(diagnostics);
}
};
let tree_type = if uri.ends_with(".fsh") {
TreeType::Fragment
} else {
TreeType::Vertex
};
let sources = self.load_sources(&nodes)?;
all_trees.push(nodes);
all_trees.push((tree_type, nodes));
all_sources.extend(sources);
}
@ -298,20 +338,20 @@ impl MinecraftShaderLanguageServer {
let graph = self.graph.borrow();
let views = merge_views::generate_merge_list(&tree.1, &all_sources, &graph);
let stdout = self.invoke_validator(views)?;
let stdout = match opengl::validate(tree.0, views) {
Some(s) => s,
None => continue,
};
eprintln!("glslangValidator output: {}\n", stdout);
diagnostics.extend(self.parse_validator_stdout(&stdout, ""));
diagnostics.extend(self.parse_validator_stdout(stdout, ""));
}
};
for (path, _) in all_sources {
diagnostics.entry(Url::from_file_path(path).unwrap()).or_default();
}
back_fill(&all_sources, &mut diagnostics);
Ok(diagnostics)
}
fn parse_validator_stdout(&self, stdout: &str, source: &str) -> HashMap<Url, Vec<Diagnostic>> {
fn parse_validator_stdout(&self, stdout: String, source: &str) -> HashMap<Url, Vec<Diagnostic>> {
let stdout_lines = stdout.split('\n');
let mut diagnostics: HashMap<Url, Vec<Diagnostic>> = HashMap::with_capacity(stdout_lines.count());
let stdout_lines = stdout.split('\n');
@ -422,34 +462,6 @@ impl MinecraftShaderLanguageServer {
Ok(Some(roots))
}
fn invoke_validator(&self, tree_type: TreeType, source: LinkedList<&str>) -> Result<String> {
/* let mut eventloop = glutin::event_loop::EventLoop::new();
let context = glutin::ContextBuilder::new().build_headless(&eventloop, glutin::dpi::PhysicalSize::new(1920, 1080)); */
Ok("".to_string())
}
/* fn invoke_validator(&self, tree_type: TreeType, source: LinkedList<&str>) -> Result<String> {
let cmd = process::Command::new(&self.config.glslang_validator_path)
.args(&["--stdin", "-S", tree_type.into()])
.stdin(process::Stdio::piped())
.stdout(process::Stdio::piped())
.spawn();
let mut child = cmd?;//.expect("glslangValidator failed to spawn");
let stdin = child.stdin.as_mut().expect("no stdin handle found");
let mut io_slices: Vec<std::io::IoSlice> = source.iter().map(|s| std::io::IoSlice::new(s.as_bytes())).collect();
stdin.write_all_vectored(&mut io_slices[..])?;//.expect("failed to write to stdin");
stdin.flush()?;
let output = child.wait_with_output()?;//.expect("expected output");
let stdout = String::from_utf8(output.stdout).unwrap();
Ok(stdout.trim().to_string())
} */
pub fn publish_diagnostic(&self, diagnostics: HashMap<Url, Vec<Diagnostic>>, document_version: Option<i32>) {
eprintln!("DIAGNOSTICS:\n{:?}", diagnostics);
for (uri, diagnostics) in diagnostics {

View file

@ -1,43 +1,11 @@
use std::mem;
use std::ptr;
use std::str;
use std::os::raw::c_void;
use std::ffi::CString;
use std::ffi::{CString, CStr};
const SCREEN_WIDTH: u32 = 800;
const SCREEN_HEIGHT: u32 = 600;
const VERTEX_SHADER_SOURCE: &str = r#"
#version 330 core
layout (location = 0) in vec3 aPos;
layout (location = 1) in vec3 aColor; // Specify a vertex attribute for color
out vec3 color;
void main()
{
gl_Position = vec4(aPos.x, aPos.y, aPos.z, 1.0);
color = aColor; // pass the color along to the fragment shader
}
"#;
const FRAGMENT_SHADER_SOURCE: &str = r#"
#version 330 core
out vec4 FragColor;
in vec3 color;
void main()
{
// Set the fragment color to the color passed from the vertex shader
FragColor = vec4(color, 1.0);
}
"#;
fn doit() {
let mut events_loop = glutin::event_loop::EventLoop::new();
let window = glutin::window::WindowBuilder::new()
.with_title("Glutin Triangle")
.with_inner_size(glutin::dpi::Size::Physical(glutin::dpi::PhysicalSize::new(1, 1)));
pub fn validate(tree_type: super::TreeType, source: String) -> Option<String> {
let events_loop = glutin::event_loop::EventLoop::new();
let gl_window = glutin::ContextBuilder::new().build_headless(&*events_loop, glutin::dpi::PhysicalSize::new(1, 1)).unwrap();
#[allow(unused_variables)]
let gl_window = unsafe {
let gl_window = gl_window.make_current().unwrap();
gl::load_with(|symbol| gl_window.get_proc_address(symbol) as *const _);
@ -45,69 +13,57 @@ fn doit() {
};
unsafe {
eprintln!("{}", String::from_utf8(CStr::from_ptr(gl::GetString(gl::VERSION) as *const _).to_bytes().to_vec()).unwrap());
eprintln!("{}", String::from_utf8(CStr::from_ptr(gl::GetString(gl::VENDOR) as *const _).to_bytes().to_vec()).unwrap());
eprintln!("{}", String::from_utf8(CStr::from_ptr(gl::GetString(gl::RENDERER) as *const _).to_bytes().to_vec()).unwrap());
// Setup shader compilation checks
let mut success = i32::from(gl::FALSE);
// Vertex shader
let vertex_shader = gl::CreateShader(gl::VERTEX_SHADER);
let c_str_vert = CString::new(VERTEX_SHADER_SOURCE.as_bytes()).unwrap();
gl::ShaderSource(vertex_shader, 1, &c_str_vert.as_ptr(), ptr::null());
gl::CompileShader(vertex_shader);
match tree_type {
crate::TreeType::Fragment => {
// Fragment shader
let fragment_shader = gl::CreateShader(gl::FRAGMENT_SHADER);
let c_str_frag = CString::new(source).unwrap();
gl::ShaderSource(fragment_shader, 1, &c_str_frag.as_ptr(), ptr::null());
gl::CompileShader(fragment_shader);
// Check for shader compilation errors
gl::GetShaderiv(vertex_shader, gl::COMPILE_STATUS, &mut success);
if success != i32::from(gl::TRUE) {
let mut info_len: gl::types::GLint = 0;
gl::GetShaderiv(vertex_shader, gl::INFO_LOG_LENGTH, &mut info_len);
let mut info = vec![0u8; info_len as usize];
gl::GetShaderInfoLog(vertex_shader, info_len as gl::types::GLsizei, ptr::null_mut(), info.as_mut_ptr() as *mut gl::types::GLchar);
info.set_len((info_len - 1) as usize); // ignore null for str::from_utf8
println!(
"ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n{}",
str::from_utf8_unchecked(&info)
);
// Check for shader compilation errors
gl::GetShaderiv(fragment_shader, gl::COMPILE_STATUS, &mut success);
let result = if success != i32::from(gl::TRUE) {
let mut info_len: gl::types::GLint = 0;
gl::GetShaderiv(fragment_shader, gl::INFO_LOG_LENGTH, &mut info_len);
let mut info = vec![0u8; info_len as usize];
gl::GetShaderInfoLog(fragment_shader, info_len as gl::types::GLsizei, ptr::null_mut(), info.as_mut_ptr() as *mut gl::types::GLchar);
info.set_len((info_len - 1) as usize); // ignore null for str::from_utf8
Some(String::from_utf8(info).unwrap())
} else {
None
};
gl::DeleteShader(fragment_shader);
result
}
crate::TreeType::Vertex => {
// Vertex shader
let vertex_shader = gl::CreateShader(gl::VERTEX_SHADER);
let c_str_vert = CString::new(source).unwrap();
gl::ShaderSource(vertex_shader, 1, &c_str_vert.as_ptr(), ptr::null());
gl::CompileShader(vertex_shader);
// Check for shader compilation errors
gl::GetShaderiv(vertex_shader, gl::COMPILE_STATUS, &mut success);
let result = if success != i32::from(gl::TRUE) {
let mut info_len: gl::types::GLint = 0;
gl::GetShaderiv(vertex_shader, gl::INFO_LOG_LENGTH, &mut info_len);
let mut info = vec![0u8; info_len as usize];
gl::GetShaderInfoLog(vertex_shader, info_len as gl::types::GLsizei, ptr::null_mut(), info.as_mut_ptr() as *mut gl::types::GLchar);
info.set_len((info_len - 1) as usize); // ignore null for str::from_utf8
Some(String::from_utf8(info).unwrap())
} else {
None
};
gl::DeleteShader(vertex_shader);
result
}
}
// Fragment shader
let fragment_shader = gl::CreateShader(gl::FRAGMENT_SHADER);
let c_str_frag = CString::new(FRAGMENT_SHADER_SOURCE.as_bytes()).unwrap();
gl::ShaderSource(fragment_shader, 1, &c_str_frag.as_ptr(), ptr::null());
gl::CompileShader(fragment_shader);
// Check for shader compilation errors
gl::GetShaderiv(fragment_shader, gl::COMPILE_STATUS, &mut success);
if success != i32::from(gl::TRUE) {
let mut info_len: gl::types::GLint = 0;
gl::GetShaderiv(fragment_shader, gl::INFO_LOG_LENGTH, &mut info_len);
let mut info = vec![0u8; info_len as usize];
gl::GetShaderInfoLog(fragment_shader, info_len as gl::types::GLsizei, ptr::null_mut(), info.as_mut_ptr() as *mut gl::types::GLchar);
info.set_len((info_len - 1) as usize); // ignore null for str::from_utf8
println!(
"ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n{}",
str::from_utf8_unchecked(&info)
);
}
// Link Shaders
let shader_program = gl::CreateProgram();
gl::AttachShader(shader_program, vertex_shader);
gl::AttachShader(shader_program, fragment_shader);
gl::LinkProgram(shader_program);
// Check for linking errors
gl::GetProgramiv(shader_program, gl::LINK_STATUS, &mut success);
if success != i32::from(gl::TRUE) {
let mut info_len: gl::types::GLint = 0;
gl::GetProgramiv(shader_program, gl::INFO_LOG_LENGTH, &mut info_len);
let mut info = vec![0u8; info_len as usize];
gl::GetProgramInfoLog(shader_program, info_len as gl::types::GLsizei, ptr::null_mut(), info.as_mut_ptr() as *mut gl::types::GLchar);
info.set_len((info_len - 1) as usize); // ignore null for str::from_utf8
println!(
"ERROR::SHADER::FRAGMENT::COMPILATION_FAILED\n{}",
str::from_utf8_unchecked(&info)
);
}
/* gl::DeleteShader(vertex_shader);
gl::DeleteShader(fragment_shader);*/
};
}
}