Skip to content

Commit

Permalink
Support libdxcompiler.so on Linux (#5)
Browse files Browse the repository at this point in the history
* Type include_handler as *const IDxcIncludeHandler instead of c_void

* os: Add BSTR type on non-Windows

* lib: Fix bitflags macro include

extern crate requires deprecated `#[macro_use]`, which should be
replaced with `use` instead.

* Make intellisense compile on Linux

* [LINUX ONLY] intellisense: Insert the usual destructor dummies

* [WINDOWS] Make OS wrapper types compatible with Windows again

HRESULT is 32-bit: https://en.wikipedia.org/wiki/HRESULT

* Delete dummy functions (virtual dtors) again

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.

* [WIN/LINUX] Implement vtable dummies (virtual dtors) through extra trait

TODO: Might as well keep the IUnknown name and "hide" the COM one (less
changes, as long as the right one is use'd.

* [LINUX] wrapper: Library is in PWD

* Add error type

* Fix return type of IDxcType::get_kind

* ffi: Replace c_void with the respective interface type

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.

* Cargo.toml: Only include winapi dependency on cfg(windows)

Using winapi on not(windows) is a no-op already, but saves pulling in
this extra dependency.

* [LINUX] Disable DXIL validation at compile-time

* README: Mention libdxcompiler.so requirement on Linux

* Improve error handling

* Add more context about the .dll / .so we're trying to load

* Expose helper on Linux as well even though it always returns an error, makes the API slightly easier to use

Co-authored-by: Tomasz Stachowiak <h3@h3.gd>
Co-authored-by: Jasper Bekkers <bekkers@gmail.com>
  • Loading branch information
3 people authored Jul 21, 2020
1 parent 04a9508 commit 94fbad7
Show file tree
Hide file tree
Showing 13 changed files with 376 additions and 160 deletions.
15 changes: 8 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,14 @@ maintenance = { status = "actively-developed" }
default-target = "x86_64-pc-windows-msvc"

[dependencies]
libloading = "0.5.2"
com-rs = "0.2.0"
winapi = "0.3.7"
bitflags = "1.1.0"
libloading = "0.6.2"
com-rs = "0.2.1"
bitflags = "1.2.1"
widestring = "0.4.2"
thiserror = "1.0"

[target.'cfg(windows)'.dependencies]
winapi = { version = "0.3.9", features = ["wtypes", "oleauto"] }

[dev-dependencies]
rspirv = "0.6.0"

[features]
default = ["winapi/wtypes", "winapi/oleauto"]
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ and add this to your crate root:
extern crate hassle_rs;
```

Then acquire `dxcompiler.dll` directly from [AppVeyor](https://ci.appveyor.com/project/antiagainst/directxshadercompiler/branch/master/artifacts) or compile it from source according to the instructions in the [DirectXShaderCompiler](https://github.com/Microsoft/DirectXShaderCompiler) GitHub repository and make sure it's in the executable enviroment.
Then acquire `dxcompiler.dll` on Windows or `libdxcompiler.so` on Linux directly from [AppVeyor](https://ci.appveyor.com/project/antiagainst/directxshadercompiler/branch/master/artifacts), or compile it from source according to the instructions in the [DirectXShaderCompiler](https://github.com/Microsoft/DirectXShaderCompiler) GitHub repository and make sure it's in the executable environment.

DxcValidator also requires `dxil.dll` which can be grabbed from any recent Windows 10 SDK flight.
More info: https://www.wihlidal.com/blog/pipeline/2018-09-16-dxil-signing-post-compile/
Expand Down
4 changes: 2 additions & 2 deletions examples/file-ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ fn main() {

let args = vec![];

let dxc = Dxc::new();
let dxc = Dxc::new().unwrap();

let intellisense = dxc.create_intellisense().unwrap();

Expand All @@ -88,7 +88,7 @@ fn main() {
let unsaved_file = intellisense.create_unsaved_file(name, source).unwrap();

let translation_unit = index
.parse_translation_unit(name, &args, &vec![&unsaved_file], local_options)
.parse_translation_unit(name, &args, &[&unsaved_file], local_options)
.unwrap();

let cursor = translation_unit.get_cursor().unwrap();
Expand Down
4 changes: 2 additions & 2 deletions examples/intellisense-tu.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ fn main() {

let args = vec![];

let dxc = Dxc::new();
let dxc = Dxc::new().unwrap();

let intellisense = dxc.create_intellisense().unwrap();

Expand All @@ -18,7 +18,7 @@ fn main() {
let unsaved_file = intellisense.create_unsaved_file(name, source).unwrap();

let translation_unit = index
.parse_translation_unit(name, &args, &vec![&unsaved_file], local_options)
.parse_translation_unit(name, &args, &[&unsaved_file], local_options)
.unwrap();

let cursor = translation_unit.get_cursor().unwrap();
Expand Down
5 changes: 3 additions & 2 deletions examples/validate.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use hassle_rs::*;

#[repr(C)]
#[repr(packed)]
pub struct MinimalHeader {
four_cc: u32,
hash_digest: [u32; 4],
}

// zero_digest & get_digest from https://github.com/gwihlidal/dxil-signing/blob/master/rust/src/main.rs

fn zero_digest(buffer: &mut [u8]) -> () {
fn zero_digest(buffer: &mut [u8]) {
let buffer_ptr: *mut u8 = buffer.as_mut_ptr();
let header_ptr: *mut MinimalHeader = buffer_ptr as *mut _;
let header_mut: &mut MinimalHeader = unsafe { &mut *header_ptr };
Expand Down Expand Up @@ -39,11 +40,11 @@ fn main() {
zero_digest(&mut dxil);

let without_digest = get_digest(&dxil);
println!("Before validation: {:?}", without_digest);

let validated_dxil = validate_dxil(&dxil).unwrap();

let with_digest = get_digest(&validated_dxil);

println!("Before validation: {:?}", without_digest);
println!("After validation: {:?}", with_digest);
}
70 changes: 35 additions & 35 deletions src/ffi.rs
Original file line number Diff line number Diff line change
@@ -1,34 +1,34 @@
#![allow(clippy::transmute_ptr_to_ptr)]
#![allow(clippy::too_many_arguments)]

use crate::os::{HRESULT, LPCWSTR, LPWSTR};
pub(crate) use crate::unknown::IDxcUnknownShim;
use com_rs::{com_interface, iid, IUnknown, IID};
use std::ffi::c_void;
use winapi::shared::ntdef::{LPCWSTR, LPWSTR};
use winapi::shared::winerror::HRESULT;

pub type DxcCreateInstanceProc =
extern "system" fn(rclsid: &IID, riid: &IID, ppv: *mut *mut c_void) -> HRESULT;

pub type DxcCreateInstanceProc2 = extern "system" fn(
malloc: *const c_void,
malloc: /* IMalloc */ *const c_void,
rclsid: &IID,
riid: &IID,
ppv: *mut *mut c_void,
) -> HRESULT;

iid!(pub IID_IDxcBlob = 0x8BA5_FB08, 0x5195, 0x40e2, 0xAC, 0x58, 0x0D, 0x98, 0x9C, 0x3A, 0x01, 0x02);
com_interface! {
interface IDxcBlob: IUnknown{
interface IDxcBlob: IDxcUnknownShim, IUnknown {
iid: IID_IDxcBlob,
vtable: IDxcBlobVtbl,
fn get_buffer_pointer() -> *const c_void;
fn get_buffer_pointer() -> *mut c_void;
fn get_buffer_size() -> usize;
}
}

iid!(pub IID_IDxcBlobEncoding = 0x7241_d424, 0x2646, 0x4191, 0x97, 0xc0, 0x98, 0xe9, 0x6e, 0x42, 0xfc, 0x68);
com_interface! {
interface IDxcBlobEncoding: IDxcBlob, IUnknown{
interface IDxcBlobEncoding: IDxcBlob, IDxcUnknownShim, IUnknown {
iid: IID_IDxcBlobEncoding,
vtable: IDxcBlobEncodingVtbl,
fn get_encoding(known: *mut u32, code_page: *mut u32) -> HRESULT;
Expand All @@ -37,25 +37,25 @@ com_interface! {

iid!(pub IID_IDxcLibrary = 0xe520_4dc7, 0xd18c, 0x4c3c, 0xbd, 0xfb, 0x85, 0x16, 0x73, 0x98, 0x0f, 0xe7);
com_interface! {
interface IDxcLibrary: IUnknown{
interface IDxcLibrary: IDxcUnknownShim, IUnknown {
iid: IID_IDxcLibrary,
vtable: IDxcLibraryVtbl,
fn set_malloc(malloc: *const c_void) -> HRESULT;
fn create_blob_from_blob(blob: *const IDxcBlob, offset: u32, length: u32, result_blob: *mut *mut IDxcBlob) -> HRESULT;
fn create_blob_from_file(filename: LPCWSTR, code_page: *const u32, blob_encoding: *mut *mut IDxcBlobEncoding) -> HRESULT;
fn create_blob_with_encoding_from_pinned(text: *const c_void, size: u32, code_page: u32, blob_encoding: *mut *mut IDxcBlobEncoding) -> HRESULT;
fn create_blob_with_encoding_on_heap_copy(text: *const c_void, size: u32, code_page: u32, blob_encoding: *mut *mut IDxcBlobEncoding) -> HRESULT;
fn create_blob_with_encoding_on_malloc(text: *const c_void, malloc: *const c_void, size: u32, code_page: u32, blob_encoding: *mut *mut IDxcBlobEncoding) -> HRESULT;
fn create_include_handler(include_handler: *mut *mut c_void) -> HRESULT;
fn create_stream_from_blob_read_only(blob: *const IDxcBlob, stream: *mut *mut c_void) -> HRESULT;
fn create_blob_with_encoding_on_malloc(text: *const c_void, malloc: /* IMalloc */ *const c_void, size: u32, code_page: u32, blob_encoding: *mut *mut IDxcBlobEncoding) -> HRESULT;
fn create_include_handler(include_handler: *mut *mut IDxcIncludeHandler) -> HRESULT;
fn create_stream_from_blob_read_only(blob: *const IDxcBlob, stream: /* IStream */ *mut *mut c_void) -> HRESULT;
fn get_blob_as_utf8(blob: *const IDxcBlob, blob_encoding: *mut *mut IDxcBlobEncoding) -> HRESULT;
fn get_blob_as_utf16(blob: *const IDxcBlob, blob_encoding: *mut *mut IDxcBlobEncoding) -> HRESULT;
}
}

iid!(pub IID_IDxcOperationResult = 0xCEDB_484A, 0xD4E9, 0x445A, 0xB9, 0x91, 0xCA, 0x21, 0xCA, 0x15, 0x7D, 0xC2);
com_interface! {
interface IDxcOperationResult: IUnknown{
interface IDxcOperationResult: IDxcUnknownShim, IUnknown {
iid: IID_IDxcOperationResult,
vtable: IDxcOperationResultVtbl,
fn get_status(status: *mut u32) -> HRESULT;
Expand All @@ -66,7 +66,7 @@ com_interface! {

iid!(pub IID_IDxcIncludeHandler = 0x7f61_fc7d, 0x950d, 0x467f, 0xb3, 0xe3, 0x3c, 0x02, 0xfb, 0x49, 0x18, 0x7c);
com_interface! {
interface IDxcIncludeHandler: IUnknown{
interface IDxcIncludeHandler: IDxcUnknownShim, IUnknown {
iid: IID_IDxcIncludeHandler,
vtable: IDxcIncludeHandlerVtbl,
fn load_source(filename: LPCWSTR, include_source: *mut *mut IDxcBlob) -> HRESULT;
Expand All @@ -82,7 +82,7 @@ pub struct DxcDefine {

iid!(pub IID_IDxcCompiler = 0x8c21_0bf3, 0x011f, 0x4422, 0x8d, 0x70, 0x6f, 0x9a, 0xcb, 0x8d, 0xb6, 0x17);
com_interface! {
interface IDxcCompiler: IUnknown{
interface IDxcCompiler: IDxcUnknownShim, IUnknown {
iid: IID_IDxcCompiler,
vtable: IDxcCompilerVtbl,
fn compile(
Expand All @@ -94,7 +94,7 @@ com_interface! {
arg_count: u32,
defines: *const DxcDefine,
def_count: u32,
include_handler: *const c_void,
include_handler: *const IDxcIncludeHandler,
result: *mut *mut IDxcOperationResult) -> HRESULT;

fn preprocess(
Expand All @@ -104,7 +104,7 @@ com_interface! {
arg_count: u32,
defines: *const DxcDefine,
def_count: u32,
include_handler: *const c_void,
include_handler: *const IDxcIncludeHandler,
result: *mut *mut IDxcOperationResult) -> HRESULT;

fn disassemble(
Expand All @@ -115,7 +115,7 @@ com_interface! {

iid!(pub IID_IDxcCompiler2 = 0xA005_A9D9, 0xB8BB, 0x4594, 0xB5, 0xC9, 0x0E, 0x63, 0x3B, 0xEC, 0x4D, 0x37);
com_interface! {
interface IDxcCompiler2: IDxcCompiler, IUnknown{
interface IDxcCompiler2: IDxcCompiler, IDxcUnknownShim, IUnknown {
iid: IID_IDxcCompiler2,
vtable: IDxcCompiler2Vtbl,

Expand All @@ -128,7 +128,7 @@ com_interface! {
arg_count: u32,
defines: *const DxcDefine,
def_count: u32,
include_handler: *const c_void,
include_handler: *const IDxcIncludeHandler,
result: *mut *mut IDxcOperationResult,
debug_blob_name: *mut LPWSTR,
debug_blob: *mut *mut IDxcBlob) -> HRESULT;
Expand All @@ -137,7 +137,7 @@ com_interface! {

iid!(pub IID_IDxcLinker = 0xF1B5_BE2A, 0x62DD, 0x4327, 0xA1, 0xC2, 0x42, 0xAC, 0x1E, 0x1E, 0x78, 0xE6);
com_interface! {
interface IDxcLinker: IUnknown{
interface IDxcLinker: IDxcUnknownShim, IUnknown {
iid: IID_IDxcLinker,
vtable: IDxcLinkerVtbl,

Expand All @@ -162,7 +162,7 @@ pub const DXC_VALIDATOR_FLAGS_VALID_MASK: u32 = 0x7;

iid!(pub IID_IDxcValidator = 0xA6E8_2BD2, 0x1FD7, 0x4826, 0x98, 0x11, 0x28, 0x57, 0xE7, 0x97, 0xF4, 0x9A);
com_interface! {
interface IDxcValidator: IUnknown{
interface IDxcValidator: IDxcUnknownShim, IUnknown {
iid: IID_IDxcValidator,
vtable: IDxcValidatorVtbl,

Expand All @@ -172,7 +172,7 @@ com_interface! {

iid!(pub IID_IDxcContainerBuilder = 0x334b_1f50, 0x2292, 0x4b35, 0x99, 0xa1, 0x25, 0x58, 0x8d, 0x8c, 0x17, 0xfe);
com_interface! {
interface IDxcContainerBuilder: IUnknown{
interface IDxcContainerBuilder: IDxcUnknownShim, IUnknown {
iid: IID_IDxcContainerBuilder,
vtable: IDxcContainerBuilderVtbl,

Expand All @@ -185,7 +185,7 @@ com_interface! {

iid!(pub IID_IDxcAssembler = 0x091f_7a26, 0x1c1f, 0x4948, 0x90, 0x4b, 0xe6, 0xe3, 0xa8, 0xa7, 0x71, 0xd5);
com_interface! {
interface IDxcAssembler: IUnknown{
interface IDxcAssembler: IDxcUnknownShim, IUnknown {
iid: IID_IDxcAssembler,
vtable: IDxcAssemblerVtbl,

Expand All @@ -195,7 +195,7 @@ com_interface! {

iid!(pub IID_IDxcContainerReflection = 0xd2c2_1b26, 0x8350, 0x4bdc, 0x97, 0x6a, 0x33, 0x1c, 0xe6, 0xf4, 0xc5, 0x4c);
com_interface! {
interface IDxcContainerReflection: IUnknown{
interface IDxcContainerReflection: IDxcUnknownShim, IUnknown {
iid: IID_IDxcContainerReflection,
vtable: IDxcContainerReflectionVtbl,

Expand All @@ -210,7 +210,7 @@ com_interface! {

iid!(pub IID_IDxcOptimizerPass = 0xAE2C_D79F, 0xCC22, 0x453F, 0x9B, 0x6B, 0xB1, 0x24, 0xE7, 0xA5, 0x20, 0x4C);
com_interface! {
interface IDxcOptimizerPass: IUnknown{
interface IDxcOptimizerPass: IDxcUnknownShim, IUnknown {
iid: IID_IDxcOptimizerPass,
vtable: IDxcOptimizerPassVtbl,

Expand All @@ -224,7 +224,7 @@ com_interface! {

iid!(pub IID_IDxcOptimizer = 0x2574_0E2E, 0x9CBA, 0x401B, 0x91, 0x19, 0x4F, 0xB4, 0x2F, 0x39, 0xF2, 0x70);
com_interface! {
interface IDxcOptimizer: IUnknown{
interface IDxcOptimizer: IDxcUnknownShim, IUnknown {
iid: IID_IDxcOptimizer,
vtable: IDxcOptimizerVtbl,

Expand All @@ -245,7 +245,7 @@ pub const DXC_VERSION_INFO_FLAGS_INTERNAL: u32 = 2; // Internal Validator (non-s

iid!(pub IID_IDxcVersionInfo = 0xb04f_5b50, 0x2059, 0x4f12, 0xa8, 0xff, 0xa1, 0xe0, 0xcd, 0xe1, 0xcc, 0x7e);
com_interface! {
interface IDxcVersionInfo: IUnknown{
interface IDxcVersionInfo: IDxcUnknownShim, IUnknown {
iid: IID_IDxcVersionInfo,
vtable: IDxcVersionInfoVtbl,

Expand All @@ -256,20 +256,20 @@ com_interface! {

iid!(pub IID_IDxcVersionInfo2 = 0xfb69_04c4, 0x42f0, 0x4b62, 0x9c, 0x46, 0x98, 0x3a, 0xf7, 0xda, 0x7c, 0x83);
com_interface! {
interface IDxcVersionInfo2: IUnknown{
interface IDxcVersionInfo2: IDxcUnknownShim, IUnknown {
iid: IID_IDxcVersionInfo2,
vtable: IDxcVersionInfo2Vtbl,

fn get_commit_info(commit_count: *mut u32, commit_hash: *mut *mut u8) -> HRESULT;
}
}

iid!(pub CLSID_DxcCompiler = 0x73e22d93, 0xe6ce, 0x47f3, 0xb5, 0xbf, 0xf0, 0x66, 0x4f, 0x39, 0xc1, 0xb0);
iid!(pub CLSID_DxcLinker = 0xef6a8087, 0xb0ea, 0x4d56, 0x9e, 0x45, 0xd0, 0x7e, 0x1a, 0x8b, 0x78, 0x6);
iid!(pub CLSID_DxcDiaDataSource = 0xcd1f6b73, 0x2ab0, 0x484d, 0x8e, 0xdc, 0xeb, 0xe7, 0xa4, 0x3c, 0xa0, 0x9f );
iid!(pub CLSID_DxcLibrary = 0x6245d6af, 0x66e0, 0x48fd, 0x80, 0xb4, 0x4d, 0x27, 0x17, 0x96, 0x74, 0x8c);
iid!(pub CLSID_DxcValidator = 0x8ca3e215, 0xf728, 0x4cf3, 0x8c, 0xdd, 0x88, 0xaf, 0x91, 0x75, 0x87, 0xa1 );
iid!(pub CLSID_DxcAssembler = 0xd728db68, 0xf903, 0x4f80, 0x94, 0xcd, 0xdc, 0xcf, 0x76, 0xec, 0x71, 0x51);
iid!(pub CLSID_DxcContainerReflection = 0xb9f54489, 0x55b8, 0x400c, 0xba, 0x3a, 0x16, 0x75, 0xe4, 0x72, 0x8b, 0x91);
iid!(pub CLSID_DxcOptimizer = 0xae2cd79f, 0xcc22, 0x453f, 0x9b, 0x6b, 0xb1, 0x24, 0xe7, 0xa5, 0x20, 0x4c);
iid!(pub CLSID_DxcContainerBuilder = 0x94134294, 0x411f, 0x4574, 0xb4, 0xd0, 0x87, 0x41, 0xe2, 0x52, 0x40, 0xd2 );
iid!(pub CLSID_DxcCompiler = 0x73e2_2d93, 0xe6ce, 0x47f3, 0xb5, 0xbf, 0xf0, 0x66, 0x4f, 0x39, 0xc1, 0xb0);
iid!(pub CLSID_DxcLinker = 0xef6a_8087, 0xb0ea, 0x4d56, 0x9e, 0x45, 0xd0, 0x7e, 0x1a, 0x8b, 0x78, 0x6);
iid!(pub CLSID_DxcDiaDataSource = 0xcd1f_6b73, 0x2ab0, 0x484d, 0x8e, 0xdc, 0xeb, 0xe7, 0xa4, 0x3c, 0xa0, 0x9f );
iid!(pub CLSID_DxcLibrary = 0x6245_d6af, 0x66e0, 0x48fd, 0x80, 0xb4, 0x4d, 0x27, 0x17, 0x96, 0x74, 0x8c);
iid!(pub CLSID_DxcValidator = 0x8ca3_e215, 0xf728, 0x4cf3, 0x8c, 0xdd, 0x88, 0xaf, 0x91, 0x75, 0x87, 0xa1 );
iid!(pub CLSID_DxcAssembler = 0xd728_db68, 0xf903, 0x4f80, 0x94, 0xcd, 0xdc, 0xcf, 0x76, 0xec, 0x71, 0x51);
iid!(pub CLSID_DxcContainerReflection = 0xb9f5_4489, 0x55b8, 0x400c, 0xba, 0x3a, 0x16, 0x75, 0xe4, 0x72, 0x8b, 0x91);
iid!(pub CLSID_DxcOptimizer = 0xae2c_d79f, 0xcc22, 0x453f, 0x9b, 0x6b, 0xb1, 0x24, 0xe7, 0xa5, 0x20, 0x4c);
iid!(pub CLSID_DxcContainerBuilder = 0x9413_4294, 0x411f, 0x4574, 0xb4, 0xd0, 0x87, 0x41, 0xe2, 0x52, 0x40, 0xd2 );
Loading

0 comments on commit 94fbad7

Please sign in to comment.