-
Notifications
You must be signed in to change notification settings - Fork 1
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
📚Separate main() into its own function in lib.rs #5
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,5 @@ | ||
/target | ||
/Cargo.lock | ||
.DS_Store | ||
.vscode/launch.json | ||
*.metallib |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,7 @@ | ||
#![doc = include_str!("../README.md")] | ||
|
||
use std::path::Path; | ||
|
||
struct IRCompilerOpaque; | ||
struct IRObjectOpaque; | ||
struct IRRootSignatureOpaque; | ||
|
@@ -499,8 +501,6 @@ impl<'lib> IRRootSignature<'lib> { | |
|
||
let me = (funcs.create_from_descriptor)(desc, &mut error); | ||
|
||
dbg!(error); | ||
|
||
Ok(Self { funcs, me }) | ||
} | ||
} | ||
|
@@ -587,10 +587,6 @@ impl<'lib> IRCompiler<'lib> { | |
) | ||
}; | ||
|
||
dbg!(v); | ||
|
||
dbg!(error); | ||
|
||
if error.is_null() { | ||
Ok(IRObject { | ||
funcs: input.funcs.clone(), | ||
|
@@ -601,3 +597,149 @@ impl<'lib> IRCompiler<'lib> { | |
} | ||
} | ||
} | ||
|
||
// Moved from main.rs to lib.rs | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nit: this comment doesn't really add anything. |
||
fn create_static_sampler( | ||
min_mag_mip_mode: IRFilter, | ||
address_mode: IRTextureAddressMode, | ||
index: u32, | ||
anisotropy: Option<u32>, | ||
) -> IRStaticSamplerDescriptor { | ||
let max_anisotropy = anisotropy.unwrap_or(1); | ||
|
||
IRStaticSamplerDescriptor { | ||
filter: min_mag_mip_mode, | ||
address_u: address_mode, | ||
address_v: address_mode, | ||
address_w: address_mode, | ||
mip_lod_bias: 0.0, | ||
max_anisotropy: max_anisotropy, | ||
comparison_func: IRComparisonFunction::IRComparisonFunctionNever, | ||
min_lod: 0.0, | ||
max_lod: 100000.0, | ||
shader_register: index, | ||
register_space: 0, | ||
shader_visibility: IRShaderVisibility::IRShaderVisibilityAll, | ||
border_color: IRStaticBorderColor::IRStaticBorderColorTransparentBlack, | ||
} | ||
} | ||
|
||
/// Takes a DXIL binary, cross-compiles it to metal and returns a metallib binary | ||
pub fn compile_dxil_to_metallib( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. None of this code should live in saxaboom, since it's specific to how breda sets up it's bindings. |
||
path_compiler_lib: &Path, | ||
dxil_binary: &Vec<u8>, | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Clippy will probably complain that this should be a slice, instead of a borrow of a forcibly-owned |
||
) -> Result<Vec<u8>, Box<dyn std::error::Error>> { | ||
unsafe { | ||
// Load the metal shader converter library | ||
let lib = libloading::Library::new(path_compiler_lib)?; | ||
|
||
// Set up root signature. This should match up with the root signature as defined in breda | ||
let parameters = { | ||
let push_constants = IRRootParameter1 { | ||
parameter_type: IRRootParameterType::IRRootParameterType32BitConstants, | ||
shader_visibility: IRShaderVisibility::IRShaderVisibilityAll, | ||
u: IRRootParameter1_u { | ||
constants: IRRootConstants { | ||
register_space: 0 as u32, | ||
shader_register: 0, | ||
num32_bit_values: 4, // debug has 6 | ||
}, | ||
}, | ||
}; | ||
|
||
let indirect_identifier = IRRootParameter1 { | ||
parameter_type: IRRootParameterType::IRRootParameterType32BitConstants, | ||
shader_visibility: IRShaderVisibility::IRShaderVisibilityAll, | ||
u: IRRootParameter1_u { | ||
constants: IRRootConstants { | ||
register_space: 1 as u32, | ||
shader_register: 0, | ||
num32_bit_values: 1, | ||
}, | ||
}, | ||
}; | ||
|
||
vec![push_constants, indirect_identifier] | ||
}; | ||
|
||
let static_samplers = [ | ||
create_static_sampler( | ||
IRFilter::IRFilterMinMagMipPoint, | ||
IRTextureAddressMode::IRTextureAddressModeWrap, | ||
0, | ||
None, | ||
), | ||
create_static_sampler( | ||
IRFilter::IRFilterMinMagMipPoint, | ||
IRTextureAddressMode::IRTextureAddressModeClamp, | ||
1, | ||
None, | ||
), | ||
create_static_sampler( | ||
IRFilter::IRFilterMinMagMipLinear, | ||
IRTextureAddressMode::IRTextureAddressModeWrap, | ||
2, | ||
None, | ||
), | ||
create_static_sampler( | ||
IRFilter::IRFilterMinMagMipLinear, | ||
IRTextureAddressMode::IRTextureAddressModeClamp, | ||
3, | ||
None, | ||
), | ||
create_static_sampler( | ||
IRFilter::IRFilterMinMagMipLinear, | ||
IRTextureAddressMode::IRTextureAddressModeBorder, | ||
4, | ||
None, | ||
), | ||
create_static_sampler( | ||
IRFilter::IRFilterAnisotropic, | ||
IRTextureAddressMode::IRTextureAddressModeWrap, | ||
5, | ||
Some(2), | ||
), | ||
create_static_sampler( | ||
IRFilter::IRFilterAnisotropic, | ||
IRTextureAddressMode::IRTextureAddressModeWrap, | ||
6, | ||
Some(4), | ||
), | ||
]; | ||
|
||
let desc_1_1 = IRRootSignatureDescriptor1 { | ||
flags: IRRootSignatureFlags::IRRootSignatureFlagCBVSRVUAVHeapDirectlyIndexed, | ||
num_parameters: parameters.len() as u32, | ||
p_parameters: parameters.as_ptr(), | ||
num_static_samplers: static_samplers.len() as u32, | ||
p_static_samplers: static_samplers.as_ptr(), | ||
}; | ||
|
||
let desc = IRVersionedRootSignatureDescriptor { | ||
version: IRRootSignatureVersion::IRRootSignatureVersion_1_1, | ||
u: IRVersionedRootSignatureDescriptor_u { desc_1_1 }, | ||
}; | ||
|
||
let root_sig = IRRootSignature::create_from_descriptor(&lib, &desc)?; | ||
|
||
// Cross-compile to Metal | ||
let mut mtl_binary = IRMetalLibBinary::new(&lib)?; | ||
let obj = IRObject::create_from_dxil(&lib, &dxil_binary)?; | ||
let mut c = IRCompiler::new(&lib)?; | ||
c.set_global_root_signature(&root_sig); | ||
let mtllib = c.alloc_compile_and_link(&[b"main\0"], &obj)?; | ||
mtllib.get_metal_lib_binary(IRShaderStage::IRShaderStageCompute, &mut mtl_binary); | ||
|
||
Ok(mtl_binary.get_byte_code()) | ||
} | ||
} | ||
|
||
pub fn compile_dxil_to_metallib_from_path( | ||
path_compiler_lib: &Path, | ||
path_dxil: &Path, | ||
) -> Result<Vec<u8>, Box<dyn std::error::Error>> { | ||
Comment on lines
+737
to
+740
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. If you're turning these into public functions, they should have doc-comments. |
||
// Load DXIL binary from path | ||
let dxil_binary = std::fs::read(path_dxil)?; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since you're only reading a file into binary, let the user pass a byte slice. This would make it compatible with our asset pipeline that does not give you access to plain files. Perhaps the same for the compiler library itself. Even better: how expensive is it to load the compiler and interface for every shader? Perhaps we need to provide an object-based API of this sort: let compiler = MetalCompiler::new("path/to/libirmetallibbinary.so")?; // TODO: Should there be a function with a sensible default path? Is it available on the system?
let _compiled = compiler.compile(&[0x13, 0x37, ...])?; |
||
let metallib = compile_dxil_to_metallib(path_compiler_lib, &dxil_binary); | ||
return metallib; | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,146 +1,15 @@ | ||
use saxaboom::{ | ||
IRComparisonFunction, IRCompiler, IRFilter, IRMetalLibBinary, IRObject, IRRootConstants, | ||
IRRootDescriptor1, IRRootParameter1, IRRootParameter1_u, IRRootParameterType, IRRootSignature, | ||
IRRootSignatureDescriptor1, IRRootSignatureFlags, IRRootSignatureVersion, IRShaderStage, | ||
IRShaderVisibility, IRStaticBorderColor, IRStaticSamplerDescriptor, IRTextureAddressMode, | ||
IRVersionedRootSignatureDescriptor, IRVersionedRootSignatureDescriptor_u, | ||
}; | ||
use std::path::Path; | ||
|
||
fn create_static_sampler( | ||
min_mag_mip_mode: IRFilter, | ||
address_mode: IRTextureAddressMode, | ||
index: u32, | ||
anisotropy: Option<u32>, | ||
) -> IRStaticSamplerDescriptor { | ||
let max_anisotropy = anisotropy.unwrap_or(1); | ||
use saxaboom::compile_dxil_to_metallib_from_path; | ||
|
||
IRStaticSamplerDescriptor { | ||
filter: min_mag_mip_mode, | ||
address_u: address_mode, | ||
address_v: address_mode, | ||
address_w: address_mode, | ||
mip_lod_bias: 0.0, | ||
max_anisotropy: max_anisotropy, | ||
comparison_func: IRComparisonFunction::IRComparisonFunctionNever, | ||
min_lod: 0.0, | ||
max_lod: 100000.0, | ||
shader_register: index, | ||
register_space: 0, | ||
shader_visibility: IRShaderVisibility::IRShaderVisibilityAll, | ||
border_color: IRStaticBorderColor::IRStaticBorderColorTransparentBlack, | ||
} | ||
} | ||
|
||
fn main() -> Result<(), Box<dyn std::error::Error>> { | ||
unsafe { | ||
let lib = libloading::Library::new( | ||
"C:/Program Files/Metal Shader Converter/lib/metalirconverter.dll", | ||
)?; | ||
|
||
let parameters = { | ||
let push_constants = IRRootParameter1 { | ||
parameter_type: IRRootParameterType::IRRootParameterType32BitConstants, | ||
shader_visibility: IRShaderVisibility::IRShaderVisibilityAll, | ||
u: IRRootParameter1_u { | ||
constants: IRRootConstants { | ||
register_space: 0 as u32, | ||
shader_register: 0, | ||
num32_bit_values: 4, // debug has 6 | ||
}, | ||
}, | ||
}; | ||
|
||
let indirect_identifier = IRRootParameter1 { | ||
parameter_type: IRRootParameterType::IRRootParameterType32BitConstants, | ||
shader_visibility: IRShaderVisibility::IRShaderVisibilityAll, | ||
u: IRRootParameter1_u { | ||
constants: IRRootConstants { | ||
register_space: 1 as u32, | ||
shader_register: 0, | ||
num32_bit_values: 1, | ||
}, | ||
}, | ||
}; | ||
|
||
vec![push_constants, indirect_identifier] | ||
}; | ||
|
||
let static_samplers = [ | ||
create_static_sampler( | ||
IRFilter::IRFilterMinMagMipPoint, | ||
IRTextureAddressMode::IRTextureAddressModeWrap, | ||
0, | ||
None, | ||
), | ||
create_static_sampler( | ||
IRFilter::IRFilterMinMagMipPoint, | ||
IRTextureAddressMode::IRTextureAddressModeClamp, | ||
1, | ||
None, | ||
), | ||
create_static_sampler( | ||
IRFilter::IRFilterMinMagMipLinear, | ||
IRTextureAddressMode::IRTextureAddressModeWrap, | ||
2, | ||
None, | ||
), | ||
create_static_sampler( | ||
IRFilter::IRFilterMinMagMipLinear, | ||
IRTextureAddressMode::IRTextureAddressModeClamp, | ||
3, | ||
None, | ||
), | ||
create_static_sampler( | ||
IRFilter::IRFilterMinMagMipLinear, | ||
IRTextureAddressMode::IRTextureAddressModeBorder, | ||
4, | ||
None, | ||
), | ||
create_static_sampler( | ||
IRFilter::IRFilterAnisotropic, | ||
IRTextureAddressMode::IRTextureAddressModeWrap, | ||
5, | ||
Some(2), | ||
), | ||
create_static_sampler( | ||
IRFilter::IRFilterAnisotropic, | ||
IRTextureAddressMode::IRTextureAddressModeWrap, | ||
6, | ||
Some(4), | ||
), | ||
]; | ||
|
||
let desc_1_1 = IRRootSignatureDescriptor1 { | ||
flags: IRRootSignatureFlags::IRRootSignatureFlagCBVSRVUAVHeapDirectlyIndexed, | ||
num_parameters: parameters.len() as u32, | ||
p_parameters: parameters.as_ptr(), | ||
num_static_samplers: static_samplers.len() as u32, | ||
p_static_samplers: static_samplers.as_ptr(), | ||
}; | ||
|
||
let desc = IRVersionedRootSignatureDescriptor { | ||
version: IRRootSignatureVersion::IRRootSignatureVersion_1_1, | ||
u: IRVersionedRootSignatureDescriptor_u { desc_1_1 }, | ||
}; | ||
|
||
let root_sig = IRRootSignature::create_from_descriptor(&lib, &desc)?; | ||
|
||
let egui_update = include_bytes!( | ||
"C:/Users/Jasper/traverse/breda/crates/breda-egui/assets/shaders/egui_update.cs.dxil" | ||
); | ||
// let memcpy = include_bytes!("C:/Users/Jasper/traverse/breda/apps/cs-memcpy/assets/shaders/memcpy.cs.dxil"); | ||
|
||
let mut mtl_binary = IRMetalLibBinary::new(&lib)?; | ||
fn main() { | ||
let shaders_to_test = ["test/output.dxil"]; | ||
|
||
let obj = IRObject::create_from_dxil(&lib, egui_update)?; | ||
let mut c = IRCompiler::new(&lib)?; | ||
c.set_global_root_signature(&root_sig); | ||
let mtllib = c.alloc_compile_and_link(&[b"main\0"], &obj)?; | ||
dbg!(mtllib.get_type()); | ||
dbg!(mtllib.get_metal_ir_shader_stage()); | ||
mtllib.get_metal_lib_binary(IRShaderStage::IRShaderStageCompute, &mut mtl_binary); | ||
dbg!(mtl_binary.get_byte_code().len()); | ||
std::fs::write("out.bin", mtl_binary.get_byte_code()); | ||
for shader_path in shaders_to_test { | ||
print!("Testing shader \"{shader_path}\": "); | ||
match compile_dxil_to_metallib_from_path(&Path::new("/usr/local/lib/libmetalirconverter.dylib"), &Path::new(shader_path)) { | ||
Ok(_) => println!("\tOk."), | ||
Err(e) => println!("Error: {e:?}"), | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's return |
||
} | ||
Ok(()) | ||
} |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Intended addition? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe just add the entire
.vscode
folder?