~mmach/netext73/mesa-ryzen

« back to all changes in this revision

Viewing changes to src/gallium/frontends/rusticl/core/program.rs

  • Committer: mmach
  • Date: 2023-11-02 21:31:35 UTC
  • Revision ID: netbit73@gmail.com-20231102213135-18d4tzh7tj0uz752
2023-11-02 22:11:57

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
use crate::api::icd::*;
2
2
use crate::core::context::*;
3
3
use crate::core::device::*;
 
4
use crate::core::kernel::*;
4
5
use crate::core::platform::Platform;
5
6
use crate::impl_cl_type_trait;
6
7
 
17
18
use std::mem::size_of;
18
19
use std::ptr;
19
20
use std::slice;
20
 
use std::sync::atomic::AtomicU32;
21
 
use std::sync::atomic::Ordering;
22
21
use std::sync::Arc;
23
22
use std::sync::Mutex;
24
23
use std::sync::MutexGuard;
39
38
static DISK_CACHE_ONCE: Once = Once::new();
40
39
 
41
40
fn get_disk_cache() -> &'static Option<DiskCache> {
 
41
    let func_ptrs = [
 
42
        // ourselves
 
43
        get_disk_cache as _,
 
44
    ];
42
45
    unsafe {
43
46
        DISK_CACHE_ONCE.call_once(|| {
44
 
            DISK_CACHE = DiskCache::new("rusticl", "rusticl", 0);
 
47
            DISK_CACHE = DiskCache::new("rusticl", &func_ptrs, 0);
45
48
        });
46
49
        &DISK_CACHE
47
50
    }
54
57
    Il(spirv::SPIRVBin),
55
58
}
56
59
 
57
 
#[repr(C)]
58
60
pub struct Program {
59
61
    pub base: CLObjectBase<CL_INVALID_PROGRAM>,
60
62
    pub context: Arc<Context>,
61
 
    pub devs: Vec<Arc<Device>>,
 
63
    pub devs: Vec<&'static Device>,
62
64
    pub src: ProgramSourceType,
63
 
    pub kernel_count: AtomicU32,
64
 
    spec_constants: Mutex<HashMap<u32, nir_const_value>>,
65
65
    build: Mutex<ProgramBuild>,
66
66
}
67
67
 
68
68
impl_cl_type_trait!(cl_program, Program, CL_INVALID_PROGRAM);
69
69
 
70
 
struct ProgramBuild {
71
 
    builds: HashMap<Arc<Device>, ProgramDevBuild>,
 
70
#[derive(Clone)]
 
71
pub struct NirKernelBuild {
 
72
    pub nirs: HashMap<&'static Device, Arc<NirShader>>,
 
73
    pub args: Vec<KernelArg>,
 
74
    pub internal_args: Vec<InternalKernelArg>,
 
75
    pub attributes_string: String,
 
76
}
 
77
 
 
78
pub(super) struct ProgramBuild {
 
79
    builds: HashMap<&'static Device, ProgramDevBuild>,
 
80
    spec_constants: HashMap<u32, nir_const_value>,
72
81
    kernels: Vec<String>,
 
82
    kernel_builds: HashMap<String, Arc<NirKernelBuild>>,
 
83
}
 
84
 
 
85
impl ProgramBuild {
 
86
    fn attribute_str(&self, kernel: &str, d: &Device) -> String {
 
87
        let info = self.dev_build(d);
 
88
 
 
89
        let attributes_strings = [
 
90
            info.spirv.as_ref().unwrap().vec_type_hint(kernel),
 
91
            info.spirv.as_ref().unwrap().local_size(kernel),
 
92
            info.spirv.as_ref().unwrap().local_size_hint(kernel),
 
93
        ];
 
94
 
 
95
        let attributes_strings: Vec<_> = attributes_strings
 
96
            .iter()
 
97
            .flatten()
 
98
            .map(String::as_str)
 
99
            .collect();
 
100
        attributes_strings.join(",")
 
101
    }
 
102
 
 
103
    fn args(&self, dev: &Device, kernel: &str) -> Vec<spirv::SPIRVKernelArg> {
 
104
        self.dev_build(dev).spirv.as_ref().unwrap().args(kernel)
 
105
    }
 
106
 
 
107
    fn build_nirs(&mut self, is_src: bool) {
 
108
        for kernel_name in &self.kernels {
 
109
            let kernel_args: HashSet<_> = self
 
110
                .devs_with_build()
 
111
                .iter()
 
112
                .map(|d| self.args(d, kernel_name))
 
113
                .collect();
 
114
 
 
115
            let args = kernel_args.into_iter().next().unwrap();
 
116
            let mut nirs = HashMap::new();
 
117
            let mut args_set = HashSet::new();
 
118
            let mut internal_args_set = HashSet::new();
 
119
            let mut attributes_string_set = HashSet::new();
 
120
 
 
121
            // TODO: we could run this in parallel?
 
122
            for d in self.devs_with_build() {
 
123
                let (nir, args, internal_args) = convert_spirv_to_nir(self, kernel_name, &args, d);
 
124
                let attributes_string = self.attribute_str(kernel_name, d);
 
125
                nirs.insert(d, Arc::new(nir));
 
126
                args_set.insert(args);
 
127
                internal_args_set.insert(internal_args);
 
128
                attributes_string_set.insert(attributes_string);
 
129
            }
 
130
 
 
131
            // we want the same (internal) args for every compiled kernel, for now
 
132
            assert!(args_set.len() == 1);
 
133
            assert!(internal_args_set.len() == 1);
 
134
            assert!(attributes_string_set.len() == 1);
 
135
            let args = args_set.into_iter().next().unwrap();
 
136
            let internal_args = internal_args_set.into_iter().next().unwrap();
 
137
 
 
138
            // spec: For kernels not created from OpenCL C source and the clCreateProgramWithSource
 
139
            // API call the string returned from this query [CL_KERNEL_ATTRIBUTES] will be empty.
 
140
            let attributes_string = if is_src {
 
141
                attributes_string_set.into_iter().next().unwrap()
 
142
            } else {
 
143
                String::new()
 
144
            };
 
145
 
 
146
            self.kernel_builds.insert(
 
147
                kernel_name.clone(),
 
148
                Arc::new(NirKernelBuild {
 
149
                    nirs: nirs,
 
150
                    args: args,
 
151
                    internal_args: internal_args,
 
152
                    attributes_string: attributes_string,
 
153
                }),
 
154
            );
 
155
        }
 
156
    }
 
157
 
 
158
    fn dev_build(&self, dev: &Device) -> &ProgramDevBuild {
 
159
        self.builds.get(dev).unwrap()
 
160
    }
 
161
 
 
162
    fn dev_build_mut(&mut self, dev: &Device) -> &mut ProgramDevBuild {
 
163
        self.builds.get_mut(dev).unwrap()
 
164
    }
 
165
 
 
166
    fn devs_with_build(&self) -> Vec<&'static Device> {
 
167
        self.builds
 
168
            .iter()
 
169
            .filter(|(_, build)| build.status == CL_BUILD_SUCCESS as cl_build_status)
 
170
            .map(|(&d, _)| d)
 
171
            .collect()
 
172
    }
 
173
 
 
174
    pub fn hash_key(&self, dev: &Device, name: &str) -> Option<cache_key> {
 
175
        if let Some(cache) = dev.screen().shader_cache() {
 
176
            let info = self.dev_build(dev);
 
177
            assert_eq!(info.status, CL_BUILD_SUCCESS as cl_build_status);
 
178
 
 
179
            let spirv = info.spirv.as_ref().unwrap();
 
180
            let mut bin = spirv.to_bin().to_vec();
 
181
            bin.extend_from_slice(name.as_bytes());
 
182
 
 
183
            for (k, v) in &self.spec_constants {
 
184
                bin.extend_from_slice(&k.to_ne_bytes());
 
185
                unsafe {
 
186
                    // SAFETY: we fully initialize this union
 
187
                    bin.extend_from_slice(&v.u64_.to_ne_bytes());
 
188
                }
 
189
            }
 
190
 
 
191
            Some(cache.gen_key(&bin))
 
192
        } else {
 
193
            None
 
194
        }
 
195
    }
 
196
 
 
197
    pub fn to_nir(&self, kernel: &str, d: &Device) -> NirShader {
 
198
        let mut spec_constants: Vec<_> = self
 
199
            .spec_constants
 
200
            .iter()
 
201
            .map(|(&id, &value)| nir_spirv_specialization {
 
202
                id: id,
 
203
                value: value,
 
204
                defined_on_module: true,
 
205
            })
 
206
            .collect();
 
207
 
 
208
        let info = self.dev_build(d);
 
209
        assert_eq!(info.status, CL_BUILD_SUCCESS as cl_build_status);
 
210
 
 
211
        let mut log = Platform::dbg().program.then(Vec::new);
 
212
        let nir = info.spirv.as_ref().unwrap().to_nir(
 
213
            kernel,
 
214
            d.screen
 
215
                .nir_shader_compiler_options(pipe_shader_type::PIPE_SHADER_COMPUTE),
 
216
            &d.lib_clc,
 
217
            &mut spec_constants,
 
218
            d.address_bits(),
 
219
            log.as_mut(),
 
220
        );
 
221
 
 
222
        if let Some(log) = log {
 
223
            for line in log {
 
224
                eprintln!("{}", line);
 
225
            }
 
226
        };
 
227
 
 
228
        nir.unwrap()
 
229
    }
73
230
}
74
231
 
75
232
struct ProgramDevBuild {
128
285
}
129
286
 
130
287
impl Program {
131
 
    fn create_default_builds(devs: &[Arc<Device>]) -> HashMap<Arc<Device>, ProgramDevBuild> {
 
288
    fn create_default_builds(
 
289
        devs: &[&'static Device],
 
290
    ) -> HashMap<&'static Device, ProgramDevBuild> {
132
291
        devs.iter()
133
 
            .map(|d| {
 
292
            .map(|&d| {
134
293
                (
135
 
                    d.clone(),
 
294
                    d,
136
295
                    ProgramDevBuild {
137
296
                        spirv: None,
138
297
                        status: CL_BUILD_NONE,
145
304
            .collect()
146
305
    }
147
306
 
148
 
    pub fn new(context: &Arc<Context>, devs: &[Arc<Device>], src: CString) -> Arc<Program> {
 
307
    pub fn new(context: &Arc<Context>, devs: &[&'static Device], src: CString) -> Arc<Program> {
149
308
        Arc::new(Self {
150
309
            base: CLObjectBase::new(),
151
310
            context: context.clone(),
152
311
            devs: devs.to_vec(),
153
312
            src: ProgramSourceType::Src(src),
154
 
            kernel_count: AtomicU32::new(0),
155
 
            spec_constants: Mutex::new(HashMap::new()),
156
313
            build: Mutex::new(ProgramBuild {
157
314
                builds: Self::create_default_builds(devs),
 
315
                spec_constants: HashMap::new(),
158
316
                kernels: Vec::new(),
 
317
                kernel_builds: HashMap::new(),
159
318
            }),
160
319
        })
161
320
    }
162
321
 
163
322
    pub fn from_bins(
164
323
        context: Arc<Context>,
165
 
        devs: Vec<Arc<Device>>,
 
324
        devs: Vec<&'static Device>,
166
325
        bins: &[&[u8]],
167
326
    ) -> Arc<Program> {
168
327
        let mut builds = HashMap::new();
169
328
        let mut kernels = HashSet::new();
170
329
 
171
 
        for (d, b) in devs.iter().zip(bins) {
 
330
        for (&d, b) in devs.iter().zip(bins) {
172
331
            let mut ptr = b.as_ptr();
173
332
            let bin_type;
174
333
            let spirv;
207
366
            }
208
367
 
209
368
            builds.insert(
210
 
                d.clone(),
 
369
                d,
211
370
                ProgramDevBuild {
212
371
                    spirv: spirv,
213
372
                    status: CL_BUILD_SUCCESS as cl_build_status,
218
377
            );
219
378
        }
220
379
 
 
380
        let mut build = ProgramBuild {
 
381
            builds: builds,
 
382
            spec_constants: HashMap::new(),
 
383
            kernels: kernels.into_iter().collect(),
 
384
            kernel_builds: HashMap::new(),
 
385
        };
 
386
        build.build_nirs(false);
 
387
 
221
388
        Arc::new(Self {
222
389
            base: CLObjectBase::new(),
223
390
            context: context,
224
391
            devs: devs,
225
392
            src: ProgramSourceType::Binary,
226
 
            kernel_count: AtomicU32::new(0),
227
 
            spec_constants: Mutex::new(HashMap::new()),
228
 
            build: Mutex::new(ProgramBuild {
229
 
                builds: builds,
230
 
                kernels: kernels.into_iter().collect(),
231
 
            }),
 
393
            build: Mutex::new(build),
232
394
        })
233
395
    }
234
396
 
239
401
            devs: context.devs.clone(),
240
402
            context: context,
241
403
            src: ProgramSourceType::Il(SPIRVBin::from_bin(spirv)),
242
 
            kernel_count: AtomicU32::new(0),
243
 
            spec_constants: Mutex::new(HashMap::new()),
244
404
            build: Mutex::new(ProgramBuild {
245
405
                builds: builds,
 
406
                spec_constants: HashMap::new(),
246
407
                kernels: Vec::new(),
 
408
                kernel_builds: HashMap::new(),
247
409
            }),
248
410
        })
249
411
    }
252
414
        self.build.lock().unwrap()
253
415
    }
254
416
 
255
 
    fn dev_build_info<'a>(
256
 
        l: &'a mut MutexGuard<ProgramBuild>,
257
 
        dev: &Arc<Device>,
258
 
    ) -> &'a mut ProgramDevBuild {
259
 
        l.builds.get_mut(dev).unwrap()
260
 
    }
261
 
 
262
 
    pub fn status(&self, dev: &Arc<Device>) -> cl_build_status {
263
 
        Self::dev_build_info(&mut self.build_info(), dev).status
264
 
    }
265
 
 
266
 
    pub fn log(&self, dev: &Arc<Device>) -> String {
267
 
        Self::dev_build_info(&mut self.build_info(), dev)
268
 
            .log
269
 
            .clone()
270
 
    }
271
 
 
272
 
    pub fn bin_type(&self, dev: &Arc<Device>) -> cl_program_binary_type {
273
 
        Self::dev_build_info(&mut self.build_info(), dev).bin_type
274
 
    }
275
 
 
276
 
    pub fn options(&self, dev: &Arc<Device>) -> String {
277
 
        Self::dev_build_info(&mut self.build_info(), dev)
278
 
            .options
279
 
            .clone()
 
417
    pub fn get_nir_kernel_build(&self, name: &str) -> Arc<NirKernelBuild> {
 
418
        let info = self.build_info();
 
419
        info.kernel_builds.get(name).unwrap().clone()
 
420
    }
 
421
 
 
422
    pub fn status(&self, dev: &Device) -> cl_build_status {
 
423
        self.build_info().dev_build(dev).status
 
424
    }
 
425
 
 
426
    pub fn log(&self, dev: &Device) -> String {
 
427
        self.build_info().dev_build(dev).log.clone()
 
428
    }
 
429
 
 
430
    pub fn bin_type(&self, dev: &Device) -> cl_program_binary_type {
 
431
        self.build_info().dev_build(dev).bin_type
 
432
    }
 
433
 
 
434
    pub fn options(&self, dev: &Device) -> String {
 
435
        self.build_info().dev_build(dev).options.clone()
280
436
    }
281
437
 
282
438
    // we need to precalculate the size
283
439
    pub fn bin_sizes(&self) -> Vec<usize> {
284
 
        let mut lock = self.build_info();
 
440
        let lock = self.build_info();
285
441
        let mut res = Vec::new();
286
442
        for d in &self.devs {
287
 
            let info = Self::dev_build_info(&mut lock, d);
 
443
            let info = lock.dev_build(d);
288
444
 
289
445
            res.push(
290
446
                info.spirv
310
466
            slice::from_raw_parts(vals.as_ptr().cast(), vals.len() / size_of::<*mut u8>())
311
467
        };
312
468
 
313
 
        let mut lock = self.build_info();
 
469
        let lock = self.build_info();
314
470
        for (i, d) in self.devs.iter().enumerate() {
315
471
            let mut ptr = ptrs[i];
316
 
            let info = Self::dev_build_info(&mut lock, d);
 
472
            let info = lock.dev_build(d);
317
473
            let spirv = info.spirv.as_ref().unwrap().to_bin();
318
474
 
319
475
            unsafe {
338
494
        ptrs.to_vec()
339
495
    }
340
496
 
341
 
    pub fn args(&self, dev: &Arc<Device>, kernel: &str) -> Vec<spirv::SPIRVKernelArg> {
342
 
        Self::dev_build_info(&mut self.build_info(), dev)
343
 
            .spirv
344
 
            .as_ref()
345
 
            .unwrap()
346
 
            .args(kernel)
 
497
    pub fn kernel_signatures(&self, kernel_name: &str) -> HashSet<Vec<spirv::SPIRVKernelArg>> {
 
498
        let build = self.build_info();
 
499
        let devs = build.devs_with_build();
 
500
 
 
501
        if devs.is_empty() {
 
502
            return HashSet::new();
 
503
        }
 
504
 
 
505
        devs.iter().map(|d| build.args(d, kernel_name)).collect()
347
506
    }
348
507
 
349
508
    pub fn kernels(&self) -> Vec<String> {
351
510
    }
352
511
 
353
512
    pub fn active_kernels(&self) -> bool {
354
 
        self.kernel_count.load(Ordering::Relaxed) != 0
 
513
        self.build_info()
 
514
            .kernel_builds
 
515
            .values()
 
516
            .any(|b| Arc::strong_count(b) > 1)
355
517
    }
356
518
 
357
 
    pub fn build(&self, dev: &Arc<Device>, options: String) -> bool {
 
519
    pub fn build(&self, dev: &Device, options: String) -> bool {
358
520
        let lib = options.contains("-create-library");
359
521
        let mut info = self.build_info();
360
522
        if !self.do_compile(dev, options, &Vec::new(), &mut info) {
361
523
            return false;
362
524
        }
363
525
 
364
 
        let d = Self::dev_build_info(&mut info, dev);
 
526
        let d = info.dev_build_mut(dev);
 
527
 
 
528
        // skip compilation if we already have the right thing.
 
529
        if self.is_bin() {
 
530
            if d.bin_type == CL_PROGRAM_BINARY_TYPE_EXECUTABLE && !lib
 
531
                || d.bin_type == CL_PROGRAM_BINARY_TYPE_LIBRARY && lib
 
532
            {
 
533
                return true;
 
534
            }
 
535
        }
 
536
 
365
537
        let spirvs = [d.spirv.as_ref().unwrap()];
366
538
        let (spirv, log) = spirv::SPIRVBin::link(&spirvs, lib);
367
539
 
368
540
        d.log.push_str(&log);
369
541
        d.spirv = spirv;
370
 
        if d.spirv.is_some() {
 
542
        if let Some(spirv) = &d.spirv {
371
543
            d.bin_type = if lib {
372
544
                CL_PROGRAM_BINARY_TYPE_LIBRARY
373
545
            } else {
374
546
                CL_PROGRAM_BINARY_TYPE_EXECUTABLE
375
547
            };
376
548
            d.status = CL_BUILD_SUCCESS as cl_build_status;
377
 
            let mut kernels = d.spirv.as_ref().unwrap().kernels();
 
549
            let mut kernels = spirv.kernels();
378
550
            info.kernels.append(&mut kernels);
 
551
            info.build_nirs(self.is_src());
379
552
            true
380
553
        } else {
381
554
            d.status = CL_BUILD_ERROR;
386
559
 
387
560
    fn do_compile(
388
561
        &self,
389
 
        dev: &Arc<Device>,
 
562
        dev: &Device,
390
563
        options: String,
391
564
        headers: &[spirv::CLCHeader],
392
565
        info: &mut MutexGuard<ProgramBuild>,
393
566
    ) -> bool {
394
 
        let d = Self::dev_build_info(info, dev);
 
567
        let d = info.dev_build_mut(dev);
395
568
 
396
569
        let (spirv, log) = match &self.src {
397
 
            ProgramSourceType::Il(spirv) => spirv.clone_on_validate(),
 
570
            ProgramSourceType::Il(spirv) => {
 
571
                let options = clc_validator_options {
 
572
                    // has to match CL_DEVICE_MAX_PARAMETER_SIZE
 
573
                    limit_max_function_arg: dev.param_max_size() as u32,
 
574
                };
 
575
                if Platform::dbg().allow_invalid_spirv {
 
576
                    (Some(spirv.clone()), String::new())
 
577
                } else {
 
578
                    spirv.clone_on_validate(&options)
 
579
                }
 
580
            }
398
581
            ProgramSourceType::Src(src) => {
399
582
                let args = prepare_options(&options, dev);
 
583
 
 
584
                if Platform::dbg().clc {
 
585
                    let src = src.to_string_lossy();
 
586
                    eprintln!("dumping compilation inputs:");
 
587
                    eprintln!("compilation arguments: {args:?}");
 
588
                    if !headers.is_empty() {
 
589
                        eprintln!("headers: {headers:#?}");
 
590
                    }
 
591
                    eprintln!("source code:\n{src}");
 
592
                }
 
593
 
400
594
                spirv::SPIRVBin::from_clc(
401
595
                    src,
402
596
                    &args,
403
597
                    headers,
404
598
                    get_disk_cache(),
405
599
                    dev.cl_features(),
 
600
                    &dev.spirv_extensions,
406
601
                    dev.address_bits(),
407
602
                )
408
603
            }
426
621
        }
427
622
    }
428
623
 
429
 
    pub fn compile(
430
 
        &self,
431
 
        dev: &Arc<Device>,
432
 
        options: String,
433
 
        headers: &[spirv::CLCHeader],
434
 
    ) -> bool {
435
 
        let mut info = self.build_info();
436
 
        self.do_compile(dev, options, headers, &mut info)
 
624
    pub fn compile(&self, dev: &Device, options: String, headers: &[spirv::CLCHeader]) -> bool {
 
625
        self.do_compile(dev, options, headers, &mut self.build_info())
437
626
    }
438
627
 
439
628
    pub fn link(
440
629
        context: Arc<Context>,
441
 
        devs: &[Arc<Device>],
 
630
        devs: &[&'static Device],
442
631
        progs: &[Arc<Program>],
443
632
        options: String,
444
633
    ) -> Arc<Program> {
445
 
        let devs: Vec<Arc<Device>> = devs.iter().map(|d| (*d).clone()).collect();
446
634
        let mut builds = HashMap::new();
447
635
        let mut kernels = HashSet::new();
448
636
        let mut locks: Vec<_> = progs.iter().map(|p| p.build_info()).collect();
449
637
        let lib = options.contains("-create-library");
450
638
 
451
 
        for d in &devs {
 
639
        for &d in devs {
452
640
            let bins: Vec<_> = locks
453
641
                .iter_mut()
454
 
                .map(|l| Self::dev_build_info(l, d).spirv.as_ref().unwrap())
 
642
                .map(|l| l.dev_build(d).spirv.as_ref().unwrap())
455
643
                .collect();
456
644
 
457
645
            let (spirv, log) = spirv::SPIRVBin::link(&bins, lib);
474
662
            };
475
663
 
476
664
            builds.insert(
477
 
                d.clone(),
 
665
                d,
478
666
                ProgramDevBuild {
479
667
                    spirv: spirv,
480
668
                    status: status,
485
673
            );
486
674
        }
487
675
 
 
676
        let mut build = ProgramBuild {
 
677
            builds: builds,
 
678
            spec_constants: HashMap::new(),
 
679
            kernels: kernels.into_iter().collect(),
 
680
            kernel_builds: HashMap::new(),
 
681
        };
 
682
 
 
683
        // Pre build nir kernels
 
684
        build.build_nirs(false);
 
685
 
488
686
        Arc::new(Self {
489
687
            base: CLObjectBase::new(),
490
688
            context: context,
491
 
            devs: devs,
 
689
            devs: devs.to_owned(),
492
690
            src: ProgramSourceType::Linked,
493
 
            kernel_count: AtomicU32::new(0),
494
 
            spec_constants: Mutex::new(HashMap::new()),
495
 
            build: Mutex::new(ProgramBuild {
496
 
                builds: builds,
497
 
                kernels: kernels.into_iter().collect(),
498
 
            }),
 
691
            build: Mutex::new(build),
499
692
        })
500
693
    }
501
694
 
502
 
    pub(super) fn hash_key(&self, dev: &Arc<Device>, name: &str) -> Option<cache_key> {
503
 
        if let Some(cache) = dev.screen().shader_cache() {
504
 
            let mut lock = self.build_info();
505
 
            let info = Self::dev_build_info(&mut lock, dev);
506
 
            assert_eq!(info.status, CL_BUILD_SUCCESS as cl_build_status);
507
 
 
508
 
            let spirv = info.spirv.as_ref().unwrap();
509
 
            let mut bin = spirv.to_bin().to_vec();
510
 
            bin.extend_from_slice(name.as_bytes());
511
 
 
512
 
            for (k, v) in self.spec_constants.lock().unwrap().iter() {
513
 
                bin.extend_from_slice(&k.to_ne_bytes());
514
 
                unsafe {
515
 
                    // SAFETY: we fully initialize this union
516
 
                    bin.extend_from_slice(&v.u64_.to_ne_bytes());
517
 
                }
518
 
            }
519
 
 
520
 
            Some(cache.gen_key(&bin))
521
 
        } else {
522
 
            None
523
 
        }
524
 
    }
525
 
 
526
 
    pub fn devs_with_build(&self) -> Vec<&Arc<Device>> {
527
 
        let mut lock = self.build_info();
528
 
        self.devs
529
 
            .iter()
530
 
            .filter(|d| {
531
 
                let info = Self::dev_build_info(&mut lock, d);
532
 
                info.status == CL_BUILD_SUCCESS as cl_build_status
533
 
            })
534
 
            .collect()
535
 
    }
536
 
 
537
 
    pub fn attribute_str(&self, kernel: &str, d: &Arc<Device>) -> String {
538
 
        let mut lock = self.build_info();
539
 
        let info = Self::dev_build_info(&mut lock, d);
540
 
 
541
 
        let attributes_strings = [
542
 
            info.spirv.as_ref().unwrap().vec_type_hint(kernel),
543
 
            info.spirv.as_ref().unwrap().local_size(kernel),
544
 
            info.spirv.as_ref().unwrap().local_size_hint(kernel),
545
 
        ];
546
 
 
547
 
        let attributes_strings: Vec<_> = attributes_strings
548
 
            .iter()
549
 
            .flatten()
550
 
            .map(String::as_str)
551
 
            .collect();
552
 
        attributes_strings.join(",")
553
 
    }
554
 
 
555
 
    pub fn to_nir(&self, kernel: &str, d: &Arc<Device>) -> NirShader {
556
 
        let constants = self.spec_constants.lock().unwrap();
557
 
        let mut spec_constants: Vec<_> = constants
558
 
            .iter()
559
 
            .map(|(&id, &value)| nir_spirv_specialization {
560
 
                id: id,
561
 
                value: value,
562
 
                defined_on_module: true,
563
 
            })
564
 
            .collect();
565
 
        drop(constants);
566
 
 
567
 
        let mut lock = self.build_info();
568
 
 
569
 
        let info = Self::dev_build_info(&mut lock, d);
570
 
        assert_eq!(info.status, CL_BUILD_SUCCESS as cl_build_status);
571
 
 
572
 
        let mut log = Platform::get().debug.program.then(Vec::new);
573
 
        let nir = info.spirv.as_ref().unwrap().to_nir(
574
 
            kernel,
575
 
            d.screen
576
 
                .nir_shader_compiler_options(pipe_shader_type::PIPE_SHADER_COMPUTE),
577
 
            &d.lib_clc,
578
 
            &mut spec_constants,
579
 
            d.address_bits(),
580
 
            log.as_mut(),
581
 
        );
582
 
 
583
 
        if let Some(log) = log {
584
 
            for line in log {
585
 
                eprintln!("{}", line);
586
 
            }
587
 
        };
588
 
 
589
 
        nir.unwrap()
 
695
    pub fn is_bin(&self) -> bool {
 
696
        matches!(self.src, ProgramSourceType::Binary)
590
697
    }
591
698
 
592
699
    pub fn is_il(&self) -> bool {
607
714
    }
608
715
 
609
716
    pub fn set_spec_constant(&self, spec_id: u32, data: &[u8]) {
610
 
        let mut lock = self.spec_constants.lock().unwrap();
 
717
        let mut lock = self.build_info();
611
718
        let mut val = nir_const_value::default();
612
719
 
613
720
        match data.len() {
618
725
            _ => unreachable!("Spec constant with invalid size!"),
619
726
        };
620
727
 
621
 
        lock.insert(spec_id, val);
 
728
        lock.spec_constants.insert(spec_id, val);
622
729
    }
623
730
}