// RUN: mlir-opt -spirv-update-vce %s | FileCheck %s //===----------------------------------------------------------------------===// // Version //===----------------------------------------------------------------------===// // Test deducing minimal version. // spirv.IAdd is available from v1.0. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.func @iadd(%val : i32) -> i32 "None" { %0 = spirv.IAdd %val, %val: i32 spirv.ReturnValue %0: i32 } } // Test deducing minimal version. // spirv.GroupNonUniformBallot is available since v1.3. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.func @group_non_uniform_ballot(%predicate : i1) -> vector<4xi32> "None" { %0 = spirv.GroupNonUniformBallot %predicate : vector<4xi32> spirv.ReturnValue %0: vector<4xi32> } } // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env<#spirv.vce, #spirv.resource_limits<>> } { spirv.func @select_with_scalar_condition(%predicate : i1, %a: vector<2xf32>, %b: vector<2xf32>) -> vector<2xf32> "None" { %0 = spirv.Select %predicate, %a, %b : i1, vector<2xf32> spirv.ReturnValue %0: vector<2xf32> } } //===----------------------------------------------------------------------===// // Capability //===----------------------------------------------------------------------===// // Test minimal capabilities. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.func @iadd(%val : i32) -> i32 "None" { %0 = spirv.IAdd %val, %val: i32 spirv.ReturnValue %0: i32 } } // Test Physical Storage Buffers are deduced correctly. // CHECK: spirv.module PhysicalStorageBuffer64 GLSL450 requires #spirv.vce spirv.module PhysicalStorageBuffer64 GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.func @physical_ptr(%val : !spirv.ptr { spirv.decoration = #spirv.decoration }) "None" { spirv.Return } } // Test deducing implied capability. // AtomicStorage implies Shader. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.func @iadd(%val : i32) -> i32 "None" { %0 = spirv.IAdd %val, %val: i32 spirv.ReturnValue %0: i32 } } // Test selecting the capability available in the target environment. // spirv.GroupNonUniform op itself can be enabled via any of // * GroupNonUniformArithmetic // * GroupNonUniformClustered // * GroupNonUniformPartitionedNV // Its 'Reduce' group operation can be enabled via any of // * Kernel // * GroupNonUniformArithmetic // * GroupNonUniformBallot // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.func @group_non_uniform_iadd(%val : i32) -> i32 "None" { %0 = spirv.GroupNonUniformIAdd %val : i32 -> i32 spirv.ReturnValue %0: i32 } } // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.func @group_non_uniform_iadd(%val : i32) -> i32 "None" { %0 = spirv.GroupNonUniformIAdd %val : i32 -> i32 spirv.ReturnValue %0: i32 } } // Test type required capabilities // Using 8-bit integers in non-interface storage class requires Int8. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.func @iadd_function(%val : i8) -> i8 "None" { %0 = spirv.IAdd %val, %val : i8 spirv.ReturnValue %0: i8 } } // Using 16-bit floats in non-interface storage class requires Float16. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.func @fadd_function(%val : f16) -> f16 "None" { %0 = spirv.FAdd %val, %val : f16 spirv.ReturnValue %0: f16 } } // Using 16-element vectors requires Vector16. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.func @iadd_v16_function(%val : vector<16xi32>) -> vector<16xi32> "None" { %0 = spirv.IAdd %val, %val : vector<16xi32> spirv.ReturnValue %0: vector<16xi32> } } //===----------------------------------------------------------------------===// // Extension //===----------------------------------------------------------------------===// // Test deducing minimal extensions. // spirv.KHR.SubgroupBallot requires the SPV_KHR_shader_ballot extension. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.func @subgroup_ballot(%predicate : i1) -> vector<4xi32> "None" { %0 = spirv.KHR.SubgroupBallot %predicate: vector<4xi32> spirv.ReturnValue %0: vector<4xi32> } } // Test deducing implied extension. // Vulkan memory model requires SPV_KHR_vulkan_memory_model, which is enabled // implicitly by v1.5. // CHECK: requires #spirv.vce spirv.module Logical Vulkan attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.func @iadd(%val : i32) -> i32 "None" { %0 = spirv.IAdd %val, %val: i32 spirv.ReturnValue %0: i32 } } // Test type required extensions // Using 8-bit integers in interface storage class requires additional // extensions and capabilities. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.func @iadd_storage_buffer(%ptr : !spirv.ptr) -> i16 "None" { %0 = spirv.Load "StorageBuffer" %ptr : i16 %1 = spirv.IAdd %0, %0 : i16 spirv.ReturnValue %1: i16 } } // Complicated nested types // * Buffer requires ImageBuffer or SampledBuffer. // * Rg32f requires StorageImageExtendedFormats. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.GlobalVariable @data : !spirv.ptr, Uniform> spirv.GlobalVariable @img : !spirv.ptr, UniformConstant> } // Using bfloat16 requires BFloat16TypeKHR capability and SPV_KHR_bfloat16 extension. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<> > } { spirv.func @load_bf16(%ptr : !spirv.ptr) -> bf16 "None" { %val = spirv.Load "StorageBuffer" %ptr : bf16 spirv.ReturnValue %val : bf16 } } // Cooperative matrix with bf16 component type // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<> > } { spirv.func @bf16_coopmatrix(%arg0: !spirv.coopmatrix<4x4xbf16, Subgroup, MatrixA>) -> !spirv.coopmatrix<4x4xbf16, Subgroup, MatrixA> "None" { spirv.ReturnValue %arg0 : !spirv.coopmatrix<4x4xbf16, Subgroup, MatrixA> } } // Cooperative matrix with f8E4M3FN component type // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<> > } { spirv.func @f8_coopmatrix(%arg0: !spirv.coopmatrix<4x4xf8E4M3FN, Subgroup, MatrixA>) -> !spirv.coopmatrix<4x4xf8E4M3FN, Subgroup, MatrixA> "None" { spirv.ReturnValue %arg0 : !spirv.coopmatrix<4x4xf8E4M3FN, Subgroup, MatrixA> } } // Cooperative matrix with f8E5M2 component type // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<> > } { spirv.func @f8_coopmatrix(%arg0: !spirv.coopmatrix<4x4xf8E5M2, Subgroup, MatrixA>) -> !spirv.coopmatrix<4x4xf8E5M2, Subgroup, MatrixA> "None" { spirv.ReturnValue %arg0 : !spirv.coopmatrix<4x4xf8E5M2, Subgroup, MatrixA> } } // CHECK: requires #spirv.vce spirv.module Logical Vulkan attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.ARM.Graph @argmax(%arg0: !spirv.arm.tensor<14x19xi8>, %arg1 : !spirv.arm.tensor<1xf16>) -> !spirv.arm.tensor<14x19xi8> { spirv.ARM.GraphOutputs %arg0 : !spirv.arm.tensor<14x19xi8> } } // Check that `bind(set, binding)` on spirv.GlobalVariable deduces the Shader // capability (DescriptorSet and Binding decorations require Shader per the spec). // CHECK: requires #spirv.vce spirv.module Logical Vulkan attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.GlobalVariable @var bind(0, 0) : !spirv.ptr, UniformConstant> } // Check that extension and capability queries handle recursive types. // CHECK: requires #spirv.vce spirv.module Physical64 GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.GlobalVariable @recursive: !spirv.ptr, StorageBuffer>)>, StorageBuffer> } //===----------------------------------------------------------------------===// // Image type capabilities //===----------------------------------------------------------------------===// // 2D + MultiSampled + NoSampler requires StorageImageMultisample. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.GlobalVariable @img_2d_ms_storage bind(0, 0) : !spirv.ptr, UniformConstant> } // 2D + MultiSampled + Arrayed + NoSampler requires both StorageImageMultisample // and ImageMSArray. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.GlobalVariable @img_2d_ms_arrayed_storage bind(0, 0) : !spirv.ptr, UniformConstant> } // 2D + SingleSampled does not request multisample-related caps. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.GlobalVariable @img_2d_storage bind(0, 0) : !spirv.ptr, UniformConstant> } // Cube without Arrayed requires Shader but not ImageCubeArray. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.GlobalVariable @img_cube bind(0, 0) : !spirv.ptr, UniformConstant> } // Cube + Arrayed requires ImageCubeArray (which transitively implies // SampledCubeArray). // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.GlobalVariable @img_cube_arrayed bind(0, 0) : !spirv.ptr, UniformConstant> } // 1D + NoSampler requires Image1D directly (and pulls in Sampled1D as an // implied capability, but the target_env need not list Sampled1D). // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.GlobalVariable @img_1d_storage bind(0, 0) : !spirv.ptr, UniformConstant> } // 1D + NeedSampler requires Sampled1D. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.GlobalVariable @img_1d_sampled bind(0, 0) : !spirv.ptr, UniformConstant> } // Buffer + NoSampler requires ImageBuffer (which transitively implies // SampledBuffer). // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.GlobalVariable @img_buffer_storage bind(0, 0) : !spirv.ptr, UniformConstant> } // 64-bit integer sampled type requires Int64ImageEXT and the // SPV_EXT_shader_image_int64 extension. // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.GlobalVariable @img_2d_i64 bind(0, 0) : !spirv.ptr, UniformConstant> } // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.func @linkonce_odr_fn() "None" attributes { linkage_attributes = #spirv.linkage_attributes< linkage_name = "linkonce_odr_fn", linkage_type = > } { spirv.Return } } // CHECK: requires #spirv.vce spirv.module Logical GLSL450 attributes { spirv.target_env = #spirv.target_env< #spirv.vce, #spirv.resource_limits<>> } { spirv.GlobalVariable @weak_var { linkage_attributes = #spirv.linkage_attributes< linkage_name = "weak_var", linkage_type = > } : !spirv.ptr }