@@ -78,6 +78,12 @@ pub(super) fn compile_fxc(
78
78
}
79
79
}
80
80
81
+ type DxcCreateInstanceFn = unsafe extern "system" fn (
82
+ rclsid : * const windows_core:: GUID ,
83
+ riid : * const windows_core:: GUID ,
84
+ ppv : * mut * mut core:: ffi:: c_void ,
85
+ ) -> windows_core:: HRESULT ;
86
+
81
87
trait DxcObj : Interface {
82
88
const CLSID : windows:: core:: GUID ;
83
89
}
@@ -97,7 +103,10 @@ struct DxcLib {
97
103
}
98
104
99
105
impl DxcLib {
100
- fn new ( lib_path : Option < PathBuf > , lib_name : & ' static str ) -> Result < Self , libloading:: Error > {
106
+ fn new_dynamic (
107
+ lib_path : Option < PathBuf > ,
108
+ lib_name : & ' static str ,
109
+ ) -> Result < Self , libloading:: Error > {
101
110
let lib_path = if let Some ( lib_path) = lib_path {
102
111
if lib_path. is_file ( ) {
103
112
lib_path
@@ -111,15 +120,19 @@ impl DxcLib {
111
120
}
112
121
113
122
pub fn create_instance < T : DxcObj > ( & self ) -> Result < T , crate :: DeviceError > {
114
- type Fun = extern "system" fn (
115
- rclsid : * const windows_core:: GUID ,
116
- riid : * const windows_core:: GUID ,
117
- ppv : * mut * mut core:: ffi:: c_void ,
118
- ) -> windows_core:: HRESULT ;
119
- let func: libloading:: Symbol < Fun > = unsafe { self . lib . get ( b"DxcCreateInstance\0 " ) } ?;
123
+ unsafe {
124
+ let func: libloading:: Symbol < DxcCreateInstanceFn > =
125
+ self . lib . get ( b"DxcCreateInstance\0 " ) ?;
126
+ dxc_create_instance :: < T > ( * func)
127
+ }
128
+ }
129
+ }
120
130
131
+ /// Invokes the provided library function to create a DXC object.
132
+ unsafe fn dxc_create_instance < T : DxcObj > ( f : DxcCreateInstanceFn ) -> Result < T , crate :: DeviceError > {
133
+ unsafe {
121
134
let mut result__ = None ;
122
- ( func ) ( & T :: CLSID , & T :: IID , <* mut _ >:: cast ( & mut result__) )
135
+ f ( & T :: CLSID , & T :: IID , <* mut _ >:: cast ( & mut result__) )
123
136
. ok ( )
124
137
. into_device_result ( "DxcCreateInstance" ) ?;
125
138
result__. ok_or ( crate :: DeviceError :: Unexpected )
@@ -130,18 +143,20 @@ impl DxcLib {
130
143
pub ( super ) struct DxcContainer {
131
144
compiler : Dxc :: IDxcCompiler3 ,
132
145
utils : Dxc :: IDxcUtils ,
133
- validator : Dxc :: IDxcValidator ,
146
+ validator : Option < Dxc :: IDxcValidator > ,
134
147
// Has to be held onto for the lifetime of the device otherwise shaders will fail to compile.
135
- _dxc : DxcLib ,
148
+ // Only needed when using dynamic linking.
149
+ _dxc : Option < DxcLib > ,
136
150
// Also Has to be held onto for the lifetime of the device otherwise shaders will fail to validate.
137
- _dxil : DxcLib ,
151
+ // Only needed when using dynamic linking.
152
+ _dxil : Option < DxcLib > ,
138
153
}
139
154
140
- pub ( super ) fn get_dxc_container (
155
+ pub ( super ) fn get_dynamic_dxc_container (
141
156
dxc_path : Option < PathBuf > ,
142
157
dxil_path : Option < PathBuf > ,
143
158
) -> Result < Option < DxcContainer > , crate :: DeviceError > {
144
- let dxc = match DxcLib :: new ( dxc_path, "dxcompiler.dll" ) {
159
+ let dxc = match DxcLib :: new_dynamic ( dxc_path, "dxcompiler.dll" ) {
145
160
Ok ( dxc) => dxc,
146
161
Err ( e) => {
147
162
log:: warn!(
@@ -153,7 +168,7 @@ pub(super) fn get_dxc_container(
153
168
}
154
169
} ;
155
170
156
- let dxil = match DxcLib :: new ( dxil_path, "dxil.dll" ) {
171
+ let dxil = match DxcLib :: new_dynamic ( dxil_path, "dxil.dll" ) {
157
172
Ok ( dxil) => dxil,
158
173
Err ( e) => {
159
174
log:: warn!(
@@ -172,12 +187,37 @@ pub(super) fn get_dxc_container(
172
187
Ok ( Some ( DxcContainer {
173
188
compiler,
174
189
utils,
175
- validator,
176
- _dxc : dxc,
177
- _dxil : dxil,
190
+ validator : Some ( validator ) ,
191
+ _dxc : Some ( dxc) ,
192
+ _dxil : Some ( dxil) ,
178
193
} ) )
179
194
}
180
195
196
+ /// Creates a [`DxcContainer`] that delegates to the statically-linked `mach-dxcompiler` library.
197
+ pub ( super ) fn get_mach_dxc_container ( ) -> Result < Option < DxcContainer > , crate :: DeviceError > {
198
+ #[ cfg( feature = "mach-dxcompiler-rs" ) ]
199
+ {
200
+ unsafe {
201
+ let compiler =
202
+ dxc_create_instance :: < Dxc :: IDxcCompiler3 > ( mach_dxcompiler_rs:: DxcCreateInstance ) ?;
203
+ let utils =
204
+ dxc_create_instance :: < Dxc :: IDxcUtils > ( mach_dxcompiler_rs:: DxcCreateInstance ) ?;
205
+
206
+ Ok ( Some ( DxcContainer {
207
+ compiler,
208
+ utils,
209
+ validator : None ,
210
+ _dxc : None ,
211
+ _dxil : None ,
212
+ } ) )
213
+ }
214
+ }
215
+ #[ cfg( not( feature = "mach-dxcompiler-rs" ) ) ]
216
+ {
217
+ panic ! ( "Attempted to create a Mach DXC shader compiler, but the mach-dxcompiler-rs feature was not enabled" )
218
+ }
219
+ }
220
+
181
221
/// Owned PCWSTR
182
222
#[ allow( clippy:: upper_case_acronyms) ]
183
223
struct OPCWSTR {
@@ -288,26 +328,24 @@ pub(super) fn compile_dxc(
288
328
289
329
let blob = get_output :: < Dxc :: IDxcBlob > ( & compile_res, Dxc :: DXC_OUT_OBJECT ) ?;
290
330
291
- let err_blob = {
292
- let res = unsafe {
293
- dxc_container
294
- . validator
295
- . Validate ( & blob, Dxc :: DxcValidatorFlags_InPlaceEdit )
296
- }
297
- . into_device_result ( "Validate" ) ?;
331
+ if let Some ( validator) = & dxc_container. validator {
332
+ let err_blob = {
333
+ let res = unsafe { validator. Validate ( & blob, Dxc :: DxcValidatorFlags_InPlaceEdit ) }
334
+ . into_device_result ( "Validate" ) ?;
298
335
299
- unsafe { res. GetErrorBuffer ( ) } . into_device_result ( "GetErrorBuffer" ) ?
300
- } ;
336
+ unsafe { res. GetErrorBuffer ( ) } . into_device_result ( "GetErrorBuffer" ) ?
337
+ } ;
301
338
302
- let size = unsafe { err_blob. GetBufferSize ( ) } ;
303
- if size != 0 {
304
- let err_blob = unsafe { dxc_container. utils . GetBlobAsUtf8 ( & err_blob) }
305
- . into_device_result ( "GetBlobAsUtf8" ) ?;
306
- let err = as_err_str ( & err_blob) ?;
307
- return Err ( crate :: PipelineError :: Linkage (
308
- stage_bit,
309
- format ! ( "DXC validation error: {err}" ) ,
310
- ) ) ;
339
+ let size = unsafe { err_blob. GetBufferSize ( ) } ;
340
+ if size != 0 {
341
+ let err_blob = unsafe { dxc_container. utils . GetBlobAsUtf8 ( & err_blob) }
342
+ . into_device_result ( "GetBlobAsUtf8" ) ?;
343
+ let err = as_err_str ( & err_blob) ?;
344
+ return Err ( crate :: PipelineError :: Linkage (
345
+ stage_bit,
346
+ format ! ( "DXC validation error: {err}" ) ,
347
+ ) ) ;
348
+ }
311
349
}
312
350
313
351
Ok ( crate :: dx12:: CompiledShader :: Dxc ( blob) )
0 commit comments