-
Notifications
You must be signed in to change notification settings - Fork 17
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
Support libdxcompiler.so on Linux #5
Conversation
extern crate requires deprecated `#[macro_use]`, which should be replaced with `use` instead.
This assumes a DXC compiled without virtual destructor! Which - as it stands - is invalid with undefined behaviour, but "works". This needs followup in DXC itself. This includes a revert of commit 308dd86.
TODO: Might as well keep the IUnknown name and "hide" the COM one (less changes, as long as the right one is use'd.
get_buffer_pointer returns a mutable (non-const) void ptr, create_include_handler returns an IDxcIncludeHandler, and annotate some c_void types. All the remaining c_void uses are that way in the official API.
Using winapi on not(windows) is a no-op already, but saves pulling in this extra dependency.
malloc: *const c_void, | ||
malloc: /* IMalloc */ *const c_void, |
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.
Perhaps we should make these pub type IMalloc = c_void;
(and pub type IStream = c_void;
below) instead?
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.
They likely won't be used any time soon, but it's good to have all non-void types (in the actual DXC API) properly represented even if the backing object isn't implemented.
src/utils.rs
Outdated
#[error("Error loading library")] | ||
LoadLibraryError(#[from] libloading::Error), |
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.
Is the underlying error printed in this case, or is that only applicable to #[error(transparent)]
?
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.
Updated, because this also wouldn't print the filename of the DLL / SO that was being attempted.
…, makes the API slightly easier to use
pub use crate::utils::{compile_hlsl, validate_dxil}; | ||
pub use crate::utils::compile_hlsl; | ||
pub use crate::utils::validate_dxil; |
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.
We might as well undo this now 😉
#[cfg(not(windows))] | ||
{ | ||
Err(HassleError::WindowsOnly( | ||
"DXIL Signing is only supported on windows at the moment".to_string(), | ||
)) | ||
} | ||
|
||
#[cfg(windows)] | ||
{ | ||
let dxil_lib = Library::new("dxil.dll").map_err(|e| HassleError::LoadLibraryError { | ||
filename: "dxil".to_string(), | ||
inner: e, | ||
})?; | ||
|
||
Ok(Self { dxil_lib }) | ||
} |
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.
Since none of this depends on cfg
-scoped symbols anymore:
#[cfg(not(windows))] | |
{ | |
Err(HassleError::WindowsOnly( | |
"DXIL Signing is only supported on windows at the moment".to_string(), | |
)) | |
} | |
#[cfg(windows)] | |
{ | |
let dxil_lib = Library::new("dxil.dll").map_err(|e| HassleError::LoadLibraryError { | |
filename: "dxil".to_string(), | |
inner: e, | |
})?; | |
Ok(Self { dxil_lib }) | |
} | |
if cfg!(windows) { | |
let dxil_lib = Library::new("dxil.dll").map_err(|e| HassleError::LoadLibraryError { | |
filename: "dxil".to_string(), | |
inner: e, | |
})?; | |
Ok(Self { dxil_lib }) | |
} else { | |
Err(HassleError::WindowsOnly( | |
"DXIL Signing is only supported on windows at the moment".to_string(), | |
)) | |
} |
The same call to SysFreeString happens in the Windows counterpart. Solves the following leaks found by valgrind: ==213075== 40 bytes in 1 blocks are definitely lost in loss record 4 of 13 ==213075== at 0x483A77F: malloc (vg_replace_malloc.c:307) ==213075== by 0x5B03395: ??? ==213075== by 0x5AFC77E: ??? ==213075== by 0x12C766: hassle_rs::intellisense::ffi::IDxcCursor::get_display_name (macros.rs:108) ==213075== by 0x116373: hassle_rs::intellisense::wrapper::DxcCursor::get_display_name (wrapper.rs:236) ==213075== by 0x11286D: intellisense_tu::main (intellisense-tu.rs:33) ==213075== by 0x11371A: core::ops::function::FnOnce::call_once (function.rs:227) ==213075== by 0x11348D: std::sys_common::backtrace::__rust_begin_short_backtrace (backtrace.rs:137) ==213075== by 0x111E10: std::rt::lang_start::{{closure}} (rt.rs:66) ==213075== by 0x150A20: call_once<(),Fn<()>> (function.rs:259) ==213075== by 0x150A20: do_call<&Fn<()>,i32> (panicking.rs:373) ==213075== by 0x150A20: try<i32,&Fn<()>> (panicking.rs:337) ==213075== by 0x150A20: catch_unwind<&Fn<()>,i32> (panic.rs:379) ==213075== by 0x150A20: std::rt::lang_start_internal (rt.rs:51) ==213075== by 0x111DE6: std::rt::lang_start (rt.rs:65) ==213075== ==213075== 56 (16 direct, 40 indirect) bytes in 1 blocks are definitely lost in loss record 5 of 13 ==213075== at 0x483ADEF: operator new(unsigned long) (vg_replace_malloc.c:342) ==213075== by 0x4FD058D: ??? ==213075== by 0x4FC04D9: ??? ==213075== by 0x40112DD: call_init.part.0 (in /usr/lib/ld-2.32.so) ==213075== by 0x40113C7: _dl_init (in /usr/lib/ld-2.32.so) ==213075== by 0x4A100E4: _dl_catch_exception (in /usr/lib/libc-2.32.so) ==213075== by 0x4015704: dl_open_worker (in /usr/lib/ld-2.32.so) ==213075== by 0x4A10087: _dl_catch_exception (in /usr/lib/libc-2.32.so) ==213075== by 0x4014F3D: _dl_open (in /usr/lib/ld-2.32.so) ==213075== by 0x489434B: ??? (in /usr/lib/libdl-2.32.so) ==213075== by 0x4A10087: _dl_catch_exception (in /usr/lib/libc-2.32.so) ==213075== by 0x4A10152: _dl_catch_error (in /usr/lib/libc-2.32.so) ==213075== ==213075== 124 bytes in 3 blocks are definitely lost in loss record 9 of 13 ==213075== at 0x483A77F: malloc (vg_replace_malloc.c:307) ==213075== by 0x5B03395: ??? ==213075== by 0x5AFC77E: ??? ==213075== by 0x12C766: hassle_rs::intellisense::ffi::IDxcCursor::get_display_name (macros.rs:108) ==213075== by 0x116373: hassle_rs::intellisense::wrapper::DxcCursor::get_display_name (wrapper.rs:236) ==213075== by 0x112F63: intellisense_tu::main (intellisense-tu.rs:52) ==213075== by 0x11371A: core::ops::function::FnOnce::call_once (function.rs:227) ==213075== by 0x11348D: std::sys_common::backtrace::__rust_begin_short_backtrace (backtrace.rs:137) ==213075== by 0x111E10: std::rt::lang_start::{{closure}} (rt.rs:66) ==213075== by 0x150A20: call_once<(),Fn<()>> (function.rs:259) ==213075== by 0x150A20: do_call<&Fn<()>,i32> (panicking.rs:373) ==213075== by 0x150A20: try<i32,&Fn<()>> (panicking.rs:337) ==213075== by 0x150A20: catch_unwind<&Fn<()>,i32> (panic.rs:379) ==213075== by 0x150A20: std::rt::lang_start_internal (rt.rs:51) ==213075== by 0x111DE6: std::rt::lang_start (rt.rs:65) Fixes: 94fbad7 ("Support libdxcompiler.so on Linux (#5)")
…ide, not UTF-8; convert return_hr to expression (#10) * utils: Mark libloading error as source In case we want to walk the .source() trace and print all inner exceptions (when these are usually rewrapped in thiserror types in higher layers), this exception needs to be marked as source to be returned from that function. * intellisense: Simplify DxcCursor retrieval and free leaked allocation Solves the following Valgrind trace: ==168242== 24 bytes in 1 blocks are definitely lost in loss record 2 of 14 ==168242== at 0x483A77F: malloc (vg_replace_malloc.c:307) ==168242== by 0x5AFC3F4: ??? ==168242== by 0x5AFCFB3: ??? ==168242== by 0x12BD23: hassle_rs::intellisense::ffi::IDxcCursor::get_children (macros.rs:108) ==168242== by 0x1167E6: hassle_rs::intellisense::wrapper::DxcCursor::get_all_children (wrapper.rs:210) ==168242== by 0x111B8A: intellisense_tu::main (intellisense-tu.rs:43) ==168242== by 0x112F5A: core::ops::function::FnOnce::call_once (function.rs:227) ==168242== by 0x1132FD: std::sys_common::backtrace::__rust_begin_short_backtrace (backtrace.rs:137) ==168242== by 0x113510: std::rt::lang_start::{{closure}} (rt.rs:66) ==168242== by 0x14F810: call_once<(),Fn<()>> (function.rs:259) ==168242== by 0x14F810: do_call<&Fn<()>,i32> (panicking.rs:373) ==168242== by 0x14F810: try<i32,&Fn<()>> (panicking.rs:337) ==168242== by 0x14F810: catch_unwind<&Fn<()>,i32> (panic.rs:379) ==168242== by 0x14F810: std::rt::lang_start_internal (rt.rs:51) ==168242== by 0x1134E6: std::rt::lang_start (rt.rs:65) * Convert return_hr to expression Make return_hr more versatile by providing Ok or Err as expession instead of forcing a return out of the current function. This follows Rusts convention to provide a block result as an unterminated expression on the last line, and allows it to be used in an expression context including with the question mark operator. * Free allocated memory using the appropriate API (free/CoTaskMemFree) On Windows the right API needs to be used to free this pointer in the same way as it was allocated by DXC (using CoTaskMemAlloc). On non-Windows platforms this call is [delegated] to `free` from libc. [delegated]: https://github.com/microsoft/DirectXShaderCompiler/blob/a8d9780046cb64a1cea842fa6fc28a250e3e2c09/include/dxc/Support/WinAdapter.h#L46 * Linux: util: Free BSTR after conversion to String The same call to SysFreeString happens in the Windows counterpart. Solves the following leaks found by valgrind: ==213075== 40 bytes in 1 blocks are definitely lost in loss record 4 of 13 ==213075== at 0x483A77F: malloc (vg_replace_malloc.c:307) ==213075== by 0x5B03395: ??? ==213075== by 0x5AFC77E: ??? ==213075== by 0x12C766: hassle_rs::intellisense::ffi::IDxcCursor::get_display_name (macros.rs:108) ==213075== by 0x116373: hassle_rs::intellisense::wrapper::DxcCursor::get_display_name (wrapper.rs:236) ==213075== by 0x11286D: intellisense_tu::main (intellisense-tu.rs:33) ==213075== by 0x11371A: core::ops::function::FnOnce::call_once (function.rs:227) ==213075== by 0x11348D: std::sys_common::backtrace::__rust_begin_short_backtrace (backtrace.rs:137) ==213075== by 0x111E10: std::rt::lang_start::{{closure}} (rt.rs:66) ==213075== by 0x150A20: call_once<(),Fn<()>> (function.rs:259) ==213075== by 0x150A20: do_call<&Fn<()>,i32> (panicking.rs:373) ==213075== by 0x150A20: try<i32,&Fn<()>> (panicking.rs:337) ==213075== by 0x150A20: catch_unwind<&Fn<()>,i32> (panic.rs:379) ==213075== by 0x150A20: std::rt::lang_start_internal (rt.rs:51) ==213075== by 0x111DE6: std::rt::lang_start (rt.rs:65) ==213075== ==213075== 56 (16 direct, 40 indirect) bytes in 1 blocks are definitely lost in loss record 5 of 13 ==213075== at 0x483ADEF: operator new(unsigned long) (vg_replace_malloc.c:342) ==213075== by 0x4FD058D: ??? ==213075== by 0x4FC04D9: ??? ==213075== by 0x40112DD: call_init.part.0 (in /usr/lib/ld-2.32.so) ==213075== by 0x40113C7: _dl_init (in /usr/lib/ld-2.32.so) ==213075== by 0x4A100E4: _dl_catch_exception (in /usr/lib/libc-2.32.so) ==213075== by 0x4015704: dl_open_worker (in /usr/lib/ld-2.32.so) ==213075== by 0x4A10087: _dl_catch_exception (in /usr/lib/libc-2.32.so) ==213075== by 0x4014F3D: _dl_open (in /usr/lib/ld-2.32.so) ==213075== by 0x489434B: ??? (in /usr/lib/libdl-2.32.so) ==213075== by 0x4A10087: _dl_catch_exception (in /usr/lib/libc-2.32.so) ==213075== by 0x4A10152: _dl_catch_error (in /usr/lib/libc-2.32.so) ==213075== ==213075== 124 bytes in 3 blocks are definitely lost in loss record 9 of 13 ==213075== at 0x483A77F: malloc (vg_replace_malloc.c:307) ==213075== by 0x5B03395: ??? ==213075== by 0x5AFC77E: ??? ==213075== by 0x12C766: hassle_rs::intellisense::ffi::IDxcCursor::get_display_name (macros.rs:108) ==213075== by 0x116373: hassle_rs::intellisense::wrapper::DxcCursor::get_display_name (wrapper.rs:236) ==213075== by 0x112F63: intellisense_tu::main (intellisense-tu.rs:52) ==213075== by 0x11371A: core::ops::function::FnOnce::call_once (function.rs:227) ==213075== by 0x11348D: std::sys_common::backtrace::__rust_begin_short_backtrace (backtrace.rs:137) ==213075== by 0x111E10: std::rt::lang_start::{{closure}} (rt.rs:66) ==213075== by 0x150A20: call_once<(),Fn<()>> (function.rs:259) ==213075== by 0x150A20: do_call<&Fn<()>,i32> (panicking.rs:373) ==213075== by 0x150A20: try<i32,&Fn<()>> (panicking.rs:337) ==213075== by 0x150A20: catch_unwind<&Fn<()>,i32> (panic.rs:379) ==213075== by 0x150A20: std::rt::lang_start_internal (rt.rs:51) ==213075== by 0x111DE6: std::rt::lang_start (rt.rs:65) Fixes: 94fbad7 ("Support libdxcompiler.so on Linux (#5)") * Linux: util: BSTR contains a wide string instead of UTF-8 Resulting strings were only one character long because the second byte for ASCII text is NULL. On Linux DXC properly uses wchar_t which is 32-bit instead of 16-bit. Fixes: 94fbad7 ("Support libdxcompiler.so on Linux (#5)") * Free leaking DxcIncludeHandlerWrapper Valgrind shows that we are leaking the DxcIncludeHandlerWrapper allocation: ==96758== 485 (80 direct, 405 indirect) bytes in 1 blocks are definitely lost in loss record 13 of 17 ==96758== at 0x483A77F: malloc (vg_replace_malloc.c:307) ==96758== by 0x1A1E4B: alloc::alloc::alloc (alloc.rs:74) ==96758== by 0x1A1F09: alloc::alloc::Global::alloc_impl (alloc.rs:153) ==96758== by 0x1A2069: <alloc::alloc::Global as core::alloc::AllocRef>::alloc (alloc.rs:203) ==96758== by 0x1A1D9A: alloc::alloc::exchange_malloc (alloc.rs:281) ==96758== by 0x199A1A: new<hassle_rs::wrapper::DxcIncludeHandlerWrapper> (boxed.rs:175) ==96758== by 0x199A1A: hassle_rs::wrapper::DxcCompiler::prep_include_handler (wrapper.rs:248) ==96758== by 0x199D6F: hassle_rs::wrapper::DxcCompiler::compile (wrapper.rs:278) ==96758== by 0x195C70: hassle_rs::utils::compile_hlsl (utils.rs:115) ==96758== by 0x127BDF: include::main (autogen_ops.rs:0) ==96758== by 0x1275CA: core::ops::function::FnOnce::call_once (autogen_context.rs:1683) ==96758== by 0x127ADD: std::sys_common::backtrace::__rust_begin_short_backtrace (backtrace.rs:137) ==96758== by 0x127530: std::rt::lang_start::{{closure}} (rt.rs:66) This happens because of Box::into_raw, which moves the pointer out of the box. Taking this pointer out of a referenced Box makes it live on till the end of the function where it is appropriately dropped. Properly freeing DxcIncludeHandlerWrapper exposes a second issue: The blobs are now freed but have already been freed within DXC becaues of a missing refcount: we are supposed to increment it before writing the pointer to it to `include_source` [1]. Now that the blobs have a proper refcount and live on until DXC cleans them up when not needed, they do not need to be kept alive inside DxcIncludeHandlerWrapper anymore. Finally, clean up the unnecessary clone of `source`: This String is already retrieved by value and can be moved straight into the Rc. [1]: https://github.com/microsoft/DirectXShaderCompiler/blob/a8d9780046cb64a1cea842fa6fc28a250e3e2c09/tools/clang/unittests/dxc_batch/dxc_batch.cpp#L553-L554
…extra trait" This reverts commit c37cb03. [This commit] is squashed in the merge of PR #5, and does not exist in-tree. microsoft/DirectXShaderCompiler#3793 has finally been merged on October 13th 2022 and now allows us to drop the vtable dummies for virtual destructors again, as those are not part of the ABI and shouldn't have been in the vtable in the first place. [This commit]: c37cb03
…extra trait" This reverts commit c37cb03. [This commit] is squashed in the merge of PR #5, and does not exist in-tree. microsoft/DirectXShaderCompiler#3793 has finally been merged on October 13th 2022 and now allows us to drop the vtable dummies for virtual destructors again, as those are not part of the ABI and shouldn't have been in the vtable in the first place. [This commit]: c37cb03
…) through extra trait" (#50) * Revert "[WIN/LINUX] Implement vtable dummies (virtual dtors) through extra trait" This reverts commit c37cb03. [This commit] is squashed in the merge of PR #5, and does not exist in-tree. microsoft/DirectXShaderCompiler#3793 has finally been merged on October 13th 2022 and now allows us to drop the vtable dummies for virtual destructors again, as those are not part of the ABI and shouldn't have been in the vtable in the first place. [This commit]: c37cb03 * README: Replace verbose compatibility "guide" with direct table It's been quite a while ago (about two years) since we landed a whole bunch of compatibility fixes for DXC, and I hope everyone is using (much) newer releases by now. I also doubt anyone is interested in detailed descriptions of what we fixed (including the how and why), and just wants a clear answer on the DXC release or commit they must minimally use for compatibility with a certain `hassle-rs` release. * README: Vtable changes have been published in DXC v1.7.2212
Thanks @h3r2tic for doing the initial porting work!
Things to sort out in the feature:
com-rs
crate to Microsofts' com-rs. This is in the works but depends on minor changes in com-rs to compile on Linux. That project is furthermore going through an API refactor which makes it hard to justify switching just yet.