|
1 | 1 | use crate::builder;
|
2 | 2 | use crate::codegen_cx::CodegenCx;
|
3 | 3 | use crate::spirv_type::SpirvType;
|
| 4 | +use crate::symbols::Symbols; |
4 | 5 | use crate::target::SpirvTarget;
|
5 | 6 | use crate::target_feature::TargetFeature;
|
6 | 7 | use rspirv::dr::{Block, Builder, Module, Operand};
|
7 | 8 | use rspirv::spirv::{AddressingModel, Capability, MemoryModel, Op, StorageClass, Word};
|
8 | 9 | use rspirv::{binary::Assemble, binary::Disassemble};
|
9 |
| -use rustc_data_structures::fx::FxHashMap; |
| 10 | +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; |
10 | 11 | use rustc_middle::bug;
|
| 12 | +use rustc_span::symbol::Symbol; |
11 | 13 | use rustc_span::{Span, DUMMY_SP};
|
12 | 14 | use std::cell::{RefCell, RefMut};
|
13 | 15 | use std::rc::Rc;
|
@@ -319,52 +321,111 @@ pub struct BuilderSpirv {
|
319 | 321 | const_to_id: RefCell<FxHashMap<WithType<SpirvConst>, WithConstLegality<Word>>>,
|
320 | 322 | id_to_const: RefCell<FxHashMap<Word, WithConstLegality<SpirvConst>>>,
|
321 | 323 | string_cache: RefCell<FxHashMap<String, Word>>,
|
| 324 | + |
| 325 | + enabled_capabilities: FxHashSet<Capability>, |
| 326 | + enabled_extensions: FxHashSet<Symbol>, |
322 | 327 | }
|
323 | 328 |
|
324 | 329 | impl BuilderSpirv {
|
325 |
| - pub fn new(target: &SpirvTarget, features: &[TargetFeature]) -> Self { |
| 330 | + pub fn new( |
| 331 | + sym: &Symbols, |
| 332 | + target: &SpirvTarget, |
| 333 | + features: &[TargetFeature], |
| 334 | + bindless: bool, |
| 335 | + ) -> Self { |
326 | 336 | let version = target.spirv_version();
|
327 | 337 | let memory_model = target.memory_model();
|
328 | 338 |
|
329 | 339 | let mut builder = Builder::new();
|
330 | 340 | builder.set_version(version.0, version.1);
|
331 | 341 |
|
| 342 | + let mut enabled_capabilities = FxHashSet::default(); |
| 343 | + let mut enabled_extensions = FxHashSet::default(); |
| 344 | + |
| 345 | + fn add_cap( |
| 346 | + builder: &mut Builder, |
| 347 | + enabled_capabilities: &mut FxHashSet<Capability>, |
| 348 | + cap: Capability, |
| 349 | + ) { |
| 350 | + // This should be the only callsite of Builder::capability (aside from tests), to make |
| 351 | + // sure the hashset stays in sync. |
| 352 | + builder.capability(cap); |
| 353 | + enabled_capabilities.insert(cap); |
| 354 | + } |
| 355 | + fn add_ext(builder: &mut Builder, enabled_extensions: &mut FxHashSet<Symbol>, ext: Symbol) { |
| 356 | + // This should be the only callsite of Builder::extension (aside from tests), to make |
| 357 | + // sure the hashset stays in sync. |
| 358 | + builder.extension(&*ext.as_str()); |
| 359 | + enabled_extensions.insert(ext); |
| 360 | + } |
| 361 | + |
332 | 362 | for feature in features {
|
333 |
| - match feature { |
334 |
| - TargetFeature::Capability(cap) => builder.capability(*cap), |
335 |
| - TargetFeature::Extension(ext) => builder.extension(&*ext.as_str()), |
| 363 | + match *feature { |
| 364 | + TargetFeature::Capability(cap) => { |
| 365 | + add_cap(&mut builder, &mut enabled_capabilities, cap); |
| 366 | + } |
| 367 | + TargetFeature::Extension(ext) => { |
| 368 | + add_ext(&mut builder, &mut enabled_extensions, ext); |
| 369 | + } |
336 | 370 | }
|
337 | 371 | }
|
338 | 372 |
|
339 | 373 | if target.is_kernel() {
|
340 |
| - builder.capability(Capability::Kernel); |
| 374 | + add_cap(&mut builder, &mut enabled_capabilities, Capability::Kernel); |
341 | 375 | } else {
|
342 |
| - builder.capability(Capability::Shader); |
| 376 | + add_cap(&mut builder, &mut enabled_capabilities, Capability::Shader); |
343 | 377 | if memory_model == MemoryModel::Vulkan {
|
344 | 378 | if version < (1, 5) {
|
345 |
| - builder.extension("SPV_KHR_vulkan_memory_model"); |
| 379 | + add_ext( |
| 380 | + &mut builder, |
| 381 | + &mut enabled_extensions, |
| 382 | + sym.spv_khr_vulkan_memory_model, |
| 383 | + ); |
346 | 384 | }
|
347 |
| - builder.capability(Capability::VulkanMemoryModel); |
| 385 | + add_cap( |
| 386 | + &mut builder, |
| 387 | + &mut enabled_capabilities, |
| 388 | + Capability::VulkanMemoryModel, |
| 389 | + ); |
348 | 390 | }
|
349 | 391 | }
|
350 | 392 |
|
351 | 393 | // The linker will always be ran on this module
|
352 |
| - builder.capability(Capability::Linkage); |
| 394 | + add_cap(&mut builder, &mut enabled_capabilities, Capability::Linkage); |
353 | 395 |
|
354 | 396 | let addressing_model = if target.is_kernel() {
|
355 |
| - builder.capability(Capability::Addresses); |
| 397 | + add_cap( |
| 398 | + &mut builder, |
| 399 | + &mut enabled_capabilities, |
| 400 | + Capability::Addresses, |
| 401 | + ); |
356 | 402 | AddressingModel::Physical32
|
357 | 403 | } else {
|
358 | 404 | AddressingModel::Logical
|
359 | 405 | };
|
360 | 406 |
|
361 | 407 | builder.memory_model(addressing_model, memory_model);
|
362 | 408 |
|
| 409 | + if bindless { |
| 410 | + add_ext( |
| 411 | + &mut builder, |
| 412 | + &mut enabled_extensions, |
| 413 | + sym.spv_ext_descriptor_indexing, |
| 414 | + ); |
| 415 | + add_cap( |
| 416 | + &mut builder, |
| 417 | + &mut enabled_capabilities, |
| 418 | + Capability::RuntimeDescriptorArray, |
| 419 | + ); |
| 420 | + } |
| 421 | + |
363 | 422 | Self {
|
364 | 423 | builder: RefCell::new(builder),
|
365 | 424 | const_to_id: Default::default(),
|
366 | 425 | id_to_const: Default::default(),
|
367 | 426 | string_cache: Default::default(),
|
| 427 | + enabled_capabilities, |
| 428 | + enabled_extensions, |
368 | 429 | }
|
369 | 430 | }
|
370 | 431 |
|
@@ -410,27 +471,11 @@ impl BuilderSpirv {
|
410 | 471 | }
|
411 | 472 |
|
412 | 473 | pub fn has_capability(&self, capability: Capability) -> bool {
|
413 |
| - self.builder |
414 |
| - .borrow() |
415 |
| - .module_ref() |
416 |
| - .capabilities |
417 |
| - .iter() |
418 |
| - .any(|inst| { |
419 |
| - inst.class.opcode == Op::Capability |
420 |
| - && inst.operands[0].unwrap_capability() == capability |
421 |
| - }) |
| 474 | + self.enabled_capabilities.contains(&capability) |
422 | 475 | }
|
423 | 476 |
|
424 |
| - pub fn has_extension(&self, extension: &str) -> bool { |
425 |
| - self.builder |
426 |
| - .borrow() |
427 |
| - .module_ref() |
428 |
| - .extensions |
429 |
| - .iter() |
430 |
| - .any(|inst| { |
431 |
| - inst.class.opcode == Op::Extension |
432 |
| - && inst.operands[0].unwrap_literal_string() == extension |
433 |
| - }) |
| 477 | + pub fn has_extension(&self, extension: Symbol) -> bool { |
| 478 | + self.enabled_extensions.contains(&extension) |
434 | 479 | }
|
435 | 480 |
|
436 | 481 | pub fn select_function_by_id(&self, id: Word) -> BuilderCursor {
|
|
0 commit comments