mirror of
https://github.com/Strum355/mcshader-lsp.git
synced 2025-07-24 19:54:35 +00:00
Using headless opengl context to lint files, removed last bits of glslangValidator
This commit is contained in:
parent
26c855f016
commit
dc1495686a
3 changed files with 107 additions and 241 deletions
|
@ -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 {
|
||||
|
|
|
@ -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);*/
|
||||
};
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue