Skip to content

Commit be9debd

Browse files
committed
Check for spv language version
When checking for capabilities in SPIR-V, `capabilities_available == None` indicates that all capabilities are available. However, some capabilities are not even defined for all language versions, so we still need to check if the requested capabilities even exist in the language version we're using.
1 parent 705dc6d commit be9debd

File tree

6 files changed

+117
-36
lines changed

6 files changed

+117
-36
lines changed

naga/src/back/spv/block.rs

+8-7
Original file line numberDiff line numberDiff line change
@@ -1143,13 +1143,14 @@ impl BlockContext<'_> {
11431143
),
11441144
},
11451145
fun @ (Mf::Dot4I8Packed | Mf::Dot4U8Packed) => {
1146-
if self
1147-
.writer
1148-
.require_all(&[
1149-
spirv::Capability::DotProduct,
1150-
spirv::Capability::DotProductInput4x8BitPacked,
1151-
])
1152-
.is_ok()
1146+
if self.writer.lang_version() >= (1, 6)
1147+
&& self
1148+
.writer
1149+
.require_all(&[
1150+
spirv::Capability::DotProduct,
1151+
spirv::Capability::DotProductInput4x8BitPacked,
1152+
])
1153+
.is_ok()
11531154
{
11541155
// Write optimized code using `PackedVectorFormat4x8Bit`.
11551156
self.writer.use_extension("SPV_KHR_integer_dot_product");

naga/src/back/spv/layout.rs

+14-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@ use alloc::format;
1212
const GENERATOR: Word = 28;
1313

1414
impl PhysicalLayout {
15-
pub(super) const fn new(version: Word) -> Self {
15+
pub(super) const fn new(major_version: u8, minor_version: u8) -> Self {
16+
let version = ((major_version as u32) << 16) | ((minor_version as u32) << 8);
1617
PhysicalLayout {
1718
magic_number: MAGIC_NUMBER,
1819
version,
@@ -29,6 +30,13 @@ impl PhysicalLayout {
2930
sink.extend(iter::once(self.bound));
3031
sink.extend(iter::once(self.instruction_schema));
3132
}
33+
34+
/// Returns `(major, minor)`.
35+
pub(super) const fn lang_version(&self) -> (u8, u8) {
36+
let major = (self.version >> 16) as u8;
37+
let minor = (self.version >> 8) as u8;
38+
(major, minor)
39+
}
3240
}
3341

3442
impl super::recyclable::Recyclable for PhysicalLayout {
@@ -150,10 +158,13 @@ impl Instruction {
150158
#[test]
151159
fn test_physical_layout_in_words() {
152160
let bound = 5;
153-
let version = 0x10203;
161+
162+
// The least and most significant bytes of `version` must both be zero
163+
// according to the SPIR-V spec.
164+
let version = 0x0001_0200;
154165

155166
let mut output = vec![];
156-
let mut layout = PhysicalLayout::new(version);
167+
let mut layout = PhysicalLayout::new(1, 2);
157168
layout.bound = bound;
158169

159170
layout.in_words(&mut output);

naga/src/back/spv/writer.rs

+6-2
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,6 @@ impl Writer {
6060
if major != 1 {
6161
return Err(Error::UnsupportedVersion(major, minor));
6262
}
63-
let raw_version = ((major as u32) << 16) | ((minor as u32) << 8);
6463

6564
let mut capabilities_used = crate::FastIndexSet::default();
6665
capabilities_used.insert(spirv::Capability::Shader);
@@ -70,7 +69,7 @@ impl Writer {
7069
let void_type = id_gen.next();
7170

7271
Ok(Writer {
73-
physical_layout: PhysicalLayout::new(raw_version),
72+
physical_layout: PhysicalLayout::new(major, minor),
7473
logical_layout: LogicalLayout::default(),
7574
id_gen,
7675
capabilities_available: options.capabilities.clone(),
@@ -99,6 +98,11 @@ impl Writer {
9998
})
10099
}
101100

101+
/// Returns `(major, minor)` of the SPIR-V language version.
102+
pub const fn lang_version(&self) -> (u8, u8) {
103+
self.physical_layout.lang_version()
104+
}
105+
102106
/// Reset `Writer` to its initial state, retaining any allocations.
103107
///
104108
/// Why not just implement `Recyclable` for `Writer`? By design,

naga/tests/in/wgsl/functions-optimized.toml

+1
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ targets = "SPIRV | HLSL"
55

66
[spv]
77
capabilities = ["DotProduct", "DotProductInput4x8BitPacked"]
8+
version = [1, 6]
89

910
[hlsl]
1011
shader_model = "V6_4"

naga/tests/out/spv/wgsl-functions-optimized.spvasm

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
; SPIR-V
2-
; Version: 1.1
2+
; Version: 1.6
33
; Generator: rspirv
44
; Bound: 30
55
OpCapability Shader

naga/tests/out/spv/wgsl-functions.spvasm

+87-23
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,12 @@
11
; SPIR-V
22
; Version: 1.1
33
; Generator: rspirv
4-
; Bound: 95
4+
; Bound: 162
55
OpCapability Shader
6-
OpCapability DotProductKHR
7-
OpCapability DotProductInput4x8BitPackedKHR
8-
OpExtension "SPV_KHR_integer_dot_product"
96
%1 = OpExtInstImport "GLSL.std.450"
107
OpMemoryModel Logical GLSL450
11-
OpEntryPoint GLCompute %89 "main"
12-
OpExecutionMode %89 LocalSize 1 1 1
8+
OpEntryPoint GLCompute %156 "main"
9+
OpExecutionMode %156 LocalSize 1 1 1
1310
%2 = OpTypeVoid
1411
%4 = OpTypeFloat 32
1512
%3 = OpTypeVector %4 2
@@ -42,7 +39,10 @@ OpExecutionMode %89 LocalSize 1 1 1
4239
%76 = OpConstant %6 6
4340
%77 = OpConstant %6 7
4441
%78 = OpConstant %6 8
45-
%90 = OpTypeFunction %2
42+
%83 = OpConstant %6 0
43+
%84 = OpConstant %6 16
44+
%85 = OpConstant %6 24
45+
%157 = OpTypeFunction %2
4646
%8 = OpFunction %3 None %9
4747
%7 = OpLabel
4848
OpBranch %14
@@ -96,22 +96,86 @@ OpFunctionEnd
9696
%69 = OpLabel
9797
OpBranch %79
9898
%79 = OpLabel
99-
%80 = OpSDotKHR %5 %22 %72 PackedVectorFormat4x8BitKHR
100-
%81 = OpUDotKHR %6 %73 %74 PackedVectorFormat4x8BitKHR
101-
%82 = OpIAdd %6 %75 %81
102-
%83 = OpIAdd %6 %76 %81
103-
%84 = OpSDotKHR %5 %82 %83 PackedVectorFormat4x8BitKHR
104-
%85 = OpIAdd %6 %77 %81
105-
%86 = OpIAdd %6 %78 %81
106-
%87 = OpUDotKHR %6 %85 %86 PackedVectorFormat4x8BitKHR
107-
OpReturnValue %87
99+
%81 = OpBitcast %5 %22
100+
%82 = OpBitcast %5 %72
101+
%86 = OpBitFieldSExtract %5 %81 %83 %78
102+
%87 = OpBitFieldSExtract %5 %82 %83 %78
103+
%88 = OpIMul %5 %86 %87
104+
%89 = OpIAdd %5 %32 %88
105+
%90 = OpBitFieldSExtract %5 %81 %78 %78
106+
%91 = OpBitFieldSExtract %5 %82 %78 %78
107+
%92 = OpIMul %5 %90 %91
108+
%93 = OpIAdd %5 %89 %92
109+
%94 = OpBitFieldSExtract %5 %81 %84 %78
110+
%95 = OpBitFieldSExtract %5 %82 %84 %78
111+
%96 = OpIMul %5 %94 %95
112+
%97 = OpIAdd %5 %93 %96
113+
%98 = OpBitFieldSExtract %5 %81 %85 %78
114+
%99 = OpBitFieldSExtract %5 %82 %85 %78
115+
%100 = OpIMul %5 %98 %99
116+
%80 = OpIAdd %5 %97 %100
117+
%102 = OpBitFieldUExtract %6 %73 %83 %78
118+
%103 = OpBitFieldUExtract %6 %74 %83 %78
119+
%104 = OpIMul %6 %102 %103
120+
%105 = OpIAdd %6 %41 %104
121+
%106 = OpBitFieldUExtract %6 %73 %78 %78
122+
%107 = OpBitFieldUExtract %6 %74 %78 %78
123+
%108 = OpIMul %6 %106 %107
124+
%109 = OpIAdd %6 %105 %108
125+
%110 = OpBitFieldUExtract %6 %73 %84 %78
126+
%111 = OpBitFieldUExtract %6 %74 %84 %78
127+
%112 = OpIMul %6 %110 %111
128+
%113 = OpIAdd %6 %109 %112
129+
%114 = OpBitFieldUExtract %6 %73 %85 %78
130+
%115 = OpBitFieldUExtract %6 %74 %85 %78
131+
%116 = OpIMul %6 %114 %115
132+
%101 = OpIAdd %6 %113 %116
133+
%117 = OpIAdd %6 %75 %101
134+
%118 = OpIAdd %6 %76 %101
135+
%120 = OpBitcast %5 %117
136+
%121 = OpBitcast %5 %118
137+
%122 = OpBitFieldSExtract %5 %120 %83 %78
138+
%123 = OpBitFieldSExtract %5 %121 %83 %78
139+
%124 = OpIMul %5 %122 %123
140+
%125 = OpIAdd %5 %32 %124
141+
%126 = OpBitFieldSExtract %5 %120 %78 %78
142+
%127 = OpBitFieldSExtract %5 %121 %78 %78
143+
%128 = OpIMul %5 %126 %127
144+
%129 = OpIAdd %5 %125 %128
145+
%130 = OpBitFieldSExtract %5 %120 %84 %78
146+
%131 = OpBitFieldSExtract %5 %121 %84 %78
147+
%132 = OpIMul %5 %130 %131
148+
%133 = OpIAdd %5 %129 %132
149+
%134 = OpBitFieldSExtract %5 %120 %85 %78
150+
%135 = OpBitFieldSExtract %5 %121 %85 %78
151+
%136 = OpIMul %5 %134 %135
152+
%119 = OpIAdd %5 %133 %136
153+
%137 = OpIAdd %6 %77 %101
154+
%138 = OpIAdd %6 %78 %101
155+
%140 = OpBitFieldUExtract %6 %137 %83 %78
156+
%141 = OpBitFieldUExtract %6 %138 %83 %78
157+
%142 = OpIMul %6 %140 %141
158+
%143 = OpIAdd %6 %41 %142
159+
%144 = OpBitFieldUExtract %6 %137 %78 %78
160+
%145 = OpBitFieldUExtract %6 %138 %78 %78
161+
%146 = OpIMul %6 %144 %145
162+
%147 = OpIAdd %6 %143 %146
163+
%148 = OpBitFieldUExtract %6 %137 %84 %78
164+
%149 = OpBitFieldUExtract %6 %138 %84 %78
165+
%150 = OpIMul %6 %148 %149
166+
%151 = OpIAdd %6 %147 %150
167+
%152 = OpBitFieldUExtract %6 %137 %85 %78
168+
%153 = OpBitFieldUExtract %6 %138 %85 %78
169+
%154 = OpIMul %6 %152 %153
170+
%139 = OpIAdd %6 %151 %154
171+
OpReturnValue %139
108172
OpFunctionEnd
109-
%89 = OpFunction %2 None %90
110-
%88 = OpLabel
111-
OpBranch %91
112-
%91 = OpLabel
113-
%92 = OpFunctionCall %3 %8
114-
%93 = OpFunctionCall %5 %17
115-
%94 = OpFunctionCall %6 %70
173+
%156 = OpFunction %2 None %157
174+
%155 = OpLabel
175+
OpBranch %158
176+
%158 = OpLabel
177+
%159 = OpFunctionCall %3 %8
178+
%160 = OpFunctionCall %5 %17
179+
%161 = OpFunctionCall %6 %70
116180
OpReturn
117181
OpFunctionEnd

0 commit comments

Comments
 (0)