mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-22 06:45:23 +00:00
Start doing something correct in the code generation
This commit is contained in:
parent
49b460e580
commit
61d00ce9a8
@ -18,74 +18,136 @@ pub fn reflect<R>(name: &str, mut spirv: R) -> Result<String, Error>
|
|||||||
let mut output = String::new();
|
let mut output = String::new();
|
||||||
|
|
||||||
{
|
{
|
||||||
|
// contains the data that was passed as input to this function
|
||||||
let spirv_data = data.iter().map(|&byte| byte.to_string())
|
let spirv_data = data.iter().map(|&byte| byte.to_string())
|
||||||
.collect::<Vec<String>>()
|
.collect::<Vec<String>>()
|
||||||
.join(", ");
|
.join(", ");
|
||||||
|
|
||||||
|
// writing the header
|
||||||
output.push_str(&format!(r#"
|
output.push_str(&format!(r#"
|
||||||
pub struct {name};
|
pub struct {name} {{
|
||||||
|
shader: ::std::sync::Arc<::vulkano::ShaderModule>,
|
||||||
|
}}
|
||||||
|
|
||||||
impl {name} {{
|
impl {name} {{
|
||||||
pub fn load(device: &::std::sync::Arc<::vulkano::Device>) {{
|
/// Loads the shader in Vulkan as a `ShaderModule`.
|
||||||
|
#[inline]
|
||||||
|
pub fn load(device: &::std::sync::Arc<::vulkano::Device>) -> {name} {{
|
||||||
unsafe {{
|
unsafe {{
|
||||||
let data = [{spirv_data}];
|
let data = [{spirv_data}];
|
||||||
|
|
||||||
::vulkano::ShaderModule::new(device, &data)
|
{name} {{
|
||||||
|
shader: ::vulkano::ShaderModule::new(device, &data)
|
||||||
|
}}
|
||||||
}}
|
}}
|
||||||
}}
|
}}
|
||||||
}}
|
|
||||||
|
/// Returns the module that was created.
|
||||||
|
#[inline]
|
||||||
|
pub fn module(&self) -> &::std::sync::Arc<::vulkano::ShaderModule> {{
|
||||||
|
&self.shader
|
||||||
|
}}
|
||||||
"#, name = name, spirv_data = spirv_data));
|
"#, name = name, spirv_data = spirv_data));
|
||||||
}
|
|
||||||
|
|
||||||
println!("{:#?}", doc);
|
// writing one method for each entry point of this module
|
||||||
|
for instruction in doc.instructions.iter() {
|
||||||
for instruction in doc.instructions.iter() {
|
if let &parse::Instruction::EntryPoint { .. } = instruction {
|
||||||
match instruction {
|
output.push_str(&write_entry_point(&doc, instruction));
|
||||||
&parse::Instruction::Variable { result_type_id, result_id, ref storage_class, .. } => {
|
}
|
||||||
match *storage_class {
|
|
||||||
enums::StorageClass::StorageClassUniformConstant => (),
|
|
||||||
enums::StorageClass::StorageClassUniform => (),
|
|
||||||
enums::StorageClass::StorageClassPushConstant => (),
|
|
||||||
_ => continue
|
|
||||||
};
|
|
||||||
|
|
||||||
let name = name_from_id(&doc, result_id);
|
|
||||||
output.push_str(&format!("{}: {};", name, type_from_id(&doc, result_type_id)));
|
|
||||||
},
|
|
||||||
_ => ()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// footer
|
||||||
|
output.push_str(&format!(r#"
|
||||||
|
}}
|
||||||
|
"#));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: remove
|
||||||
|
println!("{:#?}", doc);
|
||||||
|
|
||||||
Ok(output)
|
Ok(output)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn name_from_id(doc: &parse::Spirv, searched: u32) -> String {
|
#[derive(Debug)]
|
||||||
doc.instructions.iter().filter_map(|i| {
|
pub enum Error {
|
||||||
if let &parse::Instruction::Name { target_id, ref name } = i {
|
IoError(IoError),
|
||||||
if target_id == searched {
|
ParseError(ParseError),
|
||||||
Some(name.clone())
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
|
||||||
}).next().and_then(|n| if !n.is_empty() { Some(n) } else { None })
|
|
||||||
.unwrap_or("__unnamed".to_owned())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn member_name_from_id(doc: &parse::Spirv, searched: u32, searched_member: u32) -> String {
|
impl From<IoError> for Error {
|
||||||
doc.instructions.iter().filter_map(|i| {
|
#[inline]
|
||||||
if let &parse::Instruction::MemberName { target_id, member, ref name } = i {
|
fn from(err: IoError) -> Error {
|
||||||
if target_id == searched && member == searched_member {
|
Error::IoError(err)
|
||||||
Some(name.clone())
|
}
|
||||||
} else {
|
}
|
||||||
None
|
|
||||||
|
impl From<ParseError> for Error {
|
||||||
|
#[inline]
|
||||||
|
fn from(err: ParseError) -> Error {
|
||||||
|
Error::ParseError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_entry_point(doc: &parse::Spirv, instruction: &parse::Instruction) -> String {
|
||||||
|
let (execution, ep_name, interface) = match instruction {
|
||||||
|
&parse::Instruction::EntryPoint { ref execution, id, ref name, ref interface } => {
|
||||||
|
(execution, name, interface)
|
||||||
|
},
|
||||||
|
_ => unreachable!()
|
||||||
|
};
|
||||||
|
|
||||||
|
let ty = match *execution {
|
||||||
|
enums::ExecutionModel::ExecutionModelVertex => {
|
||||||
|
format!("VertexShaderEntryPoint")
|
||||||
|
},
|
||||||
|
|
||||||
|
enums::ExecutionModel::ExecutionModelTessellationControl => {
|
||||||
|
format!("TessControlShaderEntryPoint")
|
||||||
|
},
|
||||||
|
|
||||||
|
enums::ExecutionModel::ExecutionModelTessellationEvaluation => {
|
||||||
|
format!("TessEvaluationShaderEntryPoint")
|
||||||
|
},
|
||||||
|
|
||||||
|
enums::ExecutionModel::ExecutionModelGeometry => {
|
||||||
|
format!("GeometryShaderEntryPoint")
|
||||||
|
},
|
||||||
|
|
||||||
|
enums::ExecutionModel::ExecutionModelFragment => {
|
||||||
|
let mut output_types = Vec::new();
|
||||||
|
|
||||||
|
for interface in interface.iter() {
|
||||||
|
for i in doc.instructions.iter() {
|
||||||
|
match i {
|
||||||
|
&parse::Instruction::Variable { result_type_id, result_id,
|
||||||
|
storage_class: enums::StorageClass::StorageClassOutput, .. }
|
||||||
|
if &result_id == interface =>
|
||||||
|
{
|
||||||
|
output_types.push(type_from_id(doc, result_type_id));
|
||||||
|
},
|
||||||
|
_ => ()
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
None
|
format!("FragmentShaderEntryPoint<({output})>",
|
||||||
}
|
output = output_types.join(", ") + ",")
|
||||||
}).next().and_then(|n| if !n.is_empty() { Some(n) } else { None })
|
},
|
||||||
.unwrap_or("__unnamed".to_owned())
|
|
||||||
|
enums::ExecutionModel::ExecutionModelGLCompute => {
|
||||||
|
format!("ComputeShaderEntryPoint")
|
||||||
|
},
|
||||||
|
|
||||||
|
enums::ExecutionModel::ExecutionModelKernel => panic!("Kernels are not supported"),
|
||||||
|
};
|
||||||
|
|
||||||
|
format!(r#"
|
||||||
|
/// Returns a logical struct describing the entry point named `{ep_name}`.
|
||||||
|
#[inline]
|
||||||
|
pub fn {ep_name}_entry_point(&self) -> {ty} {{
|
||||||
|
self.shader.entry_point("{ep_name}")
|
||||||
|
}}
|
||||||
|
"#, ep_name = ep_name, ty = ty)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn type_from_id(doc: &parse::Spirv, searched: u32) -> String {
|
fn type_from_id(doc: &parse::Spirv, searched: u32) -> String {
|
||||||
@ -152,22 +214,32 @@ fn type_from_id(doc: &parse::Spirv, searched: u32) -> String {
|
|||||||
panic!("Type #{} not found", searched)
|
panic!("Type #{} not found", searched)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
fn name_from_id(doc: &parse::Spirv, searched: u32) -> String {
|
||||||
pub enum Error {
|
doc.instructions.iter().filter_map(|i| {
|
||||||
IoError(IoError),
|
if let &parse::Instruction::Name { target_id, ref name } = i {
|
||||||
ParseError(ParseError),
|
if target_id == searched {
|
||||||
|
Some(name.clone())
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}).next().and_then(|n| if !n.is_empty() { Some(n) } else { None })
|
||||||
|
.unwrap_or("__unnamed".to_owned())
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<IoError> for Error {
|
fn member_name_from_id(doc: &parse::Spirv, searched: u32, searched_member: u32) -> String {
|
||||||
#[inline]
|
doc.instructions.iter().filter_map(|i| {
|
||||||
fn from(err: IoError) -> Error {
|
if let &parse::Instruction::MemberName { target_id, member, ref name } = i {
|
||||||
Error::IoError(err)
|
if target_id == searched && member == searched_member {
|
||||||
}
|
Some(name.clone())
|
||||||
}
|
} else {
|
||||||
|
None
|
||||||
impl From<ParseError> for Error {
|
}
|
||||||
#[inline]
|
} else {
|
||||||
fn from(err: ParseError) -> Error {
|
None
|
||||||
Error::ParseError(err)
|
}
|
||||||
}
|
}).next().and_then(|n| if !n.is_empty() { Some(n) } else { None })
|
||||||
|
.unwrap_or("__unnamed".to_owned())
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user