Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Simplify extensions. Add Debug PrintF #216

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 7 additions & 55 deletions autogen/src/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,6 @@ use proc_macro2::TokenStream;
use quote::quote;
use std::collections::BTreeMap;

static GLSL_STD_450_SPEC_LINK: &str = "\
https://www.khronos.org/registry/spir-v/specs/unified1/GLSL.std.450.html";

static OPENCL_STD_SPEC_LINK: &str = "\
https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.ExtendedInstructionSet.100.html";

/// Returns the markdown string containing a link to the spec for the given
/// operand `kind`.
fn get_spec_link(kind: &str) -> String {
Expand Down Expand Up @@ -304,48 +298,10 @@ pub fn gen_spirv_header(grammar: &structs::Grammar) -> TokenStream {
}
}

/// Returns the GLSL.std.450 extended instruction opcodes.
pub fn gen_glsl_std_450_opcodes(grammar: &structs::ExtInstSetGrammar) -> TokenStream {
// Get the instruction table.
let opcodes = grammar.instructions.iter().map(|inst| {
// Omit the "Op" prefix.
let opname = as_ident(&inst.opname);
let opcode = inst.opcode;
quote! { #opname = #opcode }
});

let from_prim_list = grammar
.instructions
.iter()
.map(|inst| {
let opname = as_ident(&inst.opname);
let opcode = inst.opcode;
quote! { #opcode => GLOp::#opname }
})
.collect::<Vec<_>>();

let comment = format!(
"[GLSL.std.450]({}) extended instruction opcode",
GLSL_STD_450_SPEC_LINK
);
let attribute = value_enum_attribute();
let from_prim_impl = from_primitive_impl(&from_prim_list, &as_ident("GLOp"));

quote! {
#[doc = #comment]
#attribute
#[allow(clippy::upper_case_acronyms)]
pub enum GLOp {
#(#opcodes),*
}

#from_prim_impl
}
}

/// Returns the OpenCL.std extended instruction opcodes.
pub fn gen_opencl_std_opcodes(grammar: &structs::ExtInstSetGrammar) -> TokenStream {
// Get the instruction table.
/// Returns extended instruction opcodes
pub fn gen_opcodes(op: &str, grammar: &structs::ExtInstSetGrammar, comment: &str) -> TokenStream {
let op = as_ident(op);
// Get the instruction table
let opcodes = grammar.instructions.iter().map(|inst| {
// Omit the "Op" prefix.
let opname = as_ident(&inst.opname);
Expand All @@ -359,22 +315,18 @@ pub fn gen_opencl_std_opcodes(grammar: &structs::ExtInstSetGrammar) -> TokenStre
.map(|inst| {
let opname = as_ident(&inst.opname);
let opcode = inst.opcode;
quote! { #opcode => CLOp::#opname }
quote! { #opcode => #op::#opname }
})
.collect::<Vec<_>>();

let comment = format!(
"[OpenCL.std]({}) extended instruction opcode",
OPENCL_STD_SPEC_LINK
);
let attribute = value_enum_attribute();
let from_prim_impl = from_primitive_impl(&from_prim_list, &as_ident("CLOp"));
let from_prim_impl = from_primitive_impl(&from_prim_list, &op);

quote! {
#[doc = #comment]
#attribute
#[allow(clippy::upper_case_acronyms)]
pub enum CLOp {
pub enum #op {
#(#opcodes),*
}

Expand Down
112 changes: 65 additions & 47 deletions autogen/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@ mod table;
mod utils;

use std::{
env, fs,
io::{Read, Write},
env,
fs,
io::Write,
path::{Path, PathBuf},
process,
};
Expand Down Expand Up @@ -61,65 +62,82 @@ fn main() {
panic!("SPIRV-Headers missing - please checkout using git submodule");
}

let mut contents = String::new();

{
let path = autogen_src_dir
.join("external/SPIRV-Headers/include/spirv/unified1/spirv.core.grammar.json");
let mut file = fs::File::open(path).unwrap();
file.read_to_string(&mut contents).unwrap();
}

let grammar: structs::Grammar = {
let mut original = serde_json::from_str(&contents).unwrap();
let mut original =
serde_json::from_str(
&std::str::from_utf8(
&fs::read(autogen_src_dir.join(
"external/SPIRV-Headers/include/spirv/unified1/spirv.core.grammar.json",
))
.unwrap(),
)
.unwrap(),
)
.unwrap();
Comment on lines +66 to +76
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
let mut original =
serde_json::from_str(
&std::str::from_utf8(
&fs::read(autogen_src_dir.join(
"external/SPIRV-Headers/include/spirv/unified1/spirv.core.grammar.json",
))
.unwrap(),
)
.unwrap(),
)
.unwrap();
let mut original = serde_json::from_str(
&fs::read_to_string(
autogen_src_dir
.join("external/SPIRV-Headers/include/spirv/unified1/spirv.core.grammar.json"),
)
.unwrap(),
)
.unwrap();

Maybe keep this simple with read_to_string? Same below.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes! I didn't know about it ><.
There really should be a note in std:fs::read about read_to_string existence. It's not the first time this annoys me ^^

map_reserved_instructions(&mut original);
original
};

// For GLSLstd450 extended instruction set.
{
let path = autogen_src_dir.join(
"external/SPIRV-Headers/include/spirv/unified1/extinst.glsl.std.450.grammar.json",
);
let mut file = fs::File::open(path).unwrap();
contents.clear();
file.read_to_string(&mut contents).unwrap();
}
let gl_grammar: structs::ExtInstSetGrammar = serde_json::from_str(&contents).unwrap();

// For OpenCL extended instruction set.
{
let path = autogen_src_dir.join(
"external/SPIRV-Headers/include/spirv/unified1/extinst.opencl.std.100.grammar.json",
);
let mut file = fs::File::open(path).unwrap();
contents.clear();
file.read_to_string(&mut contents).unwrap();
}
let cl_grammar: structs::ExtInstSetGrammar = serde_json::from_str(&contents).unwrap();
let extended_instruction_sets = [
("GLSL.std.450", "GLOp", "https://www.khronos.org/registry/spir-v/specs/unified1/GLSL.std.450.html"),
("OpenCL.std.100", "CLOp", "https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.ExtendedInstructionSet.100.html"),
("NonSemantic.DebugPrintF", "DebugPrintFOp", "https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/master/docs/debug_printf.md"),
Comment on lines +82 to +84
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use spaces to indent this. The autoformatter refuses to do so because the lines are too long.

Suggested change
("GLSL.std.450", "GLOp", "https://www.khronos.org/registry/spir-v/specs/unified1/GLSL.std.450.html"),
("OpenCL.std.100", "CLOp", "https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.ExtendedInstructionSet.100.html"),
("NonSemantic.DebugPrintF", "DebugPrintFOp", "https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/master/docs/debug_printf.md"),
("GLSL.std.450", "GLOp", "https://www.khronos.org/registry/spir-v/specs/unified1/GLSL.std.450.html"),
("OpenCL.std.100", "CLOp", "https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.ExtendedInstructionSet.100.html"),
("NonSemantic.DebugPrintF", "DebugPrintFOp", "https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/master/docs/debug_printf.md"),

];
let extended_instruction_sets = extended_instruction_sets.map(|(ext, op, url)| {
let grammar: structs::ExtInstSetGrammar = serde_json::from_str(
&std::str::from_utf8(
&fs::read(autogen_src_dir.join(format!(
"external/SPIRV-Headers/include/spirv/unified1/extinst.{}.grammar.json",
ext.to_lowercase()
)))
.unwrap(),
)
.unwrap(),
)
.unwrap();
(ext, op, url, grammar)
});

// Path to the generated SPIR-V header file.
// SPIR-V header
write_formatted(&autogen_src_dir.join("../spirv/autogen_spirv.rs"), {
let core = header::gen_spirv_header(&grammar);
let gl = header::gen_glsl_std_450_opcodes(&gl_grammar);
let cl = header::gen_opencl_std_opcodes(&cl_grammar);
format!("{}\n{}\n{}", core, gl, cl)
let extended_instruction_sets =
extended_instruction_sets
.iter()
.map(|(ext, op, url, grammar)| {
header::gen_opcodes(
op,
&grammar,
&format!("[{}]({}) extended instruction opcode", ext, url),
)
.to_string()
});
format!(
"{}\n{}",
core,
extended_instruction_sets.collect::<Box<_>>().join("\n")
)
});

// Path to the generated instruction table.
// Instruction table
write_formatted(
&autogen_src_dir.join("../rspirv/grammar/autogen_table.rs"),
table::gen_grammar_inst_table_operand_kinds(&grammar),
);
// Path to the generated GLSLstd450 extended instruction set header.
write_formatted(
&autogen_src_dir.join("../rspirv/grammar/autogen_glsl_std_450.rs"),
table::gen_glsl_std_450_inst_table(&gl_grammar),
);
write_formatted(
&autogen_src_dir.join("../rspirv/grammar/autogen_opencl_std_100.rs"),
table::gen_opencl_std_100_inst_table(&cl_grammar),
);
// Extended instruction sets
for (ext, _, _, grammar) in extended_instruction_sets {
write_formatted(
&autogen_src_dir.join(format!(
"../rspirv/grammar/autogen_{}.rs",
ext.replace(".", "_").to_lowercase()
)),
table::gen_instruction_table(
&grammar.instructions,
&format!("{}_INSTRUCTION_TABLE", ext.replace(".", "_").to_uppercase()),
true,
),
);
}

// Path to the generated operands kind in data representation.
write_formatted(
Expand Down
2 changes: 2 additions & 0 deletions autogen/src/structs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,9 @@ pub struct Grammar {

#[derive(Debug, Deserialize)]
pub struct ExtInstSetGrammar {
#[serde(default)]
pub copyright: Vec<String>,
#[serde(default)]
pub version: u32,
pub revision: u32,
pub instructions: Vec<Instruction>,
Expand Down
22 changes: 1 addition & 21 deletions autogen/src/table.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ fn convert_quantifier(quantifier: structs::Quantifier) -> Ident {
/// `grammar` is expected to be an array of SPIR-V instructions.
/// `name` is the name of the generated table.
/// `is_ext` indicates whether the grammar is for an extended instruction set.
fn gen_instruction_table(
pub(crate) fn gen_instruction_table(
grammar: &[structs::Instruction],
name: &str,
is_ext: bool,
Expand Down Expand Up @@ -82,23 +82,3 @@ pub fn gen_grammar_inst_table_operand_kinds(grammar: &structs::Grammar) -> Token
#table
}
}

/// Writes the generated instruction table for GLSLstd450 extended instruction
/// set from `grammar` to the file with the given `filename`.
pub fn gen_glsl_std_450_inst_table(grammar: &structs::ExtInstSetGrammar) -> TokenStream {
gen_instruction_table(
&grammar.instructions,
"GLSL_STD_450_INSTRUCTION_TABLE",
true,
)
}

/// Writes the generated instruction table for OpenCLstd100 extended instruction
/// set from `grammar` to the file with the given `filename`.
pub fn gen_opencl_std_100_inst_table(grammar: &structs::ExtInstSetGrammar) -> TokenStream {
gen_instruction_table(
&grammar.instructions,
"OPENCL_STD_100_INSTRUCTION_TABLE",
true,
)
}
11 changes: 11 additions & 0 deletions rspirv/grammar/autogen_nonsemantic_debugprintf.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// AUTOMATICALLY GENERATED from the SPIR-V JSON grammar:
// external/spirv.core.grammar.json.
// DO NOT MODIFY!

static NONSEMANTIC_DEBUGPRINTF_INSTRUCTION_TABLE: &[ExtendedInstruction<'static>] = &[ext_inst!(
DebugPrintf,
1u32,
[],
[],
[(IdRef, One), (IdRef, ZeroOrMore)]
)];
3 changes: 2 additions & 1 deletion rspirv/tests/spirv_blobs.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use rspirv::{
binary::{Assemble as _, Disassemble as _},
dr, lift,
dr,
lift,
};

use std::path::PathBuf;
Expand Down
23 changes: 22 additions & 1 deletion spirv/autogen_spirv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3989,7 +3989,7 @@ impl num_traits::FromPrimitive for GLOp {
Self::from_i64(n as i64)
}
}
#[doc = "[OpenCL.std](https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.ExtendedInstructionSet.100.html) extended instruction opcode"]
#[doc = "[OpenCL.std.100](https://www.khronos.org/registry/spir-v/specs/unified1/OpenCL.ExtendedInstructionSet.100.html) extended instruction opcode"]
#[repr(u32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
Expand Down Expand Up @@ -4332,3 +4332,24 @@ impl num_traits::FromPrimitive for CLOp {
Self::from_i64(n as i64)
}
}
#[doc = "[NonSemantic.DebugPrintF](https://github.com/KhronosGroup/Vulkan-ValidationLayers/blob/master/docs/debug_printf.md) extended instruction opcode"]
#[repr(u32)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[cfg_attr(feature = "serialize", derive(serde::Serialize))]
#[cfg_attr(feature = "deserialize", derive(serde::Deserialize))]
#[allow(clippy::upper_case_acronyms)]
pub enum DebugPrintFOp {
DebugPrintf = 1u32,
}
impl num_traits::FromPrimitive for DebugPrintFOp {
#[allow(trivial_numeric_casts)]
fn from_i64(n: i64) -> Option<Self> {
Some(match n as u32 {
1u32 => DebugPrintFOp::DebugPrintf,
_ => return None,
})
}
fn from_u64(n: u64) -> Option<Self> {
Self::from_i64(n as i64)
}
}