diff --git a/naga/src/back/spv/block.rs b/naga/src/back/spv/block.rs index 0799017ba2..96e8471c86 100644 --- a/naga/src/back/spv/block.rs +++ b/naga/src/back/spv/block.rs @@ -1143,13 +1143,14 @@ impl BlockContext<'_> { ), }, fun @ (Mf::Dot4I8Packed | Mf::Dot4U8Packed) => { - if self - .writer - .require_all(&[ - spirv::Capability::DotProduct, - spirv::Capability::DotProductInput4x8BitPacked, - ]) - .is_ok() + if self.writer.lang_version() >= (1, 6) + && self + .writer + .require_all(&[ + spirv::Capability::DotProduct, + spirv::Capability::DotProductInput4x8BitPacked, + ]) + .is_ok() { // Write optimized code using `PackedVectorFormat4x8Bit`. self.writer.use_extension("SPV_KHR_integer_dot_product"); diff --git a/naga/src/back/spv/layout.rs b/naga/src/back/spv/layout.rs index 177996741d..6652b33504 100644 --- a/naga/src/back/spv/layout.rs +++ b/naga/src/back/spv/layout.rs @@ -12,7 +12,8 @@ use alloc::format; const GENERATOR: Word = 28; impl PhysicalLayout { - pub(super) const fn new(version: Word) -> Self { + pub(super) const fn new(major_version: u8, minor_version: u8) -> Self { + let version = ((major_version as u32) << 16) | ((minor_version as u32) << 8); PhysicalLayout { magic_number: MAGIC_NUMBER, version, @@ -29,6 +30,13 @@ impl PhysicalLayout { sink.extend(iter::once(self.bound)); sink.extend(iter::once(self.instruction_schema)); } + + /// Returns `(major, minor)`. + pub(super) const fn lang_version(&self) -> (u8, u8) { + let major = (self.version >> 16) as u8; + let minor = (self.version >> 8) as u8; + (major, minor) + } } impl super::recyclable::Recyclable for PhysicalLayout { @@ -150,10 +158,13 @@ impl Instruction { #[test] fn test_physical_layout_in_words() { let bound = 5; - let version = 0x10203; + + // The least and most significant bytes of `version` must both be zero + // according to the SPIR-V spec. + let version = 0x0001_0200; let mut output = vec![]; - let mut layout = PhysicalLayout::new(version); + let mut layout = PhysicalLayout::new(1, 2); layout.bound = bound; layout.in_words(&mut output); diff --git a/naga/src/back/spv/writer.rs b/naga/src/back/spv/writer.rs index 3b79c91209..3819ed10e7 100644 --- a/naga/src/back/spv/writer.rs +++ b/naga/src/back/spv/writer.rs @@ -60,7 +60,6 @@ impl Writer { if major != 1 { return Err(Error::UnsupportedVersion(major, minor)); } - let raw_version = ((major as u32) << 16) | ((minor as u32) << 8); let mut capabilities_used = crate::FastIndexSet::default(); capabilities_used.insert(spirv::Capability::Shader); @@ -70,7 +69,7 @@ impl Writer { let void_type = id_gen.next(); Ok(Writer { - physical_layout: PhysicalLayout::new(raw_version), + physical_layout: PhysicalLayout::new(major, minor), logical_layout: LogicalLayout::default(), id_gen, capabilities_available: options.capabilities.clone(), @@ -99,6 +98,11 @@ impl Writer { }) } + /// Returns `(major, minor)` of the SPIR-V language version. + pub const fn lang_version(&self) -> (u8, u8) { + self.physical_layout.lang_version() + } + /// Reset `Writer` to its initial state, retaining any allocations. /// /// Why not just implement `Recyclable` for `Writer`? By design, diff --git a/naga/tests/in/wgsl/functions-optimized.toml b/naga/tests/in/wgsl/functions-optimized.toml index 457c80d16e..c8a7abfa09 100644 --- a/naga/tests/in/wgsl/functions-optimized.toml +++ b/naga/tests/in/wgsl/functions-optimized.toml @@ -5,6 +5,7 @@ targets = "SPIRV | HLSL" [spv] capabilities = ["DotProduct", "DotProductInput4x8BitPacked"] +version = [1, 6] [hlsl] shader_model = "V6_4" diff --git a/naga/tests/out/spv/wgsl-functions-optimized.spvasm b/naga/tests/out/spv/wgsl-functions-optimized.spvasm index 5366e0a9fc..7169a1e1e4 100644 --- a/naga/tests/out/spv/wgsl-functions-optimized.spvasm +++ b/naga/tests/out/spv/wgsl-functions-optimized.spvasm @@ -1,5 +1,5 @@ ; SPIR-V -; Version: 1.1 +; Version: 1.6 ; Generator: rspirv ; Bound: 30 OpCapability Shader diff --git a/naga/tests/out/spv/wgsl-functions.spvasm b/naga/tests/out/spv/wgsl-functions.spvasm index 35585e2a6c..8d271c22f2 100644 --- a/naga/tests/out/spv/wgsl-functions.spvasm +++ b/naga/tests/out/spv/wgsl-functions.spvasm @@ -1,15 +1,12 @@ ; SPIR-V ; Version: 1.1 ; Generator: rspirv -; Bound: 95 +; Bound: 162 OpCapability Shader -OpCapability DotProductKHR -OpCapability DotProductInput4x8BitPackedKHR -OpExtension "SPV_KHR_integer_dot_product" %1 = OpExtInstImport "GLSL.std.450" OpMemoryModel Logical GLSL450 -OpEntryPoint GLCompute %89 "main" -OpExecutionMode %89 LocalSize 1 1 1 +OpEntryPoint GLCompute %156 "main" +OpExecutionMode %156 LocalSize 1 1 1 %2 = OpTypeVoid %4 = OpTypeFloat 32 %3 = OpTypeVector %4 2 @@ -42,7 +39,10 @@ OpExecutionMode %89 LocalSize 1 1 1 %76 = OpConstant %6 6 %77 = OpConstant %6 7 %78 = OpConstant %6 8 -%90 = OpTypeFunction %2 +%83 = OpConstant %6 0 +%84 = OpConstant %6 16 +%85 = OpConstant %6 24 +%157 = OpTypeFunction %2 %8 = OpFunction %3 None %9 %7 = OpLabel OpBranch %14 @@ -96,22 +96,86 @@ OpFunctionEnd %69 = OpLabel OpBranch %79 %79 = OpLabel -%80 = OpSDotKHR %5 %22 %72 PackedVectorFormat4x8BitKHR -%81 = OpUDotKHR %6 %73 %74 PackedVectorFormat4x8BitKHR -%82 = OpIAdd %6 %75 %81 -%83 = OpIAdd %6 %76 %81 -%84 = OpSDotKHR %5 %82 %83 PackedVectorFormat4x8BitKHR -%85 = OpIAdd %6 %77 %81 -%86 = OpIAdd %6 %78 %81 -%87 = OpUDotKHR %6 %85 %86 PackedVectorFormat4x8BitKHR -OpReturnValue %87 +%81 = OpBitcast %5 %22 +%82 = OpBitcast %5 %72 +%86 = OpBitFieldSExtract %5 %81 %83 %78 +%87 = OpBitFieldSExtract %5 %82 %83 %78 +%88 = OpIMul %5 %86 %87 +%89 = OpIAdd %5 %32 %88 +%90 = OpBitFieldSExtract %5 %81 %78 %78 +%91 = OpBitFieldSExtract %5 %82 %78 %78 +%92 = OpIMul %5 %90 %91 +%93 = OpIAdd %5 %89 %92 +%94 = OpBitFieldSExtract %5 %81 %84 %78 +%95 = OpBitFieldSExtract %5 %82 %84 %78 +%96 = OpIMul %5 %94 %95 +%97 = OpIAdd %5 %93 %96 +%98 = OpBitFieldSExtract %5 %81 %85 %78 +%99 = OpBitFieldSExtract %5 %82 %85 %78 +%100 = OpIMul %5 %98 %99 +%80 = OpIAdd %5 %97 %100 +%102 = OpBitFieldUExtract %6 %73 %83 %78 +%103 = OpBitFieldUExtract %6 %74 %83 %78 +%104 = OpIMul %6 %102 %103 +%105 = OpIAdd %6 %41 %104 +%106 = OpBitFieldUExtract %6 %73 %78 %78 +%107 = OpBitFieldUExtract %6 %74 %78 %78 +%108 = OpIMul %6 %106 %107 +%109 = OpIAdd %6 %105 %108 +%110 = OpBitFieldUExtract %6 %73 %84 %78 +%111 = OpBitFieldUExtract %6 %74 %84 %78 +%112 = OpIMul %6 %110 %111 +%113 = OpIAdd %6 %109 %112 +%114 = OpBitFieldUExtract %6 %73 %85 %78 +%115 = OpBitFieldUExtract %6 %74 %85 %78 +%116 = OpIMul %6 %114 %115 +%101 = OpIAdd %6 %113 %116 +%117 = OpIAdd %6 %75 %101 +%118 = OpIAdd %6 %76 %101 +%120 = OpBitcast %5 %117 +%121 = OpBitcast %5 %118 +%122 = OpBitFieldSExtract %5 %120 %83 %78 +%123 = OpBitFieldSExtract %5 %121 %83 %78 +%124 = OpIMul %5 %122 %123 +%125 = OpIAdd %5 %32 %124 +%126 = OpBitFieldSExtract %5 %120 %78 %78 +%127 = OpBitFieldSExtract %5 %121 %78 %78 +%128 = OpIMul %5 %126 %127 +%129 = OpIAdd %5 %125 %128 +%130 = OpBitFieldSExtract %5 %120 %84 %78 +%131 = OpBitFieldSExtract %5 %121 %84 %78 +%132 = OpIMul %5 %130 %131 +%133 = OpIAdd %5 %129 %132 +%134 = OpBitFieldSExtract %5 %120 %85 %78 +%135 = OpBitFieldSExtract %5 %121 %85 %78 +%136 = OpIMul %5 %134 %135 +%119 = OpIAdd %5 %133 %136 +%137 = OpIAdd %6 %77 %101 +%138 = OpIAdd %6 %78 %101 +%140 = OpBitFieldUExtract %6 %137 %83 %78 +%141 = OpBitFieldUExtract %6 %138 %83 %78 +%142 = OpIMul %6 %140 %141 +%143 = OpIAdd %6 %41 %142 +%144 = OpBitFieldUExtract %6 %137 %78 %78 +%145 = OpBitFieldUExtract %6 %138 %78 %78 +%146 = OpIMul %6 %144 %145 +%147 = OpIAdd %6 %143 %146 +%148 = OpBitFieldUExtract %6 %137 %84 %78 +%149 = OpBitFieldUExtract %6 %138 %84 %78 +%150 = OpIMul %6 %148 %149 +%151 = OpIAdd %6 %147 %150 +%152 = OpBitFieldUExtract %6 %137 %85 %78 +%153 = OpBitFieldUExtract %6 %138 %85 %78 +%154 = OpIMul %6 %152 %153 +%139 = OpIAdd %6 %151 %154 +OpReturnValue %139 OpFunctionEnd -%89 = OpFunction %2 None %90 -%88 = OpLabel -OpBranch %91 -%91 = OpLabel -%92 = OpFunctionCall %3 %8 -%93 = OpFunctionCall %5 %17 -%94 = OpFunctionCall %6 %70 +%156 = OpFunction %2 None %157 +%155 = OpLabel +OpBranch %158 +%158 = OpLabel +%159 = OpFunctionCall %3 %8 +%160 = OpFunctionCall %5 %17 +%161 = OpFunctionCall %6 %70 OpReturn OpFunctionEnd \ No newline at end of file