Skip to content

Commit c904e5c

Browse files
LegNeatoeddyb
authored andcommitted
Keep #[spirv(...)] entry-points from being DCE'd by rustc.
When building a shader as a `dylib`, rustc's `cross_crate_inlinable` heuristic can mark a `pub fn` entry-point as inlinable, which internalizes it and drops its `OpEntryPoint` before codegen ever runs. Override the query to return `false` for entry-points. Fixes #590.
1 parent c41db00 commit c904e5c

3 files changed

Lines changed: 65 additions & 0 deletions

File tree

crates/rustc_codegen_spirv/src/attr.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -522,6 +522,22 @@ pub(crate) fn provide(providers: &mut Providers) {
522522
.check_mod_attrs)(tcx, module_def_id);
523523
check_mod_attrs(tcx, module_def_id);
524524
},
525+
// HACK(LegNeato) keep `#[spirv(...)]` entry-points from getting
526+
// internalized and DCE'd before codegen. See issue #590.
527+
cross_crate_inlinable: |tcx, def_id| {
528+
let sym = Symbols::get();
529+
let path = [sym.rust_gpu, sym.spirv_attr_with_version];
530+
let attrs: Vec<_> = tcx.get_attrs_by_path(def_id.to_def_id(), &path).collect();
531+
let is_entry_point = parse_attrs_for_checking(&sym, attrs)
532+
.any(|result| matches!(result, Ok((_, SpirvAttribute::Entry(_)))));
533+
if is_entry_point {
534+
false
535+
} else {
536+
(rustc_interface::DEFAULT_QUERY_PROVIDERS
537+
.queries
538+
.cross_crate_inlinable)(tcx, def_id)
539+
}
540+
},
525541
..*providers
526542
};
527543
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
// Tests that small entry-points aren't internalized by rustc and dropped
2+
// before reaching codegen. See https://github.com/Rust-GPU/rust-gpu/issues/590.
3+
4+
// build-pass
5+
// compile-flags: -C debuginfo=0 -C llvm-args=--disassemble-globals
6+
// normalize-stderr-test "OpCapability VulkanMemoryModel\n" -> ""
7+
// normalize-stderr-test "OpSource .*\n" -> ""
8+
// normalize-stderr-test "OpExtension .SPV_KHR_vulkan_memory_model.\n" -> ""
9+
// normalize-stderr-test "OpMemoryModel Logical Vulkan" -> "OpMemoryModel Logical Simple"
10+
11+
// HACK(eddyb) `compiletest` handles `ui\dis\`, but not `ui\\dis\\`, on Windows.
12+
// normalize-stderr-test "ui/dis/" -> "$$DIR/"
13+
14+
use spirv_std::glam::{UVec3, Vec4};
15+
use spirv_std::spirv;
16+
17+
#[spirv(vertex)]
18+
pub fn main_vs(#[spirv(vertex_index)] _v: i32, #[spirv(position)] _pos: &mut Vec4) {}
19+
20+
#[spirv(fragment)]
21+
pub fn main_fs(_out: &mut Vec4) {}
22+
23+
#[spirv(compute(threads(64)))]
24+
pub fn main_cs(#[spirv(global_invocation_id)] _id: UVec3) {}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
OpCapability Shader
2+
OpMemoryModel Logical Simple
3+
OpEntryPoint GLCompute %1 "main_cs" %2
4+
OpEntryPoint Fragment %3 "main_fs"
5+
OpEntryPoint Vertex %4 "main_vs" %5
6+
OpExecutionMode %1 LocalSize 64 1 1
7+
OpExecutionMode %3 OriginUpperLeft
8+
%6 = OpString "$DIR/issue-590-multiple-entry-points.rs"
9+
OpName %2 "_id"
10+
OpName %5 "_v"
11+
OpName %7 "issue_590_multiple_entry_points::main_cs"
12+
OpName %8 "issue_590_multiple_entry_points::main_fs"
13+
OpName %9 "issue_590_multiple_entry_points::main_vs"
14+
OpDecorate %2 BuiltIn GlobalInvocationId
15+
OpDecorate %5 BuiltIn VertexIndex
16+
%10 = OpTypeInt 32 0
17+
%11 = OpTypeVector %10 3
18+
%12 = OpTypePointer Input %11
19+
%13 = OpTypeVoid
20+
%14 = OpTypeFunction %13
21+
%2 = OpVariable %12 Input
22+
%15 = OpTypeFunction %13 %11
23+
%16 = OpTypeInt 32 1
24+
%17 = OpTypePointer Input %16
25+
%5 = OpVariable %17 Input

0 commit comments

Comments
 (0)